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.
54 lines
1.4 KiB
Verilog
54 lines
1.4 KiB
Verilog
// pipeline_reg.v - Single pipeline stage with valid/ready handshake
|
|
//
|
|
// valid_i && ready_o -> register data -> valid_o next cycle.
|
|
// ready_o = !valid_o || ready_i.
|
|
//
|
|
// Parameters:
|
|
// DW = data width (default 12)
|
|
//
|
|
// Interface:
|
|
// clk, rst_n - clock, active-low reset
|
|
// data_i, valid_i, ready_o - input side
|
|
// data_o, valid_o, ready_i - output side
|
|
|
|
module pipeline_reg #(parameter DW = 12) (
|
|
input clk,
|
|
input rst_n,
|
|
input [DW-1:0] data_i,
|
|
input valid_i,
|
|
output ready_o,
|
|
output [DW-1:0] data_o,
|
|
output valid_o,
|
|
input ready_i
|
|
);
|
|
|
|
reg valid_r;
|
|
reg [DW-1:0] data_r;
|
|
|
|
// ready_o: accept new data when output slot is free
|
|
assign ready_o = !valid_r || ready_i;
|
|
|
|
// Drive outputs from internal register
|
|
assign valid_o = valid_r;
|
|
assign data_o = data_r;
|
|
|
|
always @(posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
valid_r <= 1'b0;
|
|
data_r <= {DW{1'b0}};
|
|
end else begin
|
|
if (valid_r && ready_i) begin
|
|
// Output consumed, clear valid
|
|
valid_r <= 1'b0;
|
|
end
|
|
|
|
if (valid_i && ready_o) begin
|
|
// Capture new data
|
|
data_r <= data_i;
|
|
valid_r <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|