50e6ead2a5a7e6694f2f59bde1e0a3eef898655a
[microwatt.git] / countzero.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6
7 entity zero_counter is
8 port (
9 clk : in std_logic;
10 rs : in std_ulogic_vector(63 downto 0);
11 count_right : in std_ulogic;
12 is_32bit : in std_ulogic;
13 result : out std_ulogic_vector(63 downto 0)
14 );
15 end entity zero_counter;
16
17 architecture behaviour of zero_counter is
18 type intermediate_result is record
19 v16: std_ulogic_vector(15 downto 0);
20 sel_hi: std_ulogic_vector(1 downto 0);
21 is_32bit: std_ulogic;
22 count_right: std_ulogic;
23 end record;
24
25 signal r, r_in : intermediate_result;
26
27 -- Return the index of the leftmost or rightmost 1 in a set of 4 bits.
28 -- Assumes v is not "0000"; if it is, return (right ? "11" : "00").
29 function encoder(v: std_ulogic_vector(3 downto 0); right: std_ulogic) return std_ulogic_vector is
30 begin
31 if right = '0' then
32 if v(3) = '1' then
33 return "11";
34 elsif v(2) = '1' then
35 return "10";
36 elsif v(1) = '1' then
37 return "01";
38 else
39 return "00";
40 end if;
41 else
42 if v(0) = '1' then
43 return "00";
44 elsif v(1) = '1' then
45 return "01";
46 elsif v(2) = '1' then
47 return "10";
48 else
49 return "11";
50 end if;
51 end if;
52 end;
53
54 begin
55 zerocounter_0: process(clk)
56 begin
57 if rising_edge(clk) then
58 r <= r_in;
59 end if;
60 end process;
61
62 zerocounter_1: process(all)
63 variable v: intermediate_result;
64 variable y, z: std_ulogic_vector(3 downto 0);
65 variable sel: std_ulogic_vector(5 downto 0);
66 variable v4: std_ulogic_vector(3 downto 0);
67
68 begin
69 -- Test 4 groups of 16 bits each.
70 -- The top 2 groups are considered to be zero in 32-bit mode.
71 z(0) := or (rs(15 downto 0));
72 z(1) := or (rs(31 downto 16));
73 z(2) := or (rs(47 downto 32));
74 z(3) := or (rs(63 downto 48));
75 if is_32bit = '0' then
76 v.sel_hi := encoder(z, count_right);
77 else
78 v.sel_hi(1) := '0';
79 if count_right = '0' then
80 v.sel_hi(0) := z(1);
81 else
82 v.sel_hi(0) := not z(0);
83 end if;
84 end if;
85
86 -- Select the leftmost/rightmost non-zero group of 16 bits
87 case v.sel_hi is
88 when "00" =>
89 v.v16 := rs(15 downto 0);
90 when "01" =>
91 v.v16 := rs(31 downto 16);
92 when "10" =>
93 v.v16 := rs(47 downto 32);
94 when others =>
95 v.v16 := rs(63 downto 48);
96 end case;
97
98 -- Latch this and do the rest in the next cycle, for the sake of timing
99 v.is_32bit := is_32bit;
100 v.count_right := count_right;
101 r_in <= v;
102 sel(5 downto 4) := r.sel_hi;
103
104 -- Test 4 groups of 4 bits
105 y(0) := or (r.v16(3 downto 0));
106 y(1) := or (r.v16(7 downto 4));
107 y(2) := or (r.v16(11 downto 8));
108 y(3) := or (r.v16(15 downto 12));
109 sel(3 downto 2) := encoder(y, r.count_right);
110
111 -- Select the leftmost/rightmost non-zero group of 4 bits
112 case sel(3 downto 2) is
113 when "00" =>
114 v4 := r.v16(3 downto 0);
115 when "01" =>
116 v4 := r.v16(7 downto 4);
117 when "10" =>
118 v4 := r.v16(11 downto 8);
119 when others =>
120 v4 := r.v16(15 downto 12);
121 end case;
122
123 sel(1 downto 0) := encoder(v4, r.count_right);
124
125 -- sel is now the index of the leftmost/rightmost 1 bit in rs
126 if v4 = "0000" then
127 -- operand is zero, return 32 for 32-bit, else 64
128 result <= x"00000000000000" & '0' & not r.is_32bit & r.is_32bit & "00000";
129 elsif r.count_right = '0' then
130 -- return (63 - sel), trimmed to 5 bits in 32-bit mode
131 result <= x"00000000000000" & "00" & (not sel(5) and not r.is_32bit) & not sel(4 downto 0);
132 else
133 result <= x"00000000000000" & "00" & sel;
134 end if;
135
136 end process;
137 end behaviour;