You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			210 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			210 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			VHDL
		
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| library work;
 | |
| 
 | |
| package helpers is
 | |
|     function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer;
 | |
|     function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer;
 | |
| 
 | |
|     function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer;
 | |
|     function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer;
 | |
| 
 | |
|     function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
 | |
|     function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector;
 | |
|     function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
 | |
| 
 | |
|     function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
 | |
| 
 | |
|     function ppc_signed_compare(a, b: signed(63 downto 0)) return std_ulogic_vector;
 | |
|     function ppc_unsigned_compare(a, b: unsigned(63 downto 0)) return std_ulogic_vector;
 | |
| 
 | |
|     function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
 | |
| 
 | |
|     function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector;
 | |
| 
 | |
|     function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector;
 | |
| end package helpers;
 | |
| 
 | |
| package body helpers is
 | |
|     function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer is
 | |
|         variable ret: integer;
 | |
|     begin
 | |
|         ret := 32;
 | |
|         for i in val'range loop
 | |
|             if val(i) = '1' then
 | |
|                 ret := 31 - i;
 | |
|                 exit;
 | |
|             end if;
 | |
|         end loop;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer is
 | |
|         variable ret: integer;
 | |
|     begin
 | |
|         ret := 32;
 | |
|         for i in val'reverse_range loop
 | |
|             if val(i) = '1' then
 | |
|                 ret := i;
 | |
|                 exit;
 | |
|             end if;
 | |
|         end loop;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer is
 | |
|         variable ret: integer;
 | |
|     begin
 | |
|         ret := 64;
 | |
|         for i in val'range loop
 | |
|             if val(i) = '1' then
 | |
|                 ret := 63 - i;
 | |
|                 exit;
 | |
|             end if;
 | |
|         end loop;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer is
 | |
|         variable ret: integer;
 | |
|     begin
 | |
|         ret := 64;
 | |
|         for i in val'reverse_range loop
 | |
|             if val(i) = '1' then
 | |
|                 ret := i;
 | |
|                 exit;
 | |
|             end if;
 | |
|         end loop;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: unsigned(3 downto 0) := (others => '0');
 | |
|     begin
 | |
|         for i in val'range loop
 | |
|             ret := ret + ("000" & val(i));
 | |
|         end loop;
 | |
| 
 | |
|         return std_ulogic_vector(resize(ret, val'length));
 | |
|     end;
 | |
| 
 | |
|     function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: unsigned(5 downto 0) := (others => '0');
 | |
|     begin
 | |
|         for i in val'range loop
 | |
|             ret := ret + ("00000" & val(i));
 | |
|         end loop;
 | |
| 
 | |
|         return std_ulogic_vector(resize(ret, val'length));
 | |
|     end;
 | |
| 
 | |
|     function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: unsigned(6 downto 0) := (others => '0');
 | |
|     begin
 | |
|         for i in val'range loop
 | |
|             ret := ret + ("000000" & val(i));
 | |
|         end loop;
 | |
| 
 | |
|         return std_ulogic_vector(resize(ret, val'length));
 | |
|     end;
 | |
| 
 | |
|     function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: std_ulogic_vector(7 downto 0);
 | |
|     begin
 | |
|         if a = b then
 | |
|             ret := x"ff";
 | |
|         else
 | |
|             ret := x"00";
 | |
|         end if;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function ppc_signed_compare(a, b: signed(63 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: std_ulogic_vector(3 downto 0);
 | |
|     begin
 | |
|         if a < b then
 | |
|             ret := "1000";
 | |
|         elsif a > b then
 | |
|             ret := "0100";
 | |
|         else
 | |
|             ret := "0010";
 | |
|         end if;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function ppc_unsigned_compare(a, b: unsigned(63 downto 0)) return std_ulogic_vector is
 | |
|         variable ret: std_ulogic_vector(3 downto 0);
 | |
|     begin
 | |
|         if a < b then
 | |
|             ret := "1000";
 | |
|         elsif a > b then
 | |
|             ret := "0100";
 | |
|         else
 | |
|             ret := "0010";
 | |
|         end if;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
 | |
|     begin
 | |
|         if to_integer(unsigned(reg)) = 0 then
 | |
|             return x"0000000000000000";
 | |
|         else
 | |
|             return ra;
 | |
|         end if;
 | |
|     end;
 | |
| 
 | |
|     function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector is
 | |
|         variable ret : std_ulogic_vector(63 downto 0) := (others => '0');
 | |
|     begin
 | |
|         -- Vivado doesn't support non constant vector slices, so we have to code
 | |
|         -- each of these.
 | |
|         case_0: case size is
 | |
|             when 2 =>
 | |
|                 for_2 : for k in 0 to 1 loop
 | |
|                     ret(((8*k)+7) downto (8*k)) := val((8*(1-k)+7) downto (8*(1-k)));
 | |
|                 end loop;
 | |
|             when 4 =>
 | |
|                 for_4 : for k in 0 to 3 loop
 | |
|                     ret(((8*k)+7) downto (8*k)) := val((8*(3-k)+7) downto (8*(3-k)));
 | |
|                 end loop;
 | |
|             when 8 =>
 | |
|                 for_8 : for k in 0 to 7 loop
 | |
|                     ret(((8*k)+7) downto (8*k)) := val((8*(7-k)+7) downto (8*(7-k)));
 | |
|                 end loop;
 | |
|             when others =>
 | |
|                 report "bad byte reverse length " & integer'image(size) severity failure;
 | |
|         end case;
 | |
| 
 | |
|         return ret;
 | |
|     end;
 | |
| 
 | |
|     function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector is
 | |
|         variable ret : signed(63 downto 0) := (others => '0');
 | |
|         variable upper : integer := 0;
 | |
|     begin
 | |
|         case_0: case size is
 | |
|             when 2 =>
 | |
|                 ret := resize(signed(val(15 downto 0)), 64);
 | |
|             when 4 =>
 | |
|                 ret := resize(signed(val(31 downto 0)), 64);
 | |
|             when 8 =>
 | |
|                 ret := resize(signed(val(63 downto 0)), 64);
 | |
|             when others =>
 | |
|                 report "bad byte reverse length " & integer'image(size) severity failure;
 | |
|         end case;
 | |
| 
 | |
|         return std_ulogic_vector(ret);
 | |
| 
 | |
|     end;
 | |
| end package body helpers;
 |