feat(top): add shared keccak variants, arbiter, and mlkem_top integration
- sha3_chain_top_shared.v: external keccak_core interface (6 ports) - sample_cbd_sync_shared.v: shared keccak variant (6 ports) - sample_ntt_sync_shared.v: shared keccak variant (6 ports) - keccak_arbiter.v: fixed-priority arbiter for 3 keccak consumers - mlkem_top.v: 1403-line monolithic FSM with KeyGen/Encaps/Decaps Architecture: keccak_arbiter → keccak_core → keccak_round (shared) sha3_chain_top_shared (consumer 0) sample_cbd_sync_shared (consumer 1) sample_ntt_sync_shared (consumer 2) sha3_top (separate, own keccak_core) rng_sync, ntt_core, poly_arith, poly_mul, comp_decomp, mod_add sd_bram for polynomial storage All original RTL files preserved unchanged.
This commit is contained in:
143
sync_rtl/top/keccak_arbiter.v
Normal file
143
sync_rtl/top/keccak_arbiter.v
Normal file
@@ -0,0 +1,143 @@
|
||||
// keccak_arbiter.v - Fixed-priority arbiter for sharing a single keccak_core
|
||||
//
|
||||
// Allows N consumers (sha3_chain, sample_cbd, sample_ntt, sha3_top) to
|
||||
// share one keccak_core instance. Consumer 0 has highest priority — used
|
||||
// for sha3_chain which needs fast turnaround during KeyGen.
|
||||
//
|
||||
// State machine:
|
||||
// IDLE: Wait for any cons_valid_i. Grant to highest-priority consumer
|
||||
// (lowest index). Assert kc_valid_i to start permutation.
|
||||
// BUSY: Hold grant until kc_valid_o fires (permutation done), then
|
||||
// return to IDLE. cons_valid_o pulses for the granted consumer.
|
||||
//
|
||||
// Parameters:
|
||||
// NUM_CONSUMERS = 4
|
||||
//
|
||||
// Interface:
|
||||
// Keccak side: kc_state_i/o, kc_valid_i/o, kc_ready_i/o (single instance)
|
||||
// Consumer side: packed per-consumer valid/ready/state vectors
|
||||
|
||||
module keccak_arbiter #(
|
||||
parameter NUM_CONSUMERS = 4
|
||||
) (
|
||||
input clk,
|
||||
input rst_n,
|
||||
|
||||
// ── Keccak core side (single keccak_core instance) ──────────────
|
||||
output [1599:0] kc_state_i,
|
||||
output kc_valid_i,
|
||||
input kc_ready_o,
|
||||
input [1599:0] kc_state_o,
|
||||
input kc_valid_o,
|
||||
output kc_ready_i,
|
||||
|
||||
// ── Consumer side (N copies, packed) ────────────────────────────
|
||||
input [NUM_CONSUMERS*1600-1:0] cons_state_i,
|
||||
input [NUM_CONSUMERS-1:0] cons_valid_i,
|
||||
output [NUM_CONSUMERS-1:0] cons_ready_o,
|
||||
output [NUM_CONSUMERS*1600-1:0] cons_state_o,
|
||||
output [NUM_CONSUMERS-1:0] cons_valid_o,
|
||||
/* verilator lint_off UNUSEDSIGNAL */
|
||||
input [NUM_CONSUMERS-1:0] cons_ready_i
|
||||
/* verilator lint_on UNUSEDSIGNAL */
|
||||
);
|
||||
|
||||
// ================================================================
|
||||
// State machine
|
||||
// ================================================================
|
||||
localparam ST_IDLE = 1'b0;
|
||||
localparam ST_BUSY = 1'b1;
|
||||
|
||||
reg state_r, state_next;
|
||||
|
||||
// ================================================================
|
||||
// Grant logic
|
||||
// ================================================================
|
||||
localparam GRANT_W = $clog2(NUM_CONSUMERS);
|
||||
|
||||
reg [GRANT_W-1:0] grant_r; // registered grant (held during BUSY)
|
||||
reg [GRANT_W-1:0] grant_comb; // priority-encoded index (combinational)
|
||||
|
||||
// Any consumer requesting
|
||||
wire any_valid;
|
||||
assign any_valid = |cons_valid_i;
|
||||
|
||||
// Priority encoder: consumer 0 has highest priority (lowest index).
|
||||
// Reverse iteration so last assignment wins → lowest-index priority.
|
||||
integer i;
|
||||
always @(*) begin
|
||||
grant_comb = {GRANT_W{1'b0}};
|
||||
for (i = NUM_CONSUMERS - 1; i >= 0; i = i - 1) begin
|
||||
if (cons_valid_i[i]) begin
|
||||
/* verilator lint_off WIDTHTRUNC */
|
||||
grant_comb = i; // intentional truncation: i ∈ [0,NUM_CONSUMERS-1] fits GRANT_W
|
||||
/* verilator lint_on WIDTHTRUNC */
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Active grant: combinational in IDLE, registered (held) in BUSY
|
||||
wire [GRANT_W-1:0] active_grant;
|
||||
assign active_grant = (state_r == ST_IDLE) ? grant_comb : grant_r;
|
||||
|
||||
// ================================================================
|
||||
// FSM next-state logic
|
||||
// ================================================================
|
||||
always @(*) begin
|
||||
state_next = state_r;
|
||||
case (state_r)
|
||||
ST_IDLE: if (kc_ready_o && any_valid) state_next = ST_BUSY;
|
||||
ST_BUSY: if (kc_valid_o) state_next = ST_IDLE;
|
||||
default: state_next = ST_IDLE;
|
||||
endcase
|
||||
end
|
||||
|
||||
// ================================================================
|
||||
// Sequential logic
|
||||
// ================================================================
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
state_r <= ST_IDLE;
|
||||
grant_r <= {GRANT_W{1'b0}};
|
||||
end else begin
|
||||
state_r <= state_next;
|
||||
// Capture grant on IDLE→BUSY transition
|
||||
if (state_r == ST_IDLE && state_next == ST_BUSY)
|
||||
grant_r <= grant_comb;
|
||||
end
|
||||
end
|
||||
|
||||
// ================================================================
|
||||
// Keccak core side
|
||||
// ================================================================
|
||||
// Route selected consumer's state to keccak
|
||||
assign kc_state_i = cons_state_i[active_grant * 1600 +: 1600];
|
||||
|
||||
// Start permutation when IDLE, keccak ready, and any consumer wants access
|
||||
assign kc_valid_i = (state_r == ST_IDLE) && kc_ready_o && any_valid;
|
||||
|
||||
// Always accept keccak output (keccak_core's ready_i)
|
||||
assign kc_ready_i = 1'b1;
|
||||
|
||||
// ================================================================
|
||||
// Consumer side (generated per consumer)
|
||||
// ================================================================
|
||||
genvar g;
|
||||
generate
|
||||
for (g = 0; g < NUM_CONSUMERS; g = g + 1) begin : gen_consumer
|
||||
// cons_ready_o: this consumer is granted AND keccak is ready
|
||||
assign cons_ready_o[g] = (active_grant == g)
|
||||
&& any_valid
|
||||
&& (state_r == ST_IDLE)
|
||||
&& kc_ready_o;
|
||||
|
||||
// cons_valid_o: this consumer was granted AND keccak finished
|
||||
assign cons_valid_o[g] = (grant_r == g) && kc_valid_o;
|
||||
|
||||
// cons_state_o: broadcast keccak output to all consumers.
|
||||
// Each consumer latches only when its own valid_o is high.
|
||||
assign cons_state_o[g*1600 +: 1600] = kc_state_o;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user