mirror of
https://github.com/SikongJueluo/Mini-Nav.git
synced 2026-07-12 20:15:31 +08:00
- Make cam_read_noise a pass-through module, removing all noise injection logic - Switch write noise to use noise_mask_bernoulli instead of noise_mask_grouped - Add state machine to cam_write_noise for mask generation timing - Remove noise_mask_grouped.sv (no longer needed) - Remove read noise parameters from cam_noisy and cam_top - Update simulation and benchmark code to reflect read noise removal - Sync documentation to reflect Phase 2 architecture
114 lines
3.7 KiB
Systemverilog
114 lines
3.7 KiB
Systemverilog
`timescale 1ns / 1ps
|
|
`include "cam_params.svh"
|
|
|
|
module cam_write_noise #(
|
|
parameter bit WRITE_NOISE_EN = 1'b1,
|
|
parameter int WRITE_NOISE_RATE_NUM = 1,
|
|
parameter int WRITE_NOISE_RATE_DEN = 100,
|
|
parameter logic [63:0] WRITE_NOISE_SEED = 64'hB504_F32D_B504_F32D
|
|
) (
|
|
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,
|
|
output logic core_wr_valid,
|
|
output logic [(`ROW_BITS)-1:0] core_wr_row,
|
|
output logic [(`HASH_BITS)-1:0] core_wr_hash
|
|
);
|
|
|
|
localparam int PROB_BITS = 8;
|
|
localparam int SAMPLE_RANGE = 1 << PROB_BITS;
|
|
localparam int WRITE_NOISE_THRESHOLD_RAW =
|
|
(WRITE_NOISE_RATE_NUM * SAMPLE_RANGE) / WRITE_NOISE_RATE_DEN;
|
|
localparam int WRITE_NOISE_THRESHOLD =
|
|
(WRITE_NOISE_THRESHOLD_RAW > (SAMPLE_RANGE - 1)) ?
|
|
(SAMPLE_RANGE - 1) : WRITE_NOISE_THRESHOLD_RAW;
|
|
|
|
wire noise_active = WRITE_NOISE_EN && (WRITE_NOISE_RATE_NUM > 0) && (WRITE_NOISE_THRESHOLD > 0);
|
|
|
|
typedef enum logic [1:0] {
|
|
STATE_IDLE,
|
|
STATE_WAIT_MASK
|
|
} state_t;
|
|
|
|
state_t state_q;
|
|
logic mask_start_q;
|
|
logic mask_busy;
|
|
logic mask_done;
|
|
logic [(`HASH_BITS)-1:0] flip_mask;
|
|
logic [(`ROW_BITS)-1:0] row_q;
|
|
logic [(`HASH_BITS)-1:0] hash_q;
|
|
|
|
assign wr_ready = (state_q == STATE_IDLE);
|
|
|
|
noise_mask_bernoulli #(
|
|
.HASH_BITS (`HASH_BITS),
|
|
.PROB_BITS (PROB_BITS),
|
|
.PRNG_WORDS (2),
|
|
.BITS_PER_CYCLE (32),
|
|
.SEED (WRITE_NOISE_SEED)
|
|
) u_bernoulli_mask (
|
|
.clk (clk),
|
|
.rst_n (rst_n),
|
|
.start_i (mask_start_q),
|
|
.threshold_i (PROB_BITS'(WRITE_NOISE_THRESHOLD)),
|
|
.busy_o (mask_busy),
|
|
.done_o (mask_done),
|
|
.mask_o (flip_mask)
|
|
);
|
|
|
|
`ifndef SYNTHESIS
|
|
initial begin
|
|
if (WRITE_NOISE_SEED == 64'd0) $fatal(1, "WRITE_NOISE_SEED must be nonzero");
|
|
end
|
|
`endif
|
|
|
|
always_ff @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
state_q <= STATE_IDLE;
|
|
mask_start_q <= 1'b0;
|
|
row_q <= '0;
|
|
hash_q <= '0;
|
|
core_wr_valid <= 1'b0;
|
|
core_wr_row <= '0;
|
|
core_wr_hash <= '0;
|
|
end else begin
|
|
core_wr_valid <= 1'b0;
|
|
mask_start_q <= 1'b0;
|
|
|
|
unique case (state_q)
|
|
STATE_IDLE: begin
|
|
if (wr_valid && wr_ready) begin
|
|
row_q <= wr_row;
|
|
hash_q <= wr_hash;
|
|
if (noise_active) begin
|
|
mask_start_q <= 1'b1;
|
|
state_q <= STATE_WAIT_MASK;
|
|
end else begin
|
|
// Noise inactive: pass through immediately (one-cycle)
|
|
core_wr_valid <= 1'b1;
|
|
core_wr_row <= wr_row;
|
|
core_wr_hash <= wr_hash;
|
|
end
|
|
end
|
|
end
|
|
|
|
STATE_WAIT_MASK: begin
|
|
if (mask_done) begin
|
|
core_wr_valid <= 1'b1;
|
|
core_wr_row <= row_q;
|
|
core_wr_hash <= hash_q ^ flip_mask;
|
|
state_q <= STATE_IDLE;
|
|
end
|
|
end
|
|
|
|
default: begin
|
|
state_q <= STATE_IDLE;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
endmodule
|