mlkem test diagnostics and allocator updates
This commit is contained in:
@@ -4,13 +4,15 @@
|
||||
// maps do not overlap:
|
||||
// ML-KEM: 0x0000..0x3fff
|
||||
// FFT: 0x8000..0xcfff
|
||||
// PRNG: 0xd000..0xd0ff
|
||||
// Route the low ML-KEM block to ML-KEM, the high FFT block to FFT, and the
|
||||
// following 0xdxxx block to PRNG.
|
||||
// Route the low ML-KEM block to ML-KEM and the remaining accelerator window to
|
||||
// FFT.
|
||||
module fft_mlkem_axi_slave (
|
||||
input clk,
|
||||
input resetn,
|
||||
|
||||
input mlkem_clk,
|
||||
input mlkem_resetn,
|
||||
|
||||
input [4:0] s_axi_awid,
|
||||
input [31:0] s_axi_awaddr,
|
||||
input [7:0] s_axi_awlen,
|
||||
@@ -58,17 +60,12 @@ module fft_mlkem_axi_slave (
|
||||
|
||||
localparam SEL_MLKEM = 2'd0;
|
||||
localparam SEL_FFT = 2'd1;
|
||||
localparam SEL_PRNG = 2'd2;
|
||||
|
||||
wire aw_to_mlkem = (s_axi_awaddr[15:12] <= 4'h3);
|
||||
wire aw_to_prng = (s_axi_awaddr[15:12] == 4'hd);
|
||||
wire ar_to_mlkem = (s_axi_araddr[15:12] <= 4'h3);
|
||||
wire ar_to_prng = (s_axi_araddr[15:12] == 4'hd);
|
||||
|
||||
wire [1:0] aw_sel = aw_to_mlkem ? SEL_MLKEM :
|
||||
aw_to_prng ? SEL_PRNG : SEL_FFT;
|
||||
wire [1:0] ar_sel = ar_to_mlkem ? SEL_MLKEM :
|
||||
ar_to_prng ? SEL_PRNG : SEL_FFT;
|
||||
wire [1:0] aw_sel = aw_to_mlkem ? SEL_MLKEM : SEL_FFT;
|
||||
wire [1:0] ar_sel = ar_to_mlkem ? SEL_MLKEM : SEL_FFT;
|
||||
|
||||
reg [1:0] write_sel;
|
||||
reg write_active;
|
||||
@@ -83,6 +80,44 @@ module fft_mlkem_axi_slave (
|
||||
wire [31:0] mlkem_rdata;
|
||||
wire [1:0] mlkem_rresp;
|
||||
|
||||
wire mlkem_m_awvalid;
|
||||
wire mlkem_m_awready;
|
||||
wire [31:0] mlkem_m_awaddr;
|
||||
wire [4:0] mlkem_m_awid;
|
||||
wire [7:0] mlkem_m_awlen;
|
||||
wire [2:0] mlkem_m_awsize;
|
||||
wire [1:0] mlkem_m_awburst;
|
||||
wire [0:0] mlkem_m_awlock;
|
||||
wire [3:0] mlkem_m_awcache;
|
||||
wire [2:0] mlkem_m_awprot;
|
||||
wire mlkem_m_wvalid;
|
||||
wire mlkem_m_wready;
|
||||
wire [31:0] mlkem_m_wdata;
|
||||
wire [3:0] mlkem_m_wstrb;
|
||||
wire mlkem_m_wlast;
|
||||
wire mlkem_m_bvalid;
|
||||
wire mlkem_m_bready;
|
||||
wire [4:0] mlkem_m_bid;
|
||||
wire [1:0] mlkem_m_bresp;
|
||||
wire mlkem_m_arvalid;
|
||||
wire mlkem_m_arready;
|
||||
wire [31:0] mlkem_m_araddr;
|
||||
wire [4:0] mlkem_m_arid;
|
||||
wire [7:0] mlkem_m_arlen;
|
||||
wire [2:0] mlkem_m_arsize;
|
||||
wire [1:0] mlkem_m_arburst;
|
||||
wire [0:0] mlkem_m_arlock;
|
||||
wire [3:0] mlkem_m_arcache;
|
||||
wire [2:0] mlkem_m_arprot;
|
||||
wire mlkem_m_rvalid;
|
||||
wire mlkem_m_rready;
|
||||
wire [31:0] mlkem_m_rdata;
|
||||
wire [4:0] mlkem_m_rid;
|
||||
wire [1:0] mlkem_m_rresp;
|
||||
wire mlkem_m_rlast;
|
||||
wire mlkem_intr_m;
|
||||
(* async_reg = "true" *) reg [1:0] mlkem_intr_sync;
|
||||
|
||||
wire fft_awready, fft_wready, fft_bvalid;
|
||||
wire [4:0] fft_bid;
|
||||
wire [1:0] fft_bresp;
|
||||
@@ -91,52 +126,33 @@ module fft_mlkem_axi_slave (
|
||||
wire [31:0] fft_rdata;
|
||||
wire [1:0] fft_rresp;
|
||||
|
||||
wire prng_awready, prng_wready, prng_bvalid;
|
||||
wire [4:0] prng_bid;
|
||||
wire [1:0] prng_bresp;
|
||||
wire prng_arready, prng_rvalid, prng_rlast;
|
||||
wire [4:0] prng_rid;
|
||||
wire [31:0] prng_rdata;
|
||||
wire [1:0] prng_rresp;
|
||||
|
||||
wire [1:0] sel_w = write_active ? write_sel : aw_sel;
|
||||
wire [1:0] sel_r = read_active ? read_sel : ar_sel;
|
||||
|
||||
assign s_axi_awready = !write_active && (
|
||||
(aw_sel == SEL_MLKEM) ? mlkem_awready :
|
||||
(aw_sel == SEL_PRNG) ? prng_awready :
|
||||
fft_awready);
|
||||
assign s_axi_wready = (sel_w == SEL_MLKEM) ? mlkem_wready :
|
||||
(sel_w == SEL_PRNG) ? prng_wready :
|
||||
fft_wready;
|
||||
assign s_axi_bvalid = (sel_w == SEL_MLKEM) ? mlkem_bvalid :
|
||||
(sel_w == SEL_PRNG) ? prng_bvalid :
|
||||
fft_bvalid;
|
||||
assign s_axi_bid = (sel_w == SEL_MLKEM) ? mlkem_bid :
|
||||
(sel_w == SEL_PRNG) ? prng_bid :
|
||||
fft_bid;
|
||||
assign s_axi_bresp = (sel_w == SEL_MLKEM) ? mlkem_bresp :
|
||||
(sel_w == SEL_PRNG) ? prng_bresp :
|
||||
fft_bresp;
|
||||
|
||||
assign s_axi_arready = !read_active && (
|
||||
(ar_sel == SEL_MLKEM) ? mlkem_arready :
|
||||
(ar_sel == SEL_PRNG) ? prng_arready :
|
||||
fft_arready);
|
||||
assign s_axi_rvalid = (sel_r == SEL_MLKEM) ? mlkem_rvalid :
|
||||
(sel_r == SEL_PRNG) ? prng_rvalid :
|
||||
fft_rvalid;
|
||||
assign s_axi_rlast = (sel_r == SEL_MLKEM) ? mlkem_rlast :
|
||||
(sel_r == SEL_PRNG) ? prng_rlast :
|
||||
fft_rlast;
|
||||
assign s_axi_rid = (sel_r == SEL_MLKEM) ? mlkem_rid :
|
||||
(sel_r == SEL_PRNG) ? prng_rid :
|
||||
fft_rid;
|
||||
assign s_axi_rdata = (sel_r == SEL_MLKEM) ? mlkem_rdata :
|
||||
(sel_r == SEL_PRNG) ? prng_rdata :
|
||||
fft_rdata;
|
||||
assign s_axi_rresp = (sel_r == SEL_MLKEM) ? mlkem_rresp :
|
||||
(sel_r == SEL_PRNG) ? prng_rresp :
|
||||
fft_rresp;
|
||||
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
@@ -162,52 +178,140 @@ module fft_mlkem_axi_slave (
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (!resetn)
|
||||
mlkem_intr_sync <= 2'b00;
|
||||
else
|
||||
mlkem_intr_sync <= {mlkem_intr_sync[0], mlkem_intr_m};
|
||||
end
|
||||
|
||||
assign mlkem_intr = mlkem_intr_sync[1];
|
||||
|
||||
Axi_CDC u_mlkem_axi_cdc (
|
||||
.axiInClk (clk),
|
||||
.axiInRstn (resetn),
|
||||
.axiOutClk (mlkem_clk),
|
||||
.axiOutRstn (mlkem_resetn),
|
||||
|
||||
.axiIn_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_MLKEM)),
|
||||
.axiIn_awready (mlkem_awready),
|
||||
.axiIn_awaddr (s_axi_awaddr),
|
||||
.axiIn_awid (s_axi_awid),
|
||||
.axiIn_awlen (s_axi_awlen),
|
||||
.axiIn_awsize (s_axi_awsize),
|
||||
.axiIn_awburst (s_axi_awburst),
|
||||
.axiIn_awlock (s_axi_awlock),
|
||||
.axiIn_awcache (s_axi_awcache),
|
||||
.axiIn_awprot (s_axi_awprot),
|
||||
.axiIn_wvalid (s_axi_wvalid && (sel_w == SEL_MLKEM)),
|
||||
.axiIn_wready (mlkem_wready),
|
||||
.axiIn_wdata (s_axi_wdata),
|
||||
.axiIn_wstrb (s_axi_wstrb),
|
||||
.axiIn_wlast (s_axi_wlast),
|
||||
.axiIn_bvalid (mlkem_bvalid),
|
||||
.axiIn_bready (s_axi_bready && (sel_w == SEL_MLKEM)),
|
||||
.axiIn_bid (mlkem_bid),
|
||||
.axiIn_bresp (mlkem_bresp),
|
||||
.axiIn_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_MLKEM)),
|
||||
.axiIn_arready (mlkem_arready),
|
||||
.axiIn_araddr (s_axi_araddr),
|
||||
.axiIn_arid (s_axi_arid),
|
||||
.axiIn_arlen (s_axi_arlen),
|
||||
.axiIn_arsize (s_axi_arsize),
|
||||
.axiIn_arburst (s_axi_arburst),
|
||||
.axiIn_arlock (s_axi_arlock),
|
||||
.axiIn_arcache (s_axi_arcache),
|
||||
.axiIn_arprot (s_axi_arprot),
|
||||
.axiIn_rvalid (mlkem_rvalid),
|
||||
.axiIn_rready (s_axi_rready && (sel_r == SEL_MLKEM)),
|
||||
.axiIn_rdata (mlkem_rdata),
|
||||
.axiIn_rid (mlkem_rid),
|
||||
.axiIn_rresp (mlkem_rresp),
|
||||
.axiIn_rlast (mlkem_rlast),
|
||||
|
||||
.axiOut_awvalid (mlkem_m_awvalid),
|
||||
.axiOut_awready (mlkem_m_awready),
|
||||
.axiOut_awaddr (mlkem_m_awaddr),
|
||||
.axiOut_awid (mlkem_m_awid),
|
||||
.axiOut_awlen (mlkem_m_awlen),
|
||||
.axiOut_awsize (mlkem_m_awsize),
|
||||
.axiOut_awburst (mlkem_m_awburst),
|
||||
.axiOut_awlock (mlkem_m_awlock),
|
||||
.axiOut_awcache (mlkem_m_awcache),
|
||||
.axiOut_awprot (mlkem_m_awprot),
|
||||
.axiOut_wvalid (mlkem_m_wvalid),
|
||||
.axiOut_wready (mlkem_m_wready),
|
||||
.axiOut_wdata (mlkem_m_wdata),
|
||||
.axiOut_wstrb (mlkem_m_wstrb),
|
||||
.axiOut_wlast (mlkem_m_wlast),
|
||||
.axiOut_bvalid (mlkem_m_bvalid),
|
||||
.axiOut_bready (mlkem_m_bready),
|
||||
.axiOut_bid (mlkem_m_bid),
|
||||
.axiOut_bresp (mlkem_m_bresp),
|
||||
.axiOut_arvalid (mlkem_m_arvalid),
|
||||
.axiOut_arready (mlkem_m_arready),
|
||||
.axiOut_araddr (mlkem_m_araddr),
|
||||
.axiOut_arid (mlkem_m_arid),
|
||||
.axiOut_arlen (mlkem_m_arlen),
|
||||
.axiOut_arsize (mlkem_m_arsize),
|
||||
.axiOut_arburst (mlkem_m_arburst),
|
||||
.axiOut_arlock (mlkem_m_arlock),
|
||||
.axiOut_arcache (mlkem_m_arcache),
|
||||
.axiOut_arprot (mlkem_m_arprot),
|
||||
.axiOut_rvalid (mlkem_m_rvalid),
|
||||
.axiOut_rready (mlkem_m_rready),
|
||||
.axiOut_rdata (mlkem_m_rdata),
|
||||
.axiOut_rid (mlkem_m_rid),
|
||||
.axiOut_rresp (mlkem_m_rresp),
|
||||
.axiOut_rlast (mlkem_m_rlast)
|
||||
);
|
||||
|
||||
mlkem_axi_slave u_mlkem_axi_slave (
|
||||
.clk (clk),
|
||||
.resetn (resetn),
|
||||
.clk (mlkem_clk),
|
||||
.resetn (mlkem_resetn),
|
||||
|
||||
.s_axi_awid (s_axi_awid),
|
||||
.s_axi_awaddr (s_axi_awaddr),
|
||||
.s_axi_awlen (s_axi_awlen),
|
||||
.s_axi_awsize (s_axi_awsize),
|
||||
.s_axi_awburst (s_axi_awburst),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awcache (s_axi_awcache),
|
||||
.s_axi_awprot (s_axi_awprot),
|
||||
.s_axi_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_MLKEM)),
|
||||
.s_axi_awready (mlkem_awready),
|
||||
.s_axi_awid (mlkem_m_awid),
|
||||
.s_axi_awaddr (mlkem_m_awaddr),
|
||||
.s_axi_awlen (mlkem_m_awlen),
|
||||
.s_axi_awsize (mlkem_m_awsize),
|
||||
.s_axi_awburst (mlkem_m_awburst),
|
||||
.s_axi_awlock (mlkem_m_awlock[0]),
|
||||
.s_axi_awcache (mlkem_m_awcache),
|
||||
.s_axi_awprot (mlkem_m_awprot),
|
||||
.s_axi_awvalid (mlkem_m_awvalid),
|
||||
.s_axi_awready (mlkem_m_awready),
|
||||
|
||||
.s_axi_wid (s_axi_wid),
|
||||
.s_axi_wdata (s_axi_wdata),
|
||||
.s_axi_wstrb (s_axi_wstrb),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wvalid (s_axi_wvalid && (sel_w == SEL_MLKEM)),
|
||||
.s_axi_wready (mlkem_wready),
|
||||
.s_axi_wid (5'd0),
|
||||
.s_axi_wdata (mlkem_m_wdata),
|
||||
.s_axi_wstrb (mlkem_m_wstrb),
|
||||
.s_axi_wlast (mlkem_m_wlast),
|
||||
.s_axi_wvalid (mlkem_m_wvalid),
|
||||
.s_axi_wready (mlkem_m_wready),
|
||||
|
||||
.s_axi_bid (mlkem_bid),
|
||||
.s_axi_bresp (mlkem_bresp),
|
||||
.s_axi_bvalid (mlkem_bvalid),
|
||||
.s_axi_bready (s_axi_bready && (sel_w == SEL_MLKEM)),
|
||||
.s_axi_bid (mlkem_m_bid),
|
||||
.s_axi_bresp (mlkem_m_bresp),
|
||||
.s_axi_bvalid (mlkem_m_bvalid),
|
||||
.s_axi_bready (mlkem_m_bready),
|
||||
|
||||
.s_axi_arid (s_axi_arid),
|
||||
.s_axi_araddr (s_axi_araddr),
|
||||
.s_axi_arlen (s_axi_arlen),
|
||||
.s_axi_arsize (s_axi_arsize),
|
||||
.s_axi_arburst (s_axi_arburst),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arcache (s_axi_arcache),
|
||||
.s_axi_arprot (s_axi_arprot),
|
||||
.s_axi_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_MLKEM)),
|
||||
.s_axi_arready (mlkem_arready),
|
||||
.s_axi_arid (mlkem_m_arid),
|
||||
.s_axi_araddr (mlkem_m_araddr),
|
||||
.s_axi_arlen (mlkem_m_arlen),
|
||||
.s_axi_arsize (mlkem_m_arsize),
|
||||
.s_axi_arburst (mlkem_m_arburst),
|
||||
.s_axi_arlock (mlkem_m_arlock[0]),
|
||||
.s_axi_arcache (mlkem_m_arcache),
|
||||
.s_axi_arprot (mlkem_m_arprot),
|
||||
.s_axi_arvalid (mlkem_m_arvalid),
|
||||
.s_axi_arready (mlkem_m_arready),
|
||||
|
||||
.s_axi_rid (mlkem_rid),
|
||||
.s_axi_rdata (mlkem_rdata),
|
||||
.s_axi_rresp (mlkem_rresp),
|
||||
.s_axi_rlast (mlkem_rlast),
|
||||
.s_axi_rvalid (mlkem_rvalid),
|
||||
.s_axi_rready (s_axi_rready && (sel_r == SEL_MLKEM)),
|
||||
.s_axi_rid (mlkem_m_rid),
|
||||
.s_axi_rdata (mlkem_m_rdata),
|
||||
.s_axi_rresp (mlkem_m_rresp),
|
||||
.s_axi_rlast (mlkem_m_rlast),
|
||||
.s_axi_rvalid (mlkem_m_rvalid),
|
||||
.s_axi_rready (mlkem_m_rready),
|
||||
|
||||
.intr (mlkem_intr)
|
||||
.intr (mlkem_intr_m)
|
||||
);
|
||||
|
||||
fft_controller u_fft_controller (
|
||||
@@ -258,50 +362,4 @@ module fft_mlkem_axi_slave (
|
||||
.fft_finish (fft_finish)
|
||||
);
|
||||
|
||||
prng_axi_slave u_prng_axi_slave (
|
||||
.clk (clk),
|
||||
.resetn (resetn),
|
||||
|
||||
.s_axi_awid (s_axi_awid),
|
||||
.s_axi_awaddr (s_axi_awaddr),
|
||||
.s_axi_awlen (s_axi_awlen),
|
||||
.s_axi_awsize (s_axi_awsize),
|
||||
.s_axi_awburst (s_axi_awburst),
|
||||
.s_axi_awlock (s_axi_awlock),
|
||||
.s_axi_awcache (s_axi_awcache),
|
||||
.s_axi_awprot (s_axi_awprot),
|
||||
.s_axi_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_PRNG)),
|
||||
.s_axi_awready (prng_awready),
|
||||
|
||||
.s_axi_wid (s_axi_wid),
|
||||
.s_axi_wdata (s_axi_wdata),
|
||||
.s_axi_wstrb (s_axi_wstrb),
|
||||
.s_axi_wlast (s_axi_wlast),
|
||||
.s_axi_wvalid (s_axi_wvalid && (sel_w == SEL_PRNG)),
|
||||
.s_axi_wready (prng_wready),
|
||||
|
||||
.s_axi_bid (prng_bid),
|
||||
.s_axi_bresp (prng_bresp),
|
||||
.s_axi_bvalid (prng_bvalid),
|
||||
.s_axi_bready (s_axi_bready && (sel_w == SEL_PRNG)),
|
||||
|
||||
.s_axi_arid (s_axi_arid),
|
||||
.s_axi_araddr (s_axi_araddr),
|
||||
.s_axi_arlen (s_axi_arlen),
|
||||
.s_axi_arsize (s_axi_arsize),
|
||||
.s_axi_arburst (s_axi_arburst),
|
||||
.s_axi_arlock (s_axi_arlock),
|
||||
.s_axi_arcache (s_axi_arcache),
|
||||
.s_axi_arprot (s_axi_arprot),
|
||||
.s_axi_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_PRNG)),
|
||||
.s_axi_arready (prng_arready),
|
||||
|
||||
.s_axi_rid (prng_rid),
|
||||
.s_axi_rdata (prng_rdata),
|
||||
.s_axi_rresp (prng_rresp),
|
||||
.s_axi_rlast (prng_rlast),
|
||||
.s_axi_rvalid (prng_rvalid),
|
||||
.s_axi_rready (s_axi_rready && (sel_r == SEL_PRNG))
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
// mlkem_axi_slave.v — AXI4 (burst) slave wrapper for the ML-KEM core.
|
||||
// Makes the ML-KEM accelerator (KeyGen / Encaps / Decaps) CPU-controllable.
|
||||
//
|
||||
// The bus runs at sys_clk (50 MHz). The ML-KEM core cannot close timing at
|
||||
// 50 MHz, so it is clocked by mlkem_clk = sys_clk / 2 (25 MHz), produced by a
|
||||
// toggle flip-flop in this wrapper. mlkem_clk is a phase-aligned synchronous
|
||||
// divide of sys_clk; every signal crossing between the two domains still goes
|
||||
// through an explicit synchronizer or toggle handshake.
|
||||
// NOTE (FPGA): for real silicon route mlkem_clk through a BUFG/BUFGCE rather
|
||||
// than a logic-generated net; kept as a plain toggle here for portability.
|
||||
// This slave is placed behind an AXI clock-domain converter. Its AXI side and
|
||||
// mlkem_top both run in mlkem_clk; sys_clk masters reach it through Axi_CDC in
|
||||
// fft_mlkem_axi_slave.
|
||||
//
|
||||
// Register map (byte offsets from base, e.g. virtual 0xbf400000):
|
||||
// 0x000 CTRL W bit0 = start (launches op selected in CONFIG)
|
||||
// bit1 = soft_reset (resets ML-KEM core state)
|
||||
// 0x004 STATUS R bit0 busy, bit1 done, bit2 preload_busy
|
||||
// W1C write bit1=1 to clear the latched done flag
|
||||
// 0x008 CONFIG RW [2:0] k (2/3/4), [5:4] op (0=KeyGen 1=Encaps 2=Decaps)
|
||||
@@ -27,9 +24,11 @@
|
||||
// 0x1000..0x1FFF EK W: preload ek_in, R: read generated ek
|
||||
// 0x2000..0x2FFF DK W: preload dk_in, R: read generated full dk
|
||||
// 0x3000..0x3FFF CT W: preload c_in, R: read generated ciphertext
|
||||
|
||||
(* use_dsp = "no" *)
|
||||
module mlkem_axi_slave (
|
||||
input clk, // sys_clk (AXI bus clock, 50 MHz)
|
||||
input resetn, // sys_resetn (active low, already synchronized)
|
||||
input clk, // mlkem_clk AXI-side clock after Axi_CDC
|
||||
input resetn, // mlkem_resetn, active low
|
||||
|
||||
// AXI Write Address Channel
|
||||
input [4:0] s_axi_awid,
|
||||
@@ -153,20 +152,7 @@ module mlkem_axi_slave (
|
||||
endfunction
|
||||
|
||||
// ==========================================
|
||||
// mlkem_clk = sys_clk / 2 (25 MHz) via toggle FF.
|
||||
// ==========================================
|
||||
reg mlkem_clk;
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (!resetn) mlkem_clk <= 1'b0;
|
||||
else mlkem_clk <= ~mlkem_clk;
|
||||
end
|
||||
// Reset for the mlkem domain: reuse sys_resetn (async-assert, and the core's
|
||||
// own rst_n is sampled on mlkem_clk edges).
|
||||
wire mlkem_rstn = resetn;
|
||||
|
||||
// ==========================================
|
||||
// sys_clk-domain config / data registers (quasi-static; fed to the core
|
||||
// combinationally — written long before start, stable across the op).
|
||||
// AXI/core clock-domain config / data registers.
|
||||
// ==========================================
|
||||
reg [2:0] cfg_k; // 2/3/4
|
||||
reg [1:0] cfg_op; // 0=KeyGen 1=Encaps 2=Decaps
|
||||
@@ -188,55 +174,79 @@ module mlkem_axi_slave (
|
||||
reg [11:0] rdb_addr; // output byte index
|
||||
|
||||
// ==========================================
|
||||
// CDC: start pulse (sys toggle -> mlkem edge-detect -> 1-cyc start_i)
|
||||
// Start pulse: CTRL.start flips a toggle, edge-detected into start_i.
|
||||
// ==========================================
|
||||
reg start_tg; // sys-domain toggle, flips on CTRL.start write
|
||||
reg [2:0] start_sync; // mlkem-domain 2FF sync (+1 for edge)
|
||||
wire mlkem_start = start_sync[2] ^ start_sync[1]; // 1 mlkem_clk pulse
|
||||
wire mlkem_start = start_sync[2] ^ start_sync[1]; // 1 clk pulse
|
||||
|
||||
// ==========================================
|
||||
// CDC: busy / done back to sys
|
||||
// Software reset pulse: CTRL.soft_reset flips a toggle and stretches reset.
|
||||
// ==========================================
|
||||
wire core_busy; // busy_o (mlkem domain)
|
||||
wire core_done; // done_o pulse (mlkem domain)
|
||||
reg done_latch; // sticky done in mlkem domain
|
||||
reg [1:0] busy_sync; // -> sys
|
||||
reg [1:0] done_sync; // -> sys
|
||||
// done-clear: sys toggle -> mlkem edge -> clears done_latch
|
||||
reg dclr_tg; // sys-domain toggle (STATUS W1C of done)
|
||||
reg [2:0] dclr_sync; // mlkem-domain 2FF sync (+1 for edge)
|
||||
reg srst_tg; // flips on CTRL.soft_reset
|
||||
reg [2:0] srst_sync; // edge detector shift register
|
||||
reg [3:0] srst_cnt; // reset stretcher in clk domain
|
||||
wire mlkem_srst_edge = srst_sync[2] ^ srst_sync[1];
|
||||
wire mlkem_srst_active = (srst_cnt != 4'd0);
|
||||
wire core_resetn = resetn && !mlkem_srst_active;
|
||||
|
||||
// ==========================================
|
||||
// Busy / done status.
|
||||
// ==========================================
|
||||
wire core_busy;
|
||||
wire core_done;
|
||||
reg done_latch;
|
||||
reg [1:0] busy_sync;
|
||||
reg [1:0] done_sync;
|
||||
// done-clear: STATUS W1C flips a toggle, edge-detected to clear done_latch.
|
||||
reg dclr_tg;
|
||||
reg [2:0] dclr_sync;
|
||||
wire mlkem_dclr = dclr_sync[2] ^ dclr_sync[1];
|
||||
|
||||
// ==========================================
|
||||
// CDC: preload byte write handshake.
|
||||
// sys: latch {sel,addr,byte}, flip pre_req_tg, hold wready low.
|
||||
// mlkem: 2FF sync pre_req_tg, on edge pulse the selected *_in_we 1 cycle,
|
||||
// flip pre_ack_tg.
|
||||
// sys: 2FF sync pre_ack_tg, on edge release the bus (addr++).
|
||||
// Preload byte write handshake.
|
||||
// Latch {sel,addr,byte}, flip pre_req_tg, pulse the selected *_in_we for
|
||||
// one cycle, then flip pre_ack_tg to release the AXI write beat.
|
||||
// ==========================================
|
||||
reg pre_req_tg; // sys toggle: a byte is pending
|
||||
reg [2:0] pre_req_sync; // mlkem 2FF (+1 for edge)
|
||||
reg pre_req_tg; // a byte is pending
|
||||
reg [2:0] pre_req_sync; // edge detector shift register
|
||||
wire mlkem_pre_we = pre_req_sync[2] ^ pre_req_sync[1];
|
||||
reg pre_ack_tg; // mlkem toggle: byte consumed
|
||||
reg [2:0] pre_ack_sync; // sys 2FF (+1 for edge)
|
||||
reg pre_ack_tg; // byte consumed
|
||||
reg [2:0] pre_ack_sync; // edge detector shift register
|
||||
wire pre_ack_edge = pre_ack_sync[2] ^ pre_ack_sync[1];
|
||||
reg pre_busy; // sys: a preload handshake is in flight
|
||||
// latched byte/port for the in-flight preload (sys, stable while pre_busy)
|
||||
reg pre_busy; // a preload handshake is in flight
|
||||
// latched byte/port for the in-flight preload, stable while pre_busy
|
||||
reg [1:0] pre_sel_l;
|
||||
reg [11:0] pre_addr_l;
|
||||
reg [7:0] pre_byte_l;
|
||||
reg pre_auto_inc_l;
|
||||
|
||||
// ==========================================
|
||||
// Bulk readback byte handshake.
|
||||
// Hold {sel,addr}, flip rdb_req_tg, let the BRAM read settle, latch one
|
||||
// byte, then flip rdb_ack_tg.
|
||||
// ==========================================
|
||||
reg rdb_req_tg; // one readback byte request
|
||||
reg [2:0] rdb_req_sync; // edge detector shift register
|
||||
wire mlkem_rdb_req = rdb_req_sync[2] ^ rdb_req_sync[1];
|
||||
reg rdb_ack_tg; // readback byte ready
|
||||
reg [2:0] rdb_ack_sync; // edge detector shift register
|
||||
wire rdb_ack_edge = rdb_ack_sync[2] ^ rdb_ack_sync[1];
|
||||
reg [1:0] rdb_req_sel_l; // stable while request in flight
|
||||
reg [11:0] rdb_req_addr_l; // stable while request in flight
|
||||
reg [1:0] rdb_sel_m; // captured request
|
||||
reg [11:0] rdb_addr_m; // captured request
|
||||
reg [1:0] rdb_wait_m; // waits for BRAM registered read
|
||||
reg rdb_busy_m;
|
||||
reg [7:0] rdb_data_m; // held stable until next ack
|
||||
|
||||
// ==========================================
|
||||
// mlkem_top instance
|
||||
// ==========================================
|
||||
wire [7:0] dbg_byte_o, dbg_dk_o, dbg_ct_o;
|
||||
wire [255:0] ss_o;
|
||||
wire bulk_read_active;
|
||||
wire [1:0] bulk_rdb_sel;
|
||||
wire [11:0] bulk_rdb_addr;
|
||||
wire [1:0] eff_rdb_sel = bulk_read_active ? bulk_rdb_sel : rdb_sel;
|
||||
wire [11:0] eff_rdb_addr = bulk_read_active ? bulk_rdb_addr : rdb_addr;
|
||||
wire [1:0] eff_rdb_sel = rdb_busy_m ? rdb_sel_m : rdb_sel;
|
||||
wire [11:0] eff_rdb_addr = rdb_busy_m ? rdb_addr_m : rdb_addr;
|
||||
wire dbg_byte_sel = (eff_rdb_sel == 2'd1); // 0=ek, 1=dk_pke
|
||||
// The core's ek/dkp read-address muxes give dbg_dk_idx_i priority over
|
||||
// dbg_byte_idx_i whenever it lands in the ek (768..1567) or dk_pke (<768)
|
||||
@@ -245,21 +255,20 @@ module mlkem_axi_slave (
|
||||
// it out of range (0xFFF) so an ek/dk_pke readback isn't corrupted.
|
||||
wire [11:0] dbg_dk_idx = (eff_rdb_sel == 2'd2) ? eff_rdb_addr : 12'hFFF;
|
||||
|
||||
// one-cycle write-enable pulses into the core (combinational off the synced
|
||||
// edge; pre_sel_l/pre_addr_l/pre_byte_l are stable in sys, sampled by core).
|
||||
wire ek_in_we = mlkem_pre_we && (pre_sel_l == 2'd0);
|
||||
wire dk_in_we = mlkem_pre_we && (pre_sel_l == 2'd1);
|
||||
wire c_in_we = mlkem_pre_we && (pre_sel_l == 2'd2);
|
||||
// one-cycle write-enable pulses into the core.
|
||||
wire ek_in_we = core_resetn && mlkem_pre_we && (pre_sel_l == 2'd0);
|
||||
wire dk_in_we = core_resetn && mlkem_pre_we && (pre_sel_l == 2'd1);
|
||||
wire c_in_we = core_resetn && mlkem_pre_we && (pre_sel_l == 2'd2);
|
||||
|
||||
mlkem_top #(.KMAX(4)) u_mlkem (
|
||||
.clk (mlkem_clk),
|
||||
.rst_n (mlkem_rstn),
|
||||
.clk (clk),
|
||||
.rst_n (core_resetn),
|
||||
.k_i (cfg_k),
|
||||
.op_i (cfg_op),
|
||||
.d_i (d_bus),
|
||||
.z_i (z_bus),
|
||||
.msg_i (msg_bus),
|
||||
.start_i (mlkem_start),
|
||||
.start_i (core_resetn ? mlkem_start : 1'b0),
|
||||
.busy_o (core_busy),
|
||||
.done_o (core_done),
|
||||
// ek preload
|
||||
@@ -302,44 +311,82 @@ module mlkem_axi_slave (
|
||||
);
|
||||
|
||||
// ==========================================
|
||||
// mlkem_clk domain: synchronizers, done latch, preload-ack toggle.
|
||||
// Core/AXI clock domain: edge detectors, done latch, preload/readback acks.
|
||||
// ==========================================
|
||||
always @(posedge mlkem_clk or negedge mlkem_rstn) begin
|
||||
if (!mlkem_rstn) begin
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (!resetn) begin
|
||||
start_sync <= 3'd0;
|
||||
srst_sync <= 3'd0;
|
||||
srst_cnt <= 4'd0;
|
||||
dclr_sync <= 3'd0;
|
||||
pre_req_sync <= 3'd0;
|
||||
pre_ack_tg <= 1'b0;
|
||||
rdb_req_sync <= 3'd0;
|
||||
rdb_ack_tg <= 1'b0;
|
||||
rdb_sel_m <= 2'd0;
|
||||
rdb_addr_m <= 12'd0;
|
||||
rdb_wait_m <= 2'd0;
|
||||
rdb_busy_m <= 1'b0;
|
||||
rdb_data_m <= 8'd0;
|
||||
done_latch <= 1'b0;
|
||||
end else begin
|
||||
// 2FF (+edge) synchronizers of sys-domain toggles
|
||||
// Edge-detect request toggles.
|
||||
start_sync <= {start_sync[1:0], start_tg};
|
||||
srst_sync <= {srst_sync[1:0], srst_tg};
|
||||
dclr_sync <= {dclr_sync[1:0], dclr_tg};
|
||||
pre_req_sync <= {pre_req_sync[1:0], pre_req_tg};
|
||||
rdb_req_sync <= {rdb_req_sync[1:0], rdb_req_tg};
|
||||
|
||||
if (mlkem_srst_edge)
|
||||
srst_cnt <= 4'd8;
|
||||
else if (srst_cnt != 4'd0)
|
||||
srst_cnt <= srst_cnt - 4'd1;
|
||||
|
||||
// acknowledge a consumed preload byte (write-enable pulsed this cycle)
|
||||
if (mlkem_pre_we) pre_ack_tg <= ~pre_ack_tg;
|
||||
if (core_resetn && mlkem_pre_we) pre_ack_tg <= ~pre_ack_tg;
|
||||
|
||||
if (!core_resetn) begin
|
||||
rdb_wait_m <= 2'd0;
|
||||
rdb_busy_m <= 1'b0;
|
||||
end else if (mlkem_rdb_req) begin
|
||||
rdb_sel_m <= rdb_req_sel_l;
|
||||
rdb_addr_m <= rdb_req_addr_l;
|
||||
rdb_wait_m <= 2'd2;
|
||||
rdb_busy_m <= 1'b1;
|
||||
end else if (rdb_wait_m != 2'd0) begin
|
||||
if (rdb_wait_m == 2'd1) begin
|
||||
rdb_data_m <= rdb_byte;
|
||||
rdb_ack_tg <= ~rdb_ack_tg;
|
||||
rdb_wait_m <= 2'd0;
|
||||
rdb_busy_m <= 1'b0;
|
||||
end else begin
|
||||
rdb_wait_m <= rdb_wait_m - 2'd1;
|
||||
end
|
||||
end
|
||||
|
||||
// sticky done: set on the core's done_o pulse, cleared by synced W1C.
|
||||
// (mlkem_start also clears it so a new run starts with done low.)
|
||||
if (core_done) done_latch <= 1'b1;
|
||||
if (mlkem_srst_active) done_latch <= 1'b0;
|
||||
else if (core_done) done_latch <= 1'b1;
|
||||
else if (mlkem_dclr) done_latch <= 1'b0;
|
||||
else if (mlkem_start) done_latch <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// ==========================================
|
||||
// sys_clk domain: sync busy/done/preload-ack back from mlkem.
|
||||
// AXI clock domain: register status and acknowledge toggles.
|
||||
// ==========================================
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (!resetn) begin
|
||||
busy_sync <= 2'd0;
|
||||
done_sync <= 2'd0;
|
||||
pre_ack_sync <= 3'd0;
|
||||
rdb_ack_sync <= 3'd0;
|
||||
end else begin
|
||||
busy_sync <= {busy_sync[0], core_busy};
|
||||
busy_sync <= {busy_sync[0], core_busy | mlkem_srst_active};
|
||||
done_sync <= {done_sync[0], done_latch};
|
||||
pre_ack_sync <= {pre_ack_sync[1:0], pre_ack_tg};
|
||||
rdb_ack_sync <= {rdb_ack_sync[1:0], rdb_ack_tg};
|
||||
end
|
||||
end
|
||||
wire status_busy = busy_sync[1];
|
||||
@@ -389,6 +436,7 @@ module mlkem_axi_slave (
|
||||
rdb_sel <= 2'd0;
|
||||
rdb_addr <= 12'd0;
|
||||
start_tg <= 1'b0;
|
||||
srst_tg <= 1'b0;
|
||||
dclr_tg <= 1'b0;
|
||||
pre_req_tg <= 1'b0;
|
||||
pre_busy <= 1'b0;
|
||||
@@ -453,8 +501,10 @@ module mlkem_axi_slave (
|
||||
end else begin
|
||||
// normal single-cycle register write
|
||||
case (1'b1)
|
||||
(w_offset == ADDR_CTRL):
|
||||
(w_offset == ADDR_CTRL): begin
|
||||
if (s_axi_wdata[0]) start_tg <= ~start_tg;
|
||||
if (s_axi_wdata[1]) srst_tg <= ~srst_tg;
|
||||
end
|
||||
(w_offset == ADDR_STATUS):
|
||||
if (s_axi_wdata[1]) dclr_tg <= ~dclr_tg; // clear done
|
||||
(w_offset == ADDR_CONFIG): begin
|
||||
@@ -541,7 +591,6 @@ module mlkem_axi_slave (
|
||||
localparam R_IDLE = 3'd0;
|
||||
localparam R_DATA = 3'd1;
|
||||
localparam R_BULK_WAIT = 3'd2;
|
||||
localparam RDB_WAIT_CYCLES = 3'd4;
|
||||
|
||||
reg [2:0] r_state;
|
||||
reg [31:0] r_addr;
|
||||
@@ -557,13 +606,8 @@ module mlkem_axi_slave (
|
||||
reg [1:0] bulk_sel_r;
|
||||
reg [11:0] bulk_addr_r;
|
||||
reg [1:0] bulk_lane;
|
||||
reg [2:0] bulk_wait;
|
||||
reg [31:0] bulk_word;
|
||||
|
||||
assign bulk_read_active = r_bulk && (r_state == R_BULK_WAIT);
|
||||
assign bulk_rdb_sel = bulk_sel_r;
|
||||
assign bulk_rdb_addr = bulk_addr_r;
|
||||
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (!resetn) begin
|
||||
r_state <= R_IDLE;
|
||||
@@ -579,8 +623,10 @@ module mlkem_axi_slave (
|
||||
bulk_sel_r <= 2'd0;
|
||||
bulk_addr_r <= 12'd0;
|
||||
bulk_lane <= 2'd0;
|
||||
bulk_wait <= 3'd0;
|
||||
bulk_word <= 32'd0;
|
||||
rdb_req_tg <= 1'b0;
|
||||
rdb_req_sel_l <= 2'd0;
|
||||
rdb_req_addr_l <= 12'd0;
|
||||
end else begin
|
||||
case (r_state)
|
||||
R_IDLE: begin
|
||||
@@ -597,8 +643,10 @@ module mlkem_axi_slave (
|
||||
bulk_sel_r <= window_readback_sel(s_axi_araddr[15:12]);
|
||||
bulk_addr_r <= s_axi_araddr[11:0];
|
||||
bulk_lane <= 2'd0;
|
||||
bulk_wait <= RDB_WAIT_CYCLES;
|
||||
bulk_word <= 32'd0;
|
||||
rdb_req_sel_l <= window_readback_sel(s_axi_araddr[15:12]);
|
||||
rdb_req_addr_l <= s_axi_araddr[11:0];
|
||||
rdb_req_tg <= ~rdb_req_tg;
|
||||
s_axi_rvalid <= 1'b0;
|
||||
s_axi_rlast <= 1'b0;
|
||||
r_state <= R_BULK_WAIT;
|
||||
@@ -610,14 +658,12 @@ module mlkem_axi_slave (
|
||||
end
|
||||
end
|
||||
R_BULK_WAIT: begin
|
||||
if (bulk_wait != 3'd0) begin
|
||||
bulk_wait <= bulk_wait - 3'd1;
|
||||
end else begin
|
||||
if (rdb_ack_edge) begin
|
||||
case (bulk_lane)
|
||||
2'd0: bulk_word[7:0] <= rdb_byte;
|
||||
2'd1: bulk_word[15:8] <= rdb_byte;
|
||||
2'd2: bulk_word[23:16] <= rdb_byte;
|
||||
default: bulk_word[31:24] <= rdb_byte;
|
||||
2'd0: bulk_word[7:0] <= rdb_data_m;
|
||||
2'd1: bulk_word[15:8] <= rdb_data_m;
|
||||
2'd2: bulk_word[23:16] <= rdb_data_m;
|
||||
default: bulk_word[31:24] <= rdb_data_m;
|
||||
endcase
|
||||
|
||||
if (bulk_lane == 2'd3) begin
|
||||
@@ -627,7 +673,8 @@ module mlkem_axi_slave (
|
||||
end else begin
|
||||
bulk_lane <= bulk_lane + 2'd1;
|
||||
bulk_addr_r <= bulk_addr_r + 12'd1;
|
||||
bulk_wait <= RDB_WAIT_CYCLES;
|
||||
rdb_req_addr_l <= bulk_addr_r + 12'd1;
|
||||
rdb_req_tg <= ~rdb_req_tg;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -645,8 +692,10 @@ module mlkem_axi_slave (
|
||||
if (r_bulk) begin
|
||||
bulk_addr_r <= (r_burst == 2'b01) ? (r_offset + 12'd4) : r_offset;
|
||||
bulk_lane <= 2'd0;
|
||||
bulk_wait <= RDB_WAIT_CYCLES;
|
||||
bulk_word <= 32'd0;
|
||||
rdb_req_sel_l <= bulk_sel_r;
|
||||
rdb_req_addr_l <= (r_burst == 2'b01) ? (r_offset + 12'd4) : r_offset;
|
||||
rdb_req_tg <= ~rdb_req_tg;
|
||||
s_axi_rvalid <= 1'b0;
|
||||
s_axi_rlast <= 1'b0;
|
||||
r_state <= R_BULK_WAIT;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user