// Shared AXI slave for the legacy FFT accelerator and the ML-KEM accelerator. // // Both software stacks use the same base address, 0xbf400000. Their internal // 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. module fft_mlkem_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 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 [4:0] s_axi_rid, output [31:0] s_axi_rdata, output [1:0] s_axi_rresp, output s_axi_rlast, output s_axi_rvalid, input s_axi_rready, output fft_finish, output mlkem_intr ); 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; reg [1:0] write_sel; reg write_active; reg [1:0] read_sel; reg read_active; wire mlkem_awready, mlkem_wready, mlkem_bvalid; wire [4:0] mlkem_bid; wire [1:0] mlkem_bresp; wire mlkem_arready, mlkem_rvalid, mlkem_rlast; wire [4:0] mlkem_rid; wire [31:0] mlkem_rdata; wire [1:0] mlkem_rresp; wire fft_awready, fft_wready, fft_bvalid; wire [4:0] fft_bid; wire [1:0] fft_bresp; wire fft_arready, fft_rvalid, fft_rlast; wire [4:0] fft_rid; 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 if (!resetn) begin write_active <= 1'b0; write_sel <= SEL_MLKEM; read_active <= 1'b0; read_sel <= SEL_MLKEM; end else begin if (!write_active && s_axi_awvalid && s_axi_awready) begin write_active <= 1'b1; write_sel <= aw_sel; end else if (write_active && s_axi_bvalid && s_axi_bready) begin write_active <= 1'b0; end if (!read_active && s_axi_arvalid && s_axi_arready) begin read_active <= 1'b1; read_sel <= ar_sel; end else if (read_active && s_axi_rvalid && s_axi_rready && s_axi_rlast) begin read_active <= 1'b0; end end end mlkem_axi_slave u_mlkem_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_MLKEM)), .s_axi_awready (mlkem_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_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_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_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)), .intr (mlkem_intr) ); fft_controller u_fft_controller ( .aclk (clk), .aresetn (resetn), .s_awid (s_axi_awid), .s_awaddr (s_axi_awaddr), .s_awlen (s_axi_awlen), .s_awsize (s_axi_awsize), .s_awburst (s_axi_awburst), .s_awlock (s_axi_awlock), .s_awcache (s_axi_awcache), .s_awprot (s_axi_awprot), .s_awvalid (s_axi_awvalid && !write_active && (aw_sel == SEL_FFT)), .s_awready (fft_awready), .s_wid (s_axi_wid), .s_wdata (s_axi_wdata), .s_wstrb (s_axi_wstrb), .s_wlast (s_axi_wlast), .s_wvalid (s_axi_wvalid && (sel_w == SEL_FFT)), .s_wready (fft_wready), .s_bid (fft_bid), .s_bresp (fft_bresp), .s_bvalid (fft_bvalid), .s_bready (s_axi_bready && (sel_w == SEL_FFT)), .s_arid (s_axi_arid), .s_araddr (s_axi_araddr), .s_arlen (s_axi_arlen), .s_arsize (s_axi_arsize), .s_arburst (s_axi_arburst), .s_arlock (s_axi_arlock), .s_arcache (s_axi_arcache), .s_arprot (s_axi_arprot), .s_arvalid (s_axi_arvalid && !read_active && (ar_sel == SEL_FFT)), .s_arready (fft_arready), .s_rid (fft_rid), .s_rdata (fft_rdata), .s_rresp (fft_rresp), .s_rlast (fft_rlast), .s_rvalid (fft_rvalid), .s_rready (s_axi_rready && (sel_r == SEL_FFT)), .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