perf(mlkem): register butterfly inputs to cut the 100 MHz NTT critical path
At mlkem_clk=100 MHz the worst path (WNS -2.14 ns) was coeff_bram read -> butterfly diff (b-a) -> barrett first multiply stage, all in one cycle. The butterfly took its operands combinationally from the BRAM read (unlike poly_mul's basecase, which already registers them). Add an input register stage (a/b/zeta/mode/valid) in butterfly_unit_pipe so the BRAM read and the first multiply land in separate cycles; feed the a/b/mode alignment delay lines from the registered inputs. Butterfly latency 8->9; ntt_core writeback address delay lines deepened 9->10 to match. Verified byte-exact vs NIST KAT: NTT standalone TB 19/19 (fwd+inv), Encaps 9/9, Decaps 9/9, hello_world e2e — all PASS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,8 +53,8 @@ module ntt_core (
|
||||
|
||||
reg rd_fire_r; // issue_fire delayed 1 (BRAM read latency) -> feed
|
||||
// 9-deep writeback address delay lines (BRAM read + 8-stage butterfly).
|
||||
reg [7:0] a0d[0:8]; reg [7:0] b0d[0:8];
|
||||
reg [7:0] a1d[0:8]; reg [7:0] b1d[0:8];
|
||||
reg [7:0] a0d[0:9]; reg [7:0] b0d[0:9];
|
||||
reg [7:0] a1d[0:9]; reg [7:0] b1d[0:9];
|
||||
integer k;
|
||||
|
||||
reg [DW-1:0] coeff_out_r;
|
||||
@@ -128,10 +128,10 @@ module ntt_core (
|
||||
wire wr_en_1 = bf0_valid & ~loading_we;
|
||||
wire wr_en_2 = bf0_valid & ~loading_we;
|
||||
wire wr_en_3 = bf0_valid & ~loading_we;
|
||||
wire [7:0] wr_addr_0 = loading_we ? load_addr : a0d[8];
|
||||
wire [7:0] wr_addr_1 = b0d[8];
|
||||
wire [7:0] wr_addr_2 = a1d[8];
|
||||
wire [7:0] wr_addr_3 = b1d[8];
|
||||
wire [7:0] wr_addr_0 = loading_we ? load_addr : a0d[9];
|
||||
wire [7:0] wr_addr_1 = b0d[9];
|
||||
wire [7:0] wr_addr_2 = a1d[9];
|
||||
wire [7:0] wr_addr_3 = b1d[9];
|
||||
wire [11:0] wr_data_0 = loading_we ? coeff_in : bf0_a_out;
|
||||
wire [11:0] wr_data_1 = bf0_b_out;
|
||||
wire [11:0] wr_data_2 = bf1_a_out;
|
||||
@@ -185,7 +185,7 @@ module ntt_core (
|
||||
layer <= 3'd0; mode_r <= 1'b0;
|
||||
layer_issue_done <= 1'b0; bf_inflight <= 6'd0;
|
||||
rd_fire_r <= 1'b0;
|
||||
for (k = 0; k <= 8; k = k + 1) begin
|
||||
for (k = 0; k <= 9; k = k + 1) begin
|
||||
a0d[k] <= 8'd0; b0d[k] <= 8'd0; a1d[k] <= 8'd0; b1d[k] <= 8'd0;
|
||||
end
|
||||
coeff_out_r <= 12'd0; valid_o_r <= 1'b0;
|
||||
@@ -200,7 +200,7 @@ module ntt_core (
|
||||
|
||||
// writeback address delay lines: sample j-derived addrs at read cycle
|
||||
a0d[0] <= cmp_a0; b0d[0] <= cmp_b0; a1d[0] <= cmp_a1; b1d[0] <= cmp_b1;
|
||||
for (k = 1; k <= 8; k = k + 1) begin
|
||||
for (k = 1; k <= 9; k = k + 1) begin
|
||||
a0d[k] <= a0d[k-1]; b0d[k] <= b0d[k-1];
|
||||
a1d[k] <= a1d[k-1]; b1d[k] <= b1d[k-1];
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user