refactor(kg): merge G/H into single shared sha3_top (4->3 keccak_core)

ST_G (single-block G) and ST_H (multi-block H(ek)) are disjoint FSM phases,
so one sha3_top serves both: mb_en and ready_i are phase-muxed, h_hash/h_vo
alias the shared core's outputs. Removes the dedicated u_sha3_h instance and
its keccak_core. 11/11 KAT PASS (K=2 c0-4, K=3/4 c0-2), byte-exact, 0 file-not-found.
This commit is contained in:
2026-06-28 15:22:28 +08:00
parent 5a7d5d6a47
commit 851630f73c

View File

@@ -179,20 +179,29 @@ module mlkem_top #(
reg sha3_ack; // consumer ready for hash
wire [511:0] g_data = {248'b0, 5'b0, k_r, d_i}; // data_i[263:256]=k, [255:0]=d
// ---- single shared sha3_top serving BOTH G and H ----
// G (ST_G) uses single-block mode (mb_en=0); H(ek) (ST_H) uses the
// multi-block absorb path (mb_en=1). These phases are disjoint in the
// top FSM, so one sha3_top (one keccak_core) is sufficient. mb_en and
// ready_i are muxed by phase; data_i/mode only matter while mb_en=0.
wire sha3_mb_en = (st == ST_H);
sha3_top u_sha3 (
.clk(clk), .rst_n(rst_n),
.mode(2'b00), // G = SHA3-512
.mode(2'b00), // G = SHA3-512 (only used when mb_en=0)
.data_i(g_data),
.valid_i(sha3_valid),
.ready_o(sha3_ready),
.hash_o(sha3_hash),
.valid_o(sha3_vo),
.ready_i(sha3_ack),
.mb_en(1'b0), .mb_block_i(1088'b0), .mb_valid_i(1'b0),
.mb_last_i(1'b0), .mb_ready_o()
.ready_i(sha3_mb_en ? h_ack : sha3_ack),
.mb_en(sha3_mb_en),
.mb_block_i(h_block_r),
.mb_valid_i(h_mbvalid),
.mb_last_i(h_mblast),
.mb_ready_o(h_mbready)
);
// ---- second sha3_top dedicated to multi-block H(ek) (SHA3-256, 800B->6 blk) ----
// ---- multi-block H(ek) state (SHA3-256, 6/9/12 blocks); fed to shared u_sha3 ----
reg [1087:0] h_block_r; // current pre-padded rate block
reg h_mbvalid;
reg h_mblast;
@@ -213,21 +222,11 @@ module mlkem_top #(
reg [7:0] h_wb_pad; // pad constant to use if g is out of ek range
reg h_wb_inek; // 1 if g is within ek range (use BRAM data)
sha3_top u_sha3_h (
.clk(clk), .rst_n(rst_n),
.mode(2'b01), // unused in mb mode
.data_i(512'b0),
.valid_i(1'b0),
.ready_o(),
.hash_o(h_hash),
.valid_o(h_vo),
.ready_i(h_ack),
.mb_en(1'b1),
.mb_block_i(h_block_r),
.mb_valid_i(h_mbvalid),
.mb_last_i(h_mblast),
.mb_ready_o(h_mbready)
);
// h_hash / h_vo are now served by the shared u_sha3 above (mb_en=1 during
// ST_H). They alias the single core's outputs; the H consumer logic below
// already gates on st==ST_H, and u_sha3's valid_o/hash_o are mb-selected.
assign h_hash = sha3_hash;
assign h_vo = sha3_vo;
// SHA3-256 over ek (ek_bytes_rt bytes): rate=136. Padded length = h_nblk_rt*136.
// pad: byte ek_bytes_rt = 0x06 (domain + first pad bit), last byte |= 0x80.