


library ieee;




use ieee.std_logic_1164.all;




use ieee.numeric_std.all;








library work;








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;




result : out std_ulogic_vector(63 downto 0)




);




end entity zero_counter;








architecture behaviour of zero_counter is




type intermediate_result is record




v16: std_ulogic_vector(15 downto 0);




sel_hi: std_ulogic_vector(1 downto 0);




is_32bit: std_ulogic;




count_right: std_ulogic;




end record;








signal r, r_in : intermediate_result;








 Return the index of the leftmost or rightmost 1 in a set of 4 bits.




 Assumes v is not "0000"; if it is, return (right ? "11" : "00").




function encoder(v: std_ulogic_vector(3 downto 0); right: std_ulogic) return std_ulogic_vector is




begin




if right = '0' then




if v(3) = '1' then




return "11";




elsif v(2) = '1' then




return "10";




elsif v(1) = '1' then




return "01";




else




return "00";




end if;




else




if v(0) = '1' then




return "00";




elsif v(1) = '1' then




return "01";




elsif v(2) = '1' then




return "10";




else




return "11";




end if;




end if;




end;








begin




zerocounter_0: process(clk)




begin




if rising_edge(clk) then




r <= r_in;




end if;




end process;








zerocounter_1: process(all)




variable v: intermediate_result;




variable y, z: std_ulogic_vector(3 downto 0);




variable sel: std_ulogic_vector(5 downto 0);




variable v4: std_ulogic_vector(3 downto 0);








begin




 Test 4 groups of 16 bits each.




 The top 2 groups are considered to be zero in 32bit mode.




z(0) := or (rs(15 downto 0));




z(1) := or (rs(31 downto 16));




z(2) := or (rs(47 downto 32));




z(3) := or (rs(63 downto 48));




if is_32bit = '0' then




v.sel_hi := encoder(z, count_right);




else




v.sel_hi(1) := '0';




if count_right = '0' then




v.sel_hi(0) := z(1);




else




v.sel_hi(0) := not z(0);




end if;




end if;








 Select the leftmost/rightmost nonzero group of 16 bits




case v.sel_hi is




when "00" =>




v.v16 := rs(15 downto 0);




when "01" =>




v.v16 := rs(31 downto 16);




when "10" =>




v.v16 := rs(47 downto 32);




when others =>




v.v16 := rs(63 downto 48);




end case;








 Latch this and do the rest in the next cycle, for the sake of timing




v.is_32bit := is_32bit;




v.count_right := count_right;




r_in <= v;




sel(5 downto 4) := r.sel_hi;








 Test 4 groups of 4 bits




y(0) := or (r.v16(3 downto 0));




y(1) := or (r.v16(7 downto 4));




y(2) := or (r.v16(11 downto 8));




y(3) := or (r.v16(15 downto 12));




sel(3 downto 2) := encoder(y, r.count_right);








 Select the leftmost/rightmost nonzero group of 4 bits




case sel(3 downto 2) is




when "00" =>




v4 := r.v16(3 downto 0);




when "01" =>




v4 := r.v16(7 downto 4);




when "10" =>




v4 := r.v16(11 downto 8);




when others =>




v4 := r.v16(15 downto 12);




end case;








sel(1 downto 0) := encoder(v4, r.count_right);








 sel is now the index of the leftmost/rightmost 1 bit in rs




if v4 = "0000" then




 operand is zero, return 32 for 32bit, else 64




result <= x"00000000000000" & '0' & not r.is_32bit & r.is_32bit & "00000";




elsif r.count_right = '0' then




 return (63  sel), trimmed to 5 bits in 32bit mode




result <= x"00000000000000" & "00" & (not sel(5) and not r.is_32bit) & not sel(4 downto 0);




else




result <= x"00000000000000" & "00" & sel;




end if;








end process;




end behaviour;
