module axi_lite_memory( // Global input ACLK, input ARESETn, // Write address input AWVALID, input [ADDR_WIDTH-1:0] AWADDR, input [2:0] AWPROT, output reg AWREADY, // Write data input WVALID, input [DATA_WIDTH-1:0] WDATA, input [(DATA_WIDTH/8)-1:0] WSTRB, output reg WREADY, // Write response output reg BVALID, input BREADY, output reg [1:0] BRESP, // Read address input ARVALID, input [ADDR_WIDTH-1:0] ARADDR, input [2:0] ARPROT, // IGNORED output reg ARREADY, // Read data output reg RVALID, output reg [DATA_WIDTH-1:0] RDATA, output reg [1:0] RRESP, input RREADY, // Wishbone write output reg [ADDR_WIDTH-1:0] WB_WADDR, output reg [2:0] WB_WPROT, output reg [DATA_WIDTH-1:0] WB_WDATA, output reg [(DATA_WIDTH/8)-1:0] WB_WSTRB, output reg WB_WVALID = 0, input WB_WREADY, // Wishbone read output reg [ADDR_WIDTH-1:0] WB_RADDR, input [DATA_WIDTH-1:0] WB_RDATA, input WB_RVALID, output reg WB_RREADY ); parameter DATA_WIDTH = 32; // Only 32 allowed for now (AXI-Lite allows 32 or 64). 64 might work but I haven't investigated it yet. parameter ADDR_WIDTH = 12; // No minimum requirement. Typically at least 12b (4KB) parameter SYNC_DEPTH = 1; // Minimum recommended: 2. Larger synchronizer depth allows for larger delay between AXI address and data without stalling. reg [ADDR_WIDTH-1:0] sync_awaddr [0:SYNC_DEPTH-1]; reg [2:0] sync_awprot [0:SYNC_DEPTH-1]; reg [$clog2(SYNC_DEPTH)+1:0] sync_aw_fill = 0; reg [DATA_WIDTH-1:0] sync_wdata [0:SYNC_DEPTH-1]; reg [(DATA_WIDTH/8)-1:0] sync_wstrb [0:SYNC_DEPTH-1]; reg [$clog2(SYNC_DEPTH)+1:0] sync_w_fill = 0; reg [1:0] sync_bresp [0:SYNC_DEPTH-1]; // TODO: make this not be the same sync_depth? reg [$clog2(SYNC_DEPTH)+1:0] sync_b_fill = 0; localparam RESP_OKAY = 2'b00, RESP_EXOKAY = 2'b01, RESP_SLVERR = 2'b10, RESP_DECERR = 2'b11; always @(*) begin AWREADY = sync_aw_fill < SYNC_DEPTH; WREADY = sync_w_fill < SYNC_DEPTH; BRESP = RESP_OKAY; // TODO: add support for responses other than OKAY BVALID = sync_b_fill > 0; end always @(posedge ACLK or negedge ARESETn) begin: clk_update integer i; // Write direction integer event_wb_write; integer event_aw; integer event_w; integer event_b; // Read direction integer event_wb_read; integer event_ar; integer event_r; // Write direction event_wb_write = 0; event_aw = 0; event_w = 0; event_b = 0; // Read direction event_wb_read = 0; event_ar = 0; event_r = 0; if (ARESETn == 0) begin // TODO: deal with reset sync_aw_fill <= 0; sync_w_fill <= 0; sync_b_fill <= 0; end else begin if (AWREADY && AWVALID) begin event_aw = 1; for (i=0; i 0 && sync_w_fill > 0) begin WB_WVALID <= 1'b1; WB_WADDR <= sync_awaddr[sync_aw_fill-1]; WB_WPROT <= sync_awprot[sync_aw_fill-1]; WB_WDATA <= sync_wdata[sync_w_fill-1]; WB_WSTRB <= sync_wstrb[sync_w_fill-1]; end else begin WB_WVALID <= 1'b0; end end sync_aw_fill <= sync_aw_fill + event_aw - event_wb_write; sync_w_fill <= sync_w_fill + event_w - event_wb_write; sync_b_fill <= sync_b_fill - event_b + event_wb_write; // TODO: is this right? end end endmodule