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.
51 lines
1.3 KiB
Verilog
51 lines
1.3 KiB
Verilog
// rng_sync.v - 256-bit Galois LFSR PRNG (taps: 255,253,252,247,0)
|
|
module rng_sync #(
|
|
parameter [255:0] SEED = 256'hDEADBEEFCAFEBABEFEEDFACEDECAFBAD1234567887654321ABCDEF010FEDCBA9
|
|
) (
|
|
input clk,
|
|
input rst_n,
|
|
input valid_i,
|
|
output ready_o,
|
|
output [255:0] data_o,
|
|
output valid_o,
|
|
input ready_i
|
|
);
|
|
|
|
reg [255:0] state;
|
|
reg valid_r;
|
|
reg [255:0] lfsr_next;
|
|
wire feedback;
|
|
integer i;
|
|
|
|
assign ready_o = 1'b1;
|
|
assign valid_o = valid_r;
|
|
assign data_o = state;
|
|
assign feedback = state[0];
|
|
|
|
always @(*) begin
|
|
for (i = 0; i < 255; i = i + 1)
|
|
lfsr_next[i] = state[i+1];
|
|
lfsr_next[255] = feedback;
|
|
lfsr_next[254] = lfsr_next[254] ^ feedback;
|
|
lfsr_next[252] = lfsr_next[252] ^ feedback;
|
|
lfsr_next[251] = lfsr_next[251] ^ feedback;
|
|
lfsr_next[246] = lfsr_next[246] ^ feedback;
|
|
end
|
|
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
state <= SEED;
|
|
valid_r <= 1'b0;
|
|
end else begin
|
|
if (valid_r && ready_i)
|
|
valid_r <= 1'b0;
|
|
|
|
if (valid_i) begin
|
|
state <= lfsr_next;
|
|
valid_r <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|