mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: enhance AXI4 and RIBP interfaces with burst support and address generation
- Added burst handling to the AXI42RAM and AXI42RIBP modules, including support for fixed, increment, and wrap burst types. - Introduced address generation logic for read and write operations based on burst parameters. - Updated the AXI4 interconnect to validate burst types and lengths, ensuring compatibility with the AXI4 protocol. - Modified the SDRAM controller and testbench to accommodate the new burst handling features. - Enhanced test cases to verify the correct behavior of burst transactions and address patterns. - Adjusted memory map and topology tests to reflect changes in the SDRAM size and interface connections.
This commit is contained in:
27 files changed
+707
-360
No files matched your search
@@ -235,6 +235,46 @@ module axi42ribp_burst_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic issue_address_pattern_read(input logic [31:0] address, input logic [7:0] length,
|
||||
input logic [1:0] burst);
|
||||
integer beat;
|
||||
logic [31:0] expected_address;
|
||||
logic [31:0] burst_bytes;
|
||||
begin
|
||||
burst_bytes = (length + 1) * 4;
|
||||
@(negedge clk_i);
|
||||
axi4.araddr = address;
|
||||
axi4.arlen = length;
|
||||
axi4.arburst = burst;
|
||||
axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.arready);
|
||||
@(negedge clk_i);
|
||||
axi4.arvalid = 1'b0;
|
||||
axi4.rready = 1'b1;
|
||||
beat = 0;
|
||||
while (beat <= length) begin
|
||||
@(posedge clk_i);
|
||||
if (axi4.rvalid) begin
|
||||
if (burst == `AXI4_BURST_TYPE_FIXED) begin
|
||||
expected_address = address;
|
||||
end else begin
|
||||
expected_address = (address & ~(burst_bytes - 1)) |
|
||||
((address + (beat * 4)) & (burst_bytes - 1));
|
||||
end
|
||||
if (axi4.rdata != memory[expected_address[7:2]] ||
|
||||
axi4.rresp != `AXI4_RESP_OKAY || axi4.rlast != (beat == length)) begin
|
||||
$fatal(1, "address pattern mismatch beat=%0d addr=%08x data=%08x", beat,
|
||||
expected_address, axi4.rdata);
|
||||
end
|
||||
beat = beat + 1;
|
||||
end
|
||||
end
|
||||
@(negedge clk_i);
|
||||
axi4.rready = 1'b0;
|
||||
axi4.arburst = `AXI4_BURST_TYPE_INCR;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
init_axi4();
|
||||
for (int index = 0; index < 64; index++) memory[index] = '0;
|
||||
@@ -242,6 +282,9 @@ module axi42ribp_burst_tb;
|
||||
rst_n_i = 1'b1;
|
||||
issue_write4(32'h0000_0040);
|
||||
issue_read4(32'h0000_0040);
|
||||
for (int index = 0; index < 64; index++) memory[index] = 32'h5000_0000 + index;
|
||||
issue_address_pattern_read(32'h0000_0020, 8'd3, `AXI4_BURST_TYPE_FIXED);
|
||||
issue_address_pattern_read(32'h0000_002C, 8'd3, `AXI4_BURST_TYPE_WRAP);
|
||||
issue_illegal_read(32'h0000_0080);
|
||||
issue_early_last_write(32'h0000_00C0);
|
||||
burst_cycles = cycle_count;
|
||||
@@ -256,7 +299,7 @@ module axi42ribp_burst_tb;
|
||||
$fatal(1, "16-beat burst improvement is below 20%%: burst=%0d single=%0d", burst_cycles,
|
||||
single_cycles);
|
||||
end
|
||||
if (target_accesses != 41) $fatal(1, "unexpected RIBP access count");
|
||||
if (target_accesses != 49) $fatal(1, "unexpected RIBP access count");
|
||||
$display("AXI4 to RIBP burst bridge test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ module ribp_topology_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
ribp_if ribp ();
|
||||
ribp_if sdram_cfg_ribp ();
|
||||
|
||||
`include "ribp_interfaces.svh"
|
||||
`include "ribp_routes.svh"
|
||||
@@ -92,7 +93,7 @@ module ribp_topology_tb;
|
||||
u_dma_ribp_if.ready = 1'b1;
|
||||
u_sysctrl_ribp_if.ready = 1'b1;
|
||||
u_clint_ribp_if.ready = 1'b1;
|
||||
u_sdram_ribp_if.ready = 1'b1;
|
||||
sdram_cfg_ribp.ready = 1'b1;
|
||||
u_dvp_ribp_if.ready = 1'b1;
|
||||
u_sdio_ribp_if.ready = 1'b1;
|
||||
u_opipsram_ribp_if.ready = 1'b1;
|
||||
@@ -111,7 +112,7 @@ module ribp_topology_tb;
|
||||
u_dma_ribp_if.rdata = 32'hAAAA_AAAA;
|
||||
u_sysctrl_ribp_if.rdata = 32'hBBBB_BBBB;
|
||||
u_clint_ribp_if.rdata = 32'hCCCC_CCCC;
|
||||
u_sdram_ribp_if.rdata = 32'hDDDD_DDDD;
|
||||
sdram_cfg_ribp.rdata = 32'hDDDD_DDDD;
|
||||
u_dvp_ribp_if.rdata = 32'hEEEE_EEEE;
|
||||
u_sdio_ribp_if.rdata = 32'hF0F0_F0F0;
|
||||
u_opipsram_ribp_if.rdata = 32'h0F0F_0F0F;
|
||||
@@ -130,7 +131,7 @@ module ribp_topology_tb;
|
||||
u_dma_ribp_if.resp_err = 1'b0;
|
||||
u_sysctrl_ribp_if.resp_err = 1'b0;
|
||||
u_clint_ribp_if.resp_err = 1'b0;
|
||||
u_sdram_ribp_if.resp_err = 1'b0;
|
||||
sdram_cfg_ribp.resp_err = 1'b0;
|
||||
u_dvp_ribp_if.resp_err = 1'b0;
|
||||
u_sdio_ribp_if.resp_err = 1'b0;
|
||||
u_opipsram_ribp_if.resp_err = 1'b0;
|
||||
|
||||
+96
-28
@@ -5,7 +5,16 @@ module sdram_data_tb;
|
||||
logic rst_n_i = 1'b0;
|
||||
wire [15:0] s_dq;
|
||||
logic [31:0] s_read_data;
|
||||
ribp_if rib ();
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
.USER_WIDTH(1)
|
||||
) axi4 (
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
ribp_if cfg_ribp ();
|
||||
sdram_if sdram ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
@@ -13,11 +22,12 @@ module sdram_data_tb;
|
||||
assign s_dq = sdram.oe_o ? sdram.dq_o : 'z;
|
||||
assign sdram.dq_i = s_dq;
|
||||
|
||||
ribp_sdram u_ribp_sdram (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.ribp (rib),
|
||||
.sdram (sdram)
|
||||
axi4_sdram u_axi4_sdram (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.axi4 (axi4),
|
||||
.cfg_ribp(cfg_ribp),
|
||||
.sdram (sdram)
|
||||
);
|
||||
|
||||
`ifdef SDRAM_TIMING_MODEL
|
||||
@@ -48,44 +58,96 @@ module sdram_data_tb;
|
||||
);
|
||||
`endif
|
||||
|
||||
task automatic init_axi4;
|
||||
begin
|
||||
axi4.awid = '0;
|
||||
axi4.awaddr = '0;
|
||||
axi4.awlen = '0;
|
||||
axi4.awsize = `AXI4_BURST_SIZE_4BYTES;
|
||||
axi4.awburst = `AXI4_BURST_TYPE_INCR;
|
||||
axi4.awlock = `AXI4_LOCK_NORM;
|
||||
axi4.awcache = `AXI4_CACHE_NO_BUF;
|
||||
axi4.awprot = `AXI4_PROT_DATA;
|
||||
axi4.awqos = `AXI4_QOS_NORMAL;
|
||||
axi4.awregion = `AXI4_REGION_NORMAL;
|
||||
axi4.awuser = '0;
|
||||
axi4.awvalid = 1'b0;
|
||||
axi4.wdata = '0;
|
||||
axi4.wstrb = '0;
|
||||
axi4.wlast = 1'b0;
|
||||
axi4.wuser = '0;
|
||||
axi4.wvalid = 1'b0;
|
||||
axi4.bready = 1'b0;
|
||||
axi4.arid = '0;
|
||||
axi4.araddr = '0;
|
||||
axi4.arlen = '0;
|
||||
axi4.arsize = `AXI4_BURST_SIZE_4BYTES;
|
||||
axi4.arburst = `AXI4_BURST_TYPE_INCR;
|
||||
axi4.arlock = `AXI4_LOCK_NORM;
|
||||
axi4.arcache = `AXI4_CACHE_NO_BUF;
|
||||
axi4.arprot = `AXI4_PROT_DATA;
|
||||
axi4.arqos = `AXI4_QOS_NORMAL;
|
||||
axi4.arregion = `AXI4_REGION_NORMAL;
|
||||
axi4.aruser = '0;
|
||||
axi4.arvalid = 1'b0;
|
||||
axi4.rready = 1'b0;
|
||||
cfg_ribp.valid = 1'b0;
|
||||
cfg_ribp.addr = '0;
|
||||
cfg_ribp.wdata = '0;
|
||||
cfg_ribp.wstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_word(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
rib.addr = address;
|
||||
rib.wdata = data;
|
||||
rib.wstrb = strobe;
|
||||
rib.valid = 1'b1;
|
||||
do begin
|
||||
@(posedge clk_i);
|
||||
end while (!rib.ready);
|
||||
axi4.awaddr = address;
|
||||
axi4.awlen = 8'd0;
|
||||
axi4.awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.awready);
|
||||
@(negedge clk_i);
|
||||
rib.valid = 1'b0;
|
||||
rib.wstrb = '0;
|
||||
axi4.awvalid = 1'b0;
|
||||
axi4.wdata = data;
|
||||
axi4.wstrb = strobe;
|
||||
axi4.wlast = 1'b1;
|
||||
axi4.wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.wready);
|
||||
@(negedge clk_i);
|
||||
axi4.wvalid = 1'b0;
|
||||
axi4.wlast = 1'b0;
|
||||
axi4.bready = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.bvalid);
|
||||
if (axi4.bresp != `AXI4_RESP_OKAY) begin
|
||||
$fatal(1, "AXI4 SDRAM write failed at %08x", address);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
axi4.bready = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic read_word(input logic [31:0] address);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
rib.addr = address;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
rib.valid = 1'b1;
|
||||
do begin
|
||||
@(posedge clk_i);
|
||||
end while (!rib.ready);
|
||||
s_read_data = rib.rdata;
|
||||
axi4.araddr = address;
|
||||
axi4.arlen = 8'd0;
|
||||
axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.arready);
|
||||
@(negedge clk_i);
|
||||
rib.valid = 1'b0;
|
||||
axi4.arvalid = 1'b0;
|
||||
axi4.rready = 1'b1;
|
||||
do @(posedge clk_i); while (!axi4.rvalid);
|
||||
s_read_data = axi4.rdata;
|
||||
if (axi4.rresp != `AXI4_RESP_OKAY || !axi4.rlast) begin
|
||||
$fatal(1, "AXI4 SDRAM read failed at %08x", address);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
axi4.rready = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
rib.addr = '0;
|
||||
rib.valid = 1'b0;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
init_axi4();
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
@@ -104,6 +166,12 @@ module sdram_data_tb;
|
||||
$fatal(1, "masked SDRAM readback was %08x", s_read_data);
|
||||
end
|
||||
|
||||
write_word(`SOC_ADDR_SDRAM_BASE + 32'h03FF_FFFC, 32'hCAFE_BABE, 4'b1111);
|
||||
read_word(`SOC_ADDR_SDRAM_BASE + 32'h03FF_FFFC);
|
||||
if (s_read_data !== 32'hCAFE_BABE) begin
|
||||
$fatal(1, "high-address SDRAM readback was %08x", s_read_data);
|
||||
end
|
||||
|
||||
$display("sdram data integrity test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
Reference in new issue
Block a user