forked from cores/microwatt
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
5.3 KiB
VHDL
210 lines
5.3 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 =>
|
|
upper := 15;
|
|
when 4 =>
|
|
upper := 31;
|
|
when 8 =>
|
|
upper := 63;
|
|
when others =>
|
|
report "bad byte reverse length " & integer'image(size) severity failure;
|
|
end case;
|
|
|
|
ret := resize(signed(val(upper downto 0)), 64);
|
|
return std_ulogic_vector(ret);
|
|
end;
|
|
end package body helpers;
|