Files
Mini-Nav/hw/rtl/popcount.sv
SikongJueluo f71bf06484 feat(hw): add XNOR-popcount CAM design with cocotb verification
Implement a multi-lane Content Addressable Memory (CAM) that scores
rows by XNOR popcount against a query hash and returns the top-1 match.

RTL modules:
- popcount: parallel group-based population count
- argmax_update: iterative best-match tracking with tie-break
- cam_core: parameterized scanning engine (NUM_ROWS/HASH_BITS/LANES)
  with optional SIM_NOISE and SIM_DEBUG ifdef guards
- cam_top: thin wrapper exposing cam_core ports

Verification:
- Python reference model (ref_model.py) for score-level golden comparison
- cocotb testbench (test_cam_basic.py) covering write/query/reset and
  external noise mask scenarios with score debug verification
- Noise sweep script (sweep_noise.py) measuring top-1 stability under
  configurable bit-flip rates
- Verilator-oriented Makefile with parameterizable compile options
2026-05-02 23:26:16 +08:00

42 lines
1.3 KiB
Systemverilog

`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