2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
8 function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer;
9 function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer;
11 function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer;
12 function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer;
14 function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
15 function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector;
16 function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
18 function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector;
20 function ppc_signed_compare(a, b: signed(63 downto 0); so: std_ulogic) return std_ulogic_vector;
21 function ppc_unsigned_compare(a, b: unsigned(63 downto 0); so: std_ulogic) return std_ulogic_vector;
23 function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector;
25 function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector;
27 function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector;
29 function bit_reverse(a: std_ulogic_vector) return std_ulogic_vector;
30 function bit_number(a: std_ulogic_vector(63 downto 0)) return std_ulogic_vector;
31 function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector;
32 function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector;
33 function count_right_zeroes(val: std_ulogic_vector) return std_ulogic_vector;
36 package body helpers is
37 function fls_32 (val: std_ulogic_vector(31 downto 0)) return integer is
38 variable ret: integer;
41 for i in val'range loop
51 function ffs_32 (val: std_ulogic_vector(31 downto 0)) return integer is
52 variable ret: integer;
55 for i in val'reverse_range loop
65 function fls_64 (val: std_ulogic_vector(63 downto 0)) return integer is
66 variable ret: integer;
69 for i in val'range loop
79 function ffs_64 (val: std_ulogic_vector(63 downto 0)) return integer is
80 variable ret: integer;
83 for i in val'reverse_range loop
93 function popcnt8(val: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
94 variable ret: unsigned(3 downto 0) := (others => '0');
96 for i in val'range loop
97 ret := ret + ("000" & val(i));
100 return std_ulogic_vector(resize(ret, val'length));
103 function popcnt32(val: std_ulogic_vector(31 downto 0)) return std_ulogic_vector is
104 variable ret: unsigned(5 downto 0) := (others => '0');
106 for i in val'range loop
107 ret := ret + ("00000" & val(i));
110 return std_ulogic_vector(resize(ret, val'length));
113 function popcnt64(val: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
114 variable ret: unsigned(6 downto 0) := (others => '0');
116 for i in val'range loop
117 ret := ret + ("000000" & val(i));
120 return std_ulogic_vector(resize(ret, val'length));
123 function cmp_one_byte(a, b: std_ulogic_vector(7 downto 0)) return std_ulogic_vector is
124 variable ret: std_ulogic_vector(7 downto 0);
135 function ppc_signed_compare(a, b: signed(63 downto 0); so: std_ulogic) return std_ulogic_vector is
136 variable ret: std_ulogic_vector(2 downto 0);
149 function ppc_unsigned_compare(a, b: unsigned(63 downto 0); so: std_ulogic) return std_ulogic_vector is
150 variable ret: std_ulogic_vector(2 downto 0);
163 function ra_or_zero(ra: std_ulogic_vector(63 downto 0); reg: std_ulogic_vector(4 downto 0)) return std_ulogic_vector is
165 if to_integer(unsigned(reg)) = 0 then
166 return x"0000000000000000";
172 function byte_reverse(val: std_ulogic_vector(63 downto 0); size: integer) return std_ulogic_vector is
173 variable ret : std_ulogic_vector(63 downto 0) := (others => '0');
175 -- Vivado doesn't support non constant vector slices, so we have to code
179 for_2 : for k in 0 to 1 loop
180 ret(((8*k)+7) downto (8*k)) := val((8*(1-k)+7) downto (8*(1-k)));
183 for_4 : for k in 0 to 3 loop
184 ret(((8*k)+7) downto (8*k)) := val((8*(3-k)+7) downto (8*(3-k)));
187 for_8 : for k in 0 to 7 loop
188 ret(((8*k)+7) downto (8*k)) := val((8*(7-k)+7) downto (8*(7-k)));
191 report "bad byte reverse length " & integer'image(size) severity failure;
197 function sign_extend(val: std_ulogic_vector(63 downto 0); size: natural) return std_ulogic_vector is
198 variable ret : signed(63 downto 0) := (others => '0');
199 variable upper : integer := 0;
203 ret := resize(signed(val(15 downto 0)), 64);
205 ret := resize(signed(val(31 downto 0)), 64);
207 ret := resize(signed(val(63 downto 0)), 64);
209 report "bad byte reverse length " & integer'image(size) severity failure;
212 return std_ulogic_vector(ret);
216 -- Reverse the order of bits in a word
217 function bit_reverse(a: std_ulogic_vector) return std_ulogic_vector is
218 variable ret: std_ulogic_vector(a'left downto a'right);
220 for i in a'right to a'left loop
221 ret(a'left + a'right - i) := a(i);
226 -- If there is only one bit set in a doubleword, return its bit number
227 -- (counting from the right). Each bit of the result is obtained by
228 -- ORing together 32 bits of the input:
229 -- bit 0 = a[1] or a[3] or a[5] or ...
230 -- bit 1 = a[2] or a[3] or a[6] or a[7] or ...
231 -- bit 2 = a[4..7] or a[12..15] or ...
232 -- bit 5 = a[32..63] ORed together
233 function bit_number(a: std_ulogic_vector(63 downto 0)) return std_ulogic_vector is
234 variable ret: std_ulogic_vector(5 downto 0);
235 variable stride: natural;
236 variable bit: std_ulogic;
242 for j in 0 to (64 / stride) - 1 loop
244 bit := bit or (or a(k + stride - 1 downto k + (stride / 2)));
247 stride := stride * 2;
252 -- Assuming the input 'v' is a value of the form 1...10...0,
253 -- the output is the bit number of the rightmost 1 bit in v.
254 -- If v is zero, the result is zero.
255 function edgelocation(v: std_ulogic_vector; nbits: natural) return std_ulogic_vector is
256 variable p: std_ulogic_vector(nbits - 1 downto 0);
257 variable stride: natural;
258 variable b: std_ulogic;
262 for i in 0 to nbits - 1 loop
264 for j in 0 to (2**nbits / stride) - 1 loop
266 b := b or (v(k + stride - 1) and not v(k + (stride/2) - 1));
269 stride := stride * 2;
274 -- Count leading zeroes operations
275 -- Assumes the value passed in is not zero (if it is, zero is returned)
276 function count_right_zeroes(val: std_ulogic_vector) return std_ulogic_vector is
277 variable sum: std_ulogic_vector(val'left downto val'right);
278 variable onehot: std_ulogic_vector(val'left downto val'right);
279 variable edge: std_ulogic_vector(val'left downto val'right);
280 variable bn, bn_e, bn_o: std_ulogic_vector(5 downto 0);
282 sum := std_ulogic_vector(- signed(val));
283 onehot := sum and val;
285 bn_e := edgelocation(std_ulogic_vector(resize(signed(edge), 64)), 6);
286 bn_o := bit_number(std_ulogic_vector(resize(unsigned(onehot), 64)));
287 bn := bn_e(5 downto 2) & bn_o(1 downto 0);
291 function count_left_zeroes(val: std_ulogic_vector) return std_ulogic_vector is
292 variable rev: std_ulogic_vector(val'left downto val'right);
294 rev := bit_reverse(val);
295 return count_right_zeroes(rev);
298 end package body helpers;