feat(enc): Encaps E1 - rho load + A regen + byteDecode12 t_hat

ST_ENC_LOAD: stream rho (32B) from ek_bram[384k..] into rho_r (read-ahead,
1-cyc bram latency). ST_ENC_A: regenerate A_hat via SampleNTT into bank_a
(reuses ST_A datapath, gated on st==ST_A||ST_ENC_A). ST_ENC_TDEC:
byteDecode12 ek[i*384..] -> t_hat[i] into bank_t (5-cycle micro-phase per
3-byte/2-coeff triple; bt write port muxed with ST_M).

Verified (K=2 c0) A_hat (1024 coeffs) + t_hat (512) == KeyGen golden via
dbg_coeff_o; E0 ss==KAT.ss still passes all K/cases (no timeout).
This commit is contained in:
2026-06-29 01:44:50 +08:00
parent 0a8b3dae69
commit 31c967c8a4
2 changed files with 173 additions and 9 deletions

View File

@@ -91,7 +91,50 @@ module tb_mlkem_enc_katK_xsim;
if (errors == 0) $display("K=%0d CASE %0d PASS (E0): ss == KAT.ss", KP, casenum);
else $display("K=%0d CASE %0d FAIL (E0): %0d ss mismatches", KP, casenum, errors);
// ---- E1: verify A_hat (slots 0..K^2-1) and t_hat (slots slot_t..) ----
// The KAT case-0 Encaps reuses ek=pk from KeyGen case-0, so regenerated
// A_hat and decoded t_hat equal KeyGen's golden vectors (K=2 c0 only).
if (KP == 2 && casenum == 0) verify_e1;
$finish;
end
// golden coeff arrays (K=2 c0): A_hat[i][j] and t_hat[i], 256 coeffs each
reg [11:0] ga [0:4*256-1]; // A00,A01,A10,A11 concatenated (slot*256+idx)
reg [11:0] gt [0:2*256-1]; // t_hat0, t_hat1
integer ce, slot, idx;
task verify_e1;
begin
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_Ahat_0_0.hex", ga, 0, 255);
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_Ahat_0_1.hex", ga, 256, 511);
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_Ahat_1_0.hex", ga, 512, 767);
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_Ahat_1_1.hex", ga, 768, 1023);
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_that_0.hex", gt, 0, 255);
$readmemh("test_framework/modules/mlkem_keygen/golden/c000_that_1.hex", gt, 256, 511);
ce = 0;
// A_hat: slots 0..3 (i*k+j)
for (slot = 0; slot < 4; slot = slot + 1)
for (idx = 0; idx < 256; idx = idx + 1) begin
dbg_slot_i = slot[3:0]; dbg_idx_i = idx[7:0];
@(posedge clk); @(posedge clk); @(posedge clk);
if (dbg_coeff_o !== ga[slot*256+idx]) begin
if (ce < 8) $display(" A[s%0d,%0d] got=%03x exp=%03x", slot, idx, dbg_coeff_o, ga[slot*256+idx]);
ce = ce + 1;
end
end
// t_hat: slots slot_t_rt(=8) .. +1
for (slot = 0; slot < 2; slot = slot + 1)
for (idx = 0; idx < 256; idx = idx + 1) begin
dbg_slot_i = (8+slot); dbg_idx_i = idx[7:0];
@(posedge clk); @(posedge clk); @(posedge clk);
if (dbg_coeff_o !== gt[slot*256+idx]) begin
if (ce < 12) $display(" T[%0d,%0d] got=%03x exp=%03x", slot, idx, dbg_coeff_o, gt[slot*256+idx]);
ce = ce + 1;
end
end
if (ce == 0) $display("K=2 CASE 0 PASS (E1): A_hat (1024) + t_hat (512) == KeyGen golden");
else $display("K=2 CASE 0 FAIL (E1): %0d coeff mismatches", ce);
end
endtask
initial begin #120000000; $display("FAIL: global timeout"); $finish; end
endmodule