Fix count-leading/trailing-zeroes

The current code simulates correctly, but produces miscompares when synthesized
onto an FPGA. On closer inspection GHDL synthesis complains about inferred
latches and there does seem to be issues.

Convert it to variables that are always initialized to zero at the start of the
process.

Fixes: 24a4a796ce ("execute: Consolidate count-leading/trailing-zeroes implementations")
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
pull/85/head
Anton Blanchard 5 years ago committed by Anton Blanchard
parent 3c6e66dc96
commit 1b559aee31

@ -14,86 +14,94 @@ entity zero_counter is
end entity zero_counter; end entity zero_counter;


architecture behaviour of zero_counter is architecture behaviour of zero_counter is
signal l32, r32 : std_ulogic;
signal v32 : std_ulogic_vector(31 downto 0);
signal v16 : std_ulogic_vector(15 downto 0);
signal v8 : std_ulogic_vector(7 downto 0);
signal v4 : std_ulogic_vector(3 downto 0);
signal sel : std_ulogic_vector(5 downto 0);
begin begin
zerocounter0: process(all) 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 begin
l32 <= or (rs(63 downto 32)); l32 := '0';
r32 <= or (rs(31 downto 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 if (l32 = '0' or is_32bit = '1') and r32 = '0' then
-- operand is zero, return 32 for 32-bit, else 64 -- operand is zero, return 32 for 32-bit, else 64
result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000"; result <= x"00000000000000" & '0' & not is_32bit & is_32bit & "00000";
else else


if count_right = '0' then if count_right = '0' then
sel(5) <= l32 and (not is_32bit); sel(5) := l32 and (not is_32bit);
else else
sel(5) <= (not r32) and (not is_32bit); sel(5) := (not r32) and (not is_32bit);
end if; end if;
if sel(5) = '1' then if sel(5) = '1' then
v32 <= rs(63 downto 32); v32 := rs(63 downto 32);
else else
v32 <= rs(31 downto 0); v32 := rs(31 downto 0);
end if; end if;


if count_right = '0' then if count_right = '0' then
sel(4) <= or (v32(31 downto 16)); sel(4) := or (v32(31 downto 16));
else else
sel(4) <= not (or (v32(15 downto 0))); sel(4) := not (or (v32(15 downto 0)));
end if; end if;
if sel(4) = '1' then if sel(4) = '1' then
v16 <= v32(31 downto 16); v16 := v32(31 downto 16);
else else
v16 <= v32(15 downto 0); v16 := v32(15 downto 0);
end if; end if;


if count_right = '0' then if count_right = '0' then
sel(3) <= or (v16(15 downto 8)); sel(3) := or (v16(15 downto 8));
else else
sel(3) <= not (or (v16(7 downto 0))); sel(3) := not (or (v16(7 downto 0)));
end if; end if;
if sel(3) = '1' then if sel(3) = '1' then
v8 <= v16(15 downto 8); v8 := v16(15 downto 8);
else else
v8 <= v16(7 downto 0); v8 := v16(7 downto 0);
end if; end if;


if count_right = '0' then if count_right = '0' then
sel(2) <= or (v8(7 downto 4)); sel(2) := or (v8(7 downto 4));
else else
sel(2) <= not (or (v8(3 downto 0))); sel(2) := not (or (v8(3 downto 0)));
end if; end if;
if sel(2) = '1' then if sel(2) = '1' then
v4 <= v8(7 downto 4); v4 := v8(7 downto 4);
else else
v4 <= v8(3 downto 0); v4 := v8(3 downto 0);
end if; end if;


if count_right = '0' then if count_right = '0' then
if v4(3) = '1' then if v4(3) = '1' then
sel(1 downto 0) <= "11"; sel(1 downto 0) := "11";
elsif v4(2) = '1' then elsif v4(2) = '1' then
sel(1 downto 0) <= "10"; sel(1 downto 0) := "10";
elsif v4(1) = '1' then elsif v4(1) = '1' then
sel(1 downto 0) <= "01"; sel(1 downto 0) := "01";
else else
sel(1 downto 0) <= "00"; sel(1 downto 0) := "00";
end if; end if;
result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0); result <= x"00000000000000" & "00" & (not sel(5) and not is_32bit) & not sel(4 downto 0);
else else
if v4(0) = '1' then if v4(0) = '1' then
sel(1 downto 0) <= "00"; sel(1 downto 0) := "00";
elsif v4(1) = '1' then elsif v4(1) = '1' then
sel(1 downto 0) <= "01"; sel(1 downto 0) := "01";
elsif v4(2) = '1' then elsif v4(2) = '1' then
sel(1 downto 0) <= "10"; sel(1 downto 0) := "10";
else else
sel(1 downto 0) <= "11"; sel(1 downto 0) := "11";
end if; end if;
result <= x"00000000000000" & "00" & sel; result <= x"00000000000000" & "00" & sel;
end if; end if;

Loading…
Cancel
Save