|
|
|
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 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
|
|
|
|
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 non-zero 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 non-zero 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 32-bit, 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 32-bit 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;
|