`timescale 1ns/1ps module popcount #( parameter int WIDTH = 512, parameter int GROUP = 8, parameter int OUT_WIDTH = $clog2(WIDTH + 1) ) ( input logic [WIDTH-1:0] bits_i, output logic [OUT_WIDTH-1:0] count_o ); localparam int NUM_GROUPS = (WIDTH + GROUP - 1) / GROUP; localparam int GROUP_COUNT_WIDTH = $clog2(GROUP + 1); logic [GROUP_COUNT_WIDTH-1:0] group_counts [NUM_GROUPS]; genvar g; generate for (g = 0; g < NUM_GROUPS; g++) begin : gen_group_popcount always_comb begin group_counts[g] = '0; for (int b = 0; b < GROUP; b++) begin int idx; idx = g * GROUP + b; if (idx < WIDTH) begin group_counts[g] = group_counts[g] + bits_i[idx]; end end end end endgenerate // Reduction over small group counts. This is intentionally simple and // synthesis-friendly enough for the first prototype. If timing fails, // replace this block with a fully staged adder tree. always_comb begin count_o = '0; for (int i = 0; i < NUM_GROUPS; i++) begin count_o = count_o + group_counts[i]; end end endmodule