RTL was feeding d bytes in reversed order to SHA3-512, causing G(d) to produce wrong rho/sigma. Fix: add d_rev wire with byte reversal, connect to sha3_chain_top_shared.
1659 lines
66 KiB
Verilog
1659 lines
66 KiB
Verilog
// 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
|
||
wire [255:0] d_rev; // byte-reversed d (FIPS 203 byte order)
|
||
genvar gi;
|
||
generate
|
||
for (gi = 0; gi < 32; gi = gi + 1) begin : gen_d_rev
|
||
assign d_rev[gi*8 +: 8] = d_reg[(31-gi)*8 +: 8];
|
||
end
|
||
endgenerate
|
||
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
|
||
|
||
// s_hat capture registers (filled during CBD→NTT output)
|
||
reg [N*12-1:0] s_hat0_reg, s_hat1_reg;
|
||
|
||
// t_hat output registers (computed during t_hat computation)
|
||
reg [N*12-1:0] t_hat0_reg, t_hat1_reg;
|
||
|
||
// t_hat computation scratch registers
|
||
reg [11:0] tmul_pipe_reg; // 1-cycle pipeline delay for poly_mul output
|
||
reg tmul_pipe_valid; // flag: tmul_pipe_reg holds valid data
|
||
reg [8:0] tmul_out_cnt; // output coefficient counter for accumulation
|
||
reg tmul_adv_row; // flag: advancing to next row (set in ADD_E, used in MUL_LD)
|
||
|
||
// ====================================================================
|
||
// 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_MUL_LD = 7'd31;
|
||
localparam S_KG_TMUL_MUL_OUT = 7'd32;
|
||
localparam S_KG_TMUL_ACCUM = 7'd33;
|
||
localparam S_KG_TMUL_ADD_E = 7'd34;
|
||
localparam S_KG_TMUL_NEXT = 7'd35;
|
||
localparam S_KG_DONE = 7'd36;
|
||
|
||
// --- Encaps states ---
|
||
localparam S_EN_RNG_REQ = 7'd37;
|
||
localparam S_EN_RNG_WAIT = 7'd38;
|
||
localparam S_EN_H_START = 7'd39;
|
||
localparam S_EN_H_WAIT = 7'd40;
|
||
localparam S_EN_G_START = 7'd41;
|
||
localparam S_EN_G_WAIT = 7'd42;
|
||
localparam S_EN_SNT_INIT = 7'd43;
|
||
localparam S_EN_SNT_START = 7'd44;
|
||
localparam S_EN_SNT_COEFFS = 7'd45;
|
||
localparam S_EN_SNT_CLEANUP = 7'd46;
|
||
localparam S_EN_SNT_NTT_LD = 7'd47;
|
||
localparam S_EN_SNT_NTT_CMP = 7'd48;
|
||
localparam S_EN_SNT_NTT_OUT = 7'd49;
|
||
localparam S_EN_SNT_NEXT = 7'd50;
|
||
localparam S_EN_CBD_Y_INIT = 7'd51;
|
||
localparam S_EN_CBD_Y_START = 7'd52;
|
||
localparam S_EN_CBD_Y_COEFFS = 7'd53;
|
||
localparam S_EN_CBD_Y_CLNUP = 7'd54;
|
||
localparam S_EN_CBD_Y_NTT_LD = 7'd55;
|
||
localparam S_EN_CBD_Y_NTT_CMP = 7'd56;
|
||
localparam S_EN_CBD_Y_NTT_OUT = 7'd57;
|
||
localparam S_EN_CBD_Y_NEXT = 7'd58;
|
||
localparam S_EN_DONE = 7'd59;
|
||
|
||
// --- Decaps states ---
|
||
localparam S_DC_DECOMP_C1 = 7'd60;
|
||
localparam S_DC_DECOMP_C2 = 7'd61;
|
||
localparam S_DC_NTT_U_LD = 7'd62;
|
||
localparam S_DC_NTT_U_CMP = 7'd63;
|
||
localparam S_DC_NTT_U_OUT = 7'd64;
|
||
localparam S_DC_MUL_S = 7'd65;
|
||
localparam S_DC_INTT_V = 7'd66;
|
||
localparam S_DC_DECOMP_M = 7'd67;
|
||
localparam S_DC_G_CHECK = 7'd68;
|
||
localparam S_DC_REENC = 7'd69;
|
||
localparam S_DC_KDF = 7'd70;
|
||
localparam S_DC_DONE = 7'd71;
|
||
|
||
// ====================================================================
|
||
// 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_MUL_LD;
|
||
S_KG_TMUL_MUL_LD: if (phase_done) state_next = S_KG_TMUL_MUL_OUT;
|
||
S_KG_TMUL_MUL_OUT: if (phase_done) state_next = S_KG_TMUL_NEXT;
|
||
S_KG_TMUL_ACCUM: if (phase_done) state_next = S_KG_TMUL_ADD_E;
|
||
|
||
// After ADD_E: if more rows, loop to MUL_LD with next row; else DONE
|
||
S_KG_TMUL_ADD_E: begin
|
||
if (phase_done) begin
|
||
if (loop_i + 2'd1 < k_r[1:0])
|
||
state_next = S_KG_TMUL_MUL_LD;
|
||
else
|
||
state_next = S_KG_DONE;
|
||
end
|
||
end
|
||
|
||
// After MUL_OUT: check if more j terms for this row
|
||
S_KG_TMUL_NEXT: begin
|
||
if (loop_j + 2'd1 < k_r[1:0]) begin
|
||
state_next = S_KG_TMUL_MUL_LD; // more j columns
|
||
end else begin
|
||
state_next = S_KG_TMUL_ACCUM; // all j done → accumulate
|
||
end
|
||
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;
|
||
s_hat0_reg <= 0;
|
||
s_hat1_reg <= 0;
|
||
t_hat0_reg <= 0;
|
||
t_hat1_reg <= 0;
|
||
tmul_pipe_reg <= 12'd0;
|
||
tmul_pipe_valid <= 1'b0;
|
||
tmul_out_cnt <= 9'd0;
|
||
tmul_adv_row <= 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;
|
||
// Capture into s_hat registers for t_hat computation
|
||
if (loop_idx == 2'd0)
|
||
s_hat0_reg[coeff_cnt[7:0] * 12 +: 12] <= ntt_coeff_out;
|
||
else
|
||
s_hat1_reg[coeff_cnt[7:0] * 12 +: 12] <= 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
|
||
//
|
||
// For each row i (0..k-1):
|
||
// t_hat[i] = sum_j(A[i,j] * s_hat[j]) + e_hat[i]
|
||
//
|
||
// Phase 1 (S_KG_TMUL_MUL_LD): Load A[i,j], s_hat[j] into poly_mul
|
||
// Phase 2 (S_KG_TMUL_MUL_OUT): Read poly_mul result → SCRATCH0/SCRATCH1
|
||
// Phase 3 (S_KG_TMUL_ACCUM): Accumulate all A·s terms using poly_arith
|
||
// Phase 4 (S_KG_TMUL_ADD_E): Add e_hat[i] → store in t_hat_i_reg
|
||
// ============================================================
|
||
if (state_r == S_KG_TMUL_INIT) begin
|
||
loop_i <= 2'd0;
|
||
loop_j <= 2'd0;
|
||
coeff_cnt <= 9'd0;
|
||
tmul_pipe_reg <= 12'd0;
|
||
tmul_pipe_valid <= 1'b0;
|
||
tmul_out_cnt <= 9'd0;
|
||
tmul_adv_row <= 1'b0;
|
||
phase_done <= 1'b0;
|
||
end
|
||
|
||
// --- S_KG_TMUL_MUL_LD: Load A[i,j] and s_hat[j] into poly_mul ---
|
||
// Uses s_hat registers (combinational read) + A from BRAM (1-cycle delay).
|
||
// First cycle: handle row advancement (if flagged).
|
||
// Second cycle: prefetch first A coeff from BRAM.
|
||
// Cycles 3-258: feed 256 coeff pairs to poly_mul.
|
||
if (state_r == S_KG_TMUL_MUL_LD) begin
|
||
phase_active <= 1'b1;
|
||
if (coeff_cnt == 9'd0) begin
|
||
// Cycle 0: handle row advancement flag
|
||
if (tmul_adv_row) begin
|
||
loop_i <= loop_i + 2'd1;
|
||
loop_j <= 2'd0;
|
||
tmul_adv_row <= 1'b0;
|
||
end
|
||
coeff_cnt <= 9'd1;
|
||
end else if (coeff_cnt == 9'd1) begin
|
||
// Cycle 1: prefetch first A coefficient
|
||
bram_rd_addr_r <= poly_addr(A_BASE + (loop_i * K + loop_j), 8'd0);
|
||
coeff_cnt <= 9'd2;
|
||
end else if (coeff_cnt <= 9'd257) begin
|
||
// bram_rd_data holds A[i,j][coeff_cnt-2] from previous cycle
|
||
pmul_a_r <= bram_rd_data;
|
||
// s_hat value from register (combinational index)
|
||
if (loop_j == 2'd0)
|
||
pmul_b_r <= s_hat0_reg[(coeff_cnt - 9'd2) * 12 +: 12];
|
||
else
|
||
pmul_b_r <= s_hat1_reg[(coeff_cnt - 9'd2) * 12 +: 12];
|
||
pmul_valid_i_r <= 1'b1;
|
||
|
||
// Prefetch next A coefficient
|
||
if (coeff_cnt < 9'd257)
|
||
bram_rd_addr_r <= poly_addr(A_BASE + (loop_i * K + loop_j), coeff_cnt[7:0] - 8'd1);
|
||
|
||
coeff_cnt <= coeff_cnt + 9'd1;
|
||
|
||
// After feeding coeff 255 (coeff_cnt reaches 258), done
|
||
if (coeff_cnt == 9'd257) begin
|
||
phase_done <= 1'b1;
|
||
phase_active <= 1'b0;
|
||
coeff_cnt <= 9'd0;
|
||
end
|
||
end
|
||
end
|
||
|
||
// --- S_KG_TMUL_MUL_OUT: Read poly_mul result into BRAM scratch ---
|
||
// Phase 2a: Wait for first pmul_valid_o
|
||
// Phase 2b: Read 256 output coefficients
|
||
if (state_r == S_KG_TMUL_MUL_OUT) begin
|
||
phase_active <= 1'b1;
|
||
phase_done <= 1'b0;
|
||
|
||
if (pmul_valid_o) begin
|
||
// Store to SCRATCH0 (first j term) or SCRATCH1 (subsequent terms)
|
||
if (loop_j == 2'd0) begin
|
||
bram_wr_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
|
||
end else begin
|
||
bram_wr_addr_r <= poly_addr(SCRATCH1, coeff_cnt[7:0]);
|
||
end
|
||
bram_wr_en_r <= 1'b1;
|
||
bram_wr_data_r <= pmul_coeff_out;
|
||
coeff_cnt <= coeff_cnt + 9'd1;
|
||
|
||
if (coeff_cnt == 9'd255) begin
|
||
phase_done <= 1'b1;
|
||
phase_active <= 1'b0;
|
||
coeff_cnt <= 9'd0;
|
||
end
|
||
end
|
||
end
|
||
|
||
// --- S_KG_TMUL_ACCUM: Accumulate SCRATCH0 and SCRATCH1 via poly_arith ---
|
||
// Streams SCRATCH0[k] + SCRATCH1[k] → poly_arith (add) → accumulates
|
||
// into SCRATCH0 (or back into t_hat register for final result).
|
||
//
|
||
// Pipeline: rd SCRATCH0 → (1 cycle) → parith with SCRATCH1 → (1 cycle) → write
|
||
// Total: ~1 + 256 + 2 = 259 cycles for 256 coefficients
|
||
if (state_r == S_KG_TMUL_ACCUM) begin
|
||
phase_active <= 1'b1;
|
||
phase_done <= 1'b0;
|
||
|
||
// coeff_cnt tracks which coeff we're reading from BRAM
|
||
// tmul_out_cnt tracks parith results written
|
||
if (coeff_cnt == 9'd0 && tmul_out_cnt == 9'd0 && !tmul_pipe_valid) begin
|
||
// Start: read SCRATCH0[0] from BRAM
|
||
bram_rd_addr_r <= poly_addr(SCRATCH0, 8'd0);
|
||
coeff_cnt <= 9'd1;
|
||
end else if (coeff_cnt > 9'd0 && coeff_cnt <= 9'd256 && !tmul_pipe_valid) begin
|
||
// bram_rd_data has SCRATCH0[coeff_cnt-1]
|
||
// Need to read SCRATCH1[coeff_cnt-1] next
|
||
// Buffer the SCRATCH0 value, read SCRATCH1
|
||
tmul_pipe_reg <= bram_rd_data; // SCRATCH0 coeff
|
||
tmul_pipe_valid <= 1'b1;
|
||
bram_rd_addr_r <= poly_addr(SCRATCH1, coeff_cnt[7:0] - 8'd1);
|
||
end else if (tmul_pipe_valid && !parith_valid_i_r) begin
|
||
// tmul_pipe_reg has SCRATCH0 coeff
|
||
// bram_rd_data has SCRATCH1 coeff (from previous read)
|
||
parith_a_r <= tmul_pipe_reg; // SCRATCH0 coeff
|
||
parith_b_r <= bram_rd_data; // SCRATCH1 coeff
|
||
parith_mode_r <= 1'b0; // add
|
||
parith_valid_i_r <= 1'b1;
|
||
tmul_pipe_valid <= 1'b0;
|
||
|
||
// Prefetch next SCRATCH0 coefficient (if any remain)
|
||
if (coeff_cnt <= 9'd256)
|
||
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0]);
|
||
coeff_cnt <= coeff_cnt + 9'd1;
|
||
end
|
||
|
||
// Write parith result back to SCRATCH0
|
||
if (parith_valid_o) begin
|
||
bram_wr_en_r <= 1'b1;
|
||
bram_wr_addr_r <= poly_addr(SCRATCH0, tmul_out_cnt[7:0]);
|
||
bram_wr_data_r <= parith_coeff_out;
|
||
tmul_out_cnt <= tmul_out_cnt + 9'd1;
|
||
|
||
if (tmul_out_cnt == 9'd255) begin
|
||
phase_done <= 1'b1;
|
||
phase_active <= 1'b0;
|
||
coeff_cnt <= 9'd0;
|
||
tmul_out_cnt <= 9'd0;
|
||
tmul_pipe_valid <= 1'b0;
|
||
end
|
||
end
|
||
end
|
||
|
||
// --- S_KG_TMUL_ADD_E: Add e_hat[i] to accumulated sum → t_hat_i_reg ---
|
||
// Streams SCRATCH0 (accumulated A·s sum) + e_hat[i] (from BRAM)
|
||
// through poly_arith (add mode), capturing result into t_hat_i_reg.
|
||
//
|
||
// Pipeline: rd e_hat → (1 cycle) → parith with SCRATCH0 → (1 cycle) → t_hat_i_reg
|
||
if (state_r == S_KG_TMUL_ADD_E) begin
|
||
phase_active <= 1'b1;
|
||
phase_done <= 1'b0;
|
||
|
||
// coeff_cnt tracks which e_hat coeff we're reading
|
||
// tmul_out_cnt tracks parith results written to t_hat
|
||
if (coeff_cnt == 9'd0 && tmul_out_cnt == 9'd0 && !tmul_pipe_valid) begin
|
||
// Start: read e_hat[i][0] from BRAM
|
||
bram_rd_addr_r <= poly_addr(E_BASE + loop_i, 8'd0);
|
||
coeff_cnt <= 9'd1;
|
||
end else if (coeff_cnt > 9'd0 && coeff_cnt <= 9'd256 && !tmul_pipe_valid) begin
|
||
// bram_rd_data has e_hat[i][coeff_cnt-1]
|
||
// Buffer e_hat value, read accumulated sum SCRATCH0
|
||
tmul_pipe_reg <= bram_rd_data; // e_hat coeff
|
||
tmul_pipe_valid <= 1'b1;
|
||
bram_rd_addr_r <= poly_addr(SCRATCH0, coeff_cnt[7:0] - 8'd1);
|
||
end else if (tmul_pipe_valid && !parith_valid_i_r) begin
|
||
// tmul_pipe_reg has e_hat coeff
|
||
// bram_rd_data has SCRATCH0 (accumulated sum) coeff
|
||
parith_a_r <= bram_rd_data; // accumulated sum
|
||
parith_b_r <= tmul_pipe_reg; // e_hat coeff
|
||
parith_mode_r <= 1'b0; // add
|
||
parith_valid_i_r <= 1'b1;
|
||
tmul_pipe_valid <= 1'b0;
|
||
|
||
// Prefetch next e_hat coefficient
|
||
if (coeff_cnt <= 9'd256)
|
||
bram_rd_addr_r <= poly_addr(E_BASE + loop_i, coeff_cnt[7:0]);
|
||
coeff_cnt <= coeff_cnt + 9'd1;
|
||
end
|
||
|
||
// Capture parith result into t_hat_i_reg
|
||
if (parith_valid_o) begin
|
||
if (loop_i == 2'd0)
|
||
t_hat0_reg[tmul_out_cnt[7:0] * 12 +: 12] <= parith_coeff_out;
|
||
else
|
||
t_hat1_reg[tmul_out_cnt[7:0] * 12 +: 12] <= parith_coeff_out;
|
||
tmul_out_cnt <= tmul_out_cnt + 9'd1;
|
||
|
||
if (tmul_out_cnt == 9'd255) begin
|
||
phase_done <= 1'b1;
|
||
phase_active <= 1'b0;
|
||
coeff_cnt <= 9'd0;
|
||
tmul_out_cnt <= 9'd0;
|
||
tmul_pipe_valid <= 1'b0;
|
||
// Flag that we're advancing to next row (handled in MUL_LD)
|
||
if (loop_i + 2'd1 < k_r[1:0])
|
||
tmul_adv_row <= 1'b1;
|
||
end
|
||
end
|
||
end
|
||
|
||
// --- S_KG_TMUL_NEXT: Advance loop_j or transition to DONE ---
|
||
if (state_r == S_KG_TMUL_NEXT) begin
|
||
phase_done <= 1'b0;
|
||
if (loop_j + 2'd1 < k_r[1:0]) begin
|
||
loop_j <= loop_j + 2'd1;
|
||
end
|
||
// else: FSM transitions to S_KG_TMUL_ACCUM (handled by next-state logic)
|
||
end
|
||
|
||
// ============================================================
|
||
// KEYGEN: DONE — assign pk_o_r and sk_o_r
|
||
// ============================================================
|
||
if (state_r == S_KG_DONE) begin
|
||
// For k=2, pk = {t_hat1[3071:0], t_hat0[3071:0], rho[255:0]} (padded)
|
||
// t_hat0 goes to bits [12*N-1:0]
|
||
// t_hat1 goes to bits [2*12*N-1 : 12*N]
|
||
// rho embeds at bits above (for k=2, bits [12*2*N+255 : 12*2*N])
|
||
// For simplicity, assign only the lower parts (k=2):
|
||
pk_o_r[(0*N*12) +: N*12] <= t_hat0_reg;
|
||
pk_o_r[(1*N*12) +: N*12] <= t_hat1_reg;
|
||
// rho_reg is embedded in pk encoding (FIPS 203, byte-encoded)
|
||
// Store rho in the upper bits for k=2
|
||
pk_o_r[(2*N*12) +: 256] <= rho_reg;
|
||
|
||
sk_o_r[(0*N*12) +: N*12] <= s_hat0_reg;
|
||
sk_o_r[(1*N*12) +: N*12] <= s_hat1_reg;
|
||
|
||
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_rev),
|
||
.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
|