feat: refactor RIB to APB bridge and update related components

- Changed the interface from ribp to rib in soc_topology.json and related files.
- Updated formal.mk to reflect the new rib2apb naming convention.
- Implemented rib2apb module to handle RIB to APB communication.
- Modified bus.sv to integrate the new rib2apb module and adjust signal assignments accordingly.
- Updated testbench files to use the new rib interface and validate the RIB to APB functionality.
- Created rib2apb_tb for testing the direct RIB to APB bridge.
- Adjusted script tools and test scripts to accommodate the new naming and structure.
This commit is contained in:
maksyuki committed 2026-08-05 16:03:41 +08:00
1 parent 07e0d045be
commit 6be73fa6b7
27 files changed
+950 -454

No files matched your search

+20 -14
View File
@@ -15,20 +15,26 @@ module bus_fault_tb;
rib_if user_rib ();
rib_if dma_rib ();
rib_if rib ();
ribp_if apb_ribp ();
rib_if apb_rib ();
always #5 clk_i = ~clk_i;
assign rib.cmd_ready = 1'b1;
assign rib.w_ready = 1'b1;
assign rib.rsp_valid = 1'b0;
assign rib.rdata = 32'hCAFE_BABE;
assign rib.resp_err = 1'b0;
assign rib.resp_code = `RIB_RESP_OK;
assign rib.rsp_beat = '0;
assign rib.rsp_last = 1'b0;
assign apb_ribp.ready = 1'b1;
assign apb_ribp.rdata = 32'h1234_5678;
assign rib.cmd_ready = 1'b1;
assign rib.w_ready = 1'b1;
assign rib.rsp_valid = 1'b0;
assign rib.rdata = 32'hCAFE_BABE;
assign rib.resp_err = 1'b0;
assign rib.resp_code = `RIB_RESP_OK;
assign rib.rsp_beat = '0;
assign rib.rsp_last = 1'b0;
assign apb_rib.cmd_ready = 1'b1;
assign apb_rib.w_ready = 1'b1;
assign apb_rib.rsp_valid = 1'b0;
assign apb_rib.rdata = 32'h1234_5678;
assign apb_rib.resp_err = 1'b0;
assign apb_rib.resp_code = `RIB_RESP_OK;
assign apb_rib.rsp_beat = '0;
assign apb_rib.rsp_last = 1'b1;
bus u_bus (
.clk_i (clk_i),
@@ -39,7 +45,7 @@ module bus_fault_tb;
.user_bus_enable_i(1'b1),
.user_bus_idle_o (user_bus_idle_o),
.rib (rib),
.apb_ribp (apb_ribp),
.apb_rib (apb_rib),
.perf_enable_i (1'b0),
.perf_clear_i (1'b0),
.fault_valid_o (fault_valid_o),
@@ -62,7 +68,7 @@ module bus_fault_tb;
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_ribp.valid) begin
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);
@@ -95,7 +101,7 @@ module bus_fault_tb;
user_rib.w_valid = 1'b0;
end
while (!fault_valid_o) @(posedge clk_i);
if (!fault_access_o || fault_master_o != 2'd1 || rib.cmd_valid || apb_ribp.valid) begin
if (!fault_access_o || fault_master_o != 2'd1 || rib.cmd_valid || apb_rib.cmd_valid) begin
$fatal(1, "user access was not denied locally");
end
if (user_rib.rdata !== 32'd0 || !user_rib.resp_err || !user_rib.rsp_last ||
+197
View File
@@ -0,0 +1,197 @@
`timescale 1ns / 1ps
`include "rib_defs.svh"
module rib2apb_tb;
logic clk_i = 1'b0;
logic rst_n_i = 1'b0;
logic rng_ready = 1'b0;
logic rng_slverr = 1'b0;
logic [31:0] rng_rdata = 32'h1234_5678;
rib_if rib ();
apb4_pure_if archinfo ();
apb4_pure_if rng ();
apb4_pure_if uart ();
apb4_pure_if pwm ();
apb4_pure_if ps2 ();
apb4_pure_if rtc ();
apb4_pure_if wdg ();
apb4_pure_if crc ();
apb4_pure_if tmr ();
apb4_pure_if user_ip ();
always #5 clk_i = ~clk_i;
assign archinfo.pready = 1'b0;
assign archinfo.prdata = '0;
assign archinfo.pslverr = 1'b0;
assign rng.pready = rng_ready;
assign rng.prdata = rng_rdata;
assign rng.pslverr = rng_slverr;
assign uart.pready = 1'b0;
assign uart.prdata = '0;
assign uart.pslverr = 1'b0;
assign pwm.pready = 1'b0;
assign pwm.prdata = '0;
assign pwm.pslverr = 1'b0;
assign ps2.pready = 1'b0;
assign ps2.prdata = '0;
assign ps2.pslverr = 1'b0;
assign rtc.pready = 1'b0;
assign rtc.prdata = '0;
assign rtc.pslverr = 1'b0;
assign wdg.pready = 1'b0;
assign wdg.prdata = '0;
assign wdg.pslverr = 1'b0;
assign crc.pready = 1'b0;
assign crc.prdata = '0;
assign crc.pslverr = 1'b0;
assign tmr.pready = 1'b0;
assign tmr.prdata = '0;
assign tmr.pslverr = 1'b0;
assign user_ip.pready = 1'b0;
assign user_ip.prdata = '0;
assign user_ip.pslverr = 1'b0;
rib2apb u_rib2apb (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.rib (rib),
.archinfo(archinfo),
.rng (rng),
.uart (uart),
.pwm (pwm),
.ps2 (ps2),
.rtc (rtc),
.wdg (wdg),
.crc (crc),
.tmr (tmr),
.user_ip (user_ip)
);
task automatic send_command(input logic [31:0] address, input logic write,
input logic [1:0] length);
begin
@(negedge clk_i);
rib.cmd_addr = address;
rib.cmd_write = write;
rib.cmd_len = length;
rib.cmd_valid = 1'b1;
while (!rib.cmd_ready) @(posedge clk_i);
@(negedge clk_i);
rib.cmd_valid = 1'b0;
end
endtask
task automatic send_write(input logic [31:0] data, input logic [3:0] strobes, input logic last);
begin
@(negedge clk_i);
rib.wdata = data;
rib.wstrb = strobes;
rib.wlast = last;
rib.w_valid = 1'b1;
while (!rib.w_ready) @(posedge clk_i);
@(negedge clk_i);
rib.w_valid = 1'b0;
end
endtask
task automatic wait_for_rng_enable;
begin
while (!(rng.psel && rng.penable)) @(posedge clk_i);
end
endtask
task automatic expect_response(input logic expected_error, input logic [2:0] expected_code,
input logic [31:0] expected_data);
begin
while (!rib.rsp_valid) @(posedge clk_i);
#1;
if (rib.resp_err !== expected_error || rib.resp_code !== expected_code ||
rib.rdata !== expected_data || rib.rsp_beat !== 2'd0 || !rib.rsp_last) begin
$fatal(1, "unexpected RIB response error=%b/%b code=%0d/%0d data=%h/%h fsm=%0d",
rib.resp_err, expected_error, rib.resp_code, expected_code, rib.rdata,
expected_data, u_rib2apb.s_fsm_q);
end
end
endtask
initial begin
rib.cmd_valid = 1'b0;
rib.cmd_addr = '0;
rib.cmd_write = 1'b0;
rib.cmd_len = `RIB_LEN_INCR1;
rib.w_valid = 1'b0;
rib.wdata = '0;
rib.wstrb = '0;
rib.wlast = 1'b0;
rib.rsp_ready = 1'b1;
repeat (2) @(posedge clk_i);
rst_n_i = 1'b1;
send_command(32'h2000_1000, 1'b0, `RIB_LEN_INCR1);
while (!(rng.psel && !rng.penable)) @(posedge clk_i);
wait_for_rng_enable();
if (rng.paddr !== 32'h2000_1000 || rng.pwrite || rng.pstrb !== 4'd0) begin
$fatal(1, "read APB setup was not held from the RIB command");
end
repeat (2) begin
@(posedge clk_i);
if (!(rng.psel && rng.penable) || rng.paddr !== 32'h2000_1000) begin
$fatal(1, "APB read request changed while PREADY was low");
end
end
rib.rsp_ready = 1'b0;
@(negedge clk_i);
rng_ready = 1'b1;
expect_response(1'b0, `RIB_RESP_OK, 32'h1234_5678);
repeat (2) begin
@(posedge clk_i);
if (!rib.rsp_valid || rib.rdata !== 32'h1234_5678) begin
$fatal(1, "response did not remain stable under RIB backpressure");
end
end
rib.rsp_ready = 1'b1;
@(posedge clk_i);
@(negedge clk_i);
rng_ready = 1'b0;
send_command(32'h2000_1000, 1'b1, `RIB_LEN_INCR1);
send_write(32'hA5A5_5A5A, 4'hC, 1'b1);
wait_for_rng_enable();
if (!rng.pwrite || rng.pwdata !== 32'hA5A5_5A5A || rng.pstrb !== 4'hC) begin
$fatal(1, "APB write data was not held from the RIB write channel");
end
@(negedge clk_i);
rng_ready = 1'b1;
expect_response(1'b0, `RIB_RESP_OK, 32'd0);
@(posedge clk_i);
@(negedge clk_i);
rng_ready = 1'b0;
rng_slverr = 1'b1;
send_command(32'h2000_1000, 1'b0, `RIB_LEN_INCR1);
wait_for_rng_enable();
@(negedge clk_i);
rng_ready = 1'b1;
expect_response(1'b1, `RIB_RESP_SLVERR, 32'h1234_5678);
@(posedge clk_i);
@(negedge clk_i);
rng_ready = 1'b0;
rng_slverr = 1'b0;
send_command(32'h2000_1000, 1'b1, `RIB_LEN_INCR4);
send_write(32'h0000_0001, 4'hF, 1'b0);
send_write(32'h0000_0002, 4'hF, 1'b0);
send_write(32'h0000_0003, 4'hF, 1'b0);
send_write(32'h0000_0004, 4'hF, 1'b1);
if (rng.psel) $fatal(1, "illegal RIB burst reached the APB target");
expect_response(1'b1, `RIB_RESP_BURSTERR, 32'd0);
@(posedge clk_i);
$display("RIB2APB direct bridge test passed");
$finish;
end
endmodule
+11 -5
View File
@@ -20,7 +20,7 @@ module rib_bus_tb;
rib_if user_rib ();
rib_if dma_rib ();
rib_if rib ();
ribp_if apb_ribp ();
rib_if apb_rib ();
always #5 clk_i = ~clk_i;
always @(posedge clk_i) cycle_count <= cycle_count + 1;
@@ -57,8 +57,14 @@ module rib_bus_tb;
end
end
assign apb_ribp.ready = apb_ribp.valid;
assign apb_ribp.rdata = 32'h1234_5678;
assign apb_rib.cmd_ready = 1'b1;
assign apb_rib.w_ready = 1'b1;
assign apb_rib.rsp_valid = 1'b0;
assign apb_rib.rdata = 32'h1234_5678;
assign apb_rib.resp_err = 1'b0;
assign apb_rib.resp_code = `RIB_RESP_OK;
assign apb_rib.rsp_beat = '0;
assign apb_rib.rsp_last = 1'b1;
bus u_bus (
.clk_i (clk_i),
@@ -69,7 +75,7 @@ module rib_bus_tb;
.user_bus_enable_i(1'b1),
.user_bus_idle_o (user_bus_idle_o),
.rib (rib),
.apb_ribp (apb_ribp),
.apb_rib (apb_rib),
.perf_enable_i (1'b0),
.perf_clear_i (1'b0),
.fault_valid_o (fault_valid_o),
@@ -163,7 +169,7 @@ module rib_bus_tb;
issue_read(32'h1000_0000, `RIB_LEN_INCR4, 1'b1);
issue_read(32'h2000_0000, `RIB_LEN_INCR4, 1'b1);
issue_read(32'h3800_1000, 2'd2, 1'b1);
if (rib_command_count != 1 || apb_ribp.valid) begin
if (rib_command_count != 1 || apb_rib.cmd_valid) begin
$fatal(1, "illegal burst reached a downstream target");
end
+89
View File
@@ -0,0 +1,89 @@
"""RTL test for the direct RIB-to-APB bridge."""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_rib2apb_preserves_apb_and_rib_handshakes(tmp_path: Path) -> None:
iverilog = shutil.which("iverilog")
sv2v = shutil.which("sv2v")
vvp = shutil.which("vvp")
if iverilog is None or sv2v is None or vvp is None:
return
memory_map = tmp_path / "memory_map"
topology = tmp_path / "soc_topology"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/address_map/generate_memory_map.py"),
"--map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
str(memory_map),
"--have-sram-if",
"NO",
],
check=True,
)
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/integration/generate_soc_topology.py"),
"--map",
str(ROOT / "rtl/mini/integration/soc_topology.json"),
"--memory-map",
str(ROOT / "rtl/mini/address_map/memory_map.json"),
"--output-dir",
str(topology),
],
check=True,
)
source_list = tmp_path / "rib2apb.fl"
source_list.write_text(
"\n".join(
[
"+define+SV_ASSRT_DISABLE",
f"+incdir+{memory_map / 'rtl'}",
f"+incdir+{topology / 'rtl'}",
f"+incdir+{ROOT / 'rtl/mini/top'}",
f"+incdir+{ROOT / 'rtl/managed/clusterip/common/rtl'}",
str(ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_pure_if.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/register.sv"),
str(ROOT / "rtl/managed/clusterip/common/rtl/utils/spill_register.sv"),
str(ROOT / "rtl/mini/top/rib_if.sv"),
str(ROOT / "rtl/mini/top/rib2apb.sv"),
str(ROOT / "tests/rtl/rib2apb_tb.sv"),
"",
]
),
encoding="utf-8",
)
converted = tmp_path / "rib2apb_tb.v"
subprocess.run(
[
sys.executable,
str(ROOT / "rtl/mini/script/convt_sv2v.py"),
"-f",
str(source_list),
"--output",
str(converted),
],
check=True,
)
simulation = tmp_path / "rib2apb_tb"
subprocess.run(
[iverilog, "-g2012", "-s", "rib2apb_tb", "-o", str(simulation), str(converted)],
check=True,
)
result = subprocess.run([vvp, str(simulation)], text=True, capture_output=True, check=True)
assert "RIB2APB direct bridge test passed" in result.stdout
+8 -8
View File
@@ -181,7 +181,7 @@ def test_formal_filelists_are_scoped_to_the_protocol_duts(tmp_path: Path) -> Non
bus_filelist = tmp_path / "bus.fl"
rib_adapter_filelist = tmp_path / "rib_adapter.fl"
rib2apb_filelist = tmp_path / "ribp2apb.fl"
rib2apb_filelist = tmp_path / "rib2apb.fl"
sysctrl_filelist = tmp_path / "sysctrl.fl"
pll_rcu_filelist = tmp_path / "pll_rcu.fl"
gpio_user_filelist = tmp_path / "gpio_user.fl"
@@ -190,7 +190,7 @@ def test_formal_filelists_are_scoped_to_the_protocol_duts(tmp_path: Path) -> Non
"rib_adapter", rib_adapter_filelist, memory_map, topology, user_extensions
)
assert generate_formal_filelist(
"ribp2apb", rib2apb_filelist, memory_map, topology, user_extensions
"rib2apb", rib2apb_filelist, memory_map, topology, user_extensions
)
assert generate_formal_filelist(
"sysctrl", sysctrl_filelist, memory_map, topology, user_extensions
@@ -204,7 +204,7 @@ def test_formal_filelists_are_scoped_to_the_protocol_duts(tmp_path: Path) -> Non
bus = parse_filelists([bus_filelist], require_files=False)
rib_adapter = parse_filelists([rib_adapter_filelist], require_files=False)
ribp2apb = parse_filelists([rib2apb_filelist], require_files=False)
rib2apb = parse_filelists([rib2apb_filelist], require_files=False)
sysctrl = parse_filelists([sysctrl_filelist], require_files=False)
pll_rcu = parse_filelists([pll_rcu_filelist], require_files=False)
gpio_user = parse_filelists([gpio_user_filelist], require_files=False)
@@ -216,9 +216,9 @@ def test_formal_filelists_are_scoped_to_the_protocol_duts(tmp_path: Path) -> Non
assert ROOT / "rtl/mini/formal/bus_formal.sv" in bus.files
assert ROOT / "rtl/mini/top/rib2ribp.sv" in rib_adapter.files
assert ROOT / "rtl/mini/formal/rib_adapter_formal.sv" in rib_adapter.files
assert ROOT / "rtl/ip/ribp/interconnect/ribp2apb.sv" in ribp2apb.files
assert ROOT / "rtl/mini/formal/ribp2apb_formal.sv" in ribp2apb.files
assert ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_pure_if.sv" in ribp2apb.files
assert ROOT / "rtl/mini/top/rib2apb.sv" in rib2apb.files
assert ROOT / "rtl/mini/formal/rib2apb_formal.sv" in rib2apb.files
assert ROOT / "rtl/managed/clusterip/common/rtl/interface/apb4_pure_if.sv" in rib2apb.files
assert ROOT / "rtl/ip/ribp/peripheral/sysctrl.sv" in sysctrl.files
assert ROOT / "rtl/mini/formal/sysctrl_formal.sv" in sysctrl.files
assert ROOT / "rtl/mini/top/rcu.sv" in pll_rcu.files
@@ -270,7 +270,7 @@ def test_fatfs_release_script_uses_the_locked_archive_contract() -> None:
def test_formal_result_summary_requires_every_passing_step(tmp_path: Path) -> None:
proofs = ("bus", "ribp2apb", "sysctrl", "pll_rcu", "gpio_user")
proofs = ("bus", "rib2apb", "sysctrl", "pll_rcu", "gpio_user")
for proof in proofs:
directory = tmp_path / proof
directory.mkdir()
@@ -292,7 +292,7 @@ def test_formal_result_summary_requires_every_passing_step(tmp_path: Path) -> No
"--proof",
f"bus={tmp_path / 'bus'}",
"--proof",
f"ribp2apb={tmp_path / 'ribp2apb'}",
f"rib2apb={tmp_path / 'rib2apb'}",
"--proof",
f"sysctrl={tmp_path / 'sysctrl'}",
"--proof",
+7 -7
View File
@@ -86,14 +86,14 @@ def test_topology_generates_complete_rib_apb_and_gpio_bindings(tmp_path: Path) -
assert "assign u_gpio_if.alt1_do_i[22] = u_psram_if.nss_o[0];" in gpio
assert apb_interfaces.count("apb4_if u_") == 10
assert "apb4_pure_if u_archinfo_apb_pure_if ();" in apb_interfaces
assert "assign tmr.paddr = ribp.addr;" in apb_routes
assert "assign tmr.paddr = s_addr_q;" in apb_routes
assert "({32{s_psel_q[8]}} & tmr.prdata)" in apb_response
assert "localparam int NSLV = 10;" in apb_declarations
assert fabric.count("ribp_if u_") == 2
assert fabric.count("rib_if u_") == 3
assert fabric.count("ribp_if u_") == 1
assert fabric.count("rib_if u_") == 4
assert ".mgmt_ribp(u_mgmt_ribp_if)" in bus_fabric
assert ".user_rib(u_user_rib_if)" in bus_fabric
assert ".apb_ribp(u_apb_ribp_if)" in bus_fabric
assert ".apb_rib(u_apb_rib_if)" in bus_fabric
assert ".rib(u_rib_if)" in bus_fabric
assert "`define SOC_IRQ_VECTOR_WIDTH 32" in irq_config
assert "`define SOC_IRQ_RIBP_WIDTH 10" in irq_config
@@ -147,8 +147,8 @@ def test_topology_always_adds_the_user_apb_target(tmp_path: Path) -> None:
interfaces = (tmp_path / "rtl/soc_apb_interfaces.svh").read_text(encoding="utf-8")
declarations = (tmp_path / "rtl/soc_apb_declarations.svh").read_text(encoding="utf-8")
response = (tmp_path / "rtl/soc_apb_response_mux.svh").read_text(encoding="utf-8")
formal_design = (ROOT / "rtl/mini/formal/ribp2apb_formal.sv").read_text(encoding="utf-8")
formal_properties = (ROOT / "rtl/mini/formal/ribp2apb_formal_props.sv").read_text(
formal_design = (ROOT / "rtl/mini/formal/rib2apb_formal.sv").read_text(encoding="utf-8")
formal_properties = (ROOT / "rtl/mini/formal/rib2apb_formal_props.sv").read_text(
encoding="utf-8"
)
@@ -158,7 +158,7 @@ def test_topology_always_adds_the_user_apb_target(tmp_path: Path) -> None:
assert "apb4_pure_if user_ip ();" in formal_design
assert ".user_ip (user_ip)" in formal_design
assert "logic [ 9:0] psel_comb" in formal_design
assert "wire [9:0] psel_comb" in formal_properties
assert "wire [ 9:0] psel_comb" in formal_properties
def test_topology_rejects_unknown_or_non_rib_regions(tmp_path: Path) -> None: