feat(hw/rtl): add xorshift PRNG modules and refactor cam_noisy FSM

- Add random32, random64 and random128 xorshift PRNG modules
- Refactor cam_noisy FSM: split state register, next-state logic, and datapath into distinct blocks
- Rename state_q/state_d to curr_state/next_state for clarity
- Add MASK_GROUPS localparam and fix type casting in noise generation
- Update .gitignore to exclude docs/superpowers
This commit is contained in:
2026-05-04 18:03:07 +08:00
parent 2da17e101b
commit 0dd01fb1b7
5 changed files with 144 additions and 22 deletions

View File

@@ -51,7 +51,7 @@ module cam_noisy #(
S_COMMIT
} state_t;
state_t state_q, state_d;
state_t curr_state, next_state;
// ── Latch registers ──
logic [(`ROW_BITS)-1:0] addr_q;
@@ -60,6 +60,7 @@ module cam_noisy #(
// ── Noise generation ──
logic [63:0] prng_state;
logic [(`HASH_BITS)-1:0] flip_mask;
localparam int MASK_GROUPS = `HASH_BITS / NOISE_GEN_BITS;
logic [($clog2(`HASH_BITS/NOISE_GEN_BITS+1))-1:0] mask_group_idx; // 0..HASH_BITS/NOISE_GEN_BITS-1
// ── Precomputed threshold ──
@@ -81,49 +82,56 @@ module cam_noisy #(
assign noisy_hash = write_hash_q ^ flip_mask;
// ── wr_ready: only in IDLE ──
assign wr_ready = (state_q == S_IDLE);
assign wr_ready = (curr_state == S_IDLE);
// ── FSM combinational logic ──
// ── FSM block 1: state register ──
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
curr_state <= S_IDLE;
end else begin
curr_state <= next_state;
end
end
// ── FSM block 2: next-state logic ──
always_comb begin
state_d = state_q;
case (state_q)
next_state = curr_state;
case (curr_state)
S_IDLE: begin
if (wr_valid && wr_ready) begin
if (NOISE_EN && (NOISE_RATE_NUM > 0))
state_d = S_GEN_MASK;
next_state = S_GEN_MASK;
else
state_d = S_COMMIT;
next_state = S_COMMIT;
end
end
S_GEN_MASK: begin
if (mask_group_idx == (`HASH_BITS / NOISE_GEN_BITS - 1))
state_d = S_COMMIT;
if (int'(mask_group_idx) == (MASK_GROUPS - 1))
next_state = S_COMMIT;
end
S_COMMIT: begin
state_d = S_IDLE;
next_state = S_IDLE;
end
default: state_d = S_IDLE;
default: next_state = S_IDLE;
endcase
end
// ── Sequential logic ──
// ── FSM block 3: state actions / datapath registers ──
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_q <= S_IDLE;
addr_q <= '0;
write_hash_q <= '0;
flip_mask <= '0;
prng_state <= NOISE_SEED;
addr_q <= '0;
write_hash_q <= '0;
flip_mask <= '0;
prng_state <= NOISE_SEED;
mask_group_idx <= '0;
end else begin
state_q <= state_d;
case (state_q)
case (curr_state)
S_IDLE: begin
flip_mask <= '0;
flip_mask <= '0;
mask_group_idx <= '0;
if (wr_valid && wr_ready) begin
addr_q <= wr_addr;
@@ -141,7 +149,7 @@ module cam_noisy #(
for (int b = 0; b < NOISE_GEN_BITS; b++) begin
logic [NOISE_SAMPLE_BITS-1:0] sample;
sample = prng_next[b * NOISE_SAMPLE_BITS +: NOISE_SAMPLE_BITS];
if (sample < THRESHOLD) begin
if (int'(sample) < THRESHOLD) begin
flip_mask[mask_group_idx * NOISE_GEN_BITS + b] <= 1'b1;
end
end
@@ -164,7 +172,7 @@ module cam_noisy #(
logic [(`ROW_BITS)-1:0] core_wr_row;
logic [(`HASH_BITS)-1:0] core_wr_hash;
assign core_wr_en = (state_q == S_COMMIT);
assign core_wr_en = (curr_state == S_COMMIT);
assign core_wr_row = addr_q;
assign core_wr_hash = noisy_hash;