diff --git a/rtl/ip/Bus_interconnects/axi2sram_sp_external.v b/rtl/ip/Bus_interconnects/axi2sram_sp_external.v index 73fdca8..32bac78 100644 --- a/rtl/ip/Bus_interconnects/axi2sram_sp_external.v +++ b/rtl/ip/Bus_interconnects/axi2sram_sp_external.v @@ -65,6 +65,7 @@ module axi2sram_sp_external #( output reg req_o, output reg we_o, output reg [AXI_ADDR_WIDTH-1:0] addr_o, + output reg bank_o, output reg [AXI_DATA_WIDTH/8-1:0] be_o, output reg [AXI_DATA_WIDTH-1:0] data_o, input [AXI_DATA_WIDTH-1:0] data_i @@ -101,40 +102,34 @@ module axi2sram_sp_external #( localparam FIXED = 2'b00; localparam INCR = 2'b01; localparam WRAP = 2'b10; + localparam [AXI_ADDR_WIDTH-1:0] ADDR_INCR = + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1} << LOG_NR_BYTES; reg [AXI_ADDR_WIDTH-1:0] req_addr_d, req_addr_q; - reg [7:0] cnt_d, cnt_q; + reg [8:0] cnt_d, cnt_q; + reg [AXI_ADDR_WIDTH-1:0] wrap_mask_d, wrap_mask_q; + reg req_bank_d, req_bank_q; + reg [AXI_DATA_WIDTH-1:0] read_data_q; + reg read_capture; - function automatic [AXI_ADDR_WIDTH-1:0] get_wrap_boundary; - input [AXI_ADDR_WIDTH-1:0] unaligned_address; - input [7:0] len; - begin - get_wrap_boundary = 'h0; - // for wrapping transfers ax_len can only be of size 1, 3, 7 or 15 - if (len == 4'b1) - get_wrap_boundary[AXI_ADDR_WIDTH-1:1+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-1:1+LOG_NR_BYTES]; - else if (len == 4'b11) - get_wrap_boundary[AXI_ADDR_WIDTH-1:2+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-1:2+LOG_NR_BYTES]; - else if (len == 4'b111) - get_wrap_boundary[AXI_ADDR_WIDTH-1:3+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-3:2+LOG_NR_BYTES]; - else if (len == 4'b1111) - get_wrap_boundary[AXI_ADDR_WIDTH-1:4+LOG_NR_BYTES] = unaligned_address[AXI_ADDR_WIDTH-3:4+LOG_NR_BYTES]; - end - endfunction + wire [AXI_ADDR_WIDTH-1:0] ar_burst_bytes = + ({{(AXI_ADDR_WIDTH-8){1'b0}}, s_arlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES; + wire [AXI_ADDR_WIDTH-1:0] aw_burst_bytes = + ({{(AXI_ADDR_WIDTH-8){1'b0}}, s_awlen} + {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}) << LOG_NR_BYTES; + wire [AXI_ADDR_WIDTH-1:0] ar_wrap_mask = ar_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}; + wire [AXI_ADDR_WIDTH-1:0] aw_wrap_mask = aw_burst_bytes - {{(AXI_ADDR_WIDTH-1){1'b0}}, 1'b1}; - reg [AXI_ADDR_WIDTH-1:0] aligned_address; - reg [AXI_ADDR_WIDTH-1:0] wrap_boundary; - reg [AXI_ADDR_WIDTH-1:0] upper_wrap_boundary; - reg [AXI_ADDR_WIDTH-1:0] cons_addr; + reg [AXI_ADDR_WIDTH-1:0] next_addr; + reg [AXI_ADDR_WIDTH-1:0] seq_addr; always @ (*) begin - // address generation - aligned_address = {ax_req_q_addr[AXI_ADDR_WIDTH-1:LOG_NR_BYTES], {{LOG_NR_BYTES}{1'b0}}}; - wrap_boundary = get_wrap_boundary(ax_req_q_addr, ax_req_q_len); - // this will overflow - upper_wrap_boundary = wrap_boundary + ((ax_req_q_len + 1) << LOG_NR_BYTES); - // calculate consecutive address - cons_addr = aligned_address + (cnt_q << LOG_NR_BYTES); + seq_addr = req_addr_q + ADDR_INCR; + case (ax_req_q_burst) + FIXED: next_addr = req_addr_q; + INCR: next_addr = seq_addr; + WRAP: next_addr = (req_addr_q & ~wrap_mask_q) | (seq_addr & wrap_mask_q); + default: next_addr = seq_addr; + endcase // Transaction attributes // default assignments @@ -146,12 +141,16 @@ module axi2sram_sp_external #( ax_req_d_burst = ax_req_q_burst; req_addr_d = req_addr_q; cnt_d = cnt_q; + wrap_mask_d = wrap_mask_q; + req_bank_d = req_bank_q; + read_capture = 1'b0; // Memory default assignments data_o = s_wdata; be_o = s_wstrb; we_o = 1'b0; req_o = 1'b0; addr_o = 'h0; + bank_o = req_bank_q; // AXI assignments // request s_awready = 1'b0; @@ -184,14 +183,17 @@ module axi2sram_sp_external #( ax_req_d_len = s_arlen; ax_req_d_size = s_arsize; ax_req_d_burst = s_arburst; - state_d = READ; + wrap_mask_d = ar_wrap_mask; + req_bank_d = s_araddr[22]; + state_d = READ_ADDR; // we can request the first address, this saves us time req_o = 1'b1; addr_o = s_araddr; + bank_o = s_araddr[22]; // save the address req_addr_d = s_araddr; // save the ar_len - cnt_d = 1; + cnt_d = 0; // ------------ // Write // ------------ @@ -205,6 +207,9 @@ module axi2sram_sp_external #( ax_req_d_len = s_awlen; ax_req_d_size = s_awsize; ax_req_d_burst = s_awburst; + wrap_mask_d = aw_wrap_mask; + req_bank_d = s_awaddr[22]; + bank_o = s_awaddr[22]; // we've got our first w_valid so start the write process if (s_wvalid) begin req_o = 1'b1; @@ -231,40 +236,52 @@ module axi2sram_sp_external #( end READ: begin - // keep request to memory high - req_o = 1'b1; - addr_o = req_addr_q; // send the response s_rvalid = 1'b1; - s_rdata = data_i; + s_rdata = read_data_q; s_rid = ax_req_q_id; - s_rlast = (cnt_q == ax_req_q_len + 1); + s_rlast = (cnt_q == ({1'b0, ax_req_q_len} + 9'd1)); + if (FAST_READ_BURST && !s_rlast) begin + req_o = 1'b1; + addr_o = next_addr; + end // check that the master is ready, the slave must not wait on this if (s_rready) begin // we sent the last byte -> go back to idle if (s_rlast) begin - state_d = IDLE; - // we already got everything + if (s_arvalid) begin + // Accept the next burst without an intervening + // IDLE cycle and start its SRAM address phase. + s_arready = 1'b1; + ax_req_d_id = s_arid; + ax_req_d_addr = s_araddr; + ax_req_d_len = s_arlen; + ax_req_d_size = s_arsize; + ax_req_d_burst = s_arburst; + wrap_mask_d = ar_wrap_mask; + req_bank_d = s_araddr[22]; + req_o = 1'b1; + addr_o = s_araddr; + bank_o = s_araddr[22]; + req_addr_d = s_araddr; + // ARVALID was presented during the preceding + // beat, so the async-SRAM address has a full + // cycle to settle before this capture edge. + read_capture = 1'b1; + cnt_d = 1; + state_d = READ; + end else begin + state_d = IDLE; + end end else begin if (FAST_READ_BURST) begin - // Queue the next async-SRAM address for the clock - // edge after the current read data is sampled. - case (ax_req_q_burst) - FIXED, INCR: req_addr_d = cons_addr; - WRAP: begin - if (cons_addr == upper_wrap_boundary) begin - req_addr_d = wrap_boundary; - end else if (cons_addr > upper_wrap_boundary) begin - req_addr_d = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES); - end else begin - req_addr_d = cons_addr; - end - end - endcase + read_capture = 1'b1; + req_addr_d = next_addr; cnt_d = cnt_q + 1; state_d = READ; end else begin + req_addr_d = next_addr; state_d = READ_ADDR; end end @@ -272,34 +289,12 @@ module axi2sram_sp_external #( end READ_ADDR: begin - // keep request to memory high + // Fill the read data register after the async-SRAM address has + // been stable for one full sys_clk cycle. req_o = 1'b1; - // send the response - s_rvalid = 1'b0; - // ---------------------------- - // Next address generation - // ---------------------------- - // handle the correct burst type - case (ax_req_q_burst) - FIXED, INCR: addr_o = cons_addr; - WRAP: begin - // check if the address reached warp boundary - if (cons_addr == upper_wrap_boundary) begin - addr_o = wrap_boundary; - // address warped beyond boundary - end else if (cons_addr > upper_wrap_boundary) begin - addr_o = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES); - // we are still in the incremental regime - end else begin - addr_o = cons_addr; - end - end - endcase - // we need to change the address here for the upcoming request - // we can decrease the counter as the master has consumed the read data + addr_o = req_addr_q; + read_capture = 1'b1; cnt_d = cnt_q + 1; - // save the request address for the next cycle - req_addr_d = addr_o; state_d = READ; end @@ -317,24 +312,9 @@ module axi2sram_sp_external #( // Next address generation // ---------------------------- // handle the correct burst type - case (ax_req_q_burst) - - FIXED, INCR: addr_o = cons_addr; - WRAP: begin - // check if the address reached warp boundary - if (cons_addr == upper_wrap_boundary) begin - addr_o = wrap_boundary; - // address warped beyond boundary - end else if (cons_addr > upper_wrap_boundary) begin - addr_o = ax_req_q_addr + ((cnt_q - ax_req_q_len) << LOG_NR_BYTES); - // we are still in the incremental regime - end else begin - addr_o = cons_addr; - end - end - endcase + addr_o = next_addr; // save the request address for the next cycle - req_addr_d = addr_o; + req_addr_d = next_addr; // we can decrease the counter as the master has consumed the read data cnt_d = cnt_q + 1; @@ -365,7 +345,10 @@ module axi2sram_sp_external #( ax_req_q_len <= 8'h0; ax_req_q_size <= 3'h0; req_addr_q <= 'h0; - cnt_q <= 8'h0; + cnt_q <= 9'h0; + wrap_mask_q <= 'h0; + req_bank_q <= 1'b0; + read_data_q <= 'h0; end else begin state_q <= state_d; ax_req_q_addr <= ax_req_d_addr; @@ -375,6 +358,10 @@ module axi2sram_sp_external #( ax_req_q_size <= ax_req_d_size; req_addr_q <= req_addr_d; cnt_q <= cnt_d; + wrap_mask_q <= wrap_mask_d; + req_bank_q <= req_bank_d; + if (read_capture) + read_data_q <= data_i; end end diff --git a/rtl/ip/ram_wrap/axi_wrap_ram_sp_external.v b/rtl/ip/ram_wrap/axi_wrap_ram_sp_external.v index 3446a87..3bc102a 100644 --- a/rtl/ip/ram_wrap/axi_wrap_ram_sp_external.v +++ b/rtl/ip/ram_wrap/axi_wrap_ram_sp_external.v @@ -75,21 +75,21 @@ module axi_wrap_ram_sp_external ( output axi_bvalid , input axi_bready , - //BaseRAM信号 - inout [31:0] base_ram_data, //BaseRAM数据,低8位与CPLD串口控制器共享 - output [19:0] base_ram_addr, //BaseRAM地址 - output [ 3:0] base_ram_be_n, //BaseRAM字节使能,低有效。如果不使用字节使能,请保持为0 - output base_ram_ce_n, //BaseRAM片选,低有效 - output base_ram_oe_n, //BaseRAM读使能,低有效 - output base_ram_we_n, //BaseRAM写使能,低有效 + // BaseRAM + inout [31:0] base_ram_data, + output [19:0] base_ram_addr, + output [ 3:0] base_ram_be_n, + output base_ram_ce_n, + output base_ram_oe_n, + output base_ram_we_n, - //ExtRAM信号 - inout [31:0] ext_ram_data, //ExtRAM数据 - output [19:0] ext_ram_addr, //ExtRAM地址 - output [ 3:0] ext_ram_be_n, //ExtRAM字节使能,低有效。如果不使用字节使能,请保持为0 - output ext_ram_ce_n, //ExtRAM片选,低有效 - output ext_ram_oe_n, //ExtRAM读使能,低有效 - output ext_ram_we_n //ExtRAM写使能,低有效 + // ExtRAM + inout [31:0] ext_ram_data, + output [19:0] ext_ram_addr, + output [ 3:0] ext_ram_be_n, + output ext_ram_ce_n, + output ext_ram_oe_n, + output ext_ram_we_n ); @@ -139,6 +139,7 @@ wire ram_bready ; wire [31:0] soc_sram_addr; wire soc_sram_cs; wire soc_sram_we; +wire soc_sram_bank; wire [3:0] soc_sram_be; wire [31:0] soc_sram_wdata; wire [31:0] soc_sram_rdata; @@ -188,7 +189,8 @@ assign ram_bready = axi_bready ; axi2sram_sp_external #( .AXI_ID_WIDTH ( 5 ), .AXI_ADDR_WIDTH ( 32 ), - .AXI_DATA_WIDTH ( 32 )) + .AXI_DATA_WIDTH ( 32 ), + .FAST_READ_BURST( 1 )) u_axi_sram_sp ( .clk ( aclk ), .resetn ( aresetn ), @@ -232,12 +234,13 @@ axi2sram_sp_external #( .req_o ( soc_sram_cs ), .we_o ( soc_sram_we ), .addr_o ( soc_sram_addr ), + .bank_o ( soc_sram_bank ), .be_o ( soc_sram_be ), .data_o ( soc_sram_wdata ), .data_i ( soc_sram_rdata ) ); -wire choose_sram = soc_sram_addr[22];//1:ExtRAM 0:BaseRAM +wire choose_sram = soc_sram_bank;//1:ExtRAM 0:BaseRAM wire [3:0] be_out = soc_sram_we ? soc_sram_be : 4'b1111; assign base_ram_addr = soc_sram_addr[21:2];