Fix count-leading/trailing-zeroes
authorAnton Blanchard <anton@linux.ibm.com>
Thu, 10 Oct 2019 03:36:23 +0000 (14:36 +1100)
committerAnton Blanchard <anton@ozlabs.org>
Thu, 10 Oct 2019 05:05:34 +0000 (16:05 +1100)
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 <anton@linux.ibm.com>
countzero.vhdl

index 3e0cec7ca56a9caf4dda3a266ae4e3a20e0898c9..9b6d2dbd3133d931d3cab9fff7f283fbfd20bd97 100644 (file)
@@ -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;