mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-06 14:55:14 +00:00
refactor: refactor tests to replace RIBP references with APB4 equivalents
- Updated test files to change instances of ribp_if to apb4_if in various test cases, ensuring consistency with the new APB4 interface. - Modified assertions and checks in tests to reflect the new APB4 naming conventions, including changes in expected output and input files. - Adjusted the test descriptions to accurately represent the APB4 functionality being tested, particularly in timer, UART, and GPIO tests. - Ensured that all relevant paths and file names in the tests are updated to point to the new APB4 implementations, maintaining the integrity of the test suite.
This commit is contained in:
153 files changed
+5566
-3744
No files matched your search
@@ -0,0 +1,61 @@
|
||||
// Shared APB4 master helpers for unit tests.
|
||||
// The including module must provide clk_i and an apb4_if instance.
|
||||
`ifndef APB4_BFM_IF
|
||||
`define APB4_BFM_IF apb4
|
||||
`endif
|
||||
|
||||
task automatic apb4_idle();
|
||||
begin
|
||||
`APB4_BFM_IF.psel = 1'b0;
|
||||
`APB4_BFM_IF.penable = 1'b0;
|
||||
`APB4_BFM_IF.pwrite = 1'b0;
|
||||
`APB4_BFM_IF.paddr = '0;
|
||||
`APB4_BFM_IF.pwdata = '0;
|
||||
`APB4_BFM_IF.pstrb = '0;
|
||||
`APB4_BFM_IF.pprot = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb4_xfer(input logic [31:0] address, input logic write, input logic [31:0] wdata,
|
||||
input logic [3:0] strobe, input logic expected_error,
|
||||
output logic [31:0] rdata);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
`APB4_BFM_IF.paddr = address;
|
||||
`APB4_BFM_IF.pwdata = wdata;
|
||||
`APB4_BFM_IF.pstrb = write ? strobe : 4'h0;
|
||||
`APB4_BFM_IF.pwrite = write;
|
||||
`APB4_BFM_IF.pprot = '0;
|
||||
`APB4_BFM_IF.psel = 1'b1;
|
||||
`APB4_BFM_IF.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
`APB4_BFM_IF.penable = 1'b1;
|
||||
while (!`APB4_BFM_IF.pready) begin
|
||||
@(negedge clk_i);
|
||||
end
|
||||
if (`APB4_BFM_IF.pslverr !== expected_error) begin
|
||||
$fatal(1, "APB4 %s %h error=%b expected=%b", write ? "write" : "read", address,
|
||||
`APB4_BFM_IF.pslverr, expected_error);
|
||||
end
|
||||
rdata = `APB4_BFM_IF.prdata;
|
||||
`APB4_BFM_IF.psel = 1'b0;
|
||||
`APB4_BFM_IF.penable = 1'b0;
|
||||
`APB4_BFM_IF.pwrite = 1'b0;
|
||||
`APB4_BFM_IF.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error);
|
||||
logic [31:0] unused_rdata;
|
||||
begin
|
||||
apb4_xfer(address, 1'b1, data, strobe, expected_error, unused_rdata);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
|
||||
output logic [31:0] data);
|
||||
begin
|
||||
apb4_xfer(address, 1'b0, 32'd0, 4'h0, expected_error, data);
|
||||
end
|
||||
endtask
|
||||
@@ -0,0 +1,47 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "mmap_define.svh"
|
||||
|
||||
module apb4_topology_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b1;
|
||||
logic [31:0] s_decode_addr = 32'd0;
|
||||
|
||||
`include "apb4_periph_declarations.svh"
|
||||
`include "apb4_periph_select_routes.svh"
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
task automatic expect_select(input logic [31:0] address, input integer slot);
|
||||
begin
|
||||
s_decode_addr = address;
|
||||
#1;
|
||||
if (s_psel_comb !== (18'd1 << slot)) begin
|
||||
$fatal(1, "unexpected APB4 target slot for %h: got %b", address, s_psel_comb);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_disabled(input logic [31:0] address);
|
||||
begin
|
||||
s_decode_addr = address;
|
||||
#1;
|
||||
if (s_psel_comb !== '0) begin
|
||||
$fatal(1, "disabled APB4 target accepted %h: got %b", address, s_psel_comb);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
expect_select(`SOC_ADDR_APB4_GPIO_BASE, 1);
|
||||
expect_select(`SOC_ADDR_APB4_GPIO_ADMIN_BASE, 1);
|
||||
expect_select(`SOC_ADDR_APB4_PSRAM_BASE, 4);
|
||||
expect_select(`SOC_ADDR_APB4_XPI_BASE, 9);
|
||||
expect_select(`SOC_ADDR_APB4_SDRAM_BASE, 13);
|
||||
expect_select(`SOC_ADDR_APB4_I2C1_BASE, 17);
|
||||
expect_disabled(`SOC_ADDR_APB4_SDIO_BASE);
|
||||
expect_disabled(`SOC_ADDR_APB4_OPIPSRAM_BASE);
|
||||
$display("SoC topology APB4 routing test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -62,7 +62,7 @@ module axi4_interconnect_tb;
|
||||
.perf_mgmt_wait_o (),
|
||||
.perf_user_wait_o (),
|
||||
.perf_dma_wait_o (),
|
||||
.perf_ribp_wait_o (),
|
||||
.perf_apb4_wait_o (),
|
||||
.perf_apb_wait_o (),
|
||||
.perf_sdram_wait_o(),
|
||||
.perf_psram_wait_o(),
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
`include "axi4_define.svh"
|
||||
|
||||
module axi42ribp_burst_tb;
|
||||
module axi4_word_bridge_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic [31:0] memory [0:63];
|
||||
@@ -22,39 +22,51 @@ module axi42ribp_burst_tb;
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
ribp_if ribp ();
|
||||
logic req_valid;
|
||||
logic req_ready;
|
||||
logic [31:0] req_addr;
|
||||
logic [31:0] req_wdata;
|
||||
logic [ 3:0] req_wstrb;
|
||||
logic [31:0] req_rdata;
|
||||
logic req_resp_err;
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
always @(posedge clk_i) cycle_count <= cycle_count + 1;
|
||||
|
||||
axi42ribp_burst u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.axi4 (axi4),
|
||||
.ribp (ribp)
|
||||
axi4_word_bridge u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.axi4 (axi4),
|
||||
.req_valid_o (req_valid),
|
||||
.req_ready_i (req_ready),
|
||||
.req_addr_o (req_addr),
|
||||
.req_wdata_o (req_wdata),
|
||||
.req_wstrb_o (req_wstrb),
|
||||
.req_rdata_i (req_rdata),
|
||||
.req_resp_err_i(req_resp_err)
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
ribp.ready <= 1'b0;
|
||||
ribp.rdata <= '0;
|
||||
req_ready <= 1'b0;
|
||||
req_rdata <= '0;
|
||||
target_accesses <= 0;
|
||||
end else begin
|
||||
ribp.ready <= ribp.valid && !ribp.ready;
|
||||
if (ribp.valid && !ribp.ready) begin
|
||||
req_ready <= req_valid && !req_ready;
|
||||
if (req_valid && !req_ready) begin
|
||||
target_accesses <= target_accesses + 1;
|
||||
ribp.rdata <= memory[ribp.addr[7:2]];
|
||||
req_rdata <= memory[req_addr[7:2]];
|
||||
for (int lane = 0; lane < 4; lane++) begin
|
||||
if (ribp.wstrb[lane]) begin
|
||||
memory[ribp.addr[7:2]][lane*8+:8] <= ribp.wdata[lane*8+:8];
|
||||
if (req_wstrb[lane]) begin
|
||||
memory[req_addr[7:2]][lane*8+:8] <= req_wdata[lane*8+:8];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign ribp.resp_err = 1'b0;
|
||||
assign req_resp_err = 1'b0;
|
||||
|
||||
task automatic init_axi4;
|
||||
begin
|
||||
@@ -172,7 +184,7 @@ module axi42ribp_burst_tb;
|
||||
@(negedge clk_i);
|
||||
axi4.rready = 1'b0;
|
||||
if (target_accesses != accesses_before) begin
|
||||
$fatal(1, "illegal burst reached the RIBP target");
|
||||
$fatal(1, "illegal burst reached the word target");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
@@ -204,7 +216,7 @@ module axi42ribp_burst_tb;
|
||||
axi4.bready = 1'b0;
|
||||
axi4.wlast = 1'b0;
|
||||
if (target_accesses != accesses_before + 1) begin
|
||||
$fatal(1, "early WLAST must commit exactly one RIBP beat");
|
||||
$fatal(1, "early WLAST must commit exactly one word beat");
|
||||
end
|
||||
end
|
||||
endtask
|
||||
@@ -299,8 +311,8 @@ 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 != 49) $fatal(1, "unexpected RIBP access count");
|
||||
$display("AXI4 to RIBP burst bridge test passed");
|
||||
if (target_accesses != 49) $fatal(1, "unexpected word access count");
|
||||
$display("AXI4 word bridge test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
+29
-14
@@ -11,7 +11,7 @@ module bus_fault_tb;
|
||||
logic [ 1:0] fault_master_o;
|
||||
logic [ 2:0] fault_code_o;
|
||||
logic user_bus_idle_o;
|
||||
ribp_if mgmt_ribp ();
|
||||
rib_if mgmt_rib ();
|
||||
rib_if user_rib ();
|
||||
rib_if dma_rib ();
|
||||
rib_if rib ();
|
||||
@@ -39,7 +39,7 @@ module bus_fault_tb;
|
||||
rib_bus u_bus (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.mgmt_ribp (mgmt_ribp),
|
||||
.mgmt_rib (mgmt_rib),
|
||||
.user_rib (user_rib),
|
||||
.dma_rib (dma_rib),
|
||||
.user_bus_enable_i(1'b1),
|
||||
@@ -61,22 +61,32 @@ module bus_fault_tb;
|
||||
input logic reserved, input logic [2:0] expected_code);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
mgmt_ribp.addr = address;
|
||||
mgmt_ribp.wdata = 32'hA5A5_5A5A;
|
||||
mgmt_ribp.wstrb = write_strobes;
|
||||
mgmt_ribp.valid = 1'b1;
|
||||
mgmt_rib.cmd_addr = address;
|
||||
mgmt_rib.cmd_write = |write_strobes;
|
||||
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
|
||||
mgmt_rib.cmd_valid = 1'b1;
|
||||
while (!mgmt_rib.cmd_ready) @(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
mgmt_rib.cmd_valid = 1'b0;
|
||||
if (|write_strobes) begin
|
||||
mgmt_rib.wdata = 32'hA5A5_5A5A;
|
||||
mgmt_rib.wstrb = write_strobes;
|
||||
mgmt_rib.wlast = 1'b1;
|
||||
mgmt_rib.w_valid = 1'b1;
|
||||
while (!mgmt_rib.w_ready) @(posedge clk_i);
|
||||
@(negedge clk_i);
|
||||
mgmt_rib.w_valid = 1'b0;
|
||||
end
|
||||
while (!fault_valid_o) @(posedge clk_i);
|
||||
if (fault_addr_o !== address || fault_wstrb_o !== write_strobes ||
|
||||
fault_reserved_o !== reserved || fault_access_o || fault_code_o !== expected_code ||
|
||||
rib.cmd_valid || apb_rib.cmd_valid) begin
|
||||
$fatal(1, "unexpected fault response for address %h", address);
|
||||
end
|
||||
while (!mgmt_ribp.ready) @(posedge clk_i);
|
||||
if (mgmt_ribp.rdata !== 32'd0 || !mgmt_ribp.resp_err) begin
|
||||
while (!mgmt_rib.rsp_valid) @(posedge clk_i);
|
||||
if (mgmt_rib.rdata !== 32'd0 || !mgmt_rib.resp_err) begin
|
||||
$fatal(1, "fault response data must be zero");
|
||||
end
|
||||
@(negedge clk_i);
|
||||
mgmt_ribp.valid = 1'b0;
|
||||
while (fault_valid_o) @(posedge clk_i);
|
||||
end
|
||||
endtask
|
||||
@@ -113,10 +123,15 @@ module bus_fault_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
mgmt_ribp.valid = 1'b0;
|
||||
mgmt_ribp.addr = '0;
|
||||
mgmt_ribp.wdata = '0;
|
||||
mgmt_ribp.wstrb = '0;
|
||||
mgmt_rib.cmd_valid = 1'b0;
|
||||
mgmt_rib.cmd_addr = '0;
|
||||
mgmt_rib.cmd_write = 1'b0;
|
||||
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
|
||||
mgmt_rib.w_valid = 1'b0;
|
||||
mgmt_rib.wdata = '0;
|
||||
mgmt_rib.wstrb = '0;
|
||||
mgmt_rib.wlast = 1'b0;
|
||||
mgmt_rib.rsp_ready = 1'b1;
|
||||
user_rib.cmd_valid = 1'b0;
|
||||
user_rib.cmd_addr = '0;
|
||||
user_rib.cmd_write = 1'b0;
|
||||
|
||||
+53
-39
@@ -8,7 +8,10 @@ module clint_tb;
|
||||
logic timebase_tick;
|
||||
logic [31:0] value;
|
||||
integer timebase_tick_count = 0;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
clint_if #(.HartNum(2)) clint ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
@@ -29,47 +32,58 @@ module clint_tb;
|
||||
.tick_o (timebase_tick)
|
||||
);
|
||||
|
||||
ribp_clint #(
|
||||
apb4_clint #(
|
||||
.HartNum(2)
|
||||
) u_dut (
|
||||
.clk_i,
|
||||
.rst_n_i,
|
||||
.timebase_tick_i(tick_i),
|
||||
.ribp,
|
||||
.apb4,
|
||||
.clint
|
||||
);
|
||||
|
||||
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = strobe;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = strobe;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] address, output logic [31:0] data,
|
||||
task automatic apb4_read(input logic [31:0] address, output logic [31:0] data,
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
data = ribp.rdata;
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
ribp.valid = 1'b0;
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -83,45 +97,45 @@ module clint_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
ribp_read(32'h0000_0000, value, 1'b0);
|
||||
apb4_read(32'h0000_0000, value, 1'b0);
|
||||
if (value != 32'd0 || clint.software_irq_o != 2'b00) begin
|
||||
$fatal(1, "MSIP reset state is invalid");
|
||||
end
|
||||
ribp_read(32'h0000_4000, value, 1'b0);
|
||||
apb4_read(32'h0000_4000, value, 1'b0);
|
||||
if (value != 32'hFFFF_FFFF) $fatal(1, "MTIMECMP low reset state is invalid");
|
||||
ribp_read(32'h0000_4004, value, 1'b0);
|
||||
apb4_read(32'h0000_4004, value, 1'b0);
|
||||
if (value != 32'hFFFF_FFFF || clint.timer_irq_o != 2'b00) begin
|
||||
$fatal(1, "MTIMECMP high reset state is invalid");
|
||||
end
|
||||
|
||||
ribp_write(32'h0000_0004, 32'h0000_0001, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0004, 32'h0000_0001, 4'h1, 1'b0);
|
||||
if (clint.software_irq_o != 2'b10) $fatal(1, "hart 1 MSIP did not assert");
|
||||
ribp_write(32'h0000_0004, 32'h0000_0000, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0004, 32'h0000_0000, 4'h1, 1'b0);
|
||||
if (clint.software_irq_o != 2'b00) $fatal(1, "hart 1 MSIP did not clear");
|
||||
|
||||
ribp_write(32'h0000_BFFC, 32'd0, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_BFF8, 32'd10, 4'hF, 1'b0);
|
||||
ribp_read(32'h0000_BFF8, value, 1'b0);
|
||||
apb4_write(32'h0000_BFFC, 32'd0, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_BFF8, 32'd10, 4'hF, 1'b0);
|
||||
apb4_read(32'h0000_BFF8, value, 1'b0);
|
||||
if (value != 32'd10) $fatal(1, "MTIME write/read failed: %h", value);
|
||||
|
||||
ribp_write(32'h0000_4004, 32'd0, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_4000, 32'd12, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_4004, 32'd0, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_4000, 32'd12, 4'hF, 1'b0);
|
||||
pulse_tick();
|
||||
pulse_tick();
|
||||
repeat (2) @(posedge clk_i);
|
||||
if (clint.timer_irq_o[0] != 1'b1) $fatal(1, "hart 0 timer IRQ did not assert");
|
||||
if (clint.timer_irq_o[1] != 1'b0) $fatal(1, "hart 1 timer IRQ asserted unexpectedly");
|
||||
|
||||
ribp_write(32'h0000_4001, 32'd0, 4'hF, 1'b1);
|
||||
ribp_read(32'h0000_0010, value, 1'b1);
|
||||
apb4_write(32'h0000_4001, 32'd0, 4'hF, 1'b1);
|
||||
apb4_read(32'h0000_0010, value, 1'b1);
|
||||
if (value != 32'd0) $fatal(1, "invalid read did not return zero");
|
||||
|
||||
repeat (20) @(posedge clk_i);
|
||||
|
||||
+38
-25
@@ -7,9 +7,12 @@ module dvp_tb;
|
||||
logic href_i = 1'b0;
|
||||
logic vsync_i = 1'b0;
|
||||
logic [ 7:0] dat_i = 8'd0;
|
||||
logic [31:0] ribp_rdata;
|
||||
logic [31:0] apb4_rdata;
|
||||
logic irq_o;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
axi4_stream_if #(
|
||||
.DATA_WIDTH(32),
|
||||
.ID_WIDTH (1),
|
||||
@@ -32,7 +35,7 @@ module dvp_tb;
|
||||
axi4s_dvp u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.ribp (ribp),
|
||||
.apb4 (apb4),
|
||||
.rx_axis(axis),
|
||||
.dvp (dvp),
|
||||
.irq_o (irq_o)
|
||||
@@ -41,27 +44,37 @@ module dvp_tb;
|
||||
task automatic write(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = 4'hf;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
if (ribp.resp_err) $fatal(1, "unexpected write error at %h", address);
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic read(input logic [31:0] address, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
data = ribp.rdata;
|
||||
ribp.valid = 1'b0;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -106,16 +119,16 @@ module dvp_tb;
|
||||
end
|
||||
end
|
||||
initial begin
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
read(32'h0000_00f8, value);
|
||||
if (value != 32'h0002_0000) $fatal(1, "bad DVP version %h", value);
|
||||
read(32'h0000_0100, value);
|
||||
if (!ribp.resp_err) $fatal(1, "invalid DVP access was accepted");
|
||||
if (!apb4.pslverr) $fatal(1, "invalid DVP access was accepted");
|
||||
write(32'h0000_0018, {16'd2, 16'd4});
|
||||
write(32'h0000_000c, 32'd1);
|
||||
write(32'h0000_0000, 32'd3);
|
||||
@@ -127,8 +140,8 @@ module dvp_tb;
|
||||
check_frame(1, 3, 2);
|
||||
write(32'h0000_0048, 32'h0000_0004);
|
||||
read(32'h0000_003c, value);
|
||||
if (ribp.resp_err) $fatal(1, "DVP interrupt read failed");
|
||||
$display("RIBP DVP capture test passed");
|
||||
if (apb4.pslverr) $fatal(1, "DVP interrupt read failed");
|
||||
$display("APB4 DVP capture test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
+73
-71
@@ -9,14 +9,17 @@ module gpio_tb;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
gpio_if #(PinNum) gpio ();
|
||||
user_gpio_if #(PinNum) user_gpio ();
|
||||
logic [31:0] read_data;
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
ribp_gpio #(
|
||||
apb4_gpio #(
|
||||
.PinNum (PinNum),
|
||||
.UserBaseAddr (USER_BASE),
|
||||
.AdminBaseAddr(ADMIN_BASE),
|
||||
@@ -26,7 +29,7 @@ module gpio_tb;
|
||||
) dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.ribp (ribp),
|
||||
.apb4 (apb4),
|
||||
.gpio (gpio),
|
||||
.user_gpio(user_gpio)
|
||||
);
|
||||
@@ -35,19 +38,22 @@ module gpio_tb;
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = 4'hF;
|
||||
ribp.valid = 1'b1;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!ribp.ready || (ribp.resp_err !== expected_error)) begin
|
||||
$fatal(1, "write response mismatch at %08x", address);
|
||||
end
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -55,28 +61,32 @@ module gpio_tb;
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
ribp.valid = 1'b1;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!ribp.ready || (ribp.resp_err !== expected_error)) begin
|
||||
$fatal(1, "read response mismatch at %08x", address);
|
||||
end
|
||||
data = ribp.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pprot = '0;
|
||||
gpio.di_i = '0;
|
||||
gpio.alt0_do_i = '0;
|
||||
gpio.alt0_oe_i = '0;
|
||||
@@ -89,83 +99,75 @@ module gpio_tb;
|
||||
rst_n_i = 1'b1;
|
||||
repeat (3) @(posedge clk_i);
|
||||
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_CAPABILITY, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_CAPABILITY, read_data, 1'b0);
|
||||
if (read_data !== 32'h007F_4204) $fatal(1, "capability register mismatch");
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_PAD_CAPABILITY, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_PAD_CAPABILITY, read_data, 1'b0);
|
||||
if (read_data !== 32'h0000_0007) $fatal(1, "pad capability register mismatch");
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUTPUT_ENABLE, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUTPUT_ENABLE, read_data, 1'b0);
|
||||
if (read_data !== 32'd0) $fatal(1, "output enable reset value mismatch");
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUT_SET, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OE_SET, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_SET, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_SET, 32'h1, 1'b0);
|
||||
if ({gpio.oe_o[0], gpio.do_o[0]} !== 2'b11) $fatal(1, "software output failed");
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUT_TOGGLE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_TOGGLE, 32'h1, 1'b0);
|
||||
if (gpio.do_o[0] !== 1'b0) $fatal(1, "atomic output toggle failed");
|
||||
read_register(ADMIN_BASE + 32'h2, read_data, 1'b1);
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_USER_ACCESS_MASK, 32'h2, 1'b0);
|
||||
write_register(USER_BASE + `RIBP_GPIO_USER_OUT_SET, 32'h6, 1'b0);
|
||||
read_register(USER_BASE + `RIBP_GPIO_USER_DATA_OUT, read_data, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_USER_ACCESS_MASK, 32'h2, 1'b0);
|
||||
write_register(USER_BASE + `APB4_GPIO_USER_OUT_SET, 32'h6, 1'b0);
|
||||
read_register(USER_BASE + `APB4_GPIO_USER_DATA_OUT, read_data, 1'b0);
|
||||
if (read_data !== 32'h2) $fatal(1, "user access mask did not isolate output data");
|
||||
|
||||
user_gpio.do_o[2] = 1'b1;
|
||||
user_gpio.oe_o[2] = 1'b1;
|
||||
@(negedge clk_i);
|
||||
ribp.addr = ADMIN_BASE + `RIBP_GPIO_ADMIN_USER_SELECT;
|
||||
ribp.wdata = 32'h4;
|
||||
ribp.wstrb = 4'hF;
|
||||
ribp.valid = 1'b1;
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (gpio.oe_o[2] !== 1'b0) $fatal(1, "user handoff did not force high impedance");
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_USER_SELECT, 32'h4, 1'b0);
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if ({gpio.oe_o[2], gpio.do_o[2]} !== 2'b11) $fatal(1, "user output was not selected");
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OE_SET, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OPEN_DRAIN, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUT_SET, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_SET, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OPEN_DRAIN, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_SET, 32'h2, 1'b0);
|
||||
if ({gpio.oe_o[1], gpio.do_o[1]} !== 2'b00) $fatal(1, "open-drain release failed");
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OUT_CLEAR, 32'h2, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OUT_CLEAR, 32'h2, 1'b0);
|
||||
if ({gpio.oe_o[1], gpio.do_o[1]} !== 2'b10) $fatal(1, "open-drain low drive failed");
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_PULL_UP, 32'h8, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_PULL_DOWN, 32'h8, 1'b1);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_PULL_UP, 32'h8, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_PULL_DOWN, 32'h8, 1'b1);
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_ENABLE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_ENABLE, 32'h1, 1'b0);
|
||||
gpio.di_i[0] = 1'b1;
|
||||
repeat (5) @(posedge clk_i);
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_STATE, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, read_data, 1'b0);
|
||||
if ((read_data & 32'h1) == 0) $fatal(1, "rising edge interrupt was not latched");
|
||||
if (!gpio.irq_o) $fatal(1, "combined GPIO interrupt was not asserted");
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
|
||||
if (gpio.irq_o) $fatal(1, "W1C did not clear the interrupt");
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_TEST, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_TEST, 32'h1, 1'b0);
|
||||
if (!gpio.irq_o) $fatal(1, "software interrupt test failed");
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_STATE, 32'h1, 1'b0);
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h9, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_INTR_HIGH_ENABLE, 32'h8, 1'b1);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_RISE_ENABLE, 32'h9, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_INTR_HIGH_ENABLE, 32'h8, 1'b1);
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_FILTER_DIV, 32'h0, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_FILTER_COUNT, 32'h4, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_FILTER_ENABLE, 32'h8, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_DIV, 32'h0, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_COUNT, 32'h4, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_FILTER_ENABLE, 32'h8, 1'b0);
|
||||
gpio.di_i[3] = 1'b1;
|
||||
@(posedge clk_i);
|
||||
gpio.di_i[3] = 1'b0;
|
||||
repeat (5) @(posedge clk_i);
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
|
||||
if ((read_data & 32'h8) != 0) $fatal(1, "input filter accepted a short pulse");
|
||||
gpio.di_i[3] = 1'b1;
|
||||
repeat (8) @(posedge clk_i);
|
||||
read_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
|
||||
read_register(ADMIN_BASE + `APB4_GPIO_ADMIN_DATA_IN, read_data, 1'b0);
|
||||
if ((read_data & 32'h8) == 0) $fatal(1, "input filter rejected a stable input");
|
||||
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_CONFIG_LOCK, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `RIBP_GPIO_ADMIN_OE_CLEAR, 32'h1, 1'b1);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_CONFIG_LOCK, 32'h1, 1'b0);
|
||||
write_register(ADMIN_BASE + `APB4_GPIO_ADMIN_OE_CLEAR, 32'h1, 1'b1);
|
||||
if (gpio.oe_o[0] !== 1'b1) $fatal(1, "configuration lock did not protect OE");
|
||||
|
||||
$display("GPIO directed test passed");
|
||||
|
||||
+82
-73
@@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "ribp_i2c_define.svh"
|
||||
`include "apb4_i2c_define.svh"
|
||||
|
||||
module i2c_tb;
|
||||
logic clk_i = 1'b0;
|
||||
@@ -11,7 +11,10 @@ module i2c_tb;
|
||||
logic slave_sda_low = 1'b0;
|
||||
logic scl_line;
|
||||
logic sda_line;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
i2c_if i2c ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
@@ -21,54 +24,57 @@ module i2c_tb;
|
||||
assign i2c.scl_i = scl_line;
|
||||
assign i2c.sda_i = sda_line;
|
||||
|
||||
ribp_i2c u_dut (
|
||||
apb4_i2c u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.dma_tx_stall_o(dma_tx_stall),
|
||||
.dma_rx_stall_o(dma_rx_stall),
|
||||
.ribp (ribp),
|
||||
.apb4 (apb4),
|
||||
.i2c (i2c)
|
||||
);
|
||||
|
||||
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = 4'hF;
|
||||
ribp.valid = 1'b1;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "I2C write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
end
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] address, input logic expected_error,
|
||||
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
|
||||
output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
ribp.valid = 1'b1;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "I2C read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
end
|
||||
data = ribp.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -124,26 +130,26 @@ module i2c_tb;
|
||||
begin
|
||||
value = '0;
|
||||
for (attempts = 0; attempts < 4000; attempts = attempts + 1) begin
|
||||
ribp_read(`RIBP_I2C_INTR_STATE, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_INTR_STATE, 1'b0, value);
|
||||
if (value[`I2C_INTR_DONE]) begin
|
||||
attempts = 4000;
|
||||
end
|
||||
end
|
||||
if (!value[`I2C_INTR_DONE]) begin
|
||||
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, error_value);
|
||||
ribp_read(`RIBP_I2C_STATUS, 1'b0, status_value);
|
||||
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, error_value);
|
||||
apb4_read(`APB4_I2C_STATUS, 1'b0, status_value);
|
||||
$fatal(1, "I2C transaction did not complete: error=%h status=%h fsm=%0d", error_value,
|
||||
status_value, u_dut.u_i2c_core.s_fsm_q);
|
||||
end
|
||||
ribp_write(`RIBP_I2C_INTR_STATE, 32'hFF, 1'b0);
|
||||
apb4_write(`APB4_I2C_INTR_STATE, 32'hFF, 1'b0);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic clear_state;
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_ERROR_STATUS, 32'h7FF, 1'b0);
|
||||
ribp_write(`RIBP_I2C_INTR_STATE, 32'hFF, 1'b0);
|
||||
ribp_write(`RIBP_I2C_COMMAND, 32'hC, 1'b0);
|
||||
apb4_write(`APB4_I2C_ERROR_STATUS, 32'h7FF, 1'b0);
|
||||
apb4_write(`APB4_I2C_INTR_STATE, 32'hFF, 1'b0);
|
||||
apb4_write(`APB4_I2C_COMMAND, 32'hC, 1'b0);
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -153,30 +159,33 @@ module i2c_tb;
|
||||
logic nack;
|
||||
integer pulse_count;
|
||||
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pprot = '0;
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
repeat (4) @(posedge clk_i);
|
||||
|
||||
ribp_read(`RIBP_I2C_IP_VERSION, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_IP_VERSION, 1'b0, value);
|
||||
if (value != 32'h0002_0000) $fatal(1, "I2C version mismatch");
|
||||
ribp_read(`RIBP_I2C_CAPABILITY, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_CAPABILITY, 1'b0, value);
|
||||
if (value != 32'h007F_1010) $fatal(1, "I2C capability mismatch: %h", value);
|
||||
ribp_read(32'h2, 1'b1, value);
|
||||
apb4_read(32'h2, 1'b1, value);
|
||||
|
||||
ribp_write(`RIBP_I2C_SCL_TIMING, 32'h0008_0008, 1'b0);
|
||||
ribp_write(`RIBP_I2C_START_TIMING, 32'h0002_0002, 1'b0);
|
||||
ribp_write(`RIBP_I2C_DATA_TIMING, 32'h0001_0000, 1'b0);
|
||||
ribp_write(`RIBP_I2C_STOP_TIMING, 32'h0002_0002, 1'b0);
|
||||
ribp_write(`RIBP_I2C_FILTER, 0, 1'b0);
|
||||
ribp_write(`RIBP_I2C_STRETCH_TIMEOUT, 200, 1'b0);
|
||||
ribp_write(`RIBP_I2C_BUS_IDLE_TIMEOUT, 200, 1'b0);
|
||||
ribp_write(`RIBP_I2C_COMMAND_TIMEOUT, 2000, 1'b0);
|
||||
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h50, 1'b0);
|
||||
ribp_write(`RIBP_I2C_CTRL, 1, 1'b0);
|
||||
apb4_write(`APB4_I2C_SCL_TIMING, 32'h0008_0008, 1'b0);
|
||||
apb4_write(`APB4_I2C_START_TIMING, 32'h0002_0002, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_TIMING, 32'h0001_0000, 1'b0);
|
||||
apb4_write(`APB4_I2C_STOP_TIMING, 32'h0002_0002, 1'b0);
|
||||
apb4_write(`APB4_I2C_FILTER, 0, 1'b0);
|
||||
apb4_write(`APB4_I2C_STRETCH_TIMEOUT, 200, 1'b0);
|
||||
apb4_write(`APB4_I2C_BUS_IDLE_TIMEOUT, 200, 1'b0);
|
||||
apb4_write(`APB4_I2C_COMMAND_TIMEOUT, 2000, 1'b0);
|
||||
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h50, 1'b0);
|
||||
apb4_write(`APB4_I2C_CTRL, 1, 1'b0);
|
||||
|
||||
fork
|
||||
begin
|
||||
@@ -187,13 +196,13 @@ module i2c_tb;
|
||||
if (byte_value != 8'hA5) $fatal(1, "write data mismatch: %h", byte_value);
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'h4A5, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'h4A5, 1'b0);
|
||||
wait_done();
|
||||
end
|
||||
join
|
||||
|
||||
clear_state();
|
||||
ribp_write(`RIBP_I2C_TARGET_ADDR, 32'h0000_06AA, 1'b0);
|
||||
apb4_write(`APB4_I2C_TARGET_ADDR, 32'h0000_06AA, 1'b0);
|
||||
fork
|
||||
begin
|
||||
wait_start();
|
||||
@@ -208,15 +217,15 @@ module i2c_tb;
|
||||
if (!nack) $fatal(1, "final 10-bit read byte was not NACKed");
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'hD00, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'hD00, 1'b0);
|
||||
wait_done();
|
||||
ribp_read(`RIBP_I2C_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_RXDATA, 1'b0, value);
|
||||
if (value[7:0] != 8'hC3) $fatal(1, "10-bit read data mismatch: %h", value);
|
||||
end
|
||||
join
|
||||
|
||||
clear_state();
|
||||
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h50, 1'b0);
|
||||
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h50, 1'b0);
|
||||
fork
|
||||
begin
|
||||
wait_start();
|
||||
@@ -231,10 +240,10 @@ module i2c_tb;
|
||||
if (!nack) $fatal(1, "final read byte was not NACKed");
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'h012, 1'b0);
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'hF00, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'h012, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'hF00, 1'b0);
|
||||
wait_done();
|
||||
ribp_read(`RIBP_I2C_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_RXDATA, 1'b0, value);
|
||||
if (value[7:0] != 8'h5A) $fatal(1, "read data mismatch: %h", value);
|
||||
end
|
||||
join
|
||||
@@ -247,20 +256,20 @@ module i2c_tb;
|
||||
receive_byte(byte_value, 0);
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'h45C, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'h45C, 1'b0);
|
||||
wait_done();
|
||||
end
|
||||
join
|
||||
|
||||
clear_state();
|
||||
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h51, 1'b0);
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'h455, 1'b0);
|
||||
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h51, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'h455, 1'b0);
|
||||
repeat (300) @(posedge clk_i);
|
||||
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, value);
|
||||
if (!value[`I2C_ERROR_ADDR_NACK]) $fatal(1, "address NACK was not reported");
|
||||
|
||||
clear_state();
|
||||
ribp_write(`RIBP_I2C_TARGET_ADDR, 7'h7F, 1'b0);
|
||||
apb4_write(`APB4_I2C_TARGET_ADDR, 7'h7F, 1'b0);
|
||||
fork
|
||||
begin
|
||||
wait_start();
|
||||
@@ -271,11 +280,11 @@ module i2c_tb;
|
||||
slave_sda_low = 1'b0;
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_DATA_CMD, 32'h400, 1'b0);
|
||||
apb4_write(`APB4_I2C_DATA_CMD, 32'h400, 1'b0);
|
||||
end
|
||||
join
|
||||
repeat (20) @(posedge clk_i);
|
||||
ribp_read(`RIBP_I2C_ERROR_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_ERROR_STATUS, 1'b0, value);
|
||||
if (!value[`I2C_ERROR_ARB_LOST]) $fatal(1, "arbitration loss was not reported");
|
||||
|
||||
clear_state();
|
||||
@@ -290,11 +299,11 @@ module i2c_tb;
|
||||
slave_sda_low = 1'b0;
|
||||
end
|
||||
begin
|
||||
ribp_write(`RIBP_I2C_COMMAND, 32'h2, 1'b0);
|
||||
apb4_write(`APB4_I2C_COMMAND, 32'h2, 1'b0);
|
||||
end
|
||||
join
|
||||
repeat (80) @(posedge clk_i);
|
||||
ribp_read(`RIBP_I2C_INTR_STATE, 1'b0, value);
|
||||
apb4_read(`APB4_I2C_INTR_STATE, 1'b0, value);
|
||||
if (!value[`I2C_INTR_RECOVERY_DONE] || (pulse_count != 9)) begin
|
||||
$fatal(1, "bus recovery failed: intr=%h pulses=%0d", value, pulse_count);
|
||||
end
|
||||
|
||||
+41
-24
@@ -10,13 +10,16 @@ module pll_ctrl_tb;
|
||||
logic [31:0] fault_addr_i = '0;
|
||||
logic [ 3:0] fault_wstrb_i = '0;
|
||||
logic fault_reserved_i = 1'b0;
|
||||
ribp_if rib ();
|
||||
sysctrl_if sysctrl ();
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
logic sys_clk_o;
|
||||
logic sys_rst_n_o;
|
||||
logic aud_rst_n_o;
|
||||
logic sys_clkdiv4_o;
|
||||
apb4_if apb4 (
|
||||
.pclk (sys_clk_o),
|
||||
.presetn(sys_rst_n_o)
|
||||
);
|
||||
sysctrl_if sysctrl ();
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
logic [31:0] read_data;
|
||||
time edge_start;
|
||||
time edge_end;
|
||||
@@ -41,14 +44,14 @@ module pll_ctrl_tb;
|
||||
.timebase_tick_o()
|
||||
);
|
||||
|
||||
ribp_sysctrl u_sysctrl (
|
||||
apb4_sysctrl u_sysctrl (
|
||||
.clk_i (sys_clk_o),
|
||||
.rst_n_i (sys_rst_n_o),
|
||||
.fault_valid_i (fault_valid_i),
|
||||
.fault_addr_i (fault_addr_i),
|
||||
.fault_wstrb_i (fault_wstrb_i),
|
||||
.fault_reserved_i(fault_reserved_i),
|
||||
.ribp (rib),
|
||||
.apb4 (apb4),
|
||||
.sysctrl (sysctrl),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
@@ -56,29 +59,43 @@ module pll_ctrl_tb;
|
||||
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge sys_clk_o);
|
||||
rib.addr = address;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
rib.valid = 1'b1;
|
||||
while (!rib.ready) @(posedge sys_clk_o);
|
||||
data = rib.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge sys_clk_o);
|
||||
rib.valid = 1'b0;
|
||||
while (rib.ready) @(posedge sys_clk_o);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge sys_clk_o);
|
||||
if (apb4.pslverr !== 1'b0) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_register(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
@(negedge sys_clk_o);
|
||||
rib.addr = address;
|
||||
rib.wdata = data;
|
||||
rib.wstrb = 4'hF;
|
||||
rib.valid = 1'b1;
|
||||
while (!rib.ready) @(posedge sys_clk_o);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge sys_clk_o);
|
||||
rib.valid = 1'b0;
|
||||
while (rib.ready) @(posedge sys_clk_o);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge sys_clk_o);
|
||||
if (apb4.pslverr !== 1'b0) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
|
||||
end
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -101,10 +118,10 @@ module pll_ctrl_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
rib.valid = 1'b0;
|
||||
rib.addr = '0;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
sysctrl.user_bus_idle_i = 1'b1;
|
||||
sysctrl.fault_access_i = 1'b0;
|
||||
sysctrl.fault_master_i = '0;
|
||||
|
||||
+68
-56
@@ -17,7 +17,10 @@ module psram_tb;
|
||||
logic [ 1:0] held_resp;
|
||||
logic held_last;
|
||||
|
||||
ribp_if cfg_ribp ();
|
||||
apb4_if cfg_apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
axi4_if #(
|
||||
.ADDR_WIDTH(32),
|
||||
.DATA_WIDTH(32),
|
||||
@@ -38,10 +41,10 @@ module psram_tb;
|
||||
end
|
||||
assign psram.io_di_i = psram_sio;
|
||||
|
||||
ribp_psram u_dut (
|
||||
apb4_psram u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.cfg_ribp(cfg_ribp),
|
||||
.cfg_apb4(cfg_apb4),
|
||||
.mem_axi4(mem_axi4),
|
||||
.psram (psram)
|
||||
);
|
||||
@@ -131,39 +134,48 @@ module psram_tb;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_write(input logic [31:0] offset, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] offset, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
cfg_ribp.addr = offset;
|
||||
cfg_ribp.wdata = data;
|
||||
cfg_ribp.wstrb = strobe;
|
||||
cfg_ribp.valid = 1'b1;
|
||||
do @(negedge clk_i); while (!cfg_ribp.ready);
|
||||
if (cfg_ribp.resp_err != expected_error) begin
|
||||
$fatal(1, "RIBP write response mismatch at %08x", offset);
|
||||
end
|
||||
cfg_ribp.valid = 1'b0;
|
||||
cfg_ribp.wstrb = '0;
|
||||
cfg_apb4.paddr = offset;
|
||||
cfg_apb4.pwdata = data;
|
||||
cfg_apb4.pstrb = strobe;
|
||||
cfg_apb4.pwrite = 1'b1;
|
||||
cfg_apb4.psel = 1'b1;
|
||||
cfg_apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
cfg_apb4.penable = 1'b1;
|
||||
while (!cfg_apb4.pready) @(negedge clk_i);
|
||||
if (cfg_apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", offset, cfg_apb4.pslverr, expected_error);
|
||||
end
|
||||
cfg_apb4.psel = 1'b0;
|
||||
cfg_apb4.penable = 1'b0;
|
||||
cfg_apb4.pwrite = 1'b0;
|
||||
cfg_apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] offset, input logic expected_error,
|
||||
task automatic apb4_read(input logic [31:0] offset, input logic expected_error,
|
||||
output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
cfg_ribp.addr = offset;
|
||||
cfg_ribp.wdata = '0;
|
||||
cfg_ribp.wstrb = '0;
|
||||
cfg_ribp.valid = 1'b1;
|
||||
do @(negedge clk_i); while (!cfg_ribp.ready);
|
||||
if (cfg_ribp.resp_err != expected_error) begin
|
||||
$fatal(1, "RIBP read response mismatch at %08x", offset);
|
||||
end
|
||||
data = cfg_ribp.rdata;
|
||||
cfg_ribp.valid = 1'b0;
|
||||
cfg_apb4.paddr = offset;
|
||||
cfg_apb4.pwdata = '0;
|
||||
cfg_apb4.pstrb = '0;
|
||||
cfg_apb4.pwrite = 1'b0;
|
||||
cfg_apb4.psel = 1'b1;
|
||||
cfg_apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
cfg_apb4.penable = 1'b1;
|
||||
while (!cfg_apb4.pready) @(negedge clk_i);
|
||||
if (cfg_apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", offset, cfg_apb4.pslverr, expected_error);
|
||||
end
|
||||
data = cfg_apb4.prdata;
|
||||
cfg_apb4.psel = 1'b0;
|
||||
cfg_apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -172,7 +184,7 @@ module psram_tb;
|
||||
reg_data = '0;
|
||||
for (int poll = 0; poll < 200; poll++) begin
|
||||
repeat (20) @(posedge clk_i);
|
||||
ribp_read(`RIBP_PSRAM_INTR_STATE, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_INTR_STATE, 1'b0, reg_data);
|
||||
if (reg_data[`PSRAM_INTR_INIT_DONE]) return;
|
||||
end
|
||||
$fatal(1, "PSRAM initialization timed out");
|
||||
@@ -184,7 +196,7 @@ module psram_tb;
|
||||
reg_data = '0;
|
||||
for (int poll = 0; poll < 100; poll++) begin
|
||||
repeat (10) @(posedge clk_i);
|
||||
ribp_read(`RIBP_PSRAM_INTR_STATE, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_INTR_STATE, 1'b0, reg_data);
|
||||
if (reg_data[`PSRAM_INTR_INDIRECT_DONE]) return;
|
||||
end
|
||||
$fatal(1, "PSRAM indirect command timed out");
|
||||
@@ -343,39 +355,39 @@ module psram_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
cfg_ribp.valid = 1'b0;
|
||||
cfg_ribp.addr = '0;
|
||||
cfg_ribp.wdata = '0;
|
||||
cfg_ribp.wstrb = '0;
|
||||
cfg_apb4.psel = 1'b0;
|
||||
cfg_apb4.paddr = '0;
|
||||
cfg_apb4.pwdata = '0;
|
||||
cfg_apb4.pstrb = '0;
|
||||
init_axi4();
|
||||
|
||||
repeat (5) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
$display("PSRAM_TB_STAGE register_setup");
|
||||
ribp_write(`RIBP_PSRAM_POWERUP_CYCLES, 32'd1, 4'hF, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_CS_HIGH_CYCLES, 32'd2, 4'hF, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_CS_HOLD_CYCLES, 32'd3, 4'hF, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_ACCESS_TIMEOUT_CYCLES, 32'd1024, 4'hF, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_PERF_CTRL, 32'd1, 4'h1, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_STATUS, 32'd1, 4'h1, 1'b1);
|
||||
ribp_read(32'h0000_0002, 1'b1, reg_data);
|
||||
ribp_read(32'h0000_00B0, 1'b1, reg_data);
|
||||
ribp_write(`RIBP_PSRAM_COMMAND, 32'h0000_0003, 4'h1, 1'b1);
|
||||
apb4_write(`APB4_PSRAM_POWERUP_CYCLES, 32'd1, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_CS_HIGH_CYCLES, 32'd2, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_CS_HOLD_CYCLES, 32'd3, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_ACCESS_TIMEOUT_CYCLES, 32'd1024, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_PERF_CTRL, 32'd1, 4'h1, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_STATUS, 32'd1, 4'h1, 1'b1);
|
||||
apb4_read(32'h0000_0002, 1'b1, reg_data);
|
||||
apb4_read(32'h0000_00B0, 1'b1, reg_data);
|
||||
apb4_write(`APB4_PSRAM_COMMAND, 32'h0000_0003, 4'h1, 1'b1);
|
||||
|
||||
$display("PSRAM_TB_STAGE initialization");
|
||||
ribp_write(`RIBP_PSRAM_COMMAND, 32'h0000_0001, 4'h1, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_COMMAND, 32'h0000_0001, 4'h1, 1'b0);
|
||||
wait_for_init();
|
||||
ribp_read(`RIBP_PSRAM_CHIP_PRESENT, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_PRESENT, 1'b0, reg_data);
|
||||
if (reg_data[3:0] != 4'b1011) $fatal(1, "unexpected present mask");
|
||||
ribp_read(`RIBP_PSRAM_CHIP_READY, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_READY, 1'b0, reg_data);
|
||||
if (reg_data[3:0] != 4'b1011) $fatal(1, "unexpected ready mask");
|
||||
ribp_read(`RIBP_PSRAM_CHIP_ERROR, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_ERROR, 1'b0, reg_data);
|
||||
if (reg_data[3:0] != 4'b0100) $fatal(1, "missing-device error not isolated");
|
||||
ribp_read(`RIBP_PSRAM_CHIP0_ID_LO, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP0_ID_LO, 1'b0, reg_data);
|
||||
if (reg_data != 32'h0026_5D0D) $fatal(1, "chip ID mismatch");
|
||||
ribp_read(`RIBP_PSRAM_CHIP_MODE, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_MODE, 1'b0, reg_data);
|
||||
if (reg_data[3:0] != 4'b1011) $fatal(1, "QPI mode mask mismatch");
|
||||
|
||||
$display("PSRAM_TB_STAGE basic_axi");
|
||||
@@ -407,28 +419,28 @@ module psram_tb;
|
||||
if (read_data != 32'hC001_CAFE) $fatal(1, "healthy chip after missing device failed");
|
||||
|
||||
$display("PSRAM_TB_STAGE indirect");
|
||||
ribp_write(`RIBP_PSRAM_INTR_STATE, 32'hF, 4'h1, 1'b0);
|
||||
ribp_write(`RIBP_PSRAM_INDIRECT_CTRL, 32'h8000_0009, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_INTR_STATE, 32'hF, 4'h1, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_INDIRECT_CTRL, 32'h8000_0009, 4'hF, 1'b0);
|
||||
wait_for_indirect();
|
||||
ribp_read(`RIBP_PSRAM_CHIP_MODE, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_MODE, 1'b0, reg_data);
|
||||
if (!reg_data[4]) $fatal(1, "wrap32 mode did not update");
|
||||
|
||||
$display("PSRAM_TB_STAGE timeout");
|
||||
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd20, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd20, 4'hF, 1'b0);
|
||||
axi_read_single(PsramBase + 32'h0080_0800, `AXI4_BURST_SIZE_4BYTES, `AXI4_RESP_SLAVE_ERROR,
|
||||
read_data);
|
||||
ribp_read(`RIBP_PSRAM_CHIP_READY, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_CHIP_READY, 1'b0, reg_data);
|
||||
if (reg_data[3:0] != 4'b1001) $fatal(1, "timeout fault was not isolated");
|
||||
ribp_write(`RIBP_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
|
||||
apb4_write(`APB4_PSRAM_CS_MAX_LOW_CYCLES, 32'd512, 4'hF, 1'b0);
|
||||
axi_read_single(PsramBase + 32'h0180_0300, `AXI4_BURST_SIZE_4BYTES, `AXI4_RESP_OKAY, read_data);
|
||||
if (read_data != 32'hC001_CAFE) $fatal(1, "healthy chip failed after timeout");
|
||||
|
||||
$display("PSRAM_TB_STAGE counters");
|
||||
ribp_read(`RIBP_PSRAM_PERF_READ_BYTES, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_PERF_READ_BYTES, 1'b0, reg_data);
|
||||
if (reg_data == 32'd0) $fatal(1, "read performance counter did not advance");
|
||||
ribp_read(`RIBP_PSRAM_PERF_WRITE_BYTES, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_PERF_WRITE_BYTES, 1'b0, reg_data);
|
||||
if (reg_data == 32'd0) $fatal(1, "write performance counter did not advance");
|
||||
ribp_read(`RIBP_PSRAM_PERF_COMMANDS, 1'b0, reg_data);
|
||||
apb4_read(`APB4_PSRAM_PERF_COMMANDS, 1'b0, reg_data);
|
||||
if (reg_data == 32'd0) $fatal(1, "command performance counter did not advance");
|
||||
|
||||
$display("PSRAM controller integration test passed");
|
||||
|
||||
+12
-7
@@ -16,7 +16,7 @@ module rib_bus_tb;
|
||||
logic fault_valid_o;
|
||||
logic [2:0] fault_code_o;
|
||||
logic user_bus_idle_o;
|
||||
ribp_if mgmt_ribp ();
|
||||
rib_if mgmt_rib ();
|
||||
rib_if user_rib ();
|
||||
rib_if dma_rib ();
|
||||
rib_if rib ();
|
||||
@@ -69,7 +69,7 @@ module rib_bus_tb;
|
||||
rib_bus u_bus (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.mgmt_ribp (mgmt_ribp),
|
||||
.mgmt_rib (mgmt_rib),
|
||||
.user_rib (user_rib),
|
||||
.dma_rib (dma_rib),
|
||||
.user_bus_enable_i(1'b1),
|
||||
@@ -88,7 +88,7 @@ module rib_bus_tb;
|
||||
.perf_mgmt_wait_o (),
|
||||
.perf_user_wait_o (),
|
||||
.perf_dma_wait_o (),
|
||||
.perf_ribp_wait_o (),
|
||||
.perf_apb4_wait_o (),
|
||||
.perf_apb_wait_o (),
|
||||
.perf_sdram_wait_o(),
|
||||
.perf_psram_wait_o(),
|
||||
@@ -135,10 +135,15 @@ module rib_bus_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
mgmt_ribp.valid = 1'b0;
|
||||
mgmt_ribp.addr = '0;
|
||||
mgmt_ribp.wdata = '0;
|
||||
mgmt_ribp.wstrb = '0;
|
||||
mgmt_rib.cmd_valid = 1'b0;
|
||||
mgmt_rib.cmd_addr = '0;
|
||||
mgmt_rib.cmd_write = 1'b0;
|
||||
mgmt_rib.cmd_len = `RIB_LEN_INCR1;
|
||||
mgmt_rib.w_valid = 1'b0;
|
||||
mgmt_rib.wdata = '0;
|
||||
mgmt_rib.wstrb = '0;
|
||||
mgmt_rib.wlast = 1'b0;
|
||||
mgmt_rib.rsp_ready = 1'b1;
|
||||
user_rib.cmd_valid = 1'b0;
|
||||
user_rib.cmd_addr = '0;
|
||||
user_rib.cmd_write = 1'b0;
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "mmap_define.svh"
|
||||
|
||||
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"
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
task automatic expect_route(input logic [31:0] address, input integer slot,
|
||||
input logic [31:0] expected_rdata);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.valid = 1'b1;
|
||||
#1;
|
||||
if (s_slv_sel_d !== (18'd1 << slot)) begin
|
||||
$fatal(1, "unexpected target slot for %h", address);
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!ribp.ready || ribp.rdata !== expected_rdata) begin
|
||||
$fatal(1, "unexpected response for %h", address);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
@(posedge clk_i);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_disabled(input logic [31:0] address);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.valid = 1'b1;
|
||||
#1;
|
||||
if (s_slv_sel_d !== '0) begin
|
||||
$fatal(1, "disabled target accepted %h", address);
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (ribp.ready || ribp.rdata !== 32'd0) begin
|
||||
$fatal(1, "disabled target responded to %h", address);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
@(posedge clk_i);
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic expect_error_route(input logic [31:0] address, input integer slot);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.valid = 1'b1;
|
||||
#1;
|
||||
if (s_slv_sel_d !== (18'd1 << slot)) begin
|
||||
$fatal(1, "unexpected error target slot for %h", address);
|
||||
end
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
if (!ribp.ready || !ribp.resp_err) begin
|
||||
$fatal(1, "error response was not propagated for %h", address);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
@(posedge clk_i);
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
|
||||
u_uart_ribp_if.ready = 1'b1;
|
||||
u_gpio_ribp_if.ready = 1'b1;
|
||||
u_tim0_ribp_if.ready = 1'b1;
|
||||
u_tim1_ribp_if.ready = 1'b1;
|
||||
u_psram_ribp_if.ready = 1'b1;
|
||||
u_spisd_ribp_if.ready = 1'b1;
|
||||
u_i2c0_ribp_if.ready = 1'b1;
|
||||
u_i2s_ribp_if.ready = 1'b1;
|
||||
u_ws2812_ribp_if.ready = 1'b1;
|
||||
u_xpi_ribp_if.ready = 1'b1;
|
||||
u_dma_ribp_if.ready = 1'b1;
|
||||
u_sysctrl_ribp_if.ready = 1'b1;
|
||||
u_clint_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;
|
||||
u_i2c1_ribp_if.ready = 1'b1;
|
||||
|
||||
u_uart_ribp_if.rdata = 32'h0000_0000;
|
||||
u_gpio_ribp_if.rdata = 32'h1111_1111;
|
||||
u_tim0_ribp_if.rdata = 32'h2222_2222;
|
||||
u_tim1_ribp_if.rdata = 32'h3333_3333;
|
||||
u_psram_ribp_if.rdata = 32'h4444_4444;
|
||||
u_spisd_ribp_if.rdata = 32'h5555_5555;
|
||||
u_i2c0_ribp_if.rdata = 32'h6666_6666;
|
||||
u_i2s_ribp_if.rdata = 32'h7777_7777;
|
||||
u_ws2812_ribp_if.rdata = 32'h8888_8888;
|
||||
u_xpi_ribp_if.rdata = 32'h9999_9999;
|
||||
u_dma_ribp_if.rdata = 32'hAAAA_AAAA;
|
||||
u_sysctrl_ribp_if.rdata = 32'hBBBB_BBBB;
|
||||
u_clint_ribp_if.rdata = 32'hCCCC_CCCC;
|
||||
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;
|
||||
u_i2c1_ribp_if.rdata = 32'h1234_5678;
|
||||
|
||||
u_uart_ribp_if.resp_err = 1'b0;
|
||||
u_gpio_ribp_if.resp_err = 1'b0;
|
||||
u_tim0_ribp_if.resp_err = 1'b0;
|
||||
u_tim1_ribp_if.resp_err = 1'b0;
|
||||
u_psram_ribp_if.resp_err = 1'b0;
|
||||
u_spisd_ribp_if.resp_err = 1'b0;
|
||||
u_i2c0_ribp_if.resp_err = 1'b0;
|
||||
u_i2s_ribp_if.resp_err = 1'b0;
|
||||
u_ws2812_ribp_if.resp_err = 1'b0;
|
||||
u_xpi_ribp_if.resp_err = 1'b0;
|
||||
u_dma_ribp_if.resp_err = 1'b0;
|
||||
u_sysctrl_ribp_if.resp_err = 1'b0;
|
||||
u_clint_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;
|
||||
u_i2c1_ribp_if.resp_err = 1'b0;
|
||||
|
||||
repeat (2) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
expect_route(`SOC_ADDR_RIBP_GPIO_BASE, 1, 32'h1111_1111);
|
||||
expect_route(`SOC_ADDR_RIBP_GPIO_ADMIN_BASE, 1, 32'h1111_1111);
|
||||
expect_route(`SOC_ADDR_RIBP_PSRAM_BASE, 4, 32'h4444_4444);
|
||||
expect_route(`SOC_ADDR_RIBP_XPI_BASE, 9, 32'h9999_9999);
|
||||
expect_route(`SOC_ADDR_RIBP_I2C1_BASE, 17, 32'h1234_5678);
|
||||
expect_disabled(`SOC_ADDR_RIBP_SDIO_BASE);
|
||||
u_gpio_ribp_if.resp_err = 1'b1;
|
||||
expect_error_route(`SOC_ADDR_RIBP_GPIO_BASE, 1);
|
||||
u_gpio_ribp_if.resp_err = 1'b0;
|
||||
|
||||
$display("SoC topology RIBP routing test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
+40
-37
@@ -14,7 +14,10 @@ module sdram_data_tb;
|
||||
.aclk (clk_i),
|
||||
.aresetn(rst_n_i)
|
||||
);
|
||||
ribp_if cfg_ribp ();
|
||||
apb4_if cfg_apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
sdram_if sdram ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
@@ -26,7 +29,7 @@ module sdram_data_tb;
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.axi4 (axi4),
|
||||
.cfg_ribp(cfg_ribp),
|
||||
.cfg_apb4(cfg_apb4),
|
||||
.sdram (sdram)
|
||||
);
|
||||
|
||||
@@ -60,41 +63,41 @@ module sdram_data_tb;
|
||||
|
||||
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;
|
||||
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_apb4.psel = 1'b0;
|
||||
cfg_apb4.paddr = '0;
|
||||
cfg_apb4.pwdata = '0;
|
||||
cfg_apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
module soc_irq_topology_tb;
|
||||
logic [`SOC_IRQ_VECTOR_WIDTH-1:0] s_irq;
|
||||
logic [ `SOC_IRQ_RIBP_WIDTH-1:0] s_ribp_irq;
|
||||
logic [ `SOC_IRQ_APB4_WIDTH-1:0] s_apb4_irq;
|
||||
logic [ `SOC_IRQ_APB_WIDTH-1:0] s_apb_irq;
|
||||
|
||||
`include "soc_irq_wiring.svh"
|
||||
@@ -19,20 +19,20 @@ module soc_irq_topology_tb;
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
s_ribp_irq = '0;
|
||||
s_apb4_irq = '0;
|
||||
s_apb_irq = '0;
|
||||
expect_irq('0);
|
||||
|
||||
for (int bit_index = 0; bit_index < 10; bit_index++) begin
|
||||
s_ribp_irq = '0;
|
||||
s_ribp_irq[bit_index] = 1'b1;
|
||||
s_apb4_irq = '0;
|
||||
s_apb4_irq[bit_index] = 1'b1;
|
||||
s_apb_irq = '0;
|
||||
expect_irq(32'd1 << bit_index);
|
||||
end
|
||||
|
||||
for (int bit_index = 10; bit_index < `SOC_IRQ_RIBP_WIDTH; bit_index++) begin
|
||||
s_ribp_irq = '0;
|
||||
s_ribp_irq[bit_index] = 1'b1;
|
||||
for (int bit_index = 10; bit_index < `SOC_IRQ_APB4_WIDTH; bit_index++) begin
|
||||
s_apb4_irq = '0;
|
||||
s_apb4_irq[bit_index] = 1'b1;
|
||||
case (bit_index)
|
||||
13: expect_irq(32'd1 << 15);
|
||||
default: expect_irq(32'd1 << (bit_index + 7));
|
||||
@@ -40,7 +40,7 @@ module soc_irq_topology_tb;
|
||||
end
|
||||
|
||||
for (int bit_index = 0; bit_index < `SOC_IRQ_APB_WIDTH; bit_index++) begin
|
||||
s_ribp_irq = '0;
|
||||
s_apb4_irq = '0;
|
||||
s_apb_irq = '0;
|
||||
s_apb_irq[bit_index] = 1'b1;
|
||||
case (bit_index)
|
||||
|
||||
+40
-23
@@ -7,20 +7,23 @@ module sysctrl_tb;
|
||||
logic [31:0] fault_addr_i = '0;
|
||||
logic [ 3:0] fault_wstrb_i = '0;
|
||||
logic fault_reserved_i = 1'b0;
|
||||
ribp_if rib ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
sysctrl_if sysctrl ();
|
||||
pll_ctrl_if pll_ctrl ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
ribp_sysctrl u_sysctrl (
|
||||
apb4_sysctrl u_sysctrl (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.fault_valid_i (fault_valid_i),
|
||||
.fault_addr_i (fault_addr_i),
|
||||
.fault_wstrb_i (fault_wstrb_i),
|
||||
.fault_reserved_i(fault_reserved_i),
|
||||
.ribp (rib),
|
||||
.apb4 (apb4),
|
||||
.sysctrl (sysctrl),
|
||||
.pll_ctrl (pll_ctrl)
|
||||
);
|
||||
@@ -28,38 +31,52 @@ module sysctrl_tb;
|
||||
task automatic read_register(input logic [31:0] address, output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
rib.addr = address;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
rib.valid = 1'b1;
|
||||
while (!rib.ready) @(posedge clk_i);
|
||||
data = rib.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
rib.valid = 1'b0;
|
||||
while (rib.ready) @(posedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== 1'b0) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_register(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
rib.addr = address;
|
||||
rib.wdata = data;
|
||||
rib.wstrb = 4'hF;
|
||||
rib.valid = 1'b1;
|
||||
while (!rib.ready) @(posedge clk_i);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = 4'hF;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
rib.valid = 1'b0;
|
||||
while (rib.ready) @(posedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== 1'b0) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, 1'b0);
|
||||
end
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
logic [31:0] read_data;
|
||||
initial begin
|
||||
rib.valid = 1'b0;
|
||||
rib.addr = '0;
|
||||
rib.wdata = '0;
|
||||
rib.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
sysctrl.user_bus_idle_i = 1'b1;
|
||||
sysctrl.fault_access_i = 1'b0;
|
||||
sysctrl.fault_master_i = '0;
|
||||
@@ -67,7 +84,7 @@ module sysctrl_tb;
|
||||
sysctrl.perf_mgmt_wait_i = 64'd11;
|
||||
sysctrl.perf_user_wait_i = 64'd12;
|
||||
sysctrl.perf_dma_wait_i = 64'd13;
|
||||
sysctrl.perf_ribp_wait_i = 64'd14;
|
||||
sysctrl.perf_apb4_wait_i = 64'd14;
|
||||
sysctrl.perf_apb_wait_i = 64'd15;
|
||||
sysctrl.perf_sdram_wait_i = 64'd16;
|
||||
sysctrl.perf_psram_wait_i = 64'd17;
|
||||
|
||||
+91
-74
@@ -12,49 +12,63 @@ module timer_tb;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic debug_halted_i = 1'b0;
|
||||
logic irq_o;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
ribp_timer u_dut (
|
||||
apb4_timer u_dut (
|
||||
.clk_i,
|
||||
.rst_n_i,
|
||||
.debug_halted_i,
|
||||
.ribp,
|
||||
.apb4,
|
||||
.irq_o
|
||||
);
|
||||
|
||||
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = strobe;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = strobe;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] address, output logic [31:0] data,
|
||||
task automatic apb4_read(input logic [31:0] address, output logic [31:0] data,
|
||||
input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b1;
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
do @(negedge clk_i); while (!ribp.ready);
|
||||
data = ribp.rdata;
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
ribp.valid = 1'b0;
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -65,7 +79,7 @@ module timer_tb;
|
||||
status = '1;
|
||||
cycles = 0;
|
||||
while ((status[0] != 1'b0) && (cycles < 64)) begin
|
||||
ribp_read(32'h0000_001C, status, 1'b0);
|
||||
apb4_read(32'h0000_001C, status, 1'b0);
|
||||
cycles++;
|
||||
end
|
||||
if (status[0] != 1'b0) $fatal(1, "timer did not enter inactive state");
|
||||
@@ -78,98 +92,101 @@ module timer_tb;
|
||||
logic [31:0] intr_state;
|
||||
|
||||
initial begin
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pprot = '0;
|
||||
|
||||
repeat (4) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
ribp_read(32'h0000_00F8, value, 1'b0);
|
||||
apb4_read(32'h0000_00F8, value, 1'b0);
|
||||
if (value != 32'h0002_0000) $fatal(1, "unexpected timer version %h", value);
|
||||
ribp_read(32'h0000_00FC, value, 1'b0);
|
||||
apb4_read(32'h0000_00FC, value, 1'b0);
|
||||
if (value != 32'h00F2_1020) $fatal(1, "unexpected timer capability %h", value);
|
||||
ribp_read(32'h0000_0100, value, 1'b1);
|
||||
apb4_read(32'h0000_0100, value, 1'b1);
|
||||
if (value != 32'd0) $fatal(1, "invalid read did not return zero");
|
||||
ribp_read(32'h0000_0002, value, 1'b1);
|
||||
ribp_write(32'h0000_0008, 32'h1234_5678, 4'hF, 1'b1);
|
||||
ribp_read(32'h0000_002C, value, 1'b1);
|
||||
ribp_write(32'h0000_0000, 32'h0000_0006, 4'hF, 1'b1);
|
||||
apb4_read(32'h0000_0002, value, 1'b1);
|
||||
apb4_write(32'h0000_0008, 32'h1234_5678, 4'hF, 1'b1);
|
||||
apb4_read(32'h0000_002C, value, 1'b1);
|
||||
apb4_write(32'h0000_0000, 32'h0000_0006, 4'hF, 1'b1);
|
||||
|
||||
// Free-running mode wraps naturally and stops without changing its value.
|
||||
ribp_write(32'h0000_0000, CTRL_ENABLE, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_ENABLE, 4'hF, 1'b0);
|
||||
repeat (6) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
if (value == 32'd0) $fatal(1, "free-running timer did not advance");
|
||||
ribp_write(32'h0000_0000, 32'd0, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, 32'd0, 4'hF, 1'b0);
|
||||
|
||||
// Up-counting periodic mode with both compare channels.
|
||||
ribp_write(32'h0000_0010, 32'd1, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0014, 32'd1, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0018, 32'd2, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0004, 32'd3, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0024, 32'h0000_0007, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0010, 32'd0, 4'hF, 1'b1);
|
||||
apb4_write(32'h0000_0010, 32'd1, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0014, 32'd1, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0018, 32'd2, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0004, 32'd3, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0024, 32'h0000_0007, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0010, 32'd0, 4'hF, 1'b1);
|
||||
repeat (12) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0020, intr_state, 1'b0);
|
||||
apb4_read(32'h0000_0020, intr_state, 1'b0);
|
||||
if (intr_state[2:0] != 3'b111 || !irq_o) begin
|
||||
$fatal(1, "periodic compare/timeout state invalid: %h irq=%b", intr_state, irq_o);
|
||||
end
|
||||
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
ribp_write(32'h0000_0000, CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_PERIODIC | CTRL_COMPARE_ENABLE, 4'hF, 1'b0);
|
||||
|
||||
// Down-counting one-shot stops at zero and leaves a sticky timeout.
|
||||
ribp_write(32'h0000_0004, 32'd2, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_ONE_SHOT | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0004, 32'd2, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_ONE_SHOT | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
wait_inactive();
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
ribp_read(32'h0000_0020, intr_state, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_read(32'h0000_0020, intr_state, 1'b0);
|
||||
if (value != 32'd0 || !intr_state[0]) begin
|
||||
$fatal(1, "one-shot completion invalid value=%h state=%h", value, intr_state);
|
||||
end
|
||||
|
||||
// Background load updates the next down-counting period without an immediate reload.
|
||||
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
ribp_write(32'h0000_0004, 32'd5, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0010, 32'd3, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
ribp_write(32'h0000_000C, 32'd1, 4'hF, 1'b0);
|
||||
ribp_read(32'h0000_0008, frozen_value, 1'b0);
|
||||
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0004, 32'd5, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0010, 32'd3, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_write(32'h0000_000C, 32'd1, 4'hF, 1'b0);
|
||||
apb4_read(32'h0000_0008, frozen_value, 1'b0);
|
||||
if (frozen_value == 32'd1) $fatal(1, "BGLOAD changed the live counter immediately");
|
||||
repeat (32) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
if (value > 32'd1) $fatal(1, "BGLOAD was not used by the next period: %h", value);
|
||||
ribp_write(32'h0000_0000, CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_PERIODIC | CTRL_DIRECTION_DOWN, 4'hF, 1'b0);
|
||||
|
||||
// Debug freeze stops both prescaler and counter while keeping RIBP readable.
|
||||
ribp_write(32'h0000_0004, 32'd20, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0010, 32'd0, 4'hF, 1'b0);
|
||||
ribp_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DEBUG_FREEZE, 4'hF, 1'b0);
|
||||
// Debug freeze stops both prescaler and counter while keeping APB4 readable.
|
||||
apb4_write(32'h0000_0004, 32'd20, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0010, 32'd0, 4'hF, 1'b0);
|
||||
apb4_write(32'h0000_0000, CTRL_ENABLE | CTRL_PERIODIC | CTRL_DEBUG_FREEZE, 4'hF, 1'b0);
|
||||
debug_halted_i = 1'b1;
|
||||
repeat (2) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0008, frozen_value, 1'b0);
|
||||
apb4_read(32'h0000_0008, frozen_value, 1'b0);
|
||||
repeat (8) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
ribp_read(32'h0000_001C, status, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_read(32'h0000_001C, status, 1'b0);
|
||||
if (value != frozen_value || status[1:0] != 2'b11) begin
|
||||
$fatal(1, "debug freeze invalid before=%h after=%h status=%h", frozen_value, value, status);
|
||||
end
|
||||
debug_halted_i = 1'b0;
|
||||
repeat (4) @(posedge clk_i);
|
||||
ribp_read(32'h0000_0008, value, 1'b0);
|
||||
apb4_read(32'h0000_0008, value, 1'b0);
|
||||
if (value == frozen_value) $fatal(1, "timer did not resume after debug halt");
|
||||
|
||||
// Software interrupt test and W1C clear.
|
||||
ribp_write(32'h0000_002C, 32'h0000_0006, 4'h1, 1'b0);
|
||||
ribp_read(32'h0000_0020, intr_state, 1'b0);
|
||||
apb4_write(32'h0000_002C, 32'h0000_0006, 4'h1, 1'b0);
|
||||
apb4_read(32'h0000_0020, intr_state, 1'b0);
|
||||
if ((intr_state[2:1] != 2'b11) || !irq_o) $fatal(1, "interrupt test failed");
|
||||
ribp_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
apb4_write(32'h0000_0020, 32'h0000_0007, 4'h1, 1'b0);
|
||||
|
||||
$display("RIBP Timer register, mode, interrupt, and error test passed");
|
||||
$display("APB4 Timer register, mode, interrupt, and error test passed");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
+89
-83
@@ -1,71 +1,77 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "ribp_uart_define.svh"
|
||||
`include "apb4_uart_define.svh"
|
||||
|
||||
module uart_tb;
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
logic dma_tx_stall;
|
||||
logic dma_rx_stall;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
uart_if uart ();
|
||||
|
||||
always #5 clk_i = ~clk_i;
|
||||
|
||||
ribp_uart u_dut (
|
||||
apb4_uart u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i (rst_n_i),
|
||||
.dma_tx_stall_o(dma_tx_stall),
|
||||
.dma_rx_stall_o(dma_rx_stall),
|
||||
.ribp (ribp),
|
||||
.apb4 (apb4),
|
||||
.uart (uart)
|
||||
);
|
||||
|
||||
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = strobe;
|
||||
ribp.valid = 1'b1;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "UART write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
end
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = strobe;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] address, input logic expected_error,
|
||||
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
|
||||
output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
ribp.valid = 1'b1;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "UART read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
end
|
||||
data = ribp.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_ok(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
ribp_write(address, data, 4'hF, 1'b0);
|
||||
apb4_write(address, data, 4'hF, 1'b0);
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -74,15 +80,15 @@ module uart_tb;
|
||||
input logic [6:0] rts_deassert_level,
|
||||
input logic [3:0] control);
|
||||
begin
|
||||
write_ok(`RIBP_UART_CTRL, 0);
|
||||
write_ok(`APB4_UART_CTRL, 0);
|
||||
repeat (4) @(posedge clk_i);
|
||||
write_ok(`RIBP_UART_FIFO_CTRL, 3);
|
||||
write_ok(`RIBP_UART_BAUD_INT, 16);
|
||||
write_ok(`RIBP_UART_BAUD_FRAC, 0);
|
||||
write_ok(`RIBP_UART_LINE_CTRL, line_control);
|
||||
write_ok(`RIBP_UART_RTS_WATERMARK, {9'd0, rts_deassert_level, 9'd0, rts_assert_level});
|
||||
write_ok(`RIBP_UART_FLOW_CTRL, flow_control);
|
||||
write_ok(`RIBP_UART_CTRL, control);
|
||||
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
||||
write_ok(`APB4_UART_BAUD_INT, 16);
|
||||
write_ok(`APB4_UART_BAUD_FRAC, 0);
|
||||
write_ok(`APB4_UART_LINE_CTRL, line_control);
|
||||
write_ok(`APB4_UART_RTS_WATERMARK, {9'd0, rts_deassert_level, 9'd0, rts_assert_level});
|
||||
write_ok(`APB4_UART_FLOW_CTRL, flow_control);
|
||||
write_ok(`APB4_UART_CTRL, control);
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -112,10 +118,10 @@ module uart_tb;
|
||||
logic [31:0] value;
|
||||
integer index;
|
||||
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
uart.rx_i = 1'b1;
|
||||
uart.cts_n_i = 1'b1;
|
||||
repeat (4) @(posedge clk_i);
|
||||
@@ -123,84 +129,84 @@ module uart_tb;
|
||||
repeat (4) @(posedge clk_i);
|
||||
|
||||
if (uart.rts_n_o !== 1'b1) $fatal(1, "UART RTS_n was not released after reset");
|
||||
ribp_read(`RIBP_UART_IP_VERSION, 1'b0, value);
|
||||
apb4_read(`APB4_UART_IP_VERSION, 1'b0, value);
|
||||
if (value != 32'h0003_0000) $fatal(1, "UART IP version mismatch");
|
||||
ribp_read(`RIBP_UART_CAPABILITY, 1'b0, value);
|
||||
apb4_read(`APB4_UART_CAPABILITY, 1'b0, value);
|
||||
if (value != 32'h03FF_4040) $fatal(1, "UART capability mismatch");
|
||||
ribp_read(32'h0000_0002, 1'b1, value);
|
||||
ribp_read(`RIBP_UART_RXDATA, 1'b1, value);
|
||||
apb4_read(32'h0000_0002, 1'b1, value);
|
||||
apb4_read(`APB4_UART_RXDATA, 1'b1, value);
|
||||
|
||||
ribp_write(`RIBP_UART_RTS_WATERMARK, 32'h0002_0002, 4'hF, 1'b1);
|
||||
ribp_read(`RIBP_UART_ERROR_STATUS, 1'b0, value);
|
||||
apb4_write(`APB4_UART_RTS_WATERMARK, 32'h0002_0002, 4'hF, 1'b1);
|
||||
apb4_read(`APB4_UART_ERROR_STATUS, 1'b0, value);
|
||||
if (!value[`UART_ERROR_CONFIG]) $fatal(1, "UART invalid RTS watermark was not reported");
|
||||
write_ok(`RIBP_UART_ERROR_STATUS, 7'h7F);
|
||||
write_ok(`APB4_UART_ERROR_STATUS, 7'h7F);
|
||||
|
||||
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0111);
|
||||
write_ok(`RIBP_UART_TXDATA, 8'hA5);
|
||||
write_ok(`APB4_UART_TXDATA, 8'hA5);
|
||||
repeat (220) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
||||
if (value[11:0] != 12'h0A5) $fatal(1, "UART 8N1 loopback mismatch: %h", value);
|
||||
|
||||
configure_uart(5'd3, 4'b0001);
|
||||
write_ok(`RIBP_UART_TXDATA, 8'h5A);
|
||||
write_ok(`APB4_UART_TXDATA, 8'h5A);
|
||||
repeat (24) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
||||
if (!value[`UART_STATUS_TX_BUSY]) $fatal(1, "UART TX did not start before disable");
|
||||
write_ok(`RIBP_UART_CTRL, 0);
|
||||
write_ok(`APB4_UART_CTRL, 0);
|
||||
repeat (180) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
||||
if (value[`UART_STATUS_TX_BUSY] || !value[`UART_STATUS_TX_EMPTY]) begin
|
||||
$fatal(1, "UART TX did not finish its active frame after disable: %h", value);
|
||||
end
|
||||
|
||||
write_ok(`RIBP_UART_INTR_ENABLE, 7'h7F);
|
||||
write_ok(`RIBP_UART_INTR_TEST, 7'h20);
|
||||
ribp_read(`RIBP_UART_INTR_STATUS, 1'b0, value);
|
||||
write_ok(`APB4_UART_INTR_ENABLE, 7'h7F);
|
||||
write_ok(`APB4_UART_INTR_TEST, 7'h20);
|
||||
apb4_read(`APB4_UART_INTR_STATUS, 1'b0, value);
|
||||
if (!value[`UART_INTR_BREAK] || !uart.irq_o) $fatal(1, "UART interrupt test failed");
|
||||
write_ok(`RIBP_UART_INTR_STATE, 7'h7F);
|
||||
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
|
||||
|
||||
configure_uart_flow(5'd3, 2'b01, 7'd32, 7'd48, 4'b0001);
|
||||
write_ok(`RIBP_UART_INTR_ENABLE, 7'h40);
|
||||
write_ok(`RIBP_UART_TXDATA, 8'hC3);
|
||||
write_ok(`RIBP_UART_TXDATA, 8'h5C);
|
||||
write_ok(`APB4_UART_INTR_ENABLE, 7'h40);
|
||||
write_ok(`APB4_UART_TXDATA, 8'hC3);
|
||||
write_ok(`APB4_UART_TXDATA, 8'h5C);
|
||||
repeat (32) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
||||
if (!value[`UART_STATUS_TX_FLOW_BLOCKED] || value[`UART_STATUS_TX_BUSY] ||
|
||||
value[`UART_STATUS_CTS_ASSERTED]) begin
|
||||
$fatal(1, "UART CTS did not block a new frame: %h", value);
|
||||
end
|
||||
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
|
||||
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
||||
if (value[6:0] != 7'd2) $fatal(1, "UART CTS-blocked FIFO count mismatch: %h", value);
|
||||
|
||||
uart.cts_n_i = 1'b0;
|
||||
repeat (32) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
||||
if (!value[`UART_STATUS_CTS_ASSERTED] || !value[`UART_STATUS_TX_BUSY]) begin
|
||||
$fatal(1, "UART did not start after CTS assertion: %h", value);
|
||||
end
|
||||
uart.cts_n_i = 1'b1;
|
||||
repeat (200) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_STATUS, 1'b0, value);
|
||||
if (!value[`UART_STATUS_TX_FLOW_BLOCKED] || value[`UART_STATUS_TX_BUSY]) begin
|
||||
$fatal(1, "UART CTS did not stop at the frame boundary: %h", value);
|
||||
end
|
||||
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
|
||||
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
||||
if (value[6:0] != 7'd1) $fatal(1, "UART frame-boundary FIFO count mismatch: %h", value);
|
||||
ribp_read(`RIBP_UART_INTR_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_UART_INTR_STATUS, 1'b0, value);
|
||||
if (!value[`UART_INTR_CTS_CHANGE] || !uart.irq_o) begin
|
||||
$fatal(1, "UART CTS change interrupt failed: %h", value);
|
||||
end
|
||||
write_ok(`RIBP_UART_INTR_STATE, 7'h7F);
|
||||
write_ok(`APB4_UART_INTR_STATE, 7'h7F);
|
||||
uart.cts_n_i = 1'b0;
|
||||
repeat (220) @(posedge clk_i);
|
||||
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
|
||||
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
||||
if (value[6:0] != 7'd0) $fatal(1, "UART did not resume after CTS assertion: %h", value);
|
||||
|
||||
configure_uart(5'd3, 4'b0010);
|
||||
fork
|
||||
send_external_8n1(8'h3C, 1'b1);
|
||||
join
|
||||
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
||||
if ((value[7:0] != 8'h3C) || !value[`UART_RXDATA_FRAME_ERROR]) begin
|
||||
$fatal(1, "UART frame error was not retained: %h", value);
|
||||
end
|
||||
@@ -212,26 +218,26 @@ module uart_tb;
|
||||
if (uart.rts_n_o !== 1'b0) $fatal(1, "UART RTS_n asserted state did not hold below watermark");
|
||||
send_external_8n1(8'h34, 1'b0);
|
||||
if (uart.rts_n_o !== 1'b1) $fatal(1, "UART RTS_n was not released at high watermark");
|
||||
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
||||
repeat (2) @(posedge clk_i);
|
||||
if ((value[7:0] != 8'h12) || (uart.rts_n_o !== 1'b0)) begin
|
||||
$fatal(1, "UART RTS hysteresis did not reassert below low watermark: %h", value);
|
||||
end
|
||||
ribp_read(`RIBP_UART_RXDATA, 1'b0, value);
|
||||
apb4_read(`APB4_UART_RXDATA, 1'b0, value);
|
||||
if (value[7:0] != 8'h34) $fatal(1, "UART RTS test RX ordering mismatch: %h", value);
|
||||
|
||||
write_ok(`RIBP_UART_CTRL, 0);
|
||||
write_ok(`APB4_UART_CTRL, 0);
|
||||
repeat (4) @(posedge clk_i);
|
||||
write_ok(`RIBP_UART_FIFO_CTRL, 3);
|
||||
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
||||
for (index = 0; index < 64; index = index + 1) begin
|
||||
write_ok(`RIBP_UART_TXDATA, index);
|
||||
write_ok(`APB4_UART_TXDATA, index);
|
||||
end
|
||||
ribp_write(`RIBP_UART_TXDATA, 32'h55, 4'hF, 1'b1);
|
||||
ribp_read(`RIBP_UART_FIFO_LEVEL, 1'b0, value);
|
||||
apb4_write(`APB4_UART_TXDATA, 32'h55, 4'hF, 1'b1);
|
||||
apb4_read(`APB4_UART_FIFO_LEVEL, 1'b0, value);
|
||||
if (value[6:0] != 7'd64) $fatal(1, "UART TX FIFO depth mismatch: %h", value);
|
||||
|
||||
write_ok(`RIBP_UART_FIFO_CTRL, 3);
|
||||
write_ok(`RIBP_UART_DMA_CTRL, 3);
|
||||
write_ok(`APB4_UART_FIFO_CTRL, 3);
|
||||
write_ok(`APB4_UART_DMA_CTRL, 3);
|
||||
if (!dma_tx_stall || !dma_rx_stall) $fatal(1, "Disabled UART asserted a DMA request");
|
||||
|
||||
$display("UART register, FIFO, loopback, flow-control, interrupt, and DMA test passed");
|
||||
|
||||
+48
-31
@@ -27,10 +27,12 @@ module ws2812_dma_tb;
|
||||
logic [31:0] dma_error_addr;
|
||||
logic [ 1:0] dma_fsm;
|
||||
logic host_active = 1'b1;
|
||||
logic host_valid = 1'b0;
|
||||
logic host_psel = 1'b0;
|
||||
logic host_penable = 1'b0;
|
||||
logic [31:0] host_addr = '0;
|
||||
logic [31:0] host_wdata = '0;
|
||||
logic [ 3:0] host_wstrb = '0;
|
||||
logic dma_penable = 1'b0;
|
||||
logic dma_ws_valid;
|
||||
bus_state_t bus_state_q = BUS_IDLE;
|
||||
logic [31:0] bus_addr_q = '0;
|
||||
@@ -44,7 +46,10 @@ module ws2812_dma_tb;
|
||||
|
||||
dma_hw_trg_if hw_trg ();
|
||||
rib_if dma_rib ();
|
||||
ribp_if ws_ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
ws2812_if ws2812 ();
|
||||
axi4_stream_if i2s_tx_axis (
|
||||
.aclk (clk_i),
|
||||
@@ -66,13 +71,16 @@ module ws2812_dma_tb;
|
||||
$fatal(1, "WS2812 DMA integration test timeout");
|
||||
end
|
||||
|
||||
assign ws_ribp.valid = host_active ? host_valid : dma_ws_valid;
|
||||
assign ws_ribp.addr = host_active ? host_addr : bus_addr_q;
|
||||
assign ws_ribp.wdata = host_active ? host_wdata : dma_rib.wdata;
|
||||
assign ws_ribp.wstrb = host_active ? host_wstrb : dma_rib.wstrb;
|
||||
assign apb4.psel = host_active ? host_psel : dma_ws_valid;
|
||||
assign apb4.penable = host_active ? host_penable : dma_penable;
|
||||
assign apb4.pwrite = 1'b1;
|
||||
assign apb4.paddr = host_active ? host_addr : bus_addr_q;
|
||||
assign apb4.pwdata = host_active ? host_wdata : dma_rib.wdata;
|
||||
assign apb4.pstrb = host_active ? host_wstrb : dma_rib.wstrb;
|
||||
assign apb4.pprot = '0;
|
||||
|
||||
assign dma_rib.cmd_ready = bus_state_q == BUS_IDLE;
|
||||
assign dma_rib.w_ready = (bus_state_q == BUS_WRITE_DATA) && ws_ribp.ready;
|
||||
assign dma_rib.w_ready = (bus_state_q == BUS_WRITE_DATA) && dma_penable && apb4.pready;
|
||||
assign dma_rib.rsp_valid = (bus_state_q == BUS_READ_RESP) || (bus_state_q == BUS_WRITE_RESP);
|
||||
assign dma_rib.rdata = pixels[bus_addr_q[4:2]];
|
||||
assign dma_rib.resp_err = 1'b0;
|
||||
@@ -98,6 +106,18 @@ module ws2812_dma_tb;
|
||||
assign dvp_rx_axis.tuser = '0;
|
||||
assign dvp_rx_axis.tvalid = 1'b0;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
dma_penable <= 1'b0;
|
||||
end else if (!dma_ws_valid) begin
|
||||
dma_penable <= 1'b0;
|
||||
end else if (!dma_penable) begin
|
||||
dma_penable <= 1'b1;
|
||||
end else if (apb4.pready) begin
|
||||
dma_penable <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_n_i) begin
|
||||
if (!rst_n_i) begin
|
||||
bus_state_q <= BUS_IDLE;
|
||||
@@ -177,32 +197,29 @@ module ws2812_dma_tb;
|
||||
.dvp_rx_axis (dvp_rx_axis)
|
||||
);
|
||||
|
||||
ribp_ws2812 #(
|
||||
apb4_ws2812 #(
|
||||
.TxFifoDepth(4)
|
||||
) u_ws2812 (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.ribp (ws_ribp),
|
||||
.apb4 (apb4),
|
||||
.ws2812 (ws2812)
|
||||
);
|
||||
|
||||
task automatic host_write(input logic [31:0] address, input logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
host_addr = address;
|
||||
host_wdata = data;
|
||||
host_wstrb = 4'hF;
|
||||
host_valid = 1'b1;
|
||||
while (!ws_ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ws_ribp.resp_err) begin
|
||||
$fatal(1, "host write %h failed", address);
|
||||
end
|
||||
host_addr = address;
|
||||
host_wdata = data;
|
||||
host_wstrb = 4'hF;
|
||||
host_psel = 1'b1;
|
||||
host_penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
host_valid = 1'b0;
|
||||
host_wstrb = '0;
|
||||
host_penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr) $fatal(1, "WS2812 write %h unexpected error", address);
|
||||
host_psel = 1'b0;
|
||||
host_penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -258,15 +275,15 @@ module ws2812_dma_tb;
|
||||
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
host_write(`RIBP_WS2812_BIT_CYCLES, BIT_CYCLES);
|
||||
host_write(`RIBP_WS2812_T0H_CYCLES, T0H_CYCLES);
|
||||
host_write(`RIBP_WS2812_T1H_CYCLES, T1H_CYCLES);
|
||||
host_write(`RIBP_WS2812_RESET_CYCLES, RESET_CYCLES);
|
||||
host_write(`RIBP_WS2812_FIFO_WATERMARK, 3);
|
||||
host_write(`RIBP_WS2812_INTR_ENABLE, 1);
|
||||
host_write(`RIBP_WS2812_TXDATA, pixels[0]);
|
||||
host_write(`RIBP_WS2812_FRAME_WORDS, 6);
|
||||
host_write(`RIBP_WS2812_CTRL, 1);
|
||||
host_write(`APB4_WS2812_BIT_CYCLES, BIT_CYCLES);
|
||||
host_write(`APB4_WS2812_T0H_CYCLES, T0H_CYCLES);
|
||||
host_write(`APB4_WS2812_T1H_CYCLES, T1H_CYCLES);
|
||||
host_write(`APB4_WS2812_RESET_CYCLES, RESET_CYCLES);
|
||||
host_write(`APB4_WS2812_FIFO_WATERMARK, 3);
|
||||
host_write(`APB4_WS2812_INTR_ENABLE, 1);
|
||||
host_write(`APB4_WS2812_TXDATA, pixels[0]);
|
||||
host_write(`APB4_WS2812_FRAME_WORDS, 6);
|
||||
host_write(`APB4_WS2812_CTRL, 1);
|
||||
|
||||
host_active = 1'b0;
|
||||
@(negedge clk_i);
|
||||
|
||||
+92
-84
@@ -11,7 +11,10 @@ module ws2812_tb;
|
||||
|
||||
logic clk_i = 1'b0;
|
||||
logic rst_n_i = 1'b0;
|
||||
ribp_if ribp ();
|
||||
apb4_if apb4 (
|
||||
.pclk (clk_i),
|
||||
.presetn(rst_n_i)
|
||||
);
|
||||
ws2812_if ws2812 ();
|
||||
|
||||
logic monitor_enable = 1'b0;
|
||||
@@ -31,67 +34,72 @@ module ws2812_tb;
|
||||
initial begin
|
||||
repeat (10000) @(posedge clk_i);
|
||||
$fatal(1, "WS2812 test timeout at stage %0d state=%0d valid=%b ready=%b", test_stage,
|
||||
u_dut.u_ws2812_core.s_state_q, ribp.valid, ribp.ready);
|
||||
u_dut.u_ws2812_core.s_state_q, apb4.psel, apb4.pready);
|
||||
end
|
||||
|
||||
ribp_ws2812 #(
|
||||
apb4_ws2812 #(
|
||||
.TxFifoDepth(FIFO_DEPTH)
|
||||
) u_dut (
|
||||
.clk_i (clk_i),
|
||||
.rst_n_i(rst_n_i),
|
||||
.ribp (ribp),
|
||||
.apb4 (apb4),
|
||||
.ws2812 (ws2812)
|
||||
);
|
||||
|
||||
task automatic ribp_write(input logic [31:0] address, input logic [31:0] data,
|
||||
task automatic apb4_write(input logic [31:0] address, input logic [31:0] data,
|
||||
input logic [3:0] strobe, input logic expected_error,
|
||||
output integer wait_cycles);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = data;
|
||||
ribp.wstrb = strobe;
|
||||
ribp.valid = 1'b1;
|
||||
wait_cycles = 0;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
@(negedge clk_i);
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = data;
|
||||
apb4.pstrb = strobe;
|
||||
apb4.pwrite = 1'b1;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) begin
|
||||
@(negedge clk_i);
|
||||
wait_cycles = wait_cycles + 1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "write %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.pstrb = '0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic ribp_read(input logic [31:0] address, input logic expected_error,
|
||||
task automatic apb4_read(input logic [31:0] address, input logic expected_error,
|
||||
output logic [31:0] data);
|
||||
begin
|
||||
@(negedge clk_i);
|
||||
ribp.addr = address;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
ribp.valid = 1'b1;
|
||||
while (!ribp.ready) begin
|
||||
@(posedge clk_i);
|
||||
#1;
|
||||
end
|
||||
if (ribp.resp_err !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, ribp.resp_err, expected_error);
|
||||
end
|
||||
data = ribp.rdata;
|
||||
apb4.paddr = address;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
apb4.pwrite = 1'b0;
|
||||
apb4.psel = 1'b1;
|
||||
apb4.penable = 1'b0;
|
||||
@(negedge clk_i);
|
||||
ribp.valid = 1'b0;
|
||||
apb4.penable = 1'b1;
|
||||
while (!apb4.pready) @(negedge clk_i);
|
||||
if (apb4.pslverr !== expected_error) begin
|
||||
$fatal(1, "read %h error=%b expected=%b", address, apb4.pslverr, expected_error);
|
||||
end
|
||||
data = apb4.prdata;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.penable = 1'b0;
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic write_ok(input logic [31:0] address, input logic [31:0] data);
|
||||
integer ignored_wait;
|
||||
begin
|
||||
ribp_write(address, data, 4'hF, 1'b0, ignored_wait);
|
||||
apb4_write(address, data, 4'hF, 1'b0, ignored_wait);
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -100,19 +108,19 @@ module ws2812_tb;
|
||||
begin
|
||||
status = 32'h1;
|
||||
while (status[`WS2812_STATUS_BUSY]) begin
|
||||
ribp_read(`RIBP_WS2812_STATUS, 1'b0, status);
|
||||
apb4_read(`APB4_WS2812_STATUS, 1'b0, status);
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task automatic configure_timing;
|
||||
begin
|
||||
write_ok(`RIBP_WS2812_BIT_CYCLES, BIT_CYCLES);
|
||||
write_ok(`RIBP_WS2812_T0H_CYCLES, T0H_CYCLES);
|
||||
write_ok(`RIBP_WS2812_T1H_CYCLES, T1H_CYCLES);
|
||||
write_ok(`RIBP_WS2812_RESET_CYCLES, RESET_CYCLES);
|
||||
write_ok(`RIBP_WS2812_FIFO_WATERMARK, 3);
|
||||
write_ok(`RIBP_WS2812_INTR_ENABLE, 4'hF);
|
||||
write_ok(`APB4_WS2812_BIT_CYCLES, BIT_CYCLES);
|
||||
write_ok(`APB4_WS2812_T0H_CYCLES, T0H_CYCLES);
|
||||
write_ok(`APB4_WS2812_T1H_CYCLES, T1H_CYCLES);
|
||||
write_ok(`APB4_WS2812_RESET_CYCLES, RESET_CYCLES);
|
||||
write_ok(`APB4_WS2812_FIFO_WATERMARK, 3);
|
||||
write_ok(`APB4_WS2812_INTR_ENABLE, 4'hF);
|
||||
end
|
||||
endtask
|
||||
|
||||
@@ -176,50 +184,50 @@ module ws2812_tb;
|
||||
logic [31:0] value;
|
||||
integer wait_cycles;
|
||||
|
||||
ribp.valid = 1'b0;
|
||||
ribp.addr = '0;
|
||||
ribp.wdata = '0;
|
||||
ribp.wstrb = '0;
|
||||
apb4.psel = 1'b0;
|
||||
apb4.paddr = '0;
|
||||
apb4.pwdata = '0;
|
||||
apb4.pstrb = '0;
|
||||
repeat (3) @(posedge clk_i);
|
||||
rst_n_i = 1'b1;
|
||||
|
||||
test_stage = 1;
|
||||
ribp_read(`RIBP_WS2812_IP_INFO, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_IP_INFO, 1'b0, value);
|
||||
if (value !== 32'h1804_0100) begin
|
||||
$fatal(1, "unexpected IP_INFO %h", value);
|
||||
end
|
||||
ribp_read(`RIBP_WS2812_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_STATUS, 1'b0, value);
|
||||
if (value[`WS2812_STATUS_CONFIG_VALID] || !value[`WS2812_STATUS_FIFO_EMPTY]) begin
|
||||
$fatal(1, "unexpected reset status %h", value);
|
||||
end
|
||||
ribp_read(`RIBP_WS2812_CTRL, 1'b1, value);
|
||||
ribp_write(8'h02, 32'd1, 4'hF, 1'b1, wait_cycles);
|
||||
ribp_read(32'h00000100, 1'b1, value);
|
||||
ribp_write(`RIBP_WS2812_TXDATA, 24'h112233, 4'h7, 1'b1, wait_cycles);
|
||||
write_ok(`RIBP_WS2812_TXDATA, 24'h112233);
|
||||
write_ok(`RIBP_WS2812_FRAME_WORDS, 1);
|
||||
ribp_write(`RIBP_WS2812_CTRL, 32'h1, 4'hF, 1'b1, wait_cycles);
|
||||
ribp_read(`RIBP_WS2812_ERROR_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_CTRL, 1'b1, value);
|
||||
apb4_write(8'h02, 32'd1, 4'hF, 1'b1, wait_cycles);
|
||||
apb4_read(32'h00000100, 1'b1, value);
|
||||
apb4_write(`APB4_WS2812_TXDATA, 24'h112233, 4'h7, 1'b1, wait_cycles);
|
||||
write_ok(`APB4_WS2812_TXDATA, 24'h112233);
|
||||
write_ok(`APB4_WS2812_FRAME_WORDS, 1);
|
||||
apb4_write(`APB4_WS2812_CTRL, 32'h1, 4'hF, 1'b1, wait_cycles);
|
||||
apb4_read(`APB4_WS2812_ERROR_STATUS, 1'b0, value);
|
||||
if (!value[`WS2812_ERROR_CONFIG]) begin
|
||||
$fatal(1, "invalid timing did not set CONFIG error");
|
||||
end
|
||||
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h4);
|
||||
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h4);
|
||||
|
||||
configure_timing();
|
||||
ribp_read(`RIBP_WS2812_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_STATUS, 1'b0, value);
|
||||
if (!value[`WS2812_STATUS_CONFIG_VALID]) begin
|
||||
$fatal(1, "legal timing was not accepted");
|
||||
end
|
||||
|
||||
test_stage = 2;
|
||||
for (integer index = 0; index < FIFO_DEPTH; index = index + 1) begin
|
||||
write_ok(`RIBP_WS2812_TXDATA, index);
|
||||
write_ok(`APB4_WS2812_TXDATA, index);
|
||||
end
|
||||
ribp_write(`RIBP_WS2812_TXDATA, 32'h55, 4'hF, 1'b1, wait_cycles);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h4);
|
||||
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
|
||||
apb4_write(`APB4_WS2812_TXDATA, 32'h55, 4'hF, 1'b1, wait_cycles);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h4);
|
||||
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
|
||||
|
||||
test_stage = 3;
|
||||
expected_pixels[0] = 24'h800001;
|
||||
@@ -229,68 +237,68 @@ module ws2812_tb;
|
||||
expected_pixels[4] = 24'hFFFFFF;
|
||||
expected_pixels[5] = 24'h000000;
|
||||
for (integer index = 0; index < FIFO_DEPTH; index = index + 1) begin
|
||||
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[index]);
|
||||
write_ok(`APB4_WS2812_TXDATA, expected_pixels[index]);
|
||||
end
|
||||
write_ok(`RIBP_WS2812_FRAME_WORDS, 6);
|
||||
write_ok(`APB4_WS2812_FRAME_WORDS, 6);
|
||||
begin_monitor(6);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h1);
|
||||
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[4]);
|
||||
ribp_write(`RIBP_WS2812_TXDATA, expected_pixels[5], 4'hF, 1'b0, wait_cycles);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h1);
|
||||
write_ok(`APB4_WS2812_TXDATA, expected_pixels[4]);
|
||||
apb4_write(`APB4_WS2812_TXDATA, expected_pixels[5], 4'hF, 1'b0, wait_cycles);
|
||||
if (wait_cycles < (BIT_CYCLES * 20)) begin
|
||||
$fatal(1, "full FIFO write was not backpressured: %0d cycles", wait_cycles);
|
||||
end
|
||||
wait_until_idle();
|
||||
end_monitor(1'b1);
|
||||
ribp_read(`RIBP_WS2812_INTR_STATE, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_INTR_STATE, 1'b0, value);
|
||||
if ((value & 32'h3) != 32'h3 || !ws2812.irq_o) begin
|
||||
$fatal(1, "done/low-watermark interrupt missing: %h", value);
|
||||
end
|
||||
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
|
||||
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
|
||||
if (ws2812.irq_o) begin
|
||||
$fatal(1, "IRQ did not clear");
|
||||
end
|
||||
|
||||
test_stage = 4;
|
||||
expected_pixels[0] = 24'h123456;
|
||||
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[0]);
|
||||
write_ok(`RIBP_WS2812_FRAME_WORDS, 2);
|
||||
write_ok(`APB4_WS2812_TXDATA, expected_pixels[0]);
|
||||
write_ok(`APB4_WS2812_FRAME_WORDS, 2);
|
||||
begin_monitor(1);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h1);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h1);
|
||||
wait_until_idle();
|
||||
end_monitor(1'b1);
|
||||
ribp_read(`RIBP_WS2812_ERROR_STATUS, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_ERROR_STATUS, 1'b0, value);
|
||||
if (!value[`WS2812_ERROR_UNDERFLOW]) begin
|
||||
$fatal(1, "underflow was not reported");
|
||||
end
|
||||
ribp_read(`RIBP_WS2812_FIFO_LEVEL, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_FIFO_LEVEL, 1'b0, value);
|
||||
if (value != 0) begin
|
||||
$fatal(1, "underflow did not flush FIFO");
|
||||
end
|
||||
write_ok(`RIBP_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
|
||||
write_ok(`APB4_WS2812_ERROR_STATUS, 32'h7);
|
||||
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
|
||||
|
||||
test_stage = 5;
|
||||
expected_pixels[0] = 24'hABCDEF;
|
||||
expected_pixels[1] = 24'h765432;
|
||||
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[0]);
|
||||
write_ok(`RIBP_WS2812_TXDATA, expected_pixels[1]);
|
||||
write_ok(`RIBP_WS2812_FRAME_WORDS, 2);
|
||||
write_ok(`APB4_WS2812_TXDATA, expected_pixels[0]);
|
||||
write_ok(`APB4_WS2812_TXDATA, expected_pixels[1]);
|
||||
write_ok(`APB4_WS2812_FRAME_WORDS, 2);
|
||||
begin_monitor(2);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h1);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h1);
|
||||
repeat (8) @(posedge clk_i);
|
||||
write_ok(`RIBP_WS2812_CTRL, 32'h2);
|
||||
write_ok(`APB4_WS2812_CTRL, 32'h2);
|
||||
wait_until_idle();
|
||||
end_monitor(1'b0);
|
||||
ribp_read(`RIBP_WS2812_INTR_STATE, 1'b0, value);
|
||||
apb4_read(`APB4_WS2812_INTR_STATE, 1'b0, value);
|
||||
if (!value[`WS2812_INTR_ABORTED]) begin
|
||||
$fatal(1, "abort completion was not reported");
|
||||
end
|
||||
|
||||
write_ok(`RIBP_WS2812_INTR_TEST, 32'h1);
|
||||
write_ok(`APB4_WS2812_INTR_TEST, 32'h1);
|
||||
if (!ws2812.irq_o) begin
|
||||
$fatal(1, "interrupt test did not assert IRQ");
|
||||
end
|
||||
write_ok(`RIBP_WS2812_INTR_STATE, 32'hF);
|
||||
write_ok(`APB4_WS2812_INTR_STATE, 32'hF);
|
||||
|
||||
$display("WS2812 register, waveform, streaming, and error test passed");
|
||||
$finish;
|
||||
|
||||
Reference in new issue
Block a user