|
| 1 | +library ieee; |
| 2 | +use ieee.std_logic_1164.all; |
| 3 | +use ieee.numeric_std.all; |
| 4 | + |
| 5 | +library work; |
| 6 | +use work.helpers.all; |
| 7 | + |
| 8 | +entity bit_counter is |
| 9 | + port ( |
| 10 | + clk : in std_logic; |
| 11 | + rs : in std_ulogic_vector(63 downto 0); |
| 12 | + count_right : in std_ulogic; |
| 13 | + do_popcnt : in std_ulogic; |
| 14 | + is_32bit : in std_ulogic; |
| 15 | + datalen : in std_ulogic_vector(3 downto 0); |
| 16 | + result : out std_ulogic_vector(63 downto 0) |
| 17 | + ); |
| 18 | +end entity bit_counter; |
| 19 | + |
| 20 | +architecture behaviour of bit_counter is |
| 21 | + -- signals for count-leading/trailing-zeroes |
| 22 | + signal inp : std_ulogic_vector(63 downto 0); |
| 23 | + signal sum : std_ulogic_vector(64 downto 0); |
| 24 | + signal msb_r : std_ulogic; |
| 25 | + signal onehot : std_ulogic_vector(63 downto 0); |
| 26 | + signal onehot_r : std_ulogic_vector(63 downto 0); |
| 27 | + signal bitnum : std_ulogic_vector(5 downto 0); |
| 28 | + signal cntz : std_ulogic_vector(63 downto 0); |
| 29 | + |
| 30 | + -- signals for popcnt |
| 31 | + signal dlen_r : std_ulogic_vector(3 downto 0); |
| 32 | + signal pcnt_r : std_ulogic; |
| 33 | + subtype twobit is unsigned(1 downto 0); |
| 34 | + type twobit32 is array(0 to 31) of twobit; |
| 35 | + signal pc2 : twobit32; |
| 36 | + subtype threebit is unsigned(2 downto 0); |
| 37 | + type threebit16 is array(0 to 15) of threebit; |
| 38 | + signal pc4 : threebit16; |
| 39 | + subtype fourbit is unsigned(3 downto 0); |
| 40 | + type fourbit8 is array(0 to 7) of fourbit; |
| 41 | + signal pc8 : fourbit8; |
| 42 | + signal pc8_r : fourbit8; |
| 43 | + subtype sixbit is unsigned(5 downto 0); |
| 44 | + type sixbit2 is array(0 to 1) of sixbit; |
| 45 | + signal pc32 : sixbit2; |
| 46 | + signal popcnt : std_ulogic_vector(63 downto 0); |
| 47 | + |
| 48 | +begin |
| 49 | + countzero_r: process(clk) |
| 50 | + begin |
| 51 | + if rising_edge(clk) then |
| 52 | + msb_r <= sum(64); |
| 53 | + onehot_r <= onehot; |
| 54 | + end if; |
| 55 | + end process; |
| 56 | + |
| 57 | + countzero: process(all) |
| 58 | + begin |
| 59 | + if is_32bit = '0' then |
| 60 | + if count_right = '0' then |
| 61 | + inp <= bit_reverse(rs); |
| 62 | + else |
| 63 | + inp <= rs; |
| 64 | + end if; |
| 65 | + else |
| 66 | + inp(63 downto 32) <= x"FFFFFFFF"; |
| 67 | + if count_right = '0' then |
| 68 | + inp(31 downto 0) <= bit_reverse(rs(31 downto 0)); |
| 69 | + else |
| 70 | + inp(31 downto 0) <= rs(31 downto 0); |
| 71 | + end if; |
| 72 | + end if; |
| 73 | + |
| 74 | + sum <= std_ulogic_vector(unsigned('0' & not inp) + 1); |
| 75 | + onehot <= sum(63 downto 0) and inp; |
| 76 | + |
| 77 | + -- The following occurs after a clock edge |
| 78 | + bitnum <= bit_number(onehot_r); |
| 79 | + |
| 80 | + cntz <= 57x"0" & msb_r & bitnum; |
| 81 | + end process; |
| 82 | + |
| 83 | + popcnt_r: process(clk) |
| 84 | + begin |
| 85 | + if rising_edge(clk) then |
| 86 | + for i in 0 to 7 loop |
| 87 | + pc8_r(i) <= pc8(i); |
| 88 | + end loop; |
| 89 | + dlen_r <= datalen; |
| 90 | + pcnt_r <= do_popcnt; |
| 91 | + end if; |
| 92 | + end process; |
| 93 | + |
| 94 | + popcnt_a: process(all) |
| 95 | + begin |
| 96 | + for i in 0 to 31 loop |
| 97 | + pc2(i) <= unsigned("0" & rs(i * 2 downto i * 2)) + unsigned("0" & rs(i * 2 + 1 downto i * 2 + 1)); |
| 98 | + end loop; |
| 99 | + for i in 0 to 15 loop |
| 100 | + pc4(i) <= ('0' & pc2(i * 2)) + ('0' & pc2(i * 2 + 1)); |
| 101 | + end loop; |
| 102 | + for i in 0 to 7 loop |
| 103 | + pc8(i) <= ('0' & pc4(i * 2)) + ('0' & pc4(i * 2 + 1)); |
| 104 | + end loop; |
| 105 | + |
| 106 | + -- after a clock edge |
| 107 | + for i in 0 to 1 loop |
| 108 | + pc32(i) <= ("00" & pc8_r(i * 4)) + ("00" & pc8_r(i * 4 + 1)) + |
| 109 | + ("00" & pc8_r(i * 4 + 2)) + ("00" & pc8_r(i * 4 + 3)); |
| 110 | + end loop; |
| 111 | + |
| 112 | + popcnt <= (others => '0'); |
| 113 | + if dlen_r(3 downto 2) = "00" then |
| 114 | + -- popcntb |
| 115 | + for i in 0 to 7 loop |
| 116 | + popcnt(i * 8 + 3 downto i * 8) <= std_ulogic_vector(pc8_r(i)); |
| 117 | + end loop; |
| 118 | + elsif dlen_r(3) = '0' then |
| 119 | + -- popcntw |
| 120 | + for i in 0 to 1 loop |
| 121 | + popcnt(i * 32 + 5 downto i * 32) <= std_ulogic_vector(pc32(i)); |
| 122 | + end loop; |
| 123 | + else |
| 124 | + popcnt(6 downto 0) <= std_ulogic_vector(('0' & pc32(0)) + ('0' & pc32(1))); |
| 125 | + end if; |
| 126 | + end process; |
| 127 | + |
| 128 | + result <= cntz when pcnt_r = '0' else popcnt; |
| 129 | + |
| 130 | +end behaviour; |
0 commit comments