Wrap mlkem_top in an AXI4 burst slave (mlkem_axi_slave) mapped to the freed FFT slot 6 at 0x1f400000 (virtual 0xbf400000). The core runs on sys_clk/2 (25 MHz); the wrapper handles the clock-domain crossing: start toggle->pulse, wait-stated byte-preload handshake, busy/done sync, and direct readback taps (ek/dk/ct/ss). CPU drives it via a register map (CTRL/STATUS/CONFIG, d/z/msg, preload + readback windows). Wire into soc_top on the existing axiOut_6 nets (no crossbar change), add mlkem_intr on intrpt[3]. Add sdk mlkem_test example running a KeyGen->Encaps->Decaps self-consistency round trip.
68 lines
2.1 KiB
Verilog
68 lines
2.1 KiB
Verilog
// butterfly_unit.v - Cooley-Tukey / Gentleman-Sande butterfly
|
|
//
|
|
// Computes one butterfly operation for NTT or inverse NTT.
|
|
//
|
|
// Parameters:
|
|
// Q = 3329 (prime modulus)
|
|
//
|
|
// Forward NTT (mode=0):
|
|
// t = zeta * b mod Q (via barrett_mul)
|
|
// a_out = (a + t) mod Q
|
|
// b_out = (a - t) mod Q
|
|
//
|
|
// Inverse NTT (mode=1):
|
|
// a_out = (a + b) mod Q
|
|
// diff = (b - a) mod Q (handled as: if b >= a: b-a; else: b-a+Q)
|
|
// b_out = zeta * diff mod Q (via barrett_mul)
|
|
//
|
|
// Pure combinational.
|
|
|
|
module butterfly_unit (
|
|
input [11:0] a,
|
|
input [11:0] b,
|
|
input [11:0] zeta,
|
|
input mode, // 0 = forward NTT, 1 = inverse NTT
|
|
output [11:0] a_out,
|
|
output [11:0] b_out
|
|
);
|
|
localparam Q = 3329;
|
|
|
|
// Barrett modular multiplication: zeta * mul_data mod Q
|
|
wire [11:0] mul_data; // what to multiply with zeta
|
|
wire [11:0] mul_result; // result of barrett_mul(zeta, mul_data)
|
|
|
|
// Forward: mul_data = b, t = zeta * b mod Q
|
|
// Inverse: mul_data = (b - a) mod Q positive
|
|
assign mul_data = (mode == 1'b0) ? b : ((b >= a) ? (b - a) : (b - a + Q));
|
|
|
|
barrett_mul u_barrett (
|
|
.a (zeta),
|
|
.b (mul_data),
|
|
.product (mul_result)
|
|
);
|
|
|
|
// ---- a_out computation ----
|
|
// Forward: a_out = (a + t) mod Q
|
|
// Inverse: a_out = (a + b) mod Q
|
|
wire [12:0] a_sum;
|
|
wire [11:0] add_val;
|
|
assign add_val = (mode == 1'b0) ? mul_result : b;
|
|
assign a_sum = {1'b0, a} + {1'b0, add_val};
|
|
// a_sum - Q produces 13-bit result; we only need lower 12 bits since
|
|
// a_sum >= Q guarantees the result < Q < 2^12
|
|
wire [11:0] a_sub_12;
|
|
assign a_sub_12 = a_sum[11:0] - Q[11:0];
|
|
wire [11:0] a_result = (a_sum >= Q) ? a_sub_12 : a_sum[11:0];
|
|
assign a_out = a_result;
|
|
|
|
// ---- b_out computation ----
|
|
// Forward: b_out = (a - t) mod Q → if a >= t: a-t; else: a-t+Q
|
|
// Inverse: b_out = t (mul_result, which is zeta * (b-a) mod Q)
|
|
wire [11:0] sub_val;
|
|
assign sub_val = mul_result;
|
|
wire [11:0] sub_result;
|
|
assign sub_result = (a >= sub_val) ? (a - sub_val) : (a - sub_val + Q);
|
|
assign b_out = (mode == 1'b0) ? sub_result : mul_result;
|
|
|
|
endmodule
|