mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
refactor(core/cam_core_banked): extract per-bank modules for improved timing isolation
- Extract cam_bank as a parameterized submodule with independent read/write ports - Replace flat 2D memory array with generate loop of bank instances - Derive bank selection from address bit slicing instead of modulo arithmetic - Align rd_base_row_i check with new bank addressing scheme - Add test verifying bank address isolation across multiple banks
This commit is contained in:
@@ -1,6 +1,34 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "cam_params.svh"
|
||||
|
||||
module cam_bank #(
|
||||
parameter int HASH_BITS = 512,
|
||||
parameter int BANK_DEPTH = 512,
|
||||
parameter int BANK_ADDR_BITS = 9
|
||||
) (
|
||||
input logic clk,
|
||||
|
||||
input logic wr_en,
|
||||
input logic [BANK_ADDR_BITS-1:0] wr_addr,
|
||||
input logic [HASH_BITS-1:0] wr_data,
|
||||
|
||||
input logic rd_en,
|
||||
input logic [BANK_ADDR_BITS-1:0] rd_addr,
|
||||
output logic [HASH_BITS-1:0] rd_data
|
||||
);
|
||||
(* ram_style = "block" *) logic [HASH_BITS-1:0] mem [0:BANK_DEPTH-1];
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (wr_en) begin
|
||||
mem[wr_addr] <= wr_data;
|
||||
end
|
||||
|
||||
if (rd_en) begin
|
||||
rd_data <= mem[rd_addr];
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
||||
module cam_core_banked (
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
@@ -17,22 +45,52 @@ module cam_core_banked (
|
||||
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;
|
||||
localparam int BANKS = `LANES;
|
||||
localparam int BANK_DEPTH = `NUM_ROWS / BANKS;
|
||||
localparam int BANK_SEL_BITS = $clog2(BANKS);
|
||||
localparam int BANK_ADDR_BITS = $clog2(BANK_DEPTH);
|
||||
|
||||
(* ram_style = "block" *) logic [(`HASH_BITS)-1:0] bank_mem [0:BANKS-1][0:BANK_DEPTH-1];
|
||||
logic [BANK_SEL_BITS-1:0] wr_bank_id;
|
||||
logic [BANK_ADDR_BITS-1:0] wr_bank_addr;
|
||||
logic [BANK_ADDR_BITS-1:0] rd_bank_addr;
|
||||
logic [(`HASH_BITS)-1:0] bank_rd_data [0:BANKS-1];
|
||||
|
||||
assign wr_ready = 1'b1;
|
||||
assign wr_ready = 1'b1;
|
||||
assign wr_bank_id = wr_row[BANK_SEL_BITS-1:0];
|
||||
assign wr_bank_addr = wr_row[(`ROW_BITS)-1:BANK_SEL_BITS];
|
||||
assign rd_bank_addr = rd_base_row_i[(`ROW_BITS)-1:BANK_SEL_BITS];
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
initial begin
|
||||
if (`NUM_ROWS % `LANES != 0) $fatal(1, "NUM_ROWS must be divisible by LANES");
|
||||
if (`NUM_ROWS != (BANK_DEPTH * BANKS)) $fatal(1, "NUM_ROWS must be divisible by LANES");
|
||||
if (`LANES != (1 << BANK_SEL_BITS)) $fatal(1, "LANES must be a power of two");
|
||||
end
|
||||
`endif
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (wr_valid) begin
|
||||
bank_mem[wr_row % `LANES][wr_row / `LANES] <= wr_hash;
|
||||
generate
|
||||
for (genvar b = 0; b < BANKS; b++) begin : g_bank
|
||||
cam_bank #(
|
||||
.HASH_BITS(`HASH_BITS),
|
||||
.BANK_DEPTH(BANK_DEPTH),
|
||||
.BANK_ADDR_BITS(BANK_ADDR_BITS)
|
||||
) u_bank (
|
||||
.clk(clk),
|
||||
.wr_en(wr_valid && (wr_bank_id == b[BANK_SEL_BITS-1:0])),
|
||||
.wr_addr(wr_bank_addr),
|
||||
.wr_data(wr_hash),
|
||||
.rd_en(rd_valid_i),
|
||||
.rd_addr(rd_bank_addr),
|
||||
.rd_data(bank_rd_data[b])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always_comb begin
|
||||
rd_hashes_o = '0;
|
||||
if (rd_valid_o) begin
|
||||
for (int lane = 0; lane < `LANES; lane++) begin
|
||||
rd_hashes_o[lane*`HASH_BITS +: `HASH_BITS] = bank_rd_data[lane];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,21 +98,19 @@ module cam_core_banked (
|
||||
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;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
if (rd_valid_i && ((rd_base_row_i % `LANES) != 0)) begin
|
||||
if (rd_valid_i && ((rd_base_row_i[BANK_SEL_BITS-1:0]) != '0)) begin
|
||||
$fatal(1, "rd_base_row_i must be LANES-aligned");
|
||||
end
|
||||
`endif
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user