feat: add prng
This commit is contained in:
@@ -4,7 +4,9 @@
|
|||||||
// maps do not overlap:
|
// maps do not overlap:
|
||||||
// ML-KEM: 0x0000..0x3fff
|
// ML-KEM: 0x0000..0x3fff
|
||||||
// FFT: 0x8000..0xcfff
|
// FFT: 0x8000..0xcfff
|
||||||
// Route the low ML-KEM block to ML-KEM and the high FFT block to FFT.
|
// 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.
|
||||||
module fft_mlkem_axi_slave (
|
module fft_mlkem_axi_slave (
|
||||||
input clk,
|
input clk,
|
||||||
input resetn,
|
input resetn,
|
||||||
@@ -54,12 +56,23 @@ module fft_mlkem_axi_slave (
|
|||||||
output mlkem_intr
|
output mlkem_intr
|
||||||
);
|
);
|
||||||
|
|
||||||
wire aw_to_mlkem = (s_axi_awaddr[15:12] <= 4'h3);
|
localparam SEL_MLKEM = 2'd0;
|
||||||
wire ar_to_mlkem = (s_axi_araddr[15:12] <= 4'h3);
|
localparam SEL_FFT = 2'd1;
|
||||||
|
localparam SEL_PRNG = 2'd2;
|
||||||
|
|
||||||
reg write_sel_mlkem;
|
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;
|
||||||
|
|
||||||
|
reg [1:0] write_sel;
|
||||||
reg write_active;
|
reg write_active;
|
||||||
reg read_sel_mlkem;
|
reg [1:0] read_sel;
|
||||||
reg read_active;
|
reg read_active;
|
||||||
|
|
||||||
wire mlkem_awready, mlkem_wready, mlkem_bvalid;
|
wire mlkem_awready, mlkem_wready, mlkem_bvalid;
|
||||||
@@ -78,39 +91,71 @@ module fft_mlkem_axi_slave (
|
|||||||
wire [31:0] fft_rdata;
|
wire [31:0] fft_rdata;
|
||||||
wire [1:0] fft_rresp;
|
wire [1:0] fft_rresp;
|
||||||
|
|
||||||
wire sel_w_mlkem = write_active ? write_sel_mlkem : aw_to_mlkem;
|
wire prng_awready, prng_wready, prng_bvalid;
|
||||||
wire sel_r_mlkem = read_active ? read_sel_mlkem : ar_to_mlkem;
|
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;
|
||||||
|
|
||||||
assign s_axi_awready = !write_active && (aw_to_mlkem ? mlkem_awready : fft_awready);
|
wire [1:0] sel_w = write_active ? write_sel : aw_sel;
|
||||||
assign s_axi_wready = sel_w_mlkem ? mlkem_wready : fft_wready;
|
wire [1:0] sel_r = read_active ? read_sel : ar_sel;
|
||||||
assign s_axi_bvalid = sel_w_mlkem ? mlkem_bvalid : fft_bvalid;
|
|
||||||
assign s_axi_bid = sel_w_mlkem ? mlkem_bid : fft_bid;
|
|
||||||
assign s_axi_bresp = sel_w_mlkem ? mlkem_bresp : fft_bresp;
|
|
||||||
|
|
||||||
assign s_axi_arready = !read_active && (ar_to_mlkem ? mlkem_arready : fft_arready);
|
assign s_axi_awready = !write_active && (
|
||||||
assign s_axi_rvalid = sel_r_mlkem ? mlkem_rvalid : fft_rvalid;
|
(aw_sel == SEL_MLKEM) ? mlkem_awready :
|
||||||
assign s_axi_rlast = sel_r_mlkem ? mlkem_rlast : fft_rlast;
|
(aw_sel == SEL_PRNG) ? prng_awready :
|
||||||
assign s_axi_rid = sel_r_mlkem ? mlkem_rid : fft_rid;
|
fft_awready);
|
||||||
assign s_axi_rdata = sel_r_mlkem ? mlkem_rdata : fft_rdata;
|
assign s_axi_wready = (sel_w == SEL_MLKEM) ? mlkem_wready :
|
||||||
assign s_axi_rresp = sel_r_mlkem ? mlkem_rresp : fft_rresp;
|
(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
|
always @(posedge clk or negedge resetn) begin
|
||||||
if (!resetn) begin
|
if (!resetn) begin
|
||||||
write_active <= 1'b0;
|
write_active <= 1'b0;
|
||||||
write_sel_mlkem <= 1'b0;
|
write_sel <= SEL_MLKEM;
|
||||||
read_active <= 1'b0;
|
read_active <= 1'b0;
|
||||||
read_sel_mlkem <= 1'b0;
|
read_sel <= SEL_MLKEM;
|
||||||
end else begin
|
end else begin
|
||||||
if (!write_active && s_axi_awvalid && s_axi_awready) begin
|
if (!write_active && s_axi_awvalid && s_axi_awready) begin
|
||||||
write_active <= 1'b1;
|
write_active <= 1'b1;
|
||||||
write_sel_mlkem <= aw_to_mlkem;
|
write_sel <= aw_sel;
|
||||||
end else if (write_active && s_axi_bvalid && s_axi_bready) begin
|
end else if (write_active && s_axi_bvalid && s_axi_bready) begin
|
||||||
write_active <= 1'b0;
|
write_active <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (!read_active && s_axi_arvalid && s_axi_arready) begin
|
if (!read_active && s_axi_arvalid && s_axi_arready) begin
|
||||||
read_active <= 1'b1;
|
read_active <= 1'b1;
|
||||||
read_sel_mlkem <= ar_to_mlkem;
|
read_sel <= ar_sel;
|
||||||
end else if (read_active && s_axi_rvalid && s_axi_rready && s_axi_rlast) begin
|
end else if (read_active && s_axi_rvalid && s_axi_rready && s_axi_rlast) begin
|
||||||
read_active <= 1'b0;
|
read_active <= 1'b0;
|
||||||
end
|
end
|
||||||
@@ -129,20 +174,20 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_axi_awlock (s_axi_awlock),
|
.s_axi_awlock (s_axi_awlock),
|
||||||
.s_axi_awcache (s_axi_awcache),
|
.s_axi_awcache (s_axi_awcache),
|
||||||
.s_axi_awprot (s_axi_awprot),
|
.s_axi_awprot (s_axi_awprot),
|
||||||
.s_axi_awvalid (s_axi_awvalid && !write_active && aw_to_mlkem),
|
.s_axi_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_MLKEM)),
|
||||||
.s_axi_awready (mlkem_awready),
|
.s_axi_awready (mlkem_awready),
|
||||||
|
|
||||||
.s_axi_wid (s_axi_wid),
|
.s_axi_wid (s_axi_wid),
|
||||||
.s_axi_wdata (s_axi_wdata),
|
.s_axi_wdata (s_axi_wdata),
|
||||||
.s_axi_wstrb (s_axi_wstrb),
|
.s_axi_wstrb (s_axi_wstrb),
|
||||||
.s_axi_wlast (s_axi_wlast),
|
.s_axi_wlast (s_axi_wlast),
|
||||||
.s_axi_wvalid (s_axi_wvalid && sel_w_mlkem),
|
.s_axi_wvalid (s_axi_wvalid && (sel_w == SEL_MLKEM)),
|
||||||
.s_axi_wready (mlkem_wready),
|
.s_axi_wready (mlkem_wready),
|
||||||
|
|
||||||
.s_axi_bid (mlkem_bid),
|
.s_axi_bid (mlkem_bid),
|
||||||
.s_axi_bresp (mlkem_bresp),
|
.s_axi_bresp (mlkem_bresp),
|
||||||
.s_axi_bvalid (mlkem_bvalid),
|
.s_axi_bvalid (mlkem_bvalid),
|
||||||
.s_axi_bready (s_axi_bready && sel_w_mlkem),
|
.s_axi_bready (s_axi_bready && (sel_w == SEL_MLKEM)),
|
||||||
|
|
||||||
.s_axi_arid (s_axi_arid),
|
.s_axi_arid (s_axi_arid),
|
||||||
.s_axi_araddr (s_axi_araddr),
|
.s_axi_araddr (s_axi_araddr),
|
||||||
@@ -152,7 +197,7 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_axi_arlock (s_axi_arlock),
|
.s_axi_arlock (s_axi_arlock),
|
||||||
.s_axi_arcache (s_axi_arcache),
|
.s_axi_arcache (s_axi_arcache),
|
||||||
.s_axi_arprot (s_axi_arprot),
|
.s_axi_arprot (s_axi_arprot),
|
||||||
.s_axi_arvalid (s_axi_arvalid && !read_active && ar_to_mlkem),
|
.s_axi_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_MLKEM)),
|
||||||
.s_axi_arready (mlkem_arready),
|
.s_axi_arready (mlkem_arready),
|
||||||
|
|
||||||
.s_axi_rid (mlkem_rid),
|
.s_axi_rid (mlkem_rid),
|
||||||
@@ -160,7 +205,7 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_axi_rresp (mlkem_rresp),
|
.s_axi_rresp (mlkem_rresp),
|
||||||
.s_axi_rlast (mlkem_rlast),
|
.s_axi_rlast (mlkem_rlast),
|
||||||
.s_axi_rvalid (mlkem_rvalid),
|
.s_axi_rvalid (mlkem_rvalid),
|
||||||
.s_axi_rready (s_axi_rready && sel_r_mlkem),
|
.s_axi_rready (s_axi_rready && (sel_r == SEL_MLKEM)),
|
||||||
|
|
||||||
.intr (mlkem_intr)
|
.intr (mlkem_intr)
|
||||||
);
|
);
|
||||||
@@ -177,20 +222,20 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_awlock (s_axi_awlock),
|
.s_awlock (s_axi_awlock),
|
||||||
.s_awcache (s_axi_awcache),
|
.s_awcache (s_axi_awcache),
|
||||||
.s_awprot (s_axi_awprot),
|
.s_awprot (s_axi_awprot),
|
||||||
.s_awvalid (s_axi_awvalid && !write_active && !aw_to_mlkem),
|
.s_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_FFT)),
|
||||||
.s_awready (fft_awready),
|
.s_awready (fft_awready),
|
||||||
|
|
||||||
.s_wid (s_axi_wid),
|
.s_wid (s_axi_wid),
|
||||||
.s_wdata (s_axi_wdata),
|
.s_wdata (s_axi_wdata),
|
||||||
.s_wstrb (s_axi_wstrb),
|
.s_wstrb (s_axi_wstrb),
|
||||||
.s_wlast (s_axi_wlast),
|
.s_wlast (s_axi_wlast),
|
||||||
.s_wvalid (s_axi_wvalid && !sel_w_mlkem),
|
.s_wvalid (s_axi_wvalid && (sel_w == SEL_FFT)),
|
||||||
.s_wready (fft_wready),
|
.s_wready (fft_wready),
|
||||||
|
|
||||||
.s_bid (fft_bid),
|
.s_bid (fft_bid),
|
||||||
.s_bresp (fft_bresp),
|
.s_bresp (fft_bresp),
|
||||||
.s_bvalid (fft_bvalid),
|
.s_bvalid (fft_bvalid),
|
||||||
.s_bready (s_axi_bready && !sel_w_mlkem),
|
.s_bready (s_axi_bready && (sel_w == SEL_FFT)),
|
||||||
|
|
||||||
.s_arid (s_axi_arid),
|
.s_arid (s_axi_arid),
|
||||||
.s_araddr (s_axi_araddr),
|
.s_araddr (s_axi_araddr),
|
||||||
@@ -200,7 +245,7 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_arlock (s_axi_arlock),
|
.s_arlock (s_axi_arlock),
|
||||||
.s_arcache (s_axi_arcache),
|
.s_arcache (s_axi_arcache),
|
||||||
.s_arprot (s_axi_arprot),
|
.s_arprot (s_axi_arprot),
|
||||||
.s_arvalid (s_axi_arvalid && !read_active && !ar_to_mlkem),
|
.s_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_FFT)),
|
||||||
.s_arready (fft_arready),
|
.s_arready (fft_arready),
|
||||||
|
|
||||||
.s_rid (fft_rid),
|
.s_rid (fft_rid),
|
||||||
@@ -208,9 +253,55 @@ module fft_mlkem_axi_slave (
|
|||||||
.s_rresp (fft_rresp),
|
.s_rresp (fft_rresp),
|
||||||
.s_rlast (fft_rlast),
|
.s_rlast (fft_rlast),
|
||||||
.s_rvalid (fft_rvalid),
|
.s_rvalid (fft_rvalid),
|
||||||
.s_rready (s_axi_rready && !sel_r_mlkem),
|
.s_rready (s_axi_rready && (sel_r == SEL_FFT)),
|
||||||
|
|
||||||
.fft_finish (fft_finish)
|
.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
|
endmodule
|
||||||
|
|||||||
218
rtl/ip/prng/prng_axi_slave.v
Normal file
218
rtl/ip/prng/prng_axi_slave.v
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
// Lightweight AXI4 register endpoint for a pseudo-random generator.
|
||||||
|
//
|
||||||
|
// Register map, byte offsets within the shared accelerator window:
|
||||||
|
// 0xd000 CTRL W bit0=mix software seed, bit1=clear counters
|
||||||
|
// 0xd004 STATUS R bit0=ready
|
||||||
|
// 0xd008 DATA R next 32-bit random word
|
||||||
|
// 0xd00c COUNT R number of DATA reads
|
||||||
|
// 0xd010 SEED W software seed/mix value
|
||||||
|
//
|
||||||
|
// This block is deterministic unless software mixes in an external seed. It
|
||||||
|
// intentionally uses only flops, XORs, shifts, and adders.
|
||||||
|
module prng_axi_slave (
|
||||||
|
input clk,
|
||||||
|
input resetn,
|
||||||
|
|
||||||
|
input [4:0] s_axi_awid,
|
||||||
|
input [31:0] s_axi_awaddr,
|
||||||
|
input [7:0] s_axi_awlen,
|
||||||
|
input [2:0] s_axi_awsize,
|
||||||
|
input [1:0] s_axi_awburst,
|
||||||
|
input s_axi_awlock,
|
||||||
|
input [3:0] s_axi_awcache,
|
||||||
|
input [2:0] s_axi_awprot,
|
||||||
|
input s_axi_awvalid,
|
||||||
|
output s_axi_awready,
|
||||||
|
|
||||||
|
input [4:0] s_axi_wid,
|
||||||
|
input [31:0] s_axi_wdata,
|
||||||
|
input [3:0] s_axi_wstrb,
|
||||||
|
input s_axi_wlast,
|
||||||
|
input s_axi_wvalid,
|
||||||
|
output s_axi_wready,
|
||||||
|
|
||||||
|
output [4:0] s_axi_bid,
|
||||||
|
output [1:0] s_axi_bresp,
|
||||||
|
output reg s_axi_bvalid,
|
||||||
|
input s_axi_bready,
|
||||||
|
|
||||||
|
input [4:0] s_axi_arid,
|
||||||
|
input [31:0] s_axi_araddr,
|
||||||
|
input [7:0] s_axi_arlen,
|
||||||
|
input [2:0] s_axi_arsize,
|
||||||
|
input [1:0] s_axi_arburst,
|
||||||
|
input s_axi_arlock,
|
||||||
|
input [3:0] s_axi_arcache,
|
||||||
|
input [2:0] s_axi_arprot,
|
||||||
|
input s_axi_arvalid,
|
||||||
|
output s_axi_arready,
|
||||||
|
|
||||||
|
output reg [4:0] s_axi_rid,
|
||||||
|
output reg [31:0] s_axi_rdata,
|
||||||
|
output [1:0] s_axi_rresp,
|
||||||
|
output reg s_axi_rlast,
|
||||||
|
output reg s_axi_rvalid,
|
||||||
|
input s_axi_rready
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam ADDR_CTRL = 12'h000;
|
||||||
|
localparam ADDR_STATUS = 12'h004;
|
||||||
|
localparam ADDR_DATA = 12'h008;
|
||||||
|
localparam ADDR_COUNT = 12'h00c;
|
||||||
|
localparam ADDR_SEED = 12'h010;
|
||||||
|
|
||||||
|
assign s_axi_bresp = 2'b00;
|
||||||
|
assign s_axi_rresp = 2'b00;
|
||||||
|
|
||||||
|
reg [4:0] awid_reg;
|
||||||
|
reg [31:0] awaddr_reg;
|
||||||
|
reg [7:0] awleft_reg;
|
||||||
|
reg write_active;
|
||||||
|
|
||||||
|
assign s_axi_awready = !write_active && !s_axi_bvalid;
|
||||||
|
assign s_axi_wready = write_active && !s_axi_bvalid;
|
||||||
|
assign s_axi_bid = awid_reg;
|
||||||
|
|
||||||
|
reg [31:0] araddr_reg;
|
||||||
|
reg [7:0] arleft_reg;
|
||||||
|
reg read_active;
|
||||||
|
|
||||||
|
assign s_axi_arready = !read_active && !s_axi_rvalid;
|
||||||
|
|
||||||
|
reg [127:0] rng_state;
|
||||||
|
reg [63:0] free_counter;
|
||||||
|
reg [31:0] seed_mix;
|
||||||
|
reg [31:0] data_reads;
|
||||||
|
|
||||||
|
wire lfsr_fb = rng_state[127] ^ rng_state[125] ^ rng_state[100] ^
|
||||||
|
rng_state[98] ^ rng_state[27] ^ rng_state[0] ^
|
||||||
|
free_counter[0];
|
||||||
|
wire [127:0] rng_next = {rng_state[126:0], lfsr_fb} ^
|
||||||
|
{free_counter, free_counter ^ {32'h0, seed_mix}};
|
||||||
|
wire [31:0] rng_word = rng_state[31:0] ^ rng_state[63:32] ^
|
||||||
|
rng_state[95:64] ^ rng_state[127:96] ^
|
||||||
|
free_counter[31:0] ^ free_counter[63:32] ^
|
||||||
|
seed_mix;
|
||||||
|
|
||||||
|
function [31:0] apply_wstrb;
|
||||||
|
input [31:0] old_value;
|
||||||
|
input [31:0] new_value;
|
||||||
|
input [3:0] strobe;
|
||||||
|
begin
|
||||||
|
apply_wstrb = old_value;
|
||||||
|
if (strobe[0]) apply_wstrb[7:0] = new_value[7:0];
|
||||||
|
if (strobe[1]) apply_wstrb[15:8] = new_value[15:8];
|
||||||
|
if (strobe[2]) apply_wstrb[23:16] = new_value[23:16];
|
||||||
|
if (strobe[3]) apply_wstrb[31:24] = new_value[31:24];
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function [31:0] read_reg;
|
||||||
|
input [31:0] addr;
|
||||||
|
begin
|
||||||
|
case (addr[11:0])
|
||||||
|
ADDR_STATUS: read_reg = 32'h00000001;
|
||||||
|
ADDR_DATA: read_reg = rng_word;
|
||||||
|
ADDR_COUNT: read_reg = data_reads;
|
||||||
|
ADDR_SEED: read_reg = seed_mix;
|
||||||
|
default: read_reg = 32'h00000000;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
wire write_fire = s_axi_wvalid && s_axi_wready;
|
||||||
|
wire read_fire = s_axi_rvalid && s_axi_rready;
|
||||||
|
wire data_read_fire = read_fire && (araddr_reg[11:0] == ADDR_DATA);
|
||||||
|
wire [31:0] next_araddr = araddr_reg + 32'd4;
|
||||||
|
wire [31:0] next_awaddr = awaddr_reg + 32'd4;
|
||||||
|
|
||||||
|
always @(posedge clk or negedge resetn) begin
|
||||||
|
if (!resetn) begin
|
||||||
|
awid_reg <= 5'b0;
|
||||||
|
awaddr_reg <= 32'b0;
|
||||||
|
awleft_reg <= 8'b0;
|
||||||
|
write_active <= 1'b0;
|
||||||
|
s_axi_bvalid <= 1'b0;
|
||||||
|
|
||||||
|
araddr_reg <= 32'b0;
|
||||||
|
arleft_reg <= 8'b0;
|
||||||
|
read_active <= 1'b0;
|
||||||
|
s_axi_rid <= 5'b0;
|
||||||
|
s_axi_rdata <= 32'b0;
|
||||||
|
s_axi_rlast <= 1'b0;
|
||||||
|
s_axi_rvalid <= 1'b0;
|
||||||
|
|
||||||
|
rng_state <= 128'h6d5a_56c3_9e37_79b9_a5a5_3c3c_c001_c0de;
|
||||||
|
free_counter <= 64'h1;
|
||||||
|
seed_mix <= 32'h31415927;
|
||||||
|
data_reads <= 32'b0;
|
||||||
|
end else begin
|
||||||
|
free_counter <= free_counter + 64'h9e37_79b9_7f4a_7c15;
|
||||||
|
rng_state <= rng_next;
|
||||||
|
|
||||||
|
if (s_axi_awvalid && s_axi_awready) begin
|
||||||
|
awid_reg <= s_axi_awid;
|
||||||
|
awaddr_reg <= s_axi_awaddr;
|
||||||
|
awleft_reg <= s_axi_awlen;
|
||||||
|
write_active <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (write_fire) begin
|
||||||
|
case (awaddr_reg[11:0])
|
||||||
|
ADDR_CTRL: begin
|
||||||
|
if (s_axi_wdata[0]) begin
|
||||||
|
seed_mix <= seed_mix ^ s_axi_wdata ^ free_counter[31:0];
|
||||||
|
rng_state <= rng_next ^ {4{s_axi_wdata}};
|
||||||
|
end
|
||||||
|
if (s_axi_wdata[1])
|
||||||
|
data_reads <= 32'b0;
|
||||||
|
end
|
||||||
|
ADDR_SEED: begin
|
||||||
|
seed_mix <= apply_wstrb(seed_mix, s_axi_wdata, s_axi_wstrb);
|
||||||
|
rng_state <= rng_next ^ {s_axi_wdata, free_counter, ~s_axi_wdata};
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (s_axi_wlast || awleft_reg == 8'b0) begin
|
||||||
|
write_active <= 1'b0;
|
||||||
|
s_axi_bvalid <= 1'b1;
|
||||||
|
end else begin
|
||||||
|
awleft_reg <= awleft_reg - 8'd1;
|
||||||
|
awaddr_reg <= next_awaddr;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_axi_bvalid && s_axi_bready)
|
||||||
|
s_axi_bvalid <= 1'b0;
|
||||||
|
|
||||||
|
if (s_axi_arvalid && s_axi_arready) begin
|
||||||
|
read_active <= 1'b1;
|
||||||
|
araddr_reg <= s_axi_araddr;
|
||||||
|
arleft_reg <= s_axi_arlen;
|
||||||
|
s_axi_rid <= s_axi_arid;
|
||||||
|
s_axi_rdata <= read_reg(s_axi_araddr);
|
||||||
|
s_axi_rlast <= (s_axi_arlen == 8'b0);
|
||||||
|
s_axi_rvalid <= 1'b1;
|
||||||
|
end else if (read_fire) begin
|
||||||
|
if (data_read_fire) begin
|
||||||
|
data_reads <= data_reads + 32'd1;
|
||||||
|
rng_state <= rng_next ^ {rng_word, rng_word ^ free_counter[31:0],
|
||||||
|
free_counter[63:32], ~rng_word};
|
||||||
|
end
|
||||||
|
|
||||||
|
if (s_axi_rlast) begin
|
||||||
|
read_active <= 1'b0;
|
||||||
|
s_axi_rvalid <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
araddr_reg <= next_araddr;
|
||||||
|
arleft_reg <= arleft_reg - 8'd1;
|
||||||
|
s_axi_rdata <= read_reg(next_araddr);
|
||||||
|
s_axi_rlast <= (arleft_reg == 8'd1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1448,6 +1448,7 @@ axi_dvi u_axi_dvi (
|
|||||||
// slave 6 - shared FFT / ML-KEM accelerator window (0x1f400000, virtual 0xbf400000)
|
// slave 6 - shared FFT / ML-KEM accelerator window (0x1f400000, virtual 0xbf400000)
|
||||||
// ML-KEM: 0x0000..0x0114
|
// ML-KEM: 0x0000..0x0114
|
||||||
// FFT: 0x1000/0x2000/0x3000/0x4000/0xf000
|
// FFT: 0x1000/0x2000/0x3000/0x4000/0xf000
|
||||||
|
// PRNG: 0xd000..0xd010
|
||||||
fft_mlkem_axi_slave u_fft_mlkem_axi_slave (
|
fft_mlkem_axi_slave u_fft_mlkem_axi_slave (
|
||||||
.clk (sys_clk),
|
.clk (sys_clk),
|
||||||
.resetn (sys_resetn),
|
.resetn (sys_resetn),
|
||||||
|
|||||||
Reference in New Issue
Block a user