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
|
||||
|
||||
@@ -33,6 +33,7 @@ def test_axi42ribp_supports_bursts_backpressure_and_errors(tmp_path: Path) -> No
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_addr_gen.sv"),
|
||||
str(ROOT / "rtl/mini/top/axi42ribp_burst.sv"),
|
||||
str(ROOT / "tests/rtl/axi42ribp_burst_tb.sv"),
|
||||
"-Mdir",
|
||||
|
||||
@@ -56,7 +56,7 @@ def test_generated_artifacts_share_the_capacity_baseline(tmp_path: Path) -> None
|
||||
assert "`define CPU_RESET_ADDR `SOC_CPU_RESET_ADDR" in rtl
|
||||
assert "`define SOC_ADDR_IS_RESERVED(addr)" in rtl
|
||||
assert "RS_SOC_PSRAM_SIZE UINT32_C(0x00800000)" in header
|
||||
assert "RS_SOC_SDRAM_SIZE UINT32_C(0x02000000)" in header
|
||||
assert "RS_SOC_SDRAM_SIZE UINT32_C(0x04000000)" in header
|
||||
assert "RS_SOC_SPISD_SIZE UINT32_C(0x40000000)" in header
|
||||
assert "#ifdef __ASSEMBLER__" in header
|
||||
assert "#define UINT32_C(value) value" in header
|
||||
|
||||
+12
-2
@@ -35,9 +35,14 @@ def test_sdram_controller_preserves_full_and_masked_writes(tmp_path: Path) -> No
|
||||
[
|
||||
"+define+SV_ASSRT_DISABLE",
|
||||
f"+incdir+{generated / 'rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl/interface'}",
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_addr_gen.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "rtl/mini/top/axi42ribp_burst.sv"),
|
||||
str(ROOT / "rtl/mini/top/ribp_arbiter2.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram_clkgen.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram_reg.sv"),
|
||||
@@ -95,10 +100,15 @@ def test_sdram_controller_preserves_data_with_micron_timing_model(tmp_path: Path
|
||||
"+define+SV_ASSRT_DISABLE",
|
||||
"+define+SDRAM_TIMING_MODEL",
|
||||
f"+incdir+{generated / 'rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl/interface'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/third_party/model/sdram'}",
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/axi4_addr_gen.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "rtl/mini/top/axi42ribp_burst.sv"),
|
||||
str(ROOT / "rtl/mini/top/ribp_arbiter2.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram_clkgen.sv"),
|
||||
str(ROOT / "rtl/ip/memory/sdram_reg.sv"),
|
||||
|
||||
@@ -73,7 +73,7 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
|
||||
irq_sva = (tmp_path / "rtl/soc_irq_sva.svh").read_text(encoding="utf-8")
|
||||
filelist = (tmp_path / "soc_topology.fl").read_text(encoding="utf-8")
|
||||
|
||||
assert interfaces.count("ribp_if u_") == 18
|
||||
assert interfaces.count("ribp_if u_") == 17
|
||||
assert "nmi_if" not in interfaces
|
||||
assert "soc_nmi" not in interfaces
|
||||
assert "assign s_slv_sel_d[17] = u_i2c1_ribp_if.valid;" in routes
|
||||
@@ -359,6 +359,7 @@ def test_generated_rib_routes_select_and_return_the_expected_target(tmp_path: Pa
|
||||
f"+incdir+{memory_map_output / 'rtl'}",
|
||||
f"+incdir+{topology_output / 'rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
|
||||
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl/interface'}",
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/ribp_if.sv"),
|
||||
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
|
||||
str(ROOT / "tests/rtl/ribp_topology_tb.sv"),
|
||||
|
||||
@@ -52,7 +52,7 @@ def test_core_sdc_covers_current_clock_domains(tmp_path: Path) -> None:
|
||||
assert "get_pins -quiet" in sdc
|
||||
assert "get_ports -quiet" in sdc
|
||||
assert "set clk_jtag_port [require_ports \"clock jtag\" {jtag_tck_i_pad}]" in sdc
|
||||
assert "u_retrosoc.u_ip_ribp_wrapper.u_rib_dvp.u_dvp_pclk_clk_buf/clk_o" in sdc
|
||||
assert "u_retrosoc.u_ip_ribp_wrapper.u_axi4_dvp.u_dvp_pclk_clk_buf/clk_o" in sdc
|
||||
assert "-group [get_clocks {clk_external clk_system}]" in sdc
|
||||
assert "set_clock_transition 0.1 [get_clocks {clk_dvp}]" in sdc
|
||||
assert "set_input_transition" not in sdc
|
||||
|
||||
Reference in new issue
Block a user