Add Tercel PHY reset synchronization
[microwatt.git] / countzero.vhdl
index 3e0cec7ca56a9caf4dda3a266ae4e3a20e0898c9..b46f10863138cd02035893e7f0949c599bc16cab 100644 (file)
@@ -3,9 +3,11 @@ use ieee.std_logic_1164.all;
 use ieee.numeric_std.all;
 
 library work;
+use work.helpers.all;
 
 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;
@@ -14,90 +16,45 @@ 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);
+    signal inp : std_ulogic_vector(63 downto 0);
+    signal sum : std_ulogic_vector(64 downto 0);
+    signal msb_r : std_ulogic;
+    signal onehot : std_ulogic_vector(63 downto 0);
+    signal onehot_r : std_ulogic_vector(63 downto 0);
+    signal bitnum : std_ulogic_vector(5 downto 0);
+
 begin
-    zerocounter0: process(all)
+    countzero_r: process(clk)
     begin
-       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);
-           else
-               sel(5) <= (not r32) and (not is_32bit);
-           end if;
-           if sel(5) = '1' then
-               v32 <= rs(63 downto 32);
-           else
-               v32 <= rs(31 downto 0);
-           end if;
-
-           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;
-
-           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;
-
-           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;
-
-           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;
-       end if;
+        if rising_edge(clk) then
+            msb_r <= sum(64);
+            onehot_r <= onehot;
+        end if;
+    end process;
 
+    countzero: process(all)
+    begin
+        if is_32bit = '0' then
+            if count_right = '0' then
+                inp <= bit_reverse(rs);
+            else
+                inp <= rs;
+            end if;
+        else
+            inp(63 downto 32) <= x"FFFFFFFF";
+            if count_right = '0' then
+                inp(31 downto 0) <= bit_reverse(rs(31 downto 0));
+            else
+                inp(31 downto 0) <= rs(31 downto 0);
+            end if;
+        end if;
+
+        sum <= std_ulogic_vector(unsigned('0' & not inp) + 1);
+        onehot <= sum(63 downto 0) and inp;
+
+        -- The following occurs after a clock edge
+        bitnum <= bit_number(onehot_r);
+
+        result <= x"00000000000000" & "0" & msb_r & bitnum;
     end process;
 end behaviour;