use ieee.numeric_std.all;
library work;
+use work.helpers.all;
entity zero_counter is
port (
+ clk : in std_logic;
rs : in std_ulogic_vector(63 downto 0);
count_right : in std_ulogic;
is_32bit : in std_ulogic;
end entity zero_counter;
architecture behaviour of zero_counter is
+ signal inp : std_ulogic_vector(63 downto 0);
+ signal sum : std_ulogic_vector(64 downto 0);
+ signal msb_r : std_ulogic;
+ signal onehot : std_ulogic_vector(63 downto 0);
+ signal onehot_r : std_ulogic_vector(63 downto 0);
+ signal bitnum : std_ulogic_vector(5 downto 0);
+
begin
- zerocounter0: process(all)
- variable l32, r32 : std_ulogic;
- variable v32 : std_ulogic_vector(31 downto 0);
- variable v16 : std_ulogic_vector(15 downto 0);
- variable v8 : std_ulogic_vector(7 downto 0);
- variable v4 : std_ulogic_vector(3 downto 0);
- variable sel : std_ulogic_vector(5 downto 0);
+ countzero_r: process(clk)
begin
- l32 := '0';
- r32 := '0';
- v32 := (others => '0');
- v16 := (others => '0');
- v8 := (others => '0');
- v4 := (others => '0');
- sel := (others => '0');
-
- l32 := or (rs(63 downto 32));
- r32 := or (rs(31 downto 0));
- if (l32 = '0' or is_32bit = '1') and r32 = '0' then
- -- operand is zero, return 32 for 32-bit, else 64
- result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
- else
-
- if count_right = '0' then
- sel(5) := l32 and (not is_32bit);
- else
- sel(5) := (not r32) and (not is_32bit);
- end if;
- if sel(5) = '1' then
- v32 := rs(63 downto 32);
- else
- v32 := rs(31 downto 0);
- end if;
-
- if count_right = '0' then
- sel(4) := or (v32(31 downto 16));
- else
- sel(4) := not (or (v32(15 downto 0)));
- end if;
- if sel(4) = '1' then
- v16 := v32(31 downto 16);
- else
- v16 := v32(15 downto 0);
- end if;
-
- if count_right = '0' then
- sel(3) := or (v16(15 downto 8));
- else
- sel(3) := not (or (v16(7 downto 0)));
- end if;
- if sel(3) = '1' then
- v8 := v16(15 downto 8);
- else
- v8 := v16(7 downto 0);
- end if;
-
- if count_right = '0' then
- sel(2) := or (v8(7 downto 4));
- else
- sel(2) := not (or (v8(3 downto 0)));
- end if;
- if sel(2) = '1' then
- v4 := v8(7 downto 4);
- else
- v4 := v8(3 downto 0);
- end if;
-
- if count_right = '0' then
- if v4(3) = '1' then
- sel(1 downto 0) := "11";
- elsif v4(2) = '1' then
- sel(1 downto 0) := "10";
- elsif v4(1) = '1' then
- sel(1 downto 0) := "01";
- else
- sel(1 downto 0) := "00";
- end if;
- result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
- else
- if v4(0) = '1' then
- sel(1 downto 0) := "00";
- elsif v4(1) = '1' then
- sel(1 downto 0) := "01";
- elsif v4(2) = '1' then
- sel(1 downto 0) := "10";
- else
- sel(1 downto 0) := "11";
- end if;
- result <= x"00000000000000" & "00" & sel;
- end if;
- end if;
+ if rising_edge(clk) then
+ msb_r <= sum(64);
+ onehot_r <= onehot;
+ end if;
+ end process;
+ countzero: process(all)
+ begin
+ if is_32bit = '0' then
+ if count_right = '0' then
+ inp <= bit_reverse(rs);
+ else
+ inp <= rs;
+ end if;
+ else
+ inp(63 downto 32) <= x"FFFFFFFF";
+ if count_right = '0' then
+ inp(31 downto 0) <= bit_reverse(rs(31 downto 0));
+ else
+ inp(31 downto 0) <= rs(31 downto 0);
+ end if;
+ end if;
+
+ sum <= std_ulogic_vector(unsigned('0' & not inp) + 1);
+ onehot <= sum(63 downto 0) and inp;
+
+ -- The following occurs after a clock edge
+ bitnum <= bit_number(onehot_r);
+
+ result <= x"00000000000000" & "0" & msb_r & bitnum;
end process;
end behaviour;