// 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 // Route the low ML-KEM block to ML-KEM and the remaining accelerator window to // FFT. (* use_dsp = "no" *) 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, 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; wire aw_to_mlkem = (s_axi_awaddr[15:12] <= 4'h3); wire ar_to_mlkem = (s_axi_araddr[15:12] <= 4'h3); 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; 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 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; wire fft_arready, fft_rvalid, fft_rlast; wire [4:0] fft_rid; wire [31:0] fft_rdata; wire [1:0] fft_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 : fft_awready); assign s_axi_wready = (sel_w == SEL_MLKEM) ? mlkem_wready : fft_wready; assign s_axi_bvalid = (sel_w == SEL_MLKEM) ? mlkem_bvalid : fft_bvalid; assign s_axi_bid = (sel_w == SEL_MLKEM) ? mlkem_bid : fft_bid; assign s_axi_bresp = (sel_w == SEL_MLKEM) ? mlkem_bresp : fft_bresp; assign s_axi_arready = !read_active && ( (ar_sel == SEL_MLKEM) ? mlkem_arready : fft_arready); assign s_axi_rvalid = (sel_r == SEL_MLKEM) ? mlkem_rvalid : fft_rvalid; assign s_axi_rlast = (sel_r == SEL_MLKEM) ? mlkem_rlast : fft_rlast; assign s_axi_rid = (sel_r == SEL_MLKEM) ? mlkem_rid : fft_rid; assign s_axi_rdata = (sel_r == SEL_MLKEM) ? mlkem_rdata : fft_rdata; assign s_axi_rresp = (sel_r == SEL_MLKEM) ? mlkem_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 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 (mlkem_clk), .resetn (mlkem_resetn), .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 (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_m_bid), .s_axi_bresp (mlkem_m_bresp), .s_axi_bvalid (mlkem_m_bvalid), .s_axi_bready (mlkem_m_bready), .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_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_m) ); 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) ); endmodule