From 1b559aee31b539d3692ca2198f6419cba08704fc Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Thu, 10 Oct 2019 14:36:23 +1100 Subject: [PATCH] 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: 24a4a796ce1e ("execute: Consolidate count-leading/trailing-zeroes implementations") Signed-off-by: Anton Blanchard --- countzero.vhdl | 72 ++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/countzero.vhdl b/countzero.vhdl index 3e0cec7..9b6d2db 100644 --- a/countzero.vhdl +++ b/countzero.vhdl @@ -14,86 +14,94 @@ entity zero_counter is end entity zero_counter; 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 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 <= or (rs(63 downto 32)); - r32 <= or (rs(31 downto 0)); + 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); + sel(5) := l32 and (not is_32bit); else - sel(5) <= (not r32) and (not is_32bit); + sel(5) := (not r32) and (not is_32bit); end if; if sel(5) = '1' then - v32 <= rs(63 downto 32); + v32 := rs(63 downto 32); else - v32 <= rs(31 downto 0); + v32 := rs(31 downto 0); end if; if count_right = '0' then - sel(4) <= or (v32(31 downto 16)); + sel(4) := or (v32(31 downto 16)); else - sel(4) <= not (or (v32(15 downto 0))); + sel(4) := not (or (v32(15 downto 0))); end if; if sel(4) = '1' then - v16 <= v32(31 downto 16); + v16 := v32(31 downto 16); else - v16 <= v32(15 downto 0); + v16 := v32(15 downto 0); end if; if count_right = '0' then - sel(3) <= or (v16(15 downto 8)); + sel(3) := or (v16(15 downto 8)); else - sel(3) <= not (or (v16(7 downto 0))); + sel(3) := not (or (v16(7 downto 0))); end if; if sel(3) = '1' then - v8 <= v16(15 downto 8); + v8 := v16(15 downto 8); else - v8 <= v16(7 downto 0); + v8 := v16(7 downto 0); end if; if count_right = '0' then - sel(2) <= or (v8(7 downto 4)); + sel(2) := or (v8(7 downto 4)); else - sel(2) <= not (or (v8(3 downto 0))); + sel(2) := not (or (v8(3 downto 0))); end if; if sel(2) = '1' then - v4 <= v8(7 downto 4); + v4 := v8(7 downto 4); else - v4 <= v8(3 downto 0); + v4 := v8(3 downto 0); end if; if count_right = '0' then if v4(3) = '1' then - sel(1 downto 0) <= "11"; + sel(1 downto 0) := "11"; elsif v4(2) = '1' then - sel(1 downto 0) <= "10"; + sel(1 downto 0) := "10"; elsif v4(1) = '1' then - sel(1 downto 0) <= "01"; + sel(1 downto 0) := "01"; else - sel(1 downto 0) <= "00"; + 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"; + sel(1 downto 0) := "00"; elsif v4(1) = '1' then - sel(1 downto 0) <= "01"; + sel(1 downto 0) := "01"; elsif v4(2) = '1' then - sel(1 downto 0) <= "10"; + sel(1 downto 0) := "10"; else - sel(1 downto 0) <= "11"; + sel(1 downto 0) := "11"; end if; result <= x"00000000000000" & "00" & sel; end if;