mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
refactor: reorganize RTL files into core/noise subdirectories
- Move CAM core modules (cam_core_banked, match_engine_pipeline, popcount_pipeline) to hw/rtl/core/ - Move noise modules (cam_read_noise, cam_write_noise, noise_mask_grouped) to hw/rtl/noise/ - Update Makefile include paths and VERILOG_SOURCES to reflect new layout - Update docs/experiments.md file path references - Add sim/results.xml to .gitignore - Bump devenv.lock dependencies
This commit is contained in:
57
hw/rtl/core/cam_core_banked.sv
Normal file
57
hw/rtl/core/cam_core_banked.sv
Normal file
@@ -0,0 +1,57 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "cam_params.svh"
|
||||
|
||||
module cam_core_banked (
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic wr_valid,
|
||||
output logic wr_ready,
|
||||
input logic [(`ROW_BITS)-1:0] wr_row,
|
||||
input logic [(`HASH_BITS)-1:0] wr_hash,
|
||||
|
||||
input logic rd_valid_i,
|
||||
input logic [(`ROW_BITS)-1:0] rd_base_row_i,
|
||||
output logic rd_valid_o,
|
||||
output logic [(`LANES)*(`ROW_BITS)-1:0] rd_row_ids_o,
|
||||
output logic [(`LANES)*(`HASH_BITS)-1:0] rd_hashes_o,
|
||||
output logic [(`LANES)-1:0] rd_lane_valid_o
|
||||
);
|
||||
localparam int BANKS = `LANES;
|
||||
localparam int BANK_DEPTH = `NUM_ROWS / `LANES;
|
||||
|
||||
(* ram_style = "block" *) logic [(`HASH_BITS)-1:0] bank_mem [0:BANKS-1][0:BANK_DEPTH-1];
|
||||
|
||||
assign wr_ready = 1'b1;
|
||||
|
||||
initial begin
|
||||
if (`NUM_ROWS % `LANES != 0) $fatal(1, "NUM_ROWS must be divisible by LANES");
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (wr_valid) begin
|
||||
bank_mem[wr_row % `LANES][wr_row / `LANES] <= wr_hash;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
rd_valid_o <= 1'b0;
|
||||
rd_row_ids_o <= '0;
|
||||
rd_hashes_o <= '0;
|
||||
rd_lane_valid_o <= '0;
|
||||
end else begin
|
||||
rd_valid_o <= rd_valid_i;
|
||||
rd_lane_valid_o <= rd_valid_i ? {`LANES{1'b1}} : '0;
|
||||
|
||||
if (rd_valid_i && ((rd_base_row_i % `LANES) != 0)) begin
|
||||
$fatal(1, "rd_base_row_i must be LANES-aligned");
|
||||
end
|
||||
|
||||
for (int lane = 0; lane < `LANES; lane++) begin
|
||||
rd_row_ids_o[lane*`ROW_BITS +: `ROW_BITS] <= rd_base_row_i + lane[(`ROW_BITS)-1:0];
|
||||
rd_hashes_o[lane*`HASH_BITS +: `HASH_BITS] <= bank_mem[lane][rd_base_row_i / `LANES];
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
140
hw/rtl/core/match_engine_pipeline.sv
Normal file
140
hw/rtl/core/match_engine_pipeline.sv
Normal file
@@ -0,0 +1,140 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "cam_params.svh"
|
||||
|
||||
module match_engine_pipeline (
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic query_valid,
|
||||
output logic query_ready,
|
||||
input logic [(`HASH_BITS)-1:0] query_hash,
|
||||
output logic result_valid,
|
||||
input logic result_ready,
|
||||
output logic [(`ROW_BITS)-1:0] result_row,
|
||||
output logic [(`SCORE_BITS)-1:0] result_score,
|
||||
output logic busy,
|
||||
output logic rd_valid_o,
|
||||
output logic [(`ROW_BITS)-1:0] rd_base_row_o,
|
||||
input logic rd_valid_i,
|
||||
input logic [(`LANES)*(`ROW_BITS)-1:0] rd_row_ids_i,
|
||||
input logic [(`LANES)*(`HASH_BITS)-1:0] rd_hashes_i,
|
||||
input logic [(`LANES)-1:0] rd_lane_valid_i
|
||||
`ifdef SIM_DEBUG
|
||||
,output logic [(`NUM_ROWS)*(`SCORE_BITS)-1:0] score_debug_flat
|
||||
`endif
|
||||
);
|
||||
typedef enum logic [1:0] {S_IDLE, S_SCAN, S_DRAIN, S_DONE} state_t;
|
||||
state_t state_q;
|
||||
|
||||
logic [(`HASH_BITS)-1:0] query_q;
|
||||
logic [(`ROW_BITS)-1:0] issue_base_q;
|
||||
logic [$clog2(`NUM_ROWS/`LANES+1)-1:0] returned_q;
|
||||
logic [(`ROW_BITS)-1:0] best_row_q;
|
||||
logic [(`SCORE_BITS)-1:0] best_score_q;
|
||||
|
||||
logic [(`HASH_BITS)-1:0] match_bits [0:`LANES-1];
|
||||
logic score_valid [0:`LANES-1];
|
||||
logic [(`ROW_BITS)-1:0] score_row [0:`LANES-1];
|
||||
logic [(`SCORE_BITS)-1:0] lane_score [0:`LANES-1];
|
||||
logic [(`ROW_BITS)-1:0] batch_row;
|
||||
logic [(`SCORE_BITS)-1:0] batch_score;
|
||||
|
||||
assign query_ready = (state_q == S_IDLE);
|
||||
assign result_valid = (state_q == S_DONE);
|
||||
assign result_row = best_row_q;
|
||||
assign result_score = best_score_q;
|
||||
assign busy = (state_q != S_IDLE);
|
||||
assign rd_valid_o = (state_q == S_SCAN);
|
||||
assign rd_base_row_o = issue_base_q;
|
||||
|
||||
generate
|
||||
for (genvar lane = 0; lane < `LANES; lane++) begin : gen_scores
|
||||
assign match_bits[lane] = ~(query_q ^ rd_hashes_i[lane*`HASH_BITS +: `HASH_BITS]);
|
||||
popcount_pipeline #(
|
||||
.WIDTH(`HASH_BITS),
|
||||
.ROW_BITS(`ROW_BITS),
|
||||
.OUT_WIDTH(`SCORE_BITS)
|
||||
) u_popcount_pipeline (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.valid_i(rd_valid_i && rd_lane_valid_i[lane]),
|
||||
.row_i(rd_row_ids_i[lane*`ROW_BITS +: `ROW_BITS]),
|
||||
.bits_i(match_bits[lane]),
|
||||
.valid_o(score_valid[lane]),
|
||||
.row_o(score_row[lane]),
|
||||
.count_o(lane_score[lane])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_comb begin
|
||||
batch_row = score_row[0];
|
||||
batch_score = lane_score[0];
|
||||
for (int lane = 1; lane < `LANES; lane++) begin
|
||||
if ((lane_score[lane] > batch_score) ||
|
||||
((lane_score[lane] == batch_score) && (score_row[lane] < batch_row))) begin
|
||||
batch_score = lane_score[lane];
|
||||
batch_row = score_row[lane];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
state_q <= S_IDLE;
|
||||
query_q <= '0;
|
||||
issue_base_q <= '0;
|
||||
returned_q <= 0;
|
||||
best_row_q <= '0;
|
||||
best_score_q <= '0;
|
||||
`ifdef SIM_DEBUG
|
||||
score_debug_flat <= '0;
|
||||
`endif
|
||||
end else begin
|
||||
unique case (state_q)
|
||||
S_IDLE: begin
|
||||
if (query_valid) begin
|
||||
query_q <= query_hash;
|
||||
issue_base_q <= '0;
|
||||
returned_q <= 0;
|
||||
best_row_q <= TIE_BREAK_SENTINEL;
|
||||
best_score_q <= '0;
|
||||
`ifdef SIM_DEBUG
|
||||
score_debug_flat <= '0;
|
||||
`endif
|
||||
state_q <= S_SCAN;
|
||||
end
|
||||
end
|
||||
S_SCAN: begin
|
||||
if (issue_base_q + `LANES >= `NUM_ROWS) begin
|
||||
state_q <= S_DRAIN;
|
||||
end else begin
|
||||
issue_base_q <= issue_base_q + `LANES;
|
||||
end
|
||||
end
|
||||
S_DRAIN: begin
|
||||
if ((returned_q == (`NUM_ROWS / `LANES)) && !score_valid[0]) begin
|
||||
state_q <= S_DONE;
|
||||
end
|
||||
end
|
||||
S_DONE: begin
|
||||
if (result_ready) state_q <= S_IDLE;
|
||||
end
|
||||
default: state_q <= S_IDLE;
|
||||
endcase
|
||||
|
||||
if (score_valid[0]) begin
|
||||
returned_q <= returned_q + 1'b1;
|
||||
if ((batch_score > best_score_q) ||
|
||||
((batch_score == best_score_q) && (batch_row < best_row_q))) begin
|
||||
best_score_q <= batch_score;
|
||||
best_row_q <= batch_row;
|
||||
end
|
||||
`ifdef SIM_DEBUG
|
||||
for (int lane = 0; lane < `LANES; lane++) begin
|
||||
score_debug_flat[score_row[lane]*`SCORE_BITS +: `SCORE_BITS] <= lane_score[lane];
|
||||
end
|
||||
`endif
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
72
hw/rtl/core/popcount_pipeline.sv
Normal file
72
hw/rtl/core/popcount_pipeline.sv
Normal file
@@ -0,0 +1,72 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module popcount_pipeline #(
|
||||
parameter int WIDTH = 512,
|
||||
parameter int ROW_BITS = 12,
|
||||
parameter int OUT_WIDTH = $clog2(WIDTH + 1)
|
||||
) (
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic valid_i,
|
||||
input logic [ROW_BITS-1:0] row_i,
|
||||
input logic [WIDTH-1:0] bits_i,
|
||||
output logic valid_o,
|
||||
output logic [ROW_BITS-1:0] row_o,
|
||||
output logic [OUT_WIDTH-1:0] count_o
|
||||
);
|
||||
localparam int GROUP = 8;
|
||||
localparam int NUM_GROUPS = WIDTH / GROUP;
|
||||
localparam int GROUP_COUNT_WIDTH = $clog2(GROUP + 1);
|
||||
localparam int STAGE1_GROUPS = NUM_GROUPS / 4;
|
||||
|
||||
logic [GROUP_COUNT_WIDTH-1:0] group_counts [0:NUM_GROUPS-1];
|
||||
logic [OUT_WIDTH-1:0] partial_q [0:3];
|
||||
logic [OUT_WIDTH-1:0] sum_q;
|
||||
logic [ROW_BITS-1:0] row_s1_q, row_s2_q;
|
||||
logic valid_s1_q, valid_s2_q;
|
||||
logic [OUT_WIDTH-1:0] partial_comb [0:3];
|
||||
|
||||
always_comb begin
|
||||
for (int g = 0; g < NUM_GROUPS; g++) begin
|
||||
group_counts[g] = '0;
|
||||
for (int b = 0; b < GROUP; b++) begin
|
||||
group_counts[g] = group_counts[g] + bits_i[g*GROUP + b];
|
||||
end
|
||||
end
|
||||
|
||||
for (int p = 0; p < 4; p++) begin
|
||||
partial_comb[p] = '0;
|
||||
for (int g = 0; g < STAGE1_GROUPS; g++) begin
|
||||
partial_comb[p] = partial_comb[p] + group_counts[p*STAGE1_GROUPS + g];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
valid_s1_q <= 1'b0;
|
||||
valid_s2_q <= 1'b0;
|
||||
valid_o <= 1'b0;
|
||||
row_s1_q <= '0;
|
||||
row_s2_q <= '0;
|
||||
row_o <= '0;
|
||||
sum_q <= '0;
|
||||
count_o <= '0;
|
||||
for (int p = 0; p < 4; p++) partial_q[p] <= '0;
|
||||
end else begin
|
||||
valid_s1_q <= valid_i;
|
||||
row_s1_q <= row_i;
|
||||
for (int p = 0; p < 4; p++) begin
|
||||
partial_q[p] <= partial_comb[p];
|
||||
end
|
||||
|
||||
valid_s2_q <= valid_s1_q;
|
||||
row_s2_q <= row_s1_q;
|
||||
sum_q <= partial_q[0] + partial_q[1] + partial_q[2] + partial_q[3];
|
||||
|
||||
valid_o <= valid_s2_q;
|
||||
row_o <= row_s2_q;
|
||||
count_o <= sum_q;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user