Files
mlkem-sync/sync_rtl/top/mlkem_top.v
FallenSigh 03b4707879 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.
2026-06-26 03:35:37 +08:00

1404 lines
54 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// mlkem_top.v - Top-level ML-KEM integration module
//
// Monolithic FSM implementing KeyGen, Encaps, and Decaps (FIPS 203)
// using shared Keccak architecture with keccak_arbiter.
//
// Architecture:
// keccak_core (shared) ← keccak_arbiter #(3)
// ├── Consumer 0: sha3_chain_top_shared (G function)
// ├── Consumer 1: sample_cbd_sync_shared (CBD sampling)
// └── Consumer 2: sample_ntt_sync_shared (NTT sampling)
// sha3_top (separate, own keccak_core) — for H/KDF calls
// rng_sync, ntt_core, poly_mul_sync, poly_arith_sync,
// comp_decomp_sync, mod_add_sync
// sd_bram × 1 (large) — polynomial coefficient storage
//
// Parameters:
// K = 4 (max module rank; actual k selected at runtime via i_k)
`include "sync_rtl/common/defines.vh"
/* verilator lint_off UNUSEDPARAM */
module mlkem_top #(
parameter K = 4
) (
/* verilator lint_on UNUSEDPARAM */
input clk,
input rst_n,
input [1:0] mode, // 00=KeyGen, 01=Encaps, 10=Decaps
input [2:0] i_k, // actual k (2,3,4)
input valid_i,
output ready_o,
// KeyGen outputs
output [12*K*256-1:0] pk_o, // public key (raw t_hat polys + rho)
output [12*K*256-1:0] sk_o, // secret key (raw s_hat polys)
output pk_valid,
output sk_valid,
// Encaps outputs
output [12*K*256-1:0] ct_o, // ciphertext
output [255:0] K_o, // shared secret
output ct_valid,
output K_valid,
// Decaps output
output [255:0] K_o_dec, // shared secret
output K_valid_dec,
output done_o
);
// ====================================================================
// Local parameters
// ====================================================================
localparam N = `N; // 256
localparam Q = `Q; // 3329
localparam N_CONSUMERS = 3; // sha3_chain, sample_cbd, sample_ntt
localparam N_POLYS = 48; // polynomial slots
localparam POLY_SIZE = N; // 256 coeffs per polynomial
localparam BRAM_DEPTH = POLY_SIZE * N_POLYS; // 12288
localparam BRAM_AW = $clog2(BRAM_DEPTH); // 14
// BRAM address map (base address = poly_idx * 256)
// A matrix: poly 0 .. 15 (K*K max)
// s_hat: poly 16 .. 19 (K max)
// e_hat: poly 20 .. 23
// t_hat: poly 24 .. 27
// y_hat: poly 28 .. 31
// e1: poly 32 .. 35
// u: poly 36 .. 39
// scratch0: poly 44
// scratch1: poly 45
localparam A_BASE = 0;
localparam S_BASE = 16;
localparam E_BASE = 20;
localparam T_BASE = 24;
localparam Y_BASE = 28;
localparam E1_BASE = 32;
localparam U_BASE = 36;
localparam SCRATCH0 = 44;
localparam SCRATCH1 = 45;
function [BRAM_AW-1:0] poly_addr;
input [5:0] poly_idx;
input [7:0] coeff_idx;
begin
poly_addr = (poly_idx * POLY_SIZE) + coeff_idx;
end
endfunction
// ====================================================================
// I/O registers
// ====================================================================
reg [1:0] mode_r;
reg [2:0] k_r; // actual k (2,3,4)
reg ready_o_r;
reg pk_valid_r, sk_valid_r;
reg ct_valid_r, K_valid_r;
reg K_valid_dec_r;
reg done_o_r;
// KeyGen output registers
reg [12*K*256-1:0] pk_o_r;
reg [12*K*256-1:0] sk_o_r;
// Encaps output registers
reg [12*K*256-1:0] ct_o_r;
reg [255:0] K_o_r;
// Decaps output registers
reg [255:0] K_o_dec_r;
// Internal data registers
reg [255:0] d_reg; // RNG output d
reg [255:0] rho_reg; // G output rho
reg [255:0] sigma_reg; // G output sigma
reg [255:0] m_reg; // Encaps message m
reg [255:0] Kbar_reg; // G output K-bar
reg [255:0] r_reg; // G output r
reg [255:0] Hpk_reg; // H(pk) for Encaps
reg [255:0] z_reg; // implicit rejection value
// ====================================================================
// Keccak arbiter signals (3 consumers → 1 keccak_core)
// ====================================================================
// Arbiter ↔ keccak_core
wire [1599:0] arb_kc_state_i;
wire arb_kc_valid_i;
wire arb_kc_ready_o;
wire [1599:0] arb_kc_state_o;
wire arb_kc_valid_o;
wire arb_kc_ready_i; // always 1'b1
// Consumer-side packed vectors
wire [N_CONSUMERS*1600-1:0] arb_cons_state_i;
wire [N_CONSUMERS-1:0] arb_cons_valid_i;
wire [N_CONSUMERS-1:0] arb_cons_ready_o;
wire [N_CONSUMERS*1600-1:0] arb_cons_state_o;
wire [N_CONSUMERS-1:0] arb_cons_valid_o;
wire [N_CONSUMERS-1:0] arb_cons_ready_i; // all tied high
// ====================================================================
// sha3_chain_top_shared (consumer 0) signals
// ====================================================================
wire chain_start, chain_done;
wire [255:0] chain_rho, chain_sigma;
wire [1599:0] chain_kc_state_o, chain_kc_state_i;
wire chain_kc_valid_o, chain_kc_valid_i;
wire chain_kc_ready_i, chain_kc_ready_o;
// ====================================================================
// sample_cbd_sync_shared (consumer 1) signals
// ====================================================================
reg cbd_valid_i_r;
reg [7:0] cbd_nonce_r;
reg [1:0] cbd_eta_r;
wire cbd_ready_o;
wire [11:0] cbd_coeff_o;
wire cbd_valid_o, cbd_last_o;
wire [1599:0] cbd_kc_state_o, cbd_kc_state_i;
wire cbd_kc_valid_o, cbd_kc_valid_i;
wire cbd_kc_ready_i, cbd_kc_ready_o;
// CBD seed mux: sigma_reg (KeyGen) or r_reg (Encaps)
reg cbd_use_r_seed; // 1 = use r_reg, 0 = use sigma_reg
wire [255:0] cbd_seed_muxed;
assign cbd_seed_muxed = cbd_use_r_seed ? r_reg : sigma_reg;
// ====================================================================
// sample_ntt_sync_shared (consumer 2) signals
// ====================================================================
reg snt_valid_i_r;
reg [1:0] snt_i_idx_r, snt_j_idx_r;
wire snt_ready_o;
wire [11:0] snt_coeff_o;
wire snt_valid_o, snt_last_o;
wire [1599:0] snt_kc_state_o, snt_kc_state_i;
wire snt_kc_valid_o, snt_kc_valid_i;
wire snt_kc_ready_i, snt_kc_ready_o;
// ====================================================================
// sha3_top signals (separate keccak_core — not shared through arbiter)
// ====================================================================
reg [1:0] sha3_mode_r;
reg [511:0] sha3_data_r;
reg sha3_valid_i_r;
wire sha3_ready_o;
wire [511:0] sha3_hash_o;
wire sha3_valid_o;
// ====================================================================
// rng_sync signals
// ====================================================================
wire rng_valid_i;
wire rng_ready_o;
wire [255:0] rng_data_o;
wire rng_valid_o;
// ====================================================================
// ntt_core signals (FSM-driven inputs are regs)
// ====================================================================
reg [11:0] ntt_coeff_in_r;
reg ntt_valid_i_r;
wire ntt_ready_o;
reg ntt_mode_r; // 0=NTT, 1=INTT
wire [11:0] ntt_coeff_out;
wire ntt_valid_o;
wire ntt_done_o;
// ====================================================================
// poly_mul_sync signals (FSM-driven inputs)
// ====================================================================
reg [11:0] pmul_a_r, pmul_b_r;
reg pmul_valid_i_r;
wire pmul_ready_o;
wire [11:0] pmul_coeff_out;
wire pmul_valid_o;
// ====================================================================
// poly_arith_sync signals (FSM-driven inputs)
// ====================================================================
reg [11:0] parith_a_r, parith_b_r;
reg parith_mode_r; // 0=add, 1=sub
reg parith_valid_i_r;
wire parith_ready_o;
wire [11:0] parith_coeff_out;
wire parith_valid_o;
// ====================================================================
// comp_decomp_sync signals (FSM-driven inputs)
// ====================================================================
reg [11:0] comp_coeff_in_r;
reg [4:0] comp_d_r;
reg comp_mode_r; // 0=compress, 1=decompress
reg comp_valid_i_r;
wire comp_ready_o;
wire [11:0] comp_coeff_out;
wire comp_valid_o;
// ====================================================================
// mod_add_sync signals (FSM-driven inputs)
// ====================================================================
reg [11:0] madd_a_r, madd_b_r;
reg madd_valid_i_r;
wire madd_ready_o;
wire [11:0] madd_sum;
wire madd_valid_o;
// ====================================================================
// BRAM signals (sd_bram: 1 read + 1 write port)
// ====================================================================
reg [BRAM_AW-1:0] bram_rd_addr_r;
wire [11:0] bram_rd_data;
reg bram_wr_en_r;
reg [BRAM_AW-1:0] bram_wr_addr_r;
reg [11:0] bram_wr_data_r;
// ====================================================================
// FSM state definitions
// ====================================================================
localparam S_IDLE = 7'd0;
// --- KeyGen states ---
localparam S_KG_RNG_REQ = 7'd1;
localparam S_KG_RNG_WAIT = 7'd2;
localparam S_KG_G_START = 7'd3;
localparam S_KG_G_WAIT = 7'd4;
localparam S_KG_G_DONE = 7'd5;
localparam S_KG_SNT_INIT = 7'd6;
localparam S_KG_SNT_START = 7'd7;
localparam S_KG_SNT_COEFFS = 7'd8;
localparam S_KG_SNT_CLEANUP = 7'd9;
localparam S_KG_SNT_NTT_LOAD = 7'd10;
localparam S_KG_SNT_NTT_COMP = 7'd11;
localparam S_KG_SNT_NTT_OUT = 7'd12;
localparam S_KG_SNT_NEXT = 7'd13;
localparam S_KG_CBD_S_INIT = 7'd14;
localparam S_KG_CBD_S_START = 7'd15;
localparam S_KG_CBD_S_COEFFS = 7'd16;
localparam S_KG_CBD_S_CLEANUP = 7'd17;
localparam S_KG_CBD_S_NTT_LD = 7'd18;
localparam S_KG_CBD_S_NTT_CMP = 7'd19;
localparam S_KG_CBD_S_NTT_OUT = 7'd20;
localparam S_KG_CBD_S_NEXT = 7'd21;
localparam S_KG_CBD_E_INIT = 7'd22;
localparam S_KG_CBD_E_START = 7'd23;
localparam S_KG_CBD_E_COEFFS = 7'd24;
localparam S_KG_CBD_E_CLEANUP = 7'd25;
localparam S_KG_CBD_E_NTT_LD = 7'd26;
localparam S_KG_CBD_E_NTT_CMP = 7'd27;
localparam S_KG_CBD_E_NTT_OUT = 7'd28;
localparam S_KG_CBD_E_NEXT = 7'd29;
localparam S_KG_TMUL_INIT = 7'd30;
localparam S_KG_TMUL_STEP = 7'd31;
localparam S_KG_TMUL_NEXT = 7'd32;
localparam S_KG_DONE = 7'd33;
// --- Encaps states ---
localparam S_EN_RNG_REQ = 7'd34;
localparam S_EN_RNG_WAIT = 7'd35;
localparam S_EN_H_START = 7'd36;
localparam S_EN_H_WAIT = 7'd37;
localparam S_EN_G_START = 7'd38;
localparam S_EN_G_WAIT = 7'd39;
localparam S_EN_SNT_INIT = 7'd40;
localparam S_EN_SNT_START = 7'd41;
localparam S_EN_SNT_COEFFS = 7'd42;
localparam S_EN_SNT_CLEANUP = 7'd43;
localparam S_EN_SNT_NTT_LD = 7'd44;
localparam S_EN_SNT_NTT_CMP = 7'd45;
localparam S_EN_SNT_NTT_OUT = 7'd46;
localparam S_EN_SNT_NEXT = 7'd47;
localparam S_EN_CBD_Y_INIT = 7'd48;
localparam S_EN_CBD_Y_START = 7'd49;
localparam S_EN_CBD_Y_COEFFS = 7'd50;
localparam S_EN_CBD_Y_CLNUP = 7'd51;
localparam S_EN_CBD_Y_NTT_LD = 7'd52;
localparam S_EN_CBD_Y_NTT_CMP = 7'd53;
localparam S_EN_CBD_Y_NTT_OUT = 7'd54;
localparam S_EN_CBD_Y_NEXT = 7'd55;
localparam S_EN_DONE = 7'd56;
// --- Decaps states ---
localparam S_DC_DECOMP_C1 = 7'd57;
localparam S_DC_DECOMP_C2 = 7'd58;
localparam S_DC_NTT_U_LD = 7'd59;
localparam S_DC_NTT_U_CMP = 7'd60;
localparam S_DC_NTT_U_OUT = 7'd61;
localparam S_DC_MUL_S = 7'd62;
localparam S_DC_INTT_V = 7'd63;
localparam S_DC_DECOMP_M = 7'd64;
localparam S_DC_G_CHECK = 7'd65;
localparam S_DC_REENC = 7'd66;
localparam S_DC_KDF = 7'd67;
localparam S_DC_DONE = 7'd68;
// ====================================================================
// FSM registers
// ====================================================================
reg [6:0] state_r, state_next;
// Loop counters (shared across states)
reg [1:0] loop_i; // row index (0..k-1)
reg [1:0] loop_j; // col index (0..k-1)
reg [1:0] loop_idx; // generic single-loop index
reg [8:0] coeff_cnt; // 0..256 coefficient counter
reg [5:0] poly_idx_reg; // current poly base index
reg phase_active; // 1 while sub-phase is doing work
reg phase_done; // 1 when sub-phase work is complete
// ====================================================================
// Output assignments
// ====================================================================
assign ready_o = ready_o_r;
assign pk_o = pk_o_r;
assign sk_o = sk_o_r;
assign pk_valid = pk_valid_r;
assign sk_valid = sk_valid_r;
assign ct_o = ct_o_r;
assign K_o = K_o_r;
assign ct_valid = ct_valid_r;
assign K_valid = K_valid_r;
assign K_o_dec = K_o_dec_r;
assign K_valid_dec = K_valid_dec_r;
assign done_o = done_o_r;
// ====================================================================
// Default module-side connections (combinational — read state_r)
// ====================================================================
// -- sha3_chain (consumer 0) --
assign chain_start = (state_r == S_KG_G_START);
assign chain_kc_ready_o = arb_cons_ready_o[0];
assign chain_kc_state_o = arb_cons_state_o[0*1600 +: 1600];
assign chain_kc_valid_o = arb_cons_valid_o[0];
assign arb_cons_state_i[0*1600 +: 1600] = chain_kc_state_i;
assign arb_cons_valid_i[0] = chain_kc_valid_i;
assign arb_cons_ready_i[0] = 1'b1;
// -- sample_cbd (consumer 1) --
assign cbd_kc_ready_o = arb_cons_ready_o[1];
assign cbd_kc_state_o = arb_cons_state_o[1*1600 +: 1600];
assign cbd_kc_valid_o = arb_cons_valid_o[1];
assign arb_cons_state_i[1*1600 +: 1600] = cbd_kc_state_i;
assign arb_cons_valid_i[1] = cbd_kc_valid_i;
assign arb_cons_ready_i[1] = 1'b1;
// -- sample_ntt (consumer 2) --
assign snt_kc_ready_o = arb_cons_ready_o[2];
assign snt_kc_state_o = arb_cons_state_o[2*1600 +: 1600];
assign snt_kc_valid_o = arb_cons_valid_o[2];
assign arb_cons_state_i[2*1600 +: 1600] = snt_kc_state_i;
assign arb_cons_valid_i[2] = snt_kc_valid_i;
assign arb_cons_ready_i[2] = 1'b1;
// -- rng_sync (combinational drive) --
assign rng_valid_i = (state_r == S_KG_RNG_REQ || state_r == S_EN_RNG_REQ);
// ====================================================================
// FSM combinational next-state logic
//
// Transitions are triggered by:
// - phase_done: sub-phase work completed (set in sequential block)
// - External ready/valid signals (rng_valid_o, chain_done, etc.)
// - ntt_done_o: NTT core completion
//
// Loop-back for iteration: uses combinational check on registered
// loop_i/loop_j counters to decide whether to loop or advance.
// ====================================================================
always @(*) begin
state_next = state_r;
case (state_r)
// ============================================================
// IDLE
// ============================================================
S_IDLE: begin
if (valid_i && ready_o_r) begin
case (mode)
2'b00: state_next = S_KG_RNG_REQ;
2'b01: state_next = S_EN_RNG_REQ;
2'b10: state_next = S_DC_DECOMP_C1;
default: state_next = S_IDLE;
endcase
end
end
// ============================================================
// KEYGEN
// ============================================================
S_KG_RNG_REQ: state_next = S_KG_RNG_WAIT;
S_KG_RNG_WAIT: if (rng_valid_o) state_next = S_KG_G_START;
S_KG_G_START: state_next = S_KG_G_WAIT;
S_KG_G_WAIT: if (chain_done) state_next = S_KG_G_DONE;
S_KG_G_DONE: state_next = S_KG_SNT_INIT;
// -- SampleNTT A-matrix loop --
S_KG_SNT_INIT: state_next = S_KG_SNT_START;
S_KG_SNT_START: if (snt_ready_o) state_next = S_KG_SNT_COEFFS;
S_KG_SNT_COEFFS: if (phase_done) state_next = S_KG_SNT_CLEANUP;
S_KG_SNT_CLEANUP: state_next = S_KG_SNT_NTT_LOAD;
S_KG_SNT_NTT_LOAD: if (phase_done) state_next = S_KG_SNT_NTT_COMP;
S_KG_SNT_NTT_COMP: if (ntt_done_o) state_next = S_KG_SNT_NTT_OUT;
S_KG_SNT_NTT_OUT: if (phase_done) state_next = S_KG_SNT_NEXT;
// S_KG_SNT_NEXT: loop or advance
S_KG_SNT_NEXT: begin
if (loop_j + 2'd1 < k_r[1:0])
state_next = S_KG_SNT_START;
else if (loop_i + 2'd1 < k_r[1:0])
state_next = S_KG_SNT_START;
else
state_next = S_KG_CBD_S_INIT;
end
// -- CBD s loop --
S_KG_CBD_S_INIT: state_next = S_KG_CBD_S_START;
S_KG_CBD_S_START: if (cbd_ready_o) state_next = S_KG_CBD_S_COEFFS;
S_KG_CBD_S_COEFFS: if (phase_done) state_next = S_KG_CBD_S_CLEANUP;
S_KG_CBD_S_CLEANUP: state_next = S_KG_CBD_S_NTT_LD;
S_KG_CBD_S_NTT_LD: if (phase_done) state_next = S_KG_CBD_S_NTT_CMP;
S_KG_CBD_S_NTT_CMP: if (ntt_done_o) state_next = S_KG_CBD_S_NTT_OUT;
S_KG_CBD_S_NTT_OUT: if (phase_done) state_next = S_KG_CBD_S_NEXT;
S_KG_CBD_S_NEXT: begin
if (loop_idx + 2'd1 < k_r[1:0])
state_next = S_KG_CBD_S_START;
else
state_next = S_KG_CBD_E_INIT;
end
// -- CBD e loop --
S_KG_CBD_E_INIT: state_next = S_KG_CBD_E_START;
S_KG_CBD_E_START: if (cbd_ready_o) state_next = S_KG_CBD_E_COEFFS;
S_KG_CBD_E_COEFFS: if (phase_done) state_next = S_KG_CBD_E_CLEANUP;
S_KG_CBD_E_CLEANUP: state_next = S_KG_CBD_E_NTT_LD;
S_KG_CBD_E_NTT_LD: if (phase_done) state_next = S_KG_CBD_E_NTT_CMP;
S_KG_CBD_E_NTT_CMP: if (ntt_done_o) state_next = S_KG_CBD_E_NTT_OUT;
S_KG_CBD_E_NTT_OUT: if (phase_done) state_next = S_KG_CBD_E_NEXT;
S_KG_CBD_E_NEXT: begin
if (loop_idx + 2'd1 < k_r[1:0])
state_next = S_KG_CBD_E_START;
else
state_next = S_KG_TMUL_INIT;
end
// -- t_hat = sum(A·s) + e --
S_KG_TMUL_INIT: state_next = S_KG_TMUL_STEP;
S_KG_TMUL_STEP: if (phase_done) state_next = S_KG_TMUL_NEXT;
S_KG_TMUL_NEXT: begin
if (loop_i + 2'd1 < k_r[1:0])
state_next = S_KG_TMUL_STEP;
else
state_next = S_KG_DONE;
end
S_KG_DONE: state_next = S_IDLE;
// ============================================================
// ENCAPS
// ============================================================
S_EN_RNG_REQ: state_next = S_EN_RNG_WAIT;
S_EN_RNG_WAIT: if (rng_valid_o) state_next = S_EN_H_START;
S_EN_H_START: state_next = S_EN_H_WAIT;
S_EN_H_WAIT: if (sha3_valid_o) state_next = S_EN_G_START;
S_EN_G_START: state_next = S_EN_G_WAIT;
S_EN_G_WAIT: if (sha3_valid_o) state_next = S_EN_SNT_INIT;
S_EN_SNT_INIT: state_next = S_EN_SNT_START;
S_EN_SNT_START: if (snt_ready_o) state_next = S_EN_SNT_COEFFS;
S_EN_SNT_COEFFS: if (phase_done) state_next = S_EN_SNT_CLEANUP;
S_EN_SNT_CLEANUP: state_next = S_EN_SNT_NTT_LD;
S_EN_SNT_NTT_LD: if (phase_done) state_next = S_EN_SNT_NTT_CMP;
S_EN_SNT_NTT_CMP: if (ntt_done_o) state_next = S_EN_SNT_NTT_OUT;
S_EN_SNT_NTT_OUT: if (phase_done) state_next = S_EN_SNT_NEXT;
S_EN_SNT_NEXT: begin
if (loop_j + 2'd1 < k_r[1:0])
state_next = S_EN_SNT_START;
else if (loop_i + 2'd1 < k_r[1:0])
state_next = S_EN_SNT_START;
else
state_next = S_EN_CBD_Y_INIT;
end
S_EN_CBD_Y_INIT: state_next = S_EN_CBD_Y_START;
S_EN_CBD_Y_START: if (cbd_ready_o) state_next = S_EN_CBD_Y_COEFFS;
S_EN_CBD_Y_COEFFS: if (phase_done) state_next = S_EN_CBD_Y_CLNUP;
S_EN_CBD_Y_CLNUP: state_next = S_EN_CBD_Y_NTT_LD;
S_EN_CBD_Y_NTT_LD: if (phase_done) state_next = S_EN_CBD_Y_NTT_CMP;
S_EN_CBD_Y_NTT_CMP: if (ntt_done_o) state_next = S_EN_CBD_Y_NTT_OUT;
S_EN_CBD_Y_NTT_OUT: if (phase_done) state_next = S_EN_CBD_Y_NEXT;
S_EN_CBD_Y_NEXT: begin
if (loop_idx + 2'd1 < k_r[1:0])
state_next = S_EN_CBD_Y_START;
else
state_next = S_EN_DONE;
end
S_EN_DONE: state_next = S_IDLE;
// ============================================================
// DECAPS (simplified placeholder states flow)
// ============================================================
S_DC_DECOMP_C1: if (phase_done) state_next = S_DC_DECOMP_C2;
S_DC_DECOMP_C2: if (phase_done) state_next = S_DC_NTT_U_LD;
S_DC_NTT_U_LD: if (phase_done) state_next = S_DC_NTT_U_CMP;
S_DC_NTT_U_CMP: if (ntt_done_o) state_next = S_DC_NTT_U_OUT;
S_DC_NTT_U_OUT: if (phase_done) state_next = S_DC_MUL_S;
S_DC_MUL_S: if (phase_done) state_next = S_DC_INTT_V;
S_DC_INTT_V: if (phase_done) state_next = S_DC_DECOMP_M;
S_DC_DECOMP_M: if (phase_done) state_next = S_DC_G_CHECK;
S_DC_G_CHECK: if (phase_done) state_next = S_DC_REENC;
S_DC_REENC: if (phase_done) state_next = S_DC_KDF;
S_DC_KDF: if (phase_done) state_next = S_DC_DONE;
S_DC_DONE: state_next = S_IDLE;
default: state_next = S_IDLE;
endcase
end
// ====================================================================
// FSM sequential logic
// ====================================================================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_r <= S_IDLE;
mode_r <= 2'd0;
k_r <= 3'd2;
ready_o_r <= 1'b1;
pk_valid_r <= 1'b0;
sk_valid_r <= 1'b0;
ct_valid_r <= 1'b0;
K_valid_r <= 1'b0;
K_valid_dec_r <= 1'b0;
done_o_r <= 1'b0;
pk_o_r <= 0;
sk_o_r <= 0;
ct_o_r <= 0;
K_o_r <= 256'd0;
K_o_dec_r <= 256'd0;
d_reg <= 256'd0;
rho_reg <= 256'd0;
sigma_reg <= 256'd0;
m_reg <= 256'd0;
Kbar_reg <= 256'd0;
r_reg <= 256'd0;
Hpk_reg <= 256'd0;
z_reg <= 256'd0;
loop_i <= 2'd0;
loop_j <= 2'd0;
loop_idx <= 2'd0;
coeff_cnt <= 9'd0;
poly_idx_reg <= 6'd0;
phase_active <= 1'b0;
phase_done <= 1'b0;
// Drive all FSM-controlled outputs to safe defaults
cbd_valid_i_r <= 1'b0;
cbd_nonce_r <= 8'd0;
cbd_eta_r <= 2'd0;
cbd_use_r_seed <= 1'b0;
snt_valid_i_r <= 1'b0;
snt_i_idx_r <= 2'd0;
snt_j_idx_r <= 2'd0;
sha3_mode_r <= 2'd0;
sha3_data_r <= 512'd0;
sha3_valid_i_r <= 1'b0;
ntt_coeff_in_r <= 12'd0;
ntt_valid_i_r <= 1'b0;
ntt_mode_r <= 1'b0;
pmul_a_r <= 12'd0;
pmul_b_r <= 12'd0;
pmul_valid_i_r <= 1'b0;
parith_a_r <= 12'd0;
parith_b_r <= 12'd0;
parith_mode_r <= 1'b0;
parith_valid_i_r <= 1'b0;
comp_coeff_in_r <= 12'd0;
comp_d_r <= 5'd0;
comp_mode_r <= 1'b0;
comp_valid_i_r <= 1'b0;
madd_a_r <= 12'd0;
madd_b_r <= 12'd0;
madd_valid_i_r <= 1'b0;
bram_wr_en_r <= 1'b0;
bram_wr_addr_r <= 0;
bram_wr_data_r <= 12'd0;
bram_rd_addr_r <= 0;
end else begin
state_r <= state_next;
// Default: clear one-cycle pulse outputs
pk_valid_r <= 1'b0;
sk_valid_r <= 1'b0;
ct_valid_r <= 1'b0;
K_valid_r <= 1'b0;
K_valid_dec_r <= 1'b0;
done_o_r <= 1'b0;
// Default: BRAM write off
bram_wr_en_r <= 1'b0;
// Default: de-assert streaming valid signals unless driven
// (These are single-cycle; phase_active prevents glitches)
if (!phase_active) begin
ntt_valid_i_r <= 1'b0;
cbd_valid_i_r <= 1'b0;
snt_valid_i_r <= 1'b0;
sha3_valid_i_r <= 1'b0;
pmul_valid_i_r <= 1'b0;
parith_valid_i_r <= 1'b0;
comp_valid_i_r <= 1'b0;
madd_valid_i_r <= 1'b0;
end
// ============================================================
// S_IDLE: latch inputs
// ============================================================
if (state_r == S_IDLE && valid_i && ready_o_r) begin
mode_r <= mode;
k_r <= i_k;
ready_o_r <= 1'b0;
end
// ============================================================
// KEYGEN: RNG → G function
// ============================================================
if (state_r == S_KG_RNG_WAIT && rng_valid_o) begin
d_reg <= rng_data_o;
end
if (state_r == S_KG_G_WAIT && chain_done) begin
rho_reg <= chain_rho;
sigma_reg <= chain_sigma;
end
// ============================================================
// KEYGEN: SampleNTT loop
// ============================================================
if (state_r == S_KG_SNT_INIT) begin
loop_i <= 2'd0;
loop_j <= 2'd0;
phase_done <= 1'b0;
end
if (state_r == S_KG_SNT_START) begin
snt_valid_i_r <= 1'b1;
snt_i_idx_r <= loop_i;
snt_j_idx_r <= loop_j;
coeff_cnt <= 9'd0;
phase_active <= 1'b1;
phase_done <= 1'b0;
end
if (state_r == S_KG_SNT_COEFFS) begin
snt_valid_i_r <= 1'b0;
if (snt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
bram_wr_data_r <= snt_coeff_o;
coeff_cnt <= coeff_cnt + 9'd1;
if (snt_last_o) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_SNT_CLEANUP) begin
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_KG_SNT_NTT_LOAD) begin
phase_active <= 1'b1;
if (coeff_cnt < 9'd256) begin
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
ntt_coeff_in_r <= bram_rd_data;
ntt_valid_i_r <= 1'b1;
if (ntt_ready_o) begin
coeff_cnt <= coeff_cnt + 9'd1;
end
end else begin
ntt_valid_i_r <= 1'b0;
phase_done <= 1'b1;
phase_active <= 1'b0;
coeff_cnt <= 9'd0;
end
end
if (state_r == S_KG_SNT_NTT_COMP) begin
phase_done <= 1'b0;
coeff_cnt <= 9'd0;
phase_active <= 1'b0;
end
if (state_r == S_KG_SNT_NTT_OUT) begin
phase_active <= 1'b1;
if (ntt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(A_BASE + (loop_i * K + loop_j), coeff_cnt[7:0]);
bram_wr_data_r <= ntt_coeff_out;
coeff_cnt <= coeff_cnt + 9'd1;
if (coeff_cnt == 9'd255) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_SNT_NEXT) begin
phase_done <= 1'b0;
if (loop_j + 2'd1 < k_r[1:0]) begin
loop_j <= loop_j + 2'd1;
end else if (loop_i + 2'd1 < k_r[1:0]) begin
loop_i <= loop_i + 2'd1;
loop_j <= 2'd0;
end
end
// ============================================================
// KEYGEN: CBD s loop
// ============================================================
if (state_r == S_KG_CBD_S_INIT) begin
loop_idx <= 2'd0;
phase_done <= 1'b0;
cbd_use_r_seed <= 1'b0; // use sigma_reg
end
if (state_r == S_KG_CBD_S_START) begin
cbd_valid_i_r <= 1'b1;
cbd_nonce_r <= {6'b0, loop_idx};
cbd_eta_r <= (k_r == 3'd2) ? 2'd3 : 2'd2;
coeff_cnt <= 9'd0;
phase_active <= 1'b1;
phase_done <= 1'b0;
end
if (state_r == S_KG_CBD_S_COEFFS) begin
cbd_valid_i_r <= 1'b0;
if (cbd_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
bram_wr_data_r <= cbd_coeff_o;
coeff_cnt <= coeff_cnt + 9'd1;
if (cbd_last_o) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_CBD_S_CLEANUP) begin
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_KG_CBD_S_NTT_LD) begin
phase_active <= 1'b1;
if (coeff_cnt < 9'd256) begin
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
ntt_coeff_in_r <= bram_rd_data;
ntt_valid_i_r <= 1'b1;
if (ntt_ready_o) coeff_cnt <= coeff_cnt + 9'd1;
end else begin
ntt_valid_i_r <= 1'b0;
phase_done <= 1'b1;
phase_active <= 1'b0;
coeff_cnt <= 9'd0;
end
end
if (state_r == S_KG_CBD_S_NTT_CMP) begin
phase_done <= 1'b0;
coeff_cnt <= 9'd0;
phase_active <= 1'b0;
end
if (state_r == S_KG_CBD_S_NTT_OUT) begin
phase_active <= 1'b1;
if (ntt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(S_BASE + loop_idx, coeff_cnt[7:0]);
bram_wr_data_r <= ntt_coeff_out;
coeff_cnt <= coeff_cnt + 9'd1;
if (coeff_cnt == 9'd255) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_CBD_S_NEXT) begin
phase_done <= 1'b0;
if (loop_idx + 2'd1 < k_r[1:0])
loop_idx <= loop_idx + 2'd1;
end
// ============================================================
// KEYGEN: CBD e loop (same pattern as s)
// ============================================================
if (state_r == S_KG_CBD_E_INIT) begin
loop_idx <= 2'd0;
phase_done <= 1'b0;
end
if (state_r == S_KG_CBD_E_START) begin
cbd_valid_i_r <= 1'b1;
cbd_nonce_r <= k_r + {5'b0, loop_idx};
cbd_eta_r <= (k_r == 3'd2) ? 2'd3 : 2'd2;
coeff_cnt <= 9'd0;
phase_active <= 1'b1;
phase_done <= 1'b0;
end
if (state_r == S_KG_CBD_E_COEFFS) begin
cbd_valid_i_r <= 1'b0;
if (cbd_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
bram_wr_data_r <= cbd_coeff_o;
coeff_cnt <= coeff_cnt + 9'd1;
if (cbd_last_o) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_CBD_E_CLEANUP) begin
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_KG_CBD_E_NTT_LD) begin
phase_active <= 1'b1;
if (coeff_cnt < 9'd256) begin
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
ntt_coeff_in_r <= bram_rd_data;
ntt_valid_i_r <= 1'b1;
if (ntt_ready_o) coeff_cnt <= coeff_cnt + 9'd1;
end else begin
ntt_valid_i_r <= 1'b0;
phase_done <= 1'b1;
phase_active <= 1'b0;
coeff_cnt <= 9'd0;
end
end
if (state_r == S_KG_CBD_E_NTT_CMP) begin
phase_done <= 1'b0;
coeff_cnt <= 9'd0;
phase_active <= 1'b0;
end
if (state_r == S_KG_CBD_E_NTT_OUT) begin
phase_active <= 1'b1;
if (ntt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(E_BASE + loop_idx, coeff_cnt[7:0]);
bram_wr_data_r <= ntt_coeff_out;
coeff_cnt <= coeff_cnt + 9'd1;
if (coeff_cnt == 9'd255) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_KG_CBD_E_NEXT) begin
phase_done <= 1'b0;
if (loop_idx + 2'd1 < k_r[1:0])
loop_idx <= loop_idx + 2'd1;
end
// ============================================================
// KEYGEN: t_hat computation (simplified)
// ============================================================
if (state_r == S_KG_TMUL_INIT) begin
loop_i <= 2'd0;
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
end
if (state_r == S_KG_TMUL_STEP) begin
// TODO: Per-row poly_mul A[i,:]·s[:] + e[i] → t_hat[i]
// For now, placeholder: just mark done
phase_done <= 1'b1;
end
if (state_r == S_KG_TMUL_NEXT) begin
phase_done <= 1'b0;
if (loop_i + 2'd1 < k_r[1:0])
loop_i <= loop_i + 2'd1;
end
// ============================================================
// KEYGEN: DONE
// ============================================================
if (state_r == S_KG_DONE) begin
pk_valid_r <= 1'b1;
sk_valid_r <= 1'b1;
done_o_r <= 1'b1;
ready_o_r <= 1'b1;
end
// ============================================================
// ENCAPS: RNG → H → G
// ============================================================
if (state_r == S_EN_RNG_WAIT && rng_valid_o) begin
m_reg <= rng_data_o;
end
if (state_r == S_EN_H_START) begin
sha3_mode_r <= 2'b01; // H mode (SHA3-256)
sha3_data_r <= {256'b0, m_reg};
sha3_valid_i_r <= 1'b1;
end
if (state_r == S_EN_H_WAIT) begin
sha3_valid_i_r <= 1'b0;
if (sha3_valid_o)
Hpk_reg <= sha3_hash_o[255:0];
end
if (state_r == S_EN_G_START) begin
sha3_mode_r <= 2'b00; // G mode (SHA3-512)
sha3_data_r <= {248'b0, 8'd2, m_reg};
sha3_valid_i_r <= 1'b1;
end
if (state_r == S_EN_G_WAIT) begin
sha3_valid_i_r <= 1'b0;
if (sha3_valid_o) begin
Kbar_reg <= sha3_hash_o[255:0];
r_reg <= sha3_hash_o[511:256];
end
end
// ============================================================
// ENCAPS: SampleNTT loop
// ============================================================
if (state_r == S_EN_SNT_INIT) begin
loop_i <= 2'd0;
loop_j <= 2'd0;
phase_done <= 1'b0;
end
if (state_r == S_EN_SNT_START) begin
snt_valid_i_r <= 1'b1;
snt_i_idx_r <= loop_i;
snt_j_idx_r <= loop_j;
coeff_cnt <= 9'd0;
phase_active <= 1'b1;
phase_done <= 1'b0;
end
if (state_r == S_EN_SNT_COEFFS) begin
snt_valid_i_r <= 1'b0;
if (snt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
bram_wr_data_r <= snt_coeff_o;
coeff_cnt <= coeff_cnt + 9'd1;
if (snt_last_o) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_EN_SNT_CLEANUP) begin
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_EN_SNT_NTT_LD) begin
phase_active <= 1'b1;
if (coeff_cnt < 9'd256) begin
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
ntt_coeff_in_r <= bram_rd_data;
ntt_valid_i_r <= 1'b1;
if (ntt_ready_o) coeff_cnt <= coeff_cnt + 9'd1;
end else begin
ntt_valid_i_r <= 1'b0;
phase_done <= 1'b1;
phase_active <= 1'b0;
coeff_cnt <= 9'd0;
end
end
if (state_r == S_EN_SNT_NTT_CMP) begin
phase_done <= 1'b0;
coeff_cnt <= 9'd0;
phase_active <= 1'b0;
end
if (state_r == S_EN_SNT_NTT_OUT) begin
phase_active <= 1'b1;
if (ntt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(A_BASE + (loop_i * K + loop_j), coeff_cnt[7:0]);
bram_wr_data_r <= ntt_coeff_out;
coeff_cnt <= coeff_cnt + 9'd1;
if (coeff_cnt == 9'd255) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_EN_SNT_NEXT) begin
phase_done <= 1'b0;
if (loop_j + 2'd1 < k_r[1:0]) begin
loop_j <= loop_j + 2'd1;
end else if (loop_i + 2'd1 < k_r[1:0]) begin
loop_i <= loop_i + 2'd1;
loop_j <= 2'd0;
end
end
// ============================================================
// ENCAPS: CBD y loop
// ============================================================
if (state_r == S_EN_CBD_Y_INIT) begin
loop_idx <= 2'd0;
phase_done <= 1'b0;
cbd_use_r_seed <= 1'b1; // use r_reg for seed
end
if (state_r == S_EN_CBD_Y_START) begin
cbd_valid_i_r <= 1'b1;
cbd_nonce_r <= {6'b0, loop_idx};
cbd_eta_r <= (k_r == 3'd2) ? 2'd3 : 2'd2;
coeff_cnt <= 9'd0;
phase_active <= 1'b1;
phase_done <= 1'b0;
end
if (state_r == S_EN_CBD_Y_COEFFS) begin
cbd_valid_i_r <= 1'b0;
if (cbd_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
bram_wr_data_r <= cbd_coeff_o;
coeff_cnt <= coeff_cnt + 9'd1;
if (cbd_last_o) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_EN_CBD_Y_CLNUP) begin
coeff_cnt <= 9'd0;
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_EN_CBD_Y_NTT_LD) begin
phase_active <= 1'b1;
if (coeff_cnt < 9'd256) begin
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
ntt_coeff_in_r <= bram_rd_data;
ntt_valid_i_r <= 1'b1;
if (ntt_ready_o) coeff_cnt <= coeff_cnt + 9'd1;
end else begin
ntt_valid_i_r <= 1'b0;
phase_done <= 1'b1;
phase_active <= 1'b0;
coeff_cnt <= 9'd0;
end
end
if (state_r == S_EN_CBD_Y_NTT_CMP) begin
phase_done <= 1'b0;
coeff_cnt <= 9'd0;
phase_active <= 1'b0;
end
if (state_r == S_EN_CBD_Y_NTT_OUT) begin
phase_active <= 1'b1;
if (ntt_valid_o) begin
bram_wr_en_r <= 1'b1;
bram_wr_addr_r <= poly_addr(Y_BASE + loop_idx, coeff_cnt[7:0]);
bram_wr_data_r <= ntt_coeff_out;
coeff_cnt <= coeff_cnt + 9'd1;
if (coeff_cnt == 9'd255) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
end
end
if (state_r == S_EN_CBD_Y_NEXT) begin
phase_done <= 1'b0;
if (loop_idx + 2'd1 < k_r[1:0])
loop_idx <= loop_idx + 2'd1;
end
// ============================================================
// ENCAPS: DONE
// ============================================================
if (state_r == S_EN_DONE) begin
ct_valid_r <= 1'b1;
K_valid_r <= 1'b1;
K_o_r <= Kbar_reg;
done_o_r <= 1'b1;
ready_o_r <= 1'b1;
end
// ============================================================
// DECAPS: placeholder states
// ============================================================
if (state_r == S_DC_DECOMP_C1) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_DECOMP_C2) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_NTT_U_LD) begin
phase_done <= 1'b1;
phase_active <= 1'b0;
end
if (state_r == S_DC_NTT_U_CMP) begin
phase_done <= 1'b0;
phase_active <= 1'b0;
end
if (state_r == S_DC_NTT_U_OUT) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_MUL_S) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_INTT_V) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_DECOMP_M) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_G_CHECK) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_REENC) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_KDF) begin
phase_done <= 1'b1;
end
if (state_r == S_DC_DONE) begin
K_valid_dec_r <= 1'b1;
done_o_r <= 1'b1;
ready_o_r <= 1'b1;
end
end
end
// ====================================================================
// MODULE INSTANTIATIONS
// ====================================================================
// --- keccak_core (shared) ---
keccak_core #(.ROUNDS(24)) u_keccak_shared (
.clk (clk),
.rst_n (rst_n),
.state_i (arb_kc_state_i),
.valid_i (arb_kc_valid_i),
.ready_o (arb_kc_ready_o),
.state_o (arb_kc_state_o),
.valid_o (arb_kc_valid_o),
.ready_i (arb_kc_ready_i)
);
// --- keccak_arbiter (3 consumers) ---
keccak_arbiter #(.NUM_CONSUMERS(N_CONSUMERS)) u_arbiter (
.clk (clk),
.rst_n (rst_n),
.kc_state_i (arb_kc_state_i),
.kc_valid_i (arb_kc_valid_i),
.kc_ready_o (arb_kc_ready_o),
.kc_state_o (arb_kc_state_o),
.kc_valid_o (arb_kc_valid_o),
.kc_ready_i (arb_kc_ready_i),
.cons_state_i (arb_cons_state_i),
.cons_valid_i (arb_cons_valid_i),
.cons_ready_o (arb_cons_ready_o),
.cons_state_o (arb_cons_state_o),
.cons_valid_o (arb_cons_valid_o),
.cons_ready_i (arb_cons_ready_i)
);
// --- sha3_chain_top_shared (consumer 0) ---
sha3_chain_top_shared u_chain (
.clk (clk),
.rst_n (rst_n),
.d_in (d_reg),
.start_i (chain_start),
.done_o (chain_done),
.rho_out (chain_rho),
.sigma_out (chain_sigma),
.kc_state_o (chain_kc_state_o),
.kc_valid_o (chain_kc_valid_o),
.kc_ready_i (chain_kc_ready_i),
.kc_state_i (chain_kc_state_i),
.kc_valid_i (chain_kc_valid_i),
.kc_ready_o (chain_kc_ready_o)
);
// --- sample_cbd_sync_shared (consumer 1) ---
sample_cbd_sync_shared u_cbd (
.clk (clk),
.rst_n (rst_n),
.seed_i (cbd_seed_muxed),
.nonce_i (cbd_nonce_r),
.eta_i (cbd_eta_r),
.valid_i (cbd_valid_i_r),
.ready_o (cbd_ready_o),
.coeff_o (cbd_coeff_o),
.valid_o (cbd_valid_o),
.ready_i (1'b1),
.last_o (cbd_last_o),
.kc_state_o (cbd_kc_state_o),
.kc_valid_o (cbd_kc_valid_o),
.kc_ready_i (cbd_kc_ready_i),
.kc_state_i (cbd_kc_state_i),
.kc_valid_i (cbd_kc_valid_i),
.kc_ready_o (cbd_kc_ready_o)
);
// --- sample_ntt_sync_shared (consumer 2) ---
sample_ntt_sync_shared #(.K(K)) u_snt (
.clk (clk),
.rst_n (rst_n),
.rho_i (rho_reg),
.k_i (k_r),
.i_idx (snt_i_idx_r),
.j_idx (snt_j_idx_r),
.valid_i (snt_valid_i_r),
.ready_o (snt_ready_o),
.coeff_o (snt_coeff_o),
.valid_o (snt_valid_o),
.ready_i (1'b1),
.last_o (snt_last_o),
.kc_state_o (snt_kc_state_o),
.kc_valid_o (snt_kc_valid_o),
.kc_ready_i (snt_kc_ready_i),
.kc_state_i (snt_kc_state_i),
.kc_valid_i (snt_kc_valid_i),
.kc_ready_o (snt_kc_ready_o)
);
// --- sha3_top (separate keccak_core, for H/KDF calls) ---
sha3_top u_sha3 (
.clk (clk),
.rst_n (rst_n),
.mode (sha3_mode_r),
.data_i (sha3_data_r),
.valid_i (sha3_valid_i_r),
.ready_o (sha3_ready_o),
.hash_o (sha3_hash_o),
.valid_o (sha3_valid_o),
.ready_i (1'b1)
);
// --- rng_sync ---
rng_sync u_rng (
.clk (clk),
.rst_n (rst_n),
.valid_i (rng_valid_i),
.ready_o (rng_ready_o),
.data_o (rng_data_o),
.valid_o (rng_valid_o),
.ready_i (1'b1)
);
// --- ntt_core ---
ntt_core u_ntt (
.clk (clk),
.rst_n (rst_n),
.coeff_in (ntt_coeff_in_r),
.valid_i (ntt_valid_i_r),
.ready_o (ntt_ready_o),
.mode (ntt_mode_r),
.coeff_out (ntt_coeff_out),
.valid_o (ntt_valid_o),
.ready_i (1'b1),
.done_o (ntt_done_o)
);
// --- poly_mul_sync ---
poly_mul_sync u_pmul (
.clk (clk),
.rst_n (rst_n),
.coeff_a_in (pmul_a_r),
.coeff_b_in (pmul_b_r),
.valid_i (pmul_valid_i_r),
.ready_o (pmul_ready_o),
.coeff_out (pmul_coeff_out),
.valid_o (pmul_valid_o),
.ready_i (1'b1)
);
// --- poly_arith_sync ---
poly_arith_sync u_parith (
.clk (clk),
.rst_n (rst_n),
.coeff_a_in (parith_a_r),
.coeff_b_in (parith_b_r),
.mode (parith_mode_r),
.valid_i (parith_valid_i_r),
.ready_o (parith_ready_o),
.coeff_out (parith_coeff_out),
.valid_o (parith_valid_o),
.ready_i (1'b1)
);
// --- comp_decomp_sync ---
comp_decomp_sync u_comp (
.clk (clk),
.rst_n (rst_n),
.coeff_in (comp_coeff_in_r),
.d (comp_d_r),
.mode (comp_mode_r),
.valid_i (comp_valid_i_r),
.ready_o (comp_ready_o),
.coeff_out (comp_coeff_out),
.valid_o (comp_valid_o),
.ready_i (1'b1)
);
// --- mod_add_sync ---
mod_add_sync u_madd (
.clk (clk),
.rst_n (rst_n),
.a (madd_a_r),
.b (madd_b_r),
.valid_i (madd_valid_i_r),
.ready_o (madd_ready_o),
.sum (madd_sum),
.valid_o (madd_valid_o),
.ready_i (1'b1)
);
// --- sd_bram (large, for all polynomial storage) ---
sd_bram #(.W(12), .D(BRAM_DEPTH), .A(BRAM_AW)) u_bram (
.clk (clk),
.rd_addr (bram_rd_addr_r),
.rd_data (bram_rd_data),
.wr_en (bram_wr_en_r),
.wr_addr (bram_wr_addr_r),
.wr_data (bram_wr_data_r)
);
endmodule