refactor(kg): registered read-ahead for ST_M load (bank_a + bank_se)

Second per-consumer step of stage 2b. m_ld becomes a read-ahead pointer; both
poly_mul load reads (bank_a A_hat, bank_se s_hat) are registered into
pm_a_rd/pm_b_rd and fed one cycle later (pm_valid delayed 1 cyc), same pattern
as ST_N. 11/11 KAT PASS, byte-exact.
This commit is contained in:
2026-06-28 16:27:00 +08:00
parent 45e07c28e8
commit 9c08273c5f

View File

@@ -483,11 +483,14 @@ module mlkem_top #(
wire [11:0] pm_coeff;
wire pm_vo;
// pm_a: A_hat[i][j] in bank_a (abs slot m_aslot). pm_b: s_hat[j] in
// bank_se (relative slot = m_sslot - slot_s_rt = m_j).
// bank_se (relative slot = m_sslot - slot_s_rt = m_j). m_ld is a read-ahead
// pointer; both bank reads are registered into pm_a_rd/pm_b_rd and fed to
// poly_mul one cycle later (pm_valid delayed 1 cyc), like ST_N.
wire [13:0] pm_a_full = m_aslot*256 + m_ld[7:0];
wire [13:0] pm_b_full = m_j*256 + m_ld[7:0];
wire [11:0] pm_a_in = bank_a [pm_a_full[PA_AW-1:0]];
wire [11:0] pm_b_in = bank_se[pm_b_full[PSE_AW-1:0]];
reg [11:0] pm_a_rd, pm_b_rd; // registered bank reads (sd_bram timing)
wire [11:0] pm_a_in = pm_a_rd;
wire [11:0] pm_b_in = pm_b_rd;
poly_mul_sync u_pmul (
.clk(clk), .rst_n(rst_n),
@@ -561,6 +564,8 @@ module mlkem_top #(
m_loading <= 1'b0;
m_pending <= 1'b0;
pm_valid <= 1'b0;
pm_a_rd <= 12'd0;
pm_b_rd <= 12'd0;
e_poly <= 3'd0;
e_pair <= 8'd0;
e_byte <= 2'd0;
@@ -732,7 +737,9 @@ module mlkem_top #(
end
end
// Arm M stage when N finishes: start first (i=0,j=0) poly_mul load
// Arm M stage when N finishes: prime first (i=0,j=0) poly_mul load.
// m_ld read-ahead pointer; pm_a_rd/pm_b_rd registered, pm_valid
// asserted one cycle after an address is presented (like ST_N).
if (st == ST_N && st_next == ST_M) begin
m_i <= 2'd0;
m_j <= 2'd0;
@@ -740,20 +747,26 @@ module mlkem_top #(
m_oidx <= 8'd0;
m_loading <= 1'b1;
m_pending <= 1'b0;
pm_valid <= 1'b1;
pm_valid <= 1'b0;
end
// ---- ST_M: t_hat[i] = e_hat[i] + sum_j A[i][j] o s_hat[j] ----
if (st == ST_M) begin
// LOAD: stream 256 (A,shat) pairs into poly_mul
if (m_loading && pm_valid && pm_ready) begin
if (m_ld == 9'd255) begin
pm_valid <= 1'b0; // last pair presented
// LOAD: present read-ahead addr to bank_a/bank_se; the pair
// registered last cycle (pm_a_rd/pm_b_rd) is consumed by
// poly_mul this cycle (pm_valid). poly_mul holds ready high
// through LOAD, so a fixed 1-cycle skew suffices.
if (m_loading) begin
if (m_ld == 9'd256) begin
pm_valid <= 1'b0; // 256th pair consumed this cycle
m_loading <= 1'b0;
m_ld <= 9'd0;
m_oidx <= 8'd0;
end else begin
m_ld <= m_ld + 9'd1;
pm_a_rd <= bank_a [pm_a_full[PA_AW-1:0]];
pm_b_rd <= bank_se[pm_b_full[PSE_AW-1:0]];
m_ld <= m_ld + 9'd1;
pm_valid <= 1'b1; // pair presented last cycle is valid
end
end
@@ -776,12 +789,12 @@ module mlkem_top #(
end
end
// Start next (i,j) poly_mul load once core is IDLE again
// Start next (i,j) poly_mul load once core is IDLE again (re-prime)
if (m_pending && pm_ready && !pm_vo) begin
pm_valid <= 1'b1;
m_loading <= 1'b1;
m_ld <= 9'd0;
m_oidx <= 8'd0;
pm_valid <= 1'b0;
m_pending <= 1'b0;
end
end