mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
feat: add testbenches for on-chip RAM and resource controller, enhance AXI4 and APB4 support
- Introduced to validate AXI4 interface for 64-bit on-chip SRAM. - Added to test resource controller functionality including ownership, IRQ handling, and cache handshake. - Updated to include resource controller interface. - Enhanced to cover additional IRQ scenarios. - Added new tests in for AXI4 target guard timeout and isolation. - Updated to reflect changes in the high-performance profile. - Modified to verify on-chip SRAM bank configurations. - Added for directed verification of resource controller. - Updated to check SDRAM mapped window coverage. - Enhanced to ensure correct IRQ mappings and APB target generation.
This commit is contained in:
77 files changed
+2821
-513
No files matched your search
@@ -7,6 +7,8 @@ module axi4_data_crossbar_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic idle_o;
|
||||
logic [ 7:0] master_block_i = '0;
|
||||
logic [ 7:0] master_idle_o;
|
||||
logic [ 7:0] outstanding_read_o;
|
||||
logic [ 7:0] outstanding_write_o;
|
||||
logic fault_valid_o;
|
||||
@@ -46,6 +48,7 @@ module axi4_data_crossbar_tb;
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.block_new_i (1'b0),
|
||||
.master_block_i (master_block_i),
|
||||
.recovery_i (1'b0),
|
||||
.mem_pad_mode_i (2'd1),
|
||||
.ext_h_read_base_i (32'h3000_0000),
|
||||
@@ -55,6 +58,7 @@ module axi4_data_crossbar_tb;
|
||||
.masters (masters),
|
||||
.targets (targets),
|
||||
.idle_o (idle_o),
|
||||
.master_idle_o (master_idle_o),
|
||||
.outstanding_read_o (outstanding_read_o),
|
||||
.outstanding_write_o(outstanding_write_o),
|
||||
.fault_valid_o (fault_valid_o),
|
||||
@@ -172,6 +176,18 @@ module axi4_data_crossbar_tb;
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
@(negedge clk_i);
|
||||
master_block_i[1] = 1'b1;
|
||||
masters[1].arid = 6'b001_111;
|
||||
masters[1].araddr = 32'h3000_0000;
|
||||
masters[1].arvalid = 1'b1;
|
||||
#1;
|
||||
if (masters[1].arready || master_idle_o[1]) begin
|
||||
$fatal(1, "blocked master was accepted or reported idle with VALID held");
|
||||
end
|
||||
masters[1].arvalid = 1'b0;
|
||||
master_block_i[1] = 1'b0;
|
||||
|
||||
issue_master1_read(6'b001_000, 32'h3000_0000);
|
||||
issue_master1_read(6'b001_001, 32'h3800_0000);
|
||||
if (outstanding_read_o != 8'd2 || idle_o) begin
|
||||
@@ -201,6 +217,35 @@ module axi4_data_crossbar_tb;
|
||||
$fatal(1, "read completion did not drain the crossbar");
|
||||
end
|
||||
|
||||
issue_master1_read(6'b001_010, 32'h3000_0040);
|
||||
issue_master1_read(6'b001_011, 32'h3000_0080);
|
||||
if (outstanding_read_o != 8'd2) begin
|
||||
$fatal(1, "same-target reads were not tracked concurrently");
|
||||
end
|
||||
fork
|
||||
return_target0_read(6'b001_011, 64'h3333_3333_3333_3333);
|
||||
begin
|
||||
wait (masters[1].rvalid);
|
||||
if ((masters[1].rid != 6'b001_011) || (masters[1].rdata != 64'h3333_3333_3333_3333)) begin
|
||||
$fatal(1, "same-target out-of-order response was misrouted");
|
||||
end
|
||||
end
|
||||
join
|
||||
@(posedge clk_i);
|
||||
fork
|
||||
return_target0_read(6'b001_010, 64'h4444_4444_4444_4444);
|
||||
begin
|
||||
wait (masters[1].rvalid);
|
||||
if ((masters[1].rid != 6'b001_010) || (masters[1].rdata != 64'h4444_4444_4444_4444)) begin
|
||||
$fatal(1, "same-target older response was misrouted");
|
||||
end
|
||||
end
|
||||
join
|
||||
@(negedge clk_i);
|
||||
if (!idle_o || (outstanding_read_o != 8'd0)) begin
|
||||
$fatal(1, "same-target reads did not drain the crossbar");
|
||||
end
|
||||
|
||||
@(negedge clk_i);
|
||||
masters[6].arid = 6'b110_000;
|
||||
masters[6].araddr = 32'h3000_0000;
|
||||
|
||||
@@ -30,6 +30,7 @@ module axi4_downsizer_64to32_tb;
|
||||
axi4_downsizer_64to32 u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.clear_i(1'b0),
|
||||
.wide (wide),
|
||||
.narrow (narrow)
|
||||
);
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module axi4_target_guard_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic abort_o;
|
||||
logic timeout_valid_o;
|
||||
logic timeout_write_o;
|
||||
logic [ 5:0] timeout_id_o;
|
||||
logic [31:0] timeout_addr_o;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.USER_WIDTH(1)
|
||||
) source (
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.USER_WIDTH(1)
|
||||
) sink (
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
axi4_target_guard #(
|
||||
.ReadDepth (4),
|
||||
.WriteDepth(2)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.clear_i (1'b0),
|
||||
.timeout_i (32'd4),
|
||||
.clear_busy_o (),
|
||||
.abort_o (abort_o),
|
||||
.abort_done_i (abort_o),
|
||||
.timeout_valid_o(timeout_valid_o),
|
||||
.timeout_write_o(timeout_write_o),
|
||||
.timeout_id_o (timeout_id_o),
|
||||
.timeout_addr_o (timeout_addr_o),
|
||||
.source (source),
|
||||
.sink (sink)
|
||||
);
|
||||
|
||||
task automatic issue_read(input logic [5:0] id, input logic [7:0] len, input logic [31:0] addr);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
source.arid = id;
|
||||
source.arlen = len;
|
||||
source.araddr = addr;
|
||||
source.arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.arready);
|
||||
@(negedge clk_i);
|
||||
source.arvalid = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_error_read(input logic [5:0] id, input int unsigned beats);
|
||||
begin
|
||||
for (int beat = 0; beat < beats; beat++) begin
|
||||
do @(posedge clk_i); while (!source.rvalid);
|
||||
if ((source.rid != id) || (source.rresp != 2'b10) ||
|
||||
(source.rlast != (beat == beats - 1))) begin
|
||||
$fatal(1, "target guard synthetic read response mismatch");
|
||||
end
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
source.awid = '0;
|
||||
source.awaddr = '0;
|
||||
source.awlen = '0;
|
||||
source.awsize = 3'd3;
|
||||
source.awburst = 2'b01;
|
||||
source.awlock = 1'b0;
|
||||
source.awcache = '0;
|
||||
source.awprot = '0;
|
||||
source.awqos = '0;
|
||||
source.awregion = '0;
|
||||
source.awuser = '0;
|
||||
source.awvalid = 1'b0;
|
||||
source.wdata = '0;
|
||||
source.wstrb = '0;
|
||||
source.wlast = 1'b1;
|
||||
source.wuser = '0;
|
||||
source.wvalid = 1'b0;
|
||||
source.bready = 1'b1;
|
||||
source.arid = '0;
|
||||
source.araddr = '0;
|
||||
source.arlen = '0;
|
||||
source.arsize = 3'd3;
|
||||
source.arburst = 2'b01;
|
||||
source.arlock = 1'b0;
|
||||
source.arcache = '0;
|
||||
source.arprot = '0;
|
||||
source.arqos = '0;
|
||||
source.arregion = '0;
|
||||
source.aruser = '0;
|
||||
source.arvalid = 1'b0;
|
||||
source.rready = 1'b1;
|
||||
|
||||
sink.awready = 1'b1;
|
||||
sink.wready = 1'b1;
|
||||
sink.bid = '0;
|
||||
sink.bresp = '0;
|
||||
sink.buser = '0;
|
||||
sink.bvalid = 1'b0;
|
||||
sink.arready = 1'b1;
|
||||
sink.rid = '0;
|
||||
sink.rdata = '0;
|
||||
sink.rresp = '0;
|
||||
sink.rlast = 1'b0;
|
||||
sink.ruser = '0;
|
||||
sink.rvalid = 1'b0;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
issue_read(6'h09, 8'd1, 32'h3800_0040);
|
||||
wait (timeout_valid_o);
|
||||
if (timeout_write_o || (timeout_id_o != 6'h09) || (timeout_addr_o != 32'h3800_0040)) begin
|
||||
$fatal(1, "target guard read timeout attribution mismatch");
|
||||
end
|
||||
expect_error_read(6'h09, 2);
|
||||
|
||||
fork
|
||||
begin
|
||||
issue_read(6'h0A, 8'd0, 32'h3800_0080);
|
||||
expect_error_read(6'h0A, 1);
|
||||
end
|
||||
begin
|
||||
repeat (12) begin
|
||||
@(posedge clk_i);
|
||||
if (sink.arvalid) $fatal(1, "isolated target accepted a new read");
|
||||
end
|
||||
end
|
||||
join
|
||||
|
||||
@(negedge clk_i);
|
||||
source.awid = 6'h0B;
|
||||
source.awaddr = 32'h3800_0100;
|
||||
source.awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.awready);
|
||||
@(negedge clk_i);
|
||||
source.awvalid = 1'b0;
|
||||
source.wdata = 64'h0123_4567_89AB_CDEF;
|
||||
source.wstrb = 8'hFF;
|
||||
source.wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!source.wready);
|
||||
@(negedge clk_i);
|
||||
source.wvalid = 1'b0;
|
||||
do @(posedge clk_i); while (!source.bvalid);
|
||||
if ((source.bid != 6'h0B) || (source.bresp != 2'b10) || sink.awvalid || sink.wvalid) begin
|
||||
$fatal(1, "isolated target write termination mismatch");
|
||||
end
|
||||
|
||||
$display("AXI4 target guard timeout and isolation test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (200) @(posedge clk_i);
|
||||
$fatal(1, "AXI4 target guard test timed out");
|
||||
end
|
||||
endmodule
|
||||
@@ -6,26 +6,30 @@ module hp_lifecycle_controller_tb;
|
||||
logic release_req_i = 1'b0;
|
||||
logic hp_idle_i = 1'b0;
|
||||
logic flush_busy_i = 1'b0;
|
||||
logic cache_clean_i = 1'b0;
|
||||
logic hp_release_o;
|
||||
logic block_new_o;
|
||||
logic flush_o;
|
||||
logic cache_request_o;
|
||||
logic draining_o;
|
||||
logic forced_fault_o;
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
hp_lifecycle_controller u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.release_req_i (release_req_i),
|
||||
.hp_idle_i (hp_idle_i),
|
||||
.flush_busy_i (flush_busy_i),
|
||||
.timeout_i (16'd4),
|
||||
.hp_release_o (hp_release_o),
|
||||
.block_new_o (block_new_o),
|
||||
.flush_o (flush_o),
|
||||
.draining_o (draining_o),
|
||||
.forced_fault_o(forced_fault_o)
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.release_req_i (release_req_i),
|
||||
.hp_idle_i (hp_idle_i),
|
||||
.flush_busy_i (flush_busy_i),
|
||||
.cache_clean_i (cache_clean_i),
|
||||
.timeout_i (16'd4),
|
||||
.hp_release_o (hp_release_o),
|
||||
.block_new_o (block_new_o),
|
||||
.flush_o (flush_o),
|
||||
.cache_request_o(cache_request_o),
|
||||
.draining_o (draining_o),
|
||||
.forced_fault_o (forced_fault_o)
|
||||
);
|
||||
|
||||
task automatic complete_flush;
|
||||
@@ -50,6 +54,14 @@ module hp_lifecycle_controller_tb;
|
||||
|
||||
@(negedge clk_i);
|
||||
release_req_i = 1'b0;
|
||||
wait (cache_request_o);
|
||||
if (block_new_o || !hp_release_o) begin
|
||||
$fatal(1, "cache-maintenance phase blocked HP before acknowledgement");
|
||||
end
|
||||
cache_clean_i = 1'b1;
|
||||
@(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
cache_clean_i = 1'b0;
|
||||
repeat (2) @(negedge clk_i);
|
||||
if (!block_new_o || !draining_o || !hp_release_o) begin
|
||||
$fatal(1, "normal shutdown did not enter drain while HP remained released");
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "axi4_define.svh"
|
||||
`include "mmap_define.svh"
|
||||
|
||||
module onchip_ram64_tb #(
|
||||
parameter int unsigned CapacityKiB = 32
|
||||
);
|
||||
localparam logic [31:0] SramBase = `SOC_ADDR_SRAM_BASE;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(64),
|
||||
.ID_WIDTH (6),
|
||||
.USER_WIDTH(1)
|
||||
) mem_axi4 (
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
apb4_if cfg_apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
onchip_ram #(
|
||||
.Present (1'b1),
|
||||
.CapacityKiB(CapacityKiB),
|
||||
.DataWidth (64),
|
||||
.IdWidth (6)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.perf_enable_i(1'b1),
|
||||
.perf_clear_i (1'b0),
|
||||
.mem_axi4 (mem_axi4),
|
||||
.cfg_apb4 (cfg_apb4)
|
||||
);
|
||||
|
||||
task automatic issue_write(input logic [5:0] id, input logic [31:0] address,
|
||||
input logic [7:0] length, input logic [2:0] size,
|
||||
input logic [63:0] seed, input logic [7:0] strobe);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
mem_axi4.awid = id;
|
||||
mem_axi4.awaddr = address;
|
||||
mem_axi4.awlen = length;
|
||||
mem_axi4.awsize = size;
|
||||
mem_axi4.awvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!mem_axi4.awready);
|
||||
@(negedge clk_i);
|
||||
mem_axi4.awvalid = 1'b0;
|
||||
for (int beat = 0; beat <= int'(length); beat++) begin
|
||||
mem_axi4.wdata = seed + beat;
|
||||
mem_axi4.wstrb = strobe;
|
||||
mem_axi4.wlast = beat == int'(length);
|
||||
mem_axi4.wvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!mem_axi4.wready);
|
||||
@(negedge clk_i);
|
||||
end
|
||||
mem_axi4.wvalid = 1'b0;
|
||||
mem_axi4.wlast = 1'b0;
|
||||
mem_axi4.bready = 1'b1;
|
||||
do @(posedge clk_i); while (!mem_axi4.bvalid);
|
||||
if ((mem_axi4.bid != id) || (mem_axi4.bresp != `AXI4_RESP_OKAY)) begin
|
||||
$fatal(1, "AXI64 SRAM write response mismatch");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
mem_axi4.bready = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_read(input logic [5:0] id, input logic [31:0] address,
|
||||
input logic [7:0] length, input logic [63:0] seed);
|
||||
integer previous_cycle;
|
||||
integer cycle_count;
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
mem_axi4.arid = id;
|
||||
mem_axi4.araddr = address;
|
||||
mem_axi4.arlen = length;
|
||||
mem_axi4.arsize = 3'd3;
|
||||
mem_axi4.arvalid = 1'b1;
|
||||
do @(posedge clk_i); while (!mem_axi4.arready);
|
||||
@(negedge clk_i);
|
||||
mem_axi4.arvalid = 1'b0;
|
||||
mem_axi4.rready = 1'b1;
|
||||
previous_cycle = -1;
|
||||
cycle_count = 0;
|
||||
for (int beat = 0; beat <= int'(length); beat++) begin
|
||||
do begin
|
||||
@(posedge clk_i);
|
||||
cycle_count = cycle_count + 1;
|
||||
end while (!mem_axi4.rvalid);
|
||||
if ((mem_axi4.rid != id) || (mem_axi4.rresp != `AXI4_RESP_OKAY) ||
|
||||
(mem_axi4.rlast != (beat == int'(length))) ||
|
||||
(mem_axi4.rdata != (seed + beat))) begin
|
||||
$fatal(1, "AXI64 SRAM read response mismatch at beat %0d", beat);
|
||||
end
|
||||
if ((previous_cycle >= 0) && (cycle_count != previous_cycle + 1)) begin
|
||||
$fatal(1, "AXI64 SRAM read burst inserted a bubble at beat %0d", beat);
|
||||
end
|
||||
previous_cycle = cycle_count;
|
||||
end
|
||||
@(negedge clk_i);
|
||||
mem_axi4.rready = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
mem_axi4.awid = '0;
|
||||
mem_axi4.awaddr = '0;
|
||||
mem_axi4.awlen = '0;
|
||||
mem_axi4.awsize = 3'd3;
|
||||
mem_axi4.awburst = `AXI4_BURST_TYPE_INCR;
|
||||
mem_axi4.awlock = `AXI4_LOCK_NORM;
|
||||
mem_axi4.awcache = `AXI4_CACHE_NO_BUF;
|
||||
mem_axi4.awprot = `AXI4_PROT_DATA;
|
||||
mem_axi4.awqos = `AXI4_QOS_NORMAL;
|
||||
mem_axi4.awregion = `AXI4_REGION_NORMAL;
|
||||
mem_axi4.awuser = '0;
|
||||
mem_axi4.awvalid = 1'b0;
|
||||
mem_axi4.wdata = '0;
|
||||
mem_axi4.wstrb = '0;
|
||||
mem_axi4.wlast = 1'b0;
|
||||
mem_axi4.wuser = '0;
|
||||
mem_axi4.wvalid = 1'b0;
|
||||
mem_axi4.bready = 1'b0;
|
||||
mem_axi4.arid = '0;
|
||||
mem_axi4.araddr = '0;
|
||||
mem_axi4.arlen = '0;
|
||||
mem_axi4.arsize = 3'd3;
|
||||
mem_axi4.arburst = `AXI4_BURST_TYPE_INCR;
|
||||
mem_axi4.arlock = `AXI4_LOCK_NORM;
|
||||
mem_axi4.arcache = `AXI4_CACHE_NO_BUF;
|
||||
mem_axi4.arprot = `AXI4_PROT_DATA;
|
||||
mem_axi4.arqos = `AXI4_QOS_NORMAL;
|
||||
mem_axi4.arregion = `AXI4_REGION_NORMAL;
|
||||
mem_axi4.aruser = '0;
|
||||
mem_axi4.arvalid = 1'b0;
|
||||
mem_axi4.rready = 1'b0;
|
||||
cfg_apb4.paddr = '0;
|
||||
cfg_apb4.pprot = '0;
|
||||
cfg_apb4.psel = 1'b0;
|
||||
cfg_apb4.penable = 1'b0;
|
||||
cfg_apb4.pwrite = 1'b0;
|
||||
cfg_apb4.pwdata = '0;
|
||||
cfg_apb4.pstrb = '0;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
issue_write(6'h2A, SramBase + 32'h100, 8'd3, 3'd3, 64'h1000_2000_3000_4000, 8'hFF);
|
||||
expect_read(6'h2B, SramBase + 32'h100, 8'd3, 64'h1000_2000_3000_4000);
|
||||
issue_write(6'h2C, SramBase + 32'h10C, 8'd0, 3'd2, 64'hDEAD_BEEF_0000_0000, 8'hF0);
|
||||
expect_read(6'h2D, SramBase + 32'h108, 8'd0, 64'hDEAD_BEEF_3000_4001);
|
||||
|
||||
$display("native AXI64 on-chip SRAM test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (400) @(posedge clk_i);
|
||||
$fatal(1, "native AXI64 on-chip SRAM test timed out");
|
||||
end
|
||||
endmodule
|
||||
@@ -0,0 +1,146 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module resource_controller_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [ 5:0] idle_i = '0;
|
||||
logic [ 5:0] block_ack_i = '0;
|
||||
logic [ 5:0] irq_i = '0;
|
||||
logic cache_request_i = 1'b0;
|
||||
logic cache_clean_o;
|
||||
logic [ 5:0][1:0] owner_o;
|
||||
logic [ 5:0] quiesce_o;
|
||||
logic [ 5:0] reset_o;
|
||||
logic [ 5:0] irq_lp_o;
|
||||
logic [ 5:0] irq_hp_o;
|
||||
logic fault_irq_o;
|
||||
logic [31:0] read_data;
|
||||
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
resource_controller u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.idle_i (idle_i),
|
||||
.block_ack_i (block_ack_i),
|
||||
.irq_i (irq_i),
|
||||
.cache_request_i(cache_request_i),
|
||||
.cache_clean_o (cache_clean_o),
|
||||
.owner_o (owner_o),
|
||||
.quiesce_o (quiesce_o),
|
||||
.reset_o (reset_o),
|
||||
.irq_lp_o (irq_lp_o),
|
||||
.irq_hp_o (irq_hp_o),
|
||||
.fault_irq_o (fault_irq_o),
|
||||
.apb4 (apb4)
|
||||
);
|
||||
|
||||
task automatic apb_write(input logic [11:0] offset, input logic [31:0] data,
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
apb4.paddr = {20'd0, offset};
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b1;
|
||||
do @(posedge clk_i); while (!apb4.pready);
|
||||
if (apb4.pslverr != expected_error) begin
|
||||
$fatal(1, "resource controller write error mismatch at %h", offset);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb_read(input logic [11:0] offset, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
apb4.paddr = {20'd0, offset};
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b1;
|
||||
do @(posedge clk_i); while (!apb4.pready);
|
||||
if (apb4.pslverr) $fatal(1, "resource controller read failed at %h", offset);
|
||||
data = apb4.prdata;
|
||||
@(negedge clk_i);
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
apb4.paddr = '0;
|
||||
apb4.pprot = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
idle_i = 6'h3F;
|
||||
|
||||
apb_read(12'h000, read_data);
|
||||
if (read_data != 32'h5253_4354) $fatal(1, "resource controller ID mismatch");
|
||||
|
||||
irq_i[1] = 1'b1;
|
||||
#1;
|
||||
if (!irq_lp_o[1] || irq_hp_o[1]) $fatal(1, "default LP IRQ ownership mismatch");
|
||||
|
||||
idle_i[0] = 1'b0;
|
||||
block_ack_i[0] = 1'b1;
|
||||
apb_write(12'h104, 32'h0000_0001, 1'b0);
|
||||
apb_write(12'h100, 32'h0000_0001, 1'b1);
|
||||
if (!fault_irq_o || (owner_o[0] != 2'd0)) begin
|
||||
$fatal(1, "busy resource handoff did not fail closed");
|
||||
end
|
||||
apb_write(12'h10C, 32'h0000_0001, 1'b0);
|
||||
if (fault_irq_o) $fatal(1, "resource fault did not clear");
|
||||
|
||||
idle_i[0] = 1'b1;
|
||||
irq_i[0] = 1'b1;
|
||||
apb_write(12'h100, 32'h0000_0001, 1'b0);
|
||||
if ((owner_o[0] != 2'd1) || irq_lp_o[0] || !irq_hp_o[0]) begin
|
||||
$fatal(1, "HP resource ownership or IRQ routing mismatch");
|
||||
end
|
||||
apb_read(12'h110, read_data);
|
||||
if (read_data != 32'd1) $fatal(1, "resource handoff counter mismatch");
|
||||
|
||||
apb_write(12'h100, 32'h0000_0101, 1'b0);
|
||||
apb_write(12'h100, 32'h0000_0000, 1'b1);
|
||||
if (owner_o[0] != 2'd1) $fatal(1, "locked resource owner changed");
|
||||
|
||||
cache_request_i = 1'b1;
|
||||
apb_write(12'h010, 32'h0000_0001, 1'b0);
|
||||
if (!cache_clean_o) $fatal(1, "cache maintenance acknowledgement was not retained");
|
||||
cache_request_i = 1'b0;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (cache_clean_o) $fatal(1, "cache acknowledgement did not clear with request");
|
||||
|
||||
apb_write(12'h124, 32'h0000_0003, 1'b0);
|
||||
if (!quiesce_o[1] || !reset_o[1]) begin
|
||||
$fatal(1, "resource lifecycle controls did not update");
|
||||
end
|
||||
|
||||
$display("Resource Controller ownership, IRQ, and cache handshake test passed");
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
repeat (300) @(posedge clk_i);
|
||||
$fatal(1, "Resource Controller test timed out");
|
||||
end
|
||||
endmodule
|
||||
+48
-43
@@ -20,54 +20,59 @@ module rib2apb_tb;
|
||||
apb4_pure_if user_ip ();
|
||||
apb4_pure_if ext_l ();
|
||||
apb4_pure_if ext_h ();
|
||||
apb4_pure_if resource_ctrl ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
assign archinfo.pready = 1'b0;
|
||||
assign archinfo.prdata = '0;
|
||||
assign archinfo.pslverr = 1'b0;
|
||||
assign rng.pready = rng_ready;
|
||||
assign rng.prdata = rng_rdata;
|
||||
assign rng.pslverr = rng_slverr;
|
||||
assign pwm.pready = 1'b0;
|
||||
assign pwm.prdata = '0;
|
||||
assign pwm.pslverr = 1'b0;
|
||||
assign ps2.pready = 1'b0;
|
||||
assign ps2.prdata = '0;
|
||||
assign ps2.pslverr = 1'b0;
|
||||
assign rtc.pready = 1'b0;
|
||||
assign rtc.prdata = '0;
|
||||
assign rtc.pslverr = 1'b0;
|
||||
assign wdg.pready = 1'b0;
|
||||
assign wdg.prdata = '0;
|
||||
assign wdg.pslverr = 1'b0;
|
||||
assign crc.pready = 1'b0;
|
||||
assign crc.prdata = '0;
|
||||
assign crc.pslverr = 1'b0;
|
||||
assign user_ip.pready = 1'b0;
|
||||
assign user_ip.prdata = '0;
|
||||
assign user_ip.pslverr = 1'b0;
|
||||
assign ext_l.pready = 1'b0;
|
||||
assign ext_l.prdata = '0;
|
||||
assign ext_l.pslverr = 1'b0;
|
||||
assign ext_h.pready = 1'b0;
|
||||
assign ext_h.prdata = '0;
|
||||
assign ext_h.pslverr = 1'b0;
|
||||
assign archinfo.pready = 1'b0;
|
||||
assign archinfo.prdata = '0;
|
||||
assign archinfo.pslverr = 1'b0;
|
||||
assign rng.pready = rng_ready;
|
||||
assign rng.prdata = rng_rdata;
|
||||
assign rng.pslverr = rng_slverr;
|
||||
assign pwm.pready = 1'b0;
|
||||
assign pwm.prdata = '0;
|
||||
assign pwm.pslverr = 1'b0;
|
||||
assign ps2.pready = 1'b0;
|
||||
assign ps2.prdata = '0;
|
||||
assign ps2.pslverr = 1'b0;
|
||||
assign rtc.pready = 1'b0;
|
||||
assign rtc.prdata = '0;
|
||||
assign rtc.pslverr = 1'b0;
|
||||
assign wdg.pready = 1'b0;
|
||||
assign wdg.prdata = '0;
|
||||
assign wdg.pslverr = 1'b0;
|
||||
assign crc.pready = 1'b0;
|
||||
assign crc.prdata = '0;
|
||||
assign crc.pslverr = 1'b0;
|
||||
assign user_ip.pready = 1'b0;
|
||||
assign user_ip.prdata = '0;
|
||||
assign user_ip.pslverr = 1'b0;
|
||||
assign ext_l.pready = 1'b0;
|
||||
assign ext_l.prdata = '0;
|
||||
assign ext_l.pslverr = 1'b0;
|
||||
assign ext_h.pready = 1'b0;
|
||||
assign ext_h.prdata = '0;
|
||||
assign ext_h.pslverr = 1'b0;
|
||||
assign resource_ctrl.pready = 1'b0;
|
||||
assign resource_ctrl.prdata = '0;
|
||||
assign resource_ctrl.pslverr = 1'b0;
|
||||
|
||||
rib2apb u_rib2apb (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.rib (rib),
|
||||
.archinfo(archinfo),
|
||||
.rng (rng),
|
||||
.pwm (pwm),
|
||||
.ps2 (ps2),
|
||||
.rtc (rtc),
|
||||
.wdg (wdg),
|
||||
.crc (crc),
|
||||
.user_ip (user_ip),
|
||||
.ext_l (ext_l),
|
||||
.ext_h (ext_h)
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.rib (rib),
|
||||
.archinfo (archinfo),
|
||||
.rng (rng),
|
||||
.pwm (pwm),
|
||||
.ps2 (ps2),
|
||||
.rtc (rtc),
|
||||
.wdg (wdg),
|
||||
.crc (crc),
|
||||
.user_ip (user_ip),
|
||||
.ext_l (ext_l),
|
||||
.ext_h (ext_h),
|
||||
.resource_ctrl(resource_ctrl)
|
||||
);
|
||||
|
||||
task automatic send_command(input logic [31:0] address, input logic write,
|
||||
|
||||
@@ -58,6 +58,7 @@ module soc_irq_topology_tb;
|
||||
4: expect_irq(32'd1 << 16);
|
||||
5: expect_irq(32'd1 << 27);
|
||||
6: expect_irq(32'd1 << 28);
|
||||
7: expect_irq(32'd1 << 29);
|
||||
default: $fatal(1, "unexpected APB IRQ bit %0d", bit_index);
|
||||
endcase
|
||||
end
|
||||
@@ -68,7 +69,7 @@ module soc_irq_topology_tb;
|
||||
$fatal(1, "SDIO core IRQ bits are not low when sources are low: IRQ10=%b IRQ21=%b",
|
||||
s_irq[10], s_irq[21]);
|
||||
end
|
||||
if ((s_irq[31:29] !== '0) || (s_irq[19:18] !== '0)) begin
|
||||
if ((s_irq[31:30] !== '0) || (s_irq[19:18] !== '0)) begin
|
||||
$fatal(1, "unallocated core IRQ bits are not low: %h", s_irq);
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user