end entity zero_counter;
architecture behaviour of zero_counter is
-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);
- 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
+ signal y, z : std_ulogic_vector(3 downto 0);
+ signal v16 : std_ulogic_vector(15 downto 0);
+ signal v4 : std_ulogic_vector(3 downto 0);
+ signal sel : std_ulogic_vector(5 downto 0);
- if count_right = '0' then
- sel(5) := l32 and (not is_32bit);
+ -- 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
- sel(5) := (not r32) and (not is_32bit);
+ return "00";
end if;
- if sel(5) = '1' then
- v32 := rs(63 downto 32);
+ else
+ if v(0) = '1' then
+ return "00";
+ elsif v(1) = '1' then
+ return "01";
+ elsif v(2) = '1' then
+ return "10";
else
- v32 := rs(31 downto 0);
+ return "11";
end if;
+ end if;
+ end;
- 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;
+begin
+ zerocounter0: process(all)
+ begin
+ -- Test 4 groups of 16 bits each.
+ -- The top 2 groups are considered to be zero in 32-bit 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
+ sel(5 downto 4) <= encoder(z, count_right);
+ else
+ sel(5) <= '0';
+ if count_right = '0' then
+ sel(4) <= z(1);
+ else
+ sel(4) <= not z(0);
+ end if;
+ 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;
+ -- Select the leftmost/rightmost non-zero group of 16 bits
+ case sel(5 downto 4) is
+ when "00" =>
+ v16 <= rs(15 downto 0);
+ when "01" =>
+ v16 <= rs(31 downto 16);
+ when "10" =>
+ v16 <= rs(47 downto 32);
+ when others =>
+ v16 <= rs(63 downto 48);
+ end case;
- 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;
+ -- Test 4 groups of 4 bits
+ y(0) <= or (v16(3 downto 0));
+ y(1) <= or (v16(7 downto 4));
+ y(2) <= or (v16(11 downto 8));
+ y(3) <= or (v16(15 downto 12));
+ sel(3 downto 2) <= encoder(y, count_right);
- 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;
+ -- Select the leftmost/rightmost non-zero group of 4 bits
+ case sel(3 downto 2) is
+ when "00" =>
+ v4 <= v16(3 downto 0);
+ when "01" =>
+ v4 <= v16(7 downto 4);
+ when "10" =>
+ v4 <= v16(11 downto 8);
+ when others =>
+ v4 <= v16(15 downto 12);
+ end case;
+
+ sel(1 downto 0) <= encoder(v4, 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 32-bit, else 64
+ result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
+ elsif count_right = '0' then
+ -- return (63 - sel), trimmed to 5 bits in 32-bit mode
+ result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
+ else
+ result <= x"00000000000000" & "00" & sel;
end if;
end process;