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
+949 -453

No files matched your search

+2 -2
View File
@@ -210,7 +210,7 @@ endif
benchmark-report \
pin-map check-pin-map soc-topology check-soc-topology user-extensions check-user-extensions \
check-clock-reset-domains tech-cell-test rtl-lint check-rtl-lint \
formal formal-bus formal-rib-adapter formal-ribp2apb formal-clean formal-doctor
formal formal-bus formal-rib-adapter formal-rib2apb formal-clean formal-doctor
.NOTPARALLEL: setup
help:
@@ -235,7 +235,7 @@ help:
' check-user-extensions validate the canonical user-extension map' \
' check-clock-reset-domains validate the root clock/reset and CDC inventory' \
' rtl-lint | check-rtl-lint run/check strict Verilator RTL lint warnings' \
' formal | formal-bus | formal-rib-adapter | formal-ribp2apb run SBY protocol proofs' \
' formal | formal-bus | formal-rib-adapter | formal-rib2apb run SBY protocol proofs' \
' formal-sysctrl | formal-pll-rcu | formal-gpio-user run SBY peripheral-control proofs' \
' formal-doctor check the SBY, Yosys, sv2v, and Bitwuzla formal toolchain' \
' benchmark-report run the benchmark profile and write meta/performance.json' \
+1 -1
View File
@@ -111,7 +111,7 @@ Verilator regressions.
`make CONFIG=configs/ci/ihp130.mk formal` proves selected
protocol invariants with SymbiYosys, Yosys, `sv2v`, and Bitwuzla. The current
targets are `bus`, `rib_adapter`, `ribp2apb`, `sysctrl`, `pll_rcu`, and
targets are `bus`, `rib_adapter`, `rib2apb`, `sysctrl`, `pll_rcu`, and
`gpio_user`; each uses
the SBY `prove` task for bounded model checking and k-induction, plus a
`cover` task, at depth 20. `sysctrl` checks register side effects, PLL request
+3 -3
View File
@@ -104,7 +104,7 @@ digraph mini_soc_block_diagram {
];
apb_adapter [
fillcolor="#E5E7EB",
label="RIB2RIBP\nAPB bridge"
label="RIB2APB\ndirect APB bridge"
];
sysctrl [
fillcolor="#F9E1E7",
@@ -124,7 +124,7 @@ digraph mini_soc_block_diagram {
];
irq [
fillcolor="#FCE7F3",
label="Interrupt aggregation\nRIBP and APB sources to management core"
label="Interrupt aggregation\nRIBP and APB target IRQs to management core"
];
}
}
@@ -149,7 +149,7 @@ digraph mini_soc_block_diagram {
fabric -> apb_adapter [label="RIB"];
ribp_adapter -> sysctrl [label="RIBP"];
ribp_adapter -> ribp_targets [label="RIBP"];
apb_adapter -> apb_targets [label="RIBP / APB"];
apb_adapter -> apb_targets [label="APB"];
ribp_targets -> gpio_bridge [label="GPIO alternate functions"];
apb_targets -> gpio_bridge [label="user_gpio"];
+53 -53
View File
@@ -44,10 +44,10 @@
<!-- ext_io -->
<g id="node2" class="node">
<title>ext_io</title>
<path fill="#f3f4f6" stroke="#4b5563" stroke-width="1.1" d="M986,-45C986,-45 794,-45 794,-45 788,-45 782,-39 782,-33 782,-33 782,-12 782,-12 782,-6 788,0 794,0 794,0 986,0 986,0 992,0 998,-6 998,-12 998,-12 998,-33 998,-33 998,-39 992,-45 986,-45"/>
<text text-anchor="middle" x="890" y="-31" font-family="Arial" font-size="10.00" fill="#111827">External I/O and memory</text>
<text text-anchor="middle" x="890" y="-20" font-family="Arial" font-size="10.00" fill="#111827">GPIO, UART0, XPI Flash, SDRAM, PSRAM</text>
<text text-anchor="middle" x="890" y="-9" font-family="Arial" font-size="10.00" fill="#111827">SD card, I2C, I2S, DVP and serial I/O</text>
<path fill="#f3f4f6" stroke="#4b5563" stroke-width="1.1" d="M989,-45C989,-45 797,-45 797,-45 791,-45 785,-39 785,-33 785,-33 785,-12 785,-12 785,-6 791,0 797,0 797,0 989,0 989,0 995,0 1001,-6 1001,-12 1001,-12 1001,-33 1001,-33 1001,-39 995,-45 989,-45"/>
<text text-anchor="middle" x="893" y="-31" font-family="Arial" font-size="10.00" fill="#111827">External I/O and memory</text>
<text text-anchor="middle" x="893" y="-20" font-family="Arial" font-size="10.00" fill="#111827">GPIO, UART0, XPI Flash, SDRAM, PSRAM</text>
<text text-anchor="middle" x="893" y="-9" font-family="Arial" font-size="10.00" fill="#111827">SD card, I2C, I2S, DVP and serial I/O</text>
</g>
<!-- fabric -->
<g id="node8" class="node">
@@ -152,22 +152,22 @@
<!-- ribp_adapter -->
<g id="node11" class="node">
<title>ribp_adapter</title>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M753.5,-346C753.5,-346 712.5,-346 712.5,-346 706.5,-346 700.5,-340 700.5,-334 700.5,-334 700.5,-322 700.5,-322 700.5,-316 706.5,-310 712.5,-310 712.5,-310 753.5,-310 753.5,-310 759.5,-310 765.5,-316 765.5,-322 765.5,-322 765.5,-334 765.5,-334 765.5,-340 759.5,-346 753.5,-346"/>
<text text-anchor="middle" x="733" y="-325.5" font-family="Arial" font-size="10.00" fill="#111827">RIB2RIBP</text>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M756.5,-346C756.5,-346 715.5,-346 715.5,-346 709.5,-346 703.5,-340 703.5,-334 703.5,-334 703.5,-322 703.5,-322 703.5,-316 709.5,-310 715.5,-310 715.5,-310 756.5,-310 756.5,-310 762.5,-310 768.5,-316 768.5,-322 768.5,-322 768.5,-334 768.5,-334 768.5,-340 762.5,-346 756.5,-346"/>
<text text-anchor="middle" x="736" y="-325.5" font-family="Arial" font-size="10.00" fill="#111827">RIB2RIBP</text>
</g>
<!-- fabric&#45;&gt;ribp_adapter -->
<g id="edge9" class="edge">
<title>fabric&#45;&gt;ribp_adapter</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M626.94,-400.87C651.88,-383.97 680.76,-364.4 702.08,-349.95"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="703.46,-351.98 707.88,-346.02 700.71,-347.92 703.46,-351.98"/>
<text text-anchor="middle" x="679" y="-371.6" font-family="Arial" font-size="8.00" fill="#374151">RIB</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M627.94,-400.87C653.35,-383.97 682.77,-364.4 704.49,-349.95"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="705.93,-351.94 710.41,-346.02 703.22,-347.86 705.93,-351.94"/>
<text text-anchor="middle" x="681" y="-371.6" font-family="Arial" font-size="8.00" fill="#374151">RIB</text>
</g>
<!-- apb_adapter -->
<g id="node12" class="node">
<title>apb_adapter</title>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M564,-346C564,-346 520,-346 520,-346 514,-346 508,-340 508,-334 508,-334 508,-322 508,-322 508,-316 514,-310 520,-310 520,-310 564,-310 564,-310 570,-310 576,-316 576,-322 576,-322 576,-334 576,-334 576,-340 570,-346 564,-346"/>
<text text-anchor="middle" x="542" y="-331" font-family="Arial" font-size="10.00" fill="#111827">RIB2RIBP</text>
<text text-anchor="middle" x="542" y="-320" font-family="Arial" font-size="10.00" fill="#111827">APB bridge</text>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M577,-346C577,-346 507,-346 507,-346 501,-346 495,-340 495,-334 495,-334 495,-322 495,-322 495,-316 501,-310 507,-310 507,-310 577,-310 577,-310 583,-310 589,-316 589,-322 589,-322 589,-334 589,-334 589,-340 583,-346 577,-346"/>
<text text-anchor="middle" x="542" y="-331" font-family="Arial" font-size="10.00" fill="#111827">RIB2APB</text>
<text text-anchor="middle" x="542" y="-320" font-family="Arial" font-size="10.00" fill="#111827">direct APB bridge</text>
</g>
<!-- fabric&#45;&gt;apb_adapter -->
<g id="edge10" class="edge">
@@ -179,91 +179,91 @@
<!-- sysctrl -->
<g id="node13" class="node">
<title>sysctrl</title>
<path fill="#f9e1e7" stroke="#4b5563" stroke-width="1.1" d="M814.5,-255C814.5,-255 651.5,-255 651.5,-255 645.5,-255 639.5,-249 639.5,-243 639.5,-243 639.5,-222 639.5,-222 639.5,-216 645.5,-210 651.5,-210 651.5,-210 814.5,-210 814.5,-210 820.5,-210 826.5,-216 826.5,-222 826.5,-222 826.5,-243 826.5,-243 826.5,-249 820.5,-255 814.5,-255"/>
<text text-anchor="middle" x="733" y="-241" font-family="Arial" font-size="10.00" fill="#111827">SYSCTRL and CLINT</text>
<text text-anchor="middle" x="733" y="-230" font-family="Arial" font-size="10.00" fill="#111827">PLL, user&#45;core select/reset/bus enable</text>
<text text-anchor="middle" x="733" y="-219" font-family="Arial" font-size="10.00" fill="#111827">fault and performance control</text>
<path fill="#f9e1e7" stroke="#4b5563" stroke-width="1.1" d="M817.5,-255C817.5,-255 654.5,-255 654.5,-255 648.5,-255 642.5,-249 642.5,-243 642.5,-243 642.5,-222 642.5,-222 642.5,-216 648.5,-210 654.5,-210 654.5,-210 817.5,-210 817.5,-210 823.5,-210 829.5,-216 829.5,-222 829.5,-222 829.5,-243 829.5,-243 829.5,-249 823.5,-255 817.5,-255"/>
<text text-anchor="middle" x="736" y="-241" font-family="Arial" font-size="10.00" fill="#111827">SYSCTRL and CLINT</text>
<text text-anchor="middle" x="736" y="-230" font-family="Arial" font-size="10.00" fill="#111827">PLL, user&#45;core select/reset/bus enable</text>
<text text-anchor="middle" x="736" y="-219" font-family="Arial" font-size="10.00" fill="#111827">fault and performance control</text>
</g>
<!-- ribp_adapter&#45;&gt;sysctrl -->
<g id="edge11" class="edge">
<title>ribp_adapter&#45;&gt;sysctrl</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M733,-309.85C733,-296.62 733,-278.02 733,-262.49"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="735.45,-262.15 733,-255.15 730.55,-262.15 735.45,-262.15"/>
<text text-anchor="middle" x="742.5" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">RIBP</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M736,-309.85C736,-296.62 736,-278.02 736,-262.49"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="738.45,-262.15 736,-255.15 733.55,-262.15 738.45,-262.15"/>
<text text-anchor="middle" x="745.5" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">RIBP</text>
</g>
<!-- ribp_targets -->
<g id="node14" class="node">
<title>ribp_targets</title>
<path fill="#f9e1e7" stroke="#4b5563" stroke-width="1.1" d="M1055,-255C1055,-255 865,-255 865,-255 859,-255 853,-249 853,-243 853,-243 853,-222 853,-222 853,-216 859,-210 865,-210 865,-210 1055,-210 1055,-210 1061,-210 1067,-216 1067,-222 1067,-222 1067,-243 1067,-243 1067,-249 1061,-255 1055,-255"/>
<text text-anchor="middle" x="960" y="-241" font-family="Arial" font-size="10.00" fill="#111827">RIBP target wrapper</text>
<text text-anchor="middle" x="960" y="-230" font-family="Arial" font-size="10.00" fill="#111827">XPI/Flash, SDRAM, PSRAM, SPI&#45;SD, DVP</text>
<text text-anchor="middle" x="960" y="-219" font-family="Arial" font-size="10.00" fill="#111827">GPIO, UART0, timers, I2C, I2S and 1&#45;Wire</text>
<path fill="#f9e1e7" stroke="#4b5563" stroke-width="1.1" d="M1058,-255C1058,-255 868,-255 868,-255 862,-255 856,-249 856,-243 856,-243 856,-222 856,-222 856,-216 862,-210 868,-210 868,-210 1058,-210 1058,-210 1064,-210 1070,-216 1070,-222 1070,-222 1070,-243 1070,-243 1070,-249 1064,-255 1058,-255"/>
<text text-anchor="middle" x="963" y="-241" font-family="Arial" font-size="10.00" fill="#111827">RIBP target wrapper</text>
<text text-anchor="middle" x="963" y="-230" font-family="Arial" font-size="10.00" fill="#111827">XPI/Flash, SDRAM, PSRAM, SPI&#45;SD, DVP</text>
<text text-anchor="middle" x="963" y="-219" font-family="Arial" font-size="10.00" fill="#111827">GPIO, UART0, timers, I2C, I2S and 1&#45;Wire</text>
</g>
<!-- ribp_adapter&#45;&gt;ribp_targets -->
<g id="edge12" class="edge">
<title>ribp_adapter&#45;&gt;ribp_targets</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M765.52,-313.6C800.74,-299.1 857.65,-275.66 900.84,-257.87"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="901.83,-260.11 907.37,-255.18 899.97,-255.58 901.83,-260.11"/>
<text text-anchor="middle" x="855.5" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">RIBP</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M768.52,-313.6C803.74,-299.1 860.65,-275.66 903.84,-257.87"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="904.83,-260.11 910.37,-255.18 902.97,-255.58 904.83,-260.11"/>
<text text-anchor="middle" x="858.5" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">RIBP</text>
</g>
<!-- apb_targets -->
<g id="node15" class="node">
<title>apb_targets</title>
<path fill="#e6f4ea" stroke="#4b5563" stroke-width="1.1" d="M600.5,-255C600.5,-255 409.5,-255 409.5,-255 403.5,-255 397.5,-249 397.5,-243 397.5,-243 397.5,-222 397.5,-222 397.5,-216 403.5,-210 409.5,-210 409.5,-210 600.5,-210 600.5,-210 606.5,-210 612.5,-216 612.5,-222 612.5,-222 612.5,-243 612.5,-243 612.5,-249 606.5,-255 600.5,-255"/>
<text text-anchor="middle" x="505" y="-241" font-family="Arial" font-size="10.00" fill="#111827">APB target wrapper</text>
<text text-anchor="middle" x="505" y="-230" font-family="Arial" font-size="10.00" fill="#111827">Archinfo, RNG, UART1, PWM, PS/2, RTC</text>
<text text-anchor="middle" x="505" y="-219" font-family="Arial" font-size="10.00" fill="#111827">watchdog, CRC, advanced timer and user IP</text>
<path fill="#e6f4ea" stroke="#4b5563" stroke-width="1.1" d="M603.5,-255C603.5,-255 412.5,-255 412.5,-255 406.5,-255 400.5,-249 400.5,-243 400.5,-243 400.5,-222 400.5,-222 400.5,-216 406.5,-210 412.5,-210 412.5,-210 603.5,-210 603.5,-210 609.5,-210 615.5,-216 615.5,-222 615.5,-222 615.5,-243 615.5,-243 615.5,-249 609.5,-255 603.5,-255"/>
<text text-anchor="middle" x="508" y="-241" font-family="Arial" font-size="10.00" fill="#111827">APB target wrapper</text>
<text text-anchor="middle" x="508" y="-230" font-family="Arial" font-size="10.00" fill="#111827">Archinfo, RNG, UART1, PWM, PS/2, RTC</text>
<text text-anchor="middle" x="508" y="-219" font-family="Arial" font-size="10.00" fill="#111827">watchdog, CRC, advanced timer and user IP</text>
</g>
<!-- apb_adapter&#45;&gt;apb_targets -->
<g id="edge13" class="edge">
<title>apb_adapter&#45;&gt;apb_targets</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M535.21,-309.85C529.93,-296.5 522.48,-277.68 516.3,-262.07"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="518.42,-260.76 513.57,-255.15 513.86,-262.56 518.42,-260.76"/>
<text text-anchor="middle" x="545.5" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">RIBP / APB</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M535.76,-309.85C530.91,-296.5 524.07,-277.68 518.39,-262.07"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="520.57,-260.89 515.87,-255.15 515.96,-262.56 520.57,-260.89"/>
<text text-anchor="middle" x="535" y="-280.6" font-family="Arial" font-size="8.00" fill="#374151">APB</text>
</g>
<!-- ribp_targets&#45;&gt;ext_io -->
<g id="edge16" class="edge">
<title>ribp_targets&#45;&gt;ext_io</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M952.24,-203.09C940.61,-160.49 920,-85 920,-85 920,-85 911.54,-67.66 903.6,-51.39"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="949.89,-203.78 954.1,-209.88 954.62,-202.49 949.89,-203.78"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="905.76,-50.23 900.49,-45.01 901.36,-52.38 905.76,-50.23"/>
<text text-anchor="middle" x="968" y="-135.1" font-family="Arial" font-size="8.00" fill="#374151">device interfaces</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M955.24,-203.09C943.61,-160.49 923,-85 923,-85 923,-85 914.54,-67.66 906.6,-51.39"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="952.89,-203.78 957.1,-209.88 957.62,-202.49 952.89,-203.78"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="908.76,-50.23 903.49,-45.01 904.36,-52.38 908.76,-50.23"/>
<text text-anchor="middle" x="971" y="-135.1" font-family="Arial" font-size="8.00" fill="#374151">device interfaces</text>
</g>
<!-- gpio_bridge -->
<g id="node16" class="node">
<title>gpio_bridge</title>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M894,-155C894,-155 746,-155 746,-155 740,-155 734,-149 734,-143 734,-143 734,-131 734,-131 734,-125 740,-119 746,-119 746,-119 894,-119 894,-119 900,-119 906,-125 906,-131 906,-131 906,-143 906,-143 906,-149 900,-155 894,-155"/>
<text text-anchor="middle" x="820" y="-140" font-family="Arial" font-size="10.00" fill="#111827">GPIO pad bridge</text>
<text text-anchor="middle" x="820" y="-129" font-family="Arial" font-size="10.00" fill="#111827">software, alternate and user modes</text>
<path fill="#e5e7eb" stroke="#4b5563" stroke-width="1.1" d="M897,-155C897,-155 749,-155 749,-155 743,-155 737,-149 737,-143 737,-143 737,-131 737,-131 737,-125 743,-119 749,-119 749,-119 897,-119 897,-119 903,-119 909,-125 909,-131 909,-131 909,-143 909,-143 909,-149 903,-155 897,-155"/>
<text text-anchor="middle" x="823" y="-140" font-family="Arial" font-size="10.00" fill="#111827">GPIO pad bridge</text>
<text text-anchor="middle" x="823" y="-129" font-family="Arial" font-size="10.00" fill="#111827">software, alternate and user modes</text>
</g>
<!-- ribp_targets&#45;&gt;gpio_bridge -->
<g id="edge14" class="edge">
<title>ribp_targets&#45;&gt;gpio_bridge</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M907.58,-209.9C880.06,-198.56 852,-187 852,-187 852,-187 843.45,-173.9 835.19,-161.25"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="837.07,-159.66 831.19,-155.14 832.97,-162.34 837.07,-159.66"/>
<text text-anchor="middle" x="896" y="-180.6" font-family="Arial" font-size="8.00" fill="#374151">GPIO alternate functions</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M910.58,-209.9C883.06,-198.56 855,-187 855,-187 855,-187 846.45,-173.9 838.19,-161.25"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="840.07,-159.66 834.19,-155.14 835.97,-162.34 840.07,-159.66"/>
<text text-anchor="middle" x="899" y="-180.6" font-family="Arial" font-size="8.00" fill="#374151">GPIO alternate functions</text>
</g>
<!-- apb_targets&#45;&gt;gpio_bridge -->
<g id="edge15" class="edge">
<title>apb_targets&#45;&gt;gpio_bridge</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M577.66,-209.93C631.48,-193.96 704.14,-172.39 755.82,-157.05"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="756.64,-159.36 762.65,-155.02 755.24,-154.67 756.64,-159.36"/>
<text text-anchor="middle" x="699" y="-180.6" font-family="Arial" font-size="8.00" fill="#374151">user_gpio</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M580.66,-209.93C634.48,-193.96 707.14,-172.39 758.82,-157.05"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="759.64,-159.36 765.65,-155.02 758.24,-154.67 759.64,-159.36"/>
<text text-anchor="middle" x="702" y="-180.6" font-family="Arial" font-size="8.00" fill="#374151">user_gpio</text>
</g>
<!-- gpio_bridge&#45;&gt;ext_io -->
<g id="edge17" class="edge">
<title>gpio_bridge&#45;&gt;ext_io</title>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M834.43,-112.81C845.49,-95.04 860.79,-70.44 872.54,-51.56"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="832.25,-111.68 830.63,-118.91 836.41,-114.26 832.25,-111.68"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="874.76,-52.63 876.38,-45.39 870.6,-50.04 874.76,-52.63"/>
<text text-anchor="middle" x="881" y="-70.6" font-family="Arial" font-size="8.00" fill="#374151">pad control</text>
<path fill="none" stroke="#4b5563" stroke-width="1.2" d="M837.43,-112.81C848.49,-95.04 863.79,-70.44 875.54,-51.56"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="835.25,-111.68 833.63,-118.91 839.41,-114.26 835.25,-111.68"/>
<polygon fill="#4b5563" stroke="#4b5563" stroke-width="1.2" points="877.76,-52.63 879.38,-45.39 873.6,-50.04 877.76,-52.63"/>
<text text-anchor="middle" x="884" y="-70.6" font-family="Arial" font-size="8.00" fill="#374151">pad control</text>
</g>
<!-- irq -->
<g id="node17" class="node">
<title>irq</title>
<path fill="#fce7f3" stroke="#4b5563" stroke-width="1.1" d="M646,-155C646,-155 456,-155 456,-155 450,-155 444,-149 444,-143 444,-143 444,-131 444,-131 444,-125 450,-119 456,-119 456,-119 646,-119 646,-119 652,-119 658,-125 658,-131 658,-131 658,-143 658,-143 658,-149 652,-155 646,-155"/>
<text text-anchor="middle" x="551" y="-140" font-family="Arial" font-size="10.00" fill="#111827">Interrupt aggregation</text>
<text text-anchor="middle" x="551" y="-129" font-family="Arial" font-size="10.00" fill="#111827">RIBP and APB sources to management core</text>
<path fill="#fce7f3" stroke="#4b5563" stroke-width="1.1" d="M655,-155C655,-155 449,-155 449,-155 443,-155 437,-149 437,-143 437,-143 437,-131 437,-131 437,-125 443,-119 449,-119 449,-119 655,-119 655,-119 661,-119 667,-125 667,-131 667,-131 667,-143 667,-143 667,-149 661,-155 655,-155"/>
<text text-anchor="middle" x="552" y="-140" font-family="Arial" font-size="10.00" fill="#111827">Interrupt aggregation</text>
<text text-anchor="middle" x="552" y="-129" font-family="Arial" font-size="10.00" fill="#111827">RIBP and APB target IRQs to management core</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

-84
View File
@@ -1,84 +0,0 @@
// Copyright (c) 2023-2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "mmap_define.svh"
module ribp2apb (
// verilog_format: off
input logic clk_i,
input logic rst_n_i,
ribp_if.slave ribp,
`include "soc_apb_ports.svh"
// verilog_format: on
);
localparam FSM_IDLE = 2'd0;
localparam FSM_SETP = 2'd1;
localparam FSM_ENAB = 2'd2;
logic [31:0] s_rd_data;
logic s_xfer_valid, s_xfer_ready, s_xfer_error;
logic s_mem_valid_re;
logic [1:0] s_fsm_d, s_fsm_q;
// Registered slave-select one-hot for response mux
`include "soc_apb_declarations.svh"
// Generated APB request routing retains the scalar interface protocol.
`include "soc_apb_request_routes.svh"
// verilog_format: off
edge_det_sync_re #(1) u_mem_valid_edge_det_sync_re (
clk_i,
rst_n_i,
ribp.valid,
s_mem_valid_re
);
// verilog_format: on
assign s_xfer_valid = ((s_fsm_q == FSM_IDLE) && s_mem_valid_re) ||
(s_fsm_q == FSM_SETP) || (s_fsm_q == FSM_ENAB);
always_comb begin
s_fsm_d = s_fsm_q;
unique case (s_fsm_q)
FSM_IDLE: if (s_mem_valid_re) s_fsm_d = FSM_SETP;
FSM_SETP: s_fsm_d = FSM_ENAB;
FSM_ENAB: if (s_xfer_ready) s_fsm_d = FSM_IDLE;
default: s_fsm_d = s_fsm_q;
endcase
end
dffr #(2) u_fsm_dffr (
clk_i,
rst_n_i,
s_fsm_d,
s_fsm_q
);
assign ribp.ready = ribp.valid && (s_fsm_q == FSM_ENAB) && s_xfer_ready;
assign ribp.rdata = {32{ribp.ready}} & s_rd_data;
assign ribp.resp_err = ribp.ready && s_xfer_error;
// Capture slave-select one-hot at FSM_SETP for cleaner response mux.
`include "soc_apb_select_routes.svh"
assign s_psel_d = (s_fsm_q == FSM_IDLE && s_mem_valid_re) ? s_psel_comb : s_psel_q;
dffr #(NSLV) u_psel_dffr (
clk_i,
rst_n_i,
s_psel_d,
s_psel_q
);
// Generated response mux uses the registered one-hot target selection.
`include "soc_apb_response_mux.svh"
endmodule
+13 -4
View File
@@ -61,25 +61,34 @@ module rib2apb_sva #(
input logic rst_n_i,
input logic [NSLV-1:0] psel_comb_i,
input logic [NSLV-1:0] psel_q_i,
input logic rib_ready_i,
input logic [ 2:0] fsm_q_i,
input logic rsp_valid_i,
input logic [ 1:0] rsp_beat_i,
input logic rsp_last_i,
input logic xfer_ready_i
);
// Address regions are disjoint and only the registered select drives a response.
assert property (@(posedge clk_i) disable iff (!rst_n_i) $onehot0(psel_comb_i));
assert property (@(posedge clk_i) disable iff (!rst_n_i) $onehot0(psel_q_i));
assert property (@(posedge clk_i) disable iff (!rst_n_i) rib_ready_i |-> xfer_ready_i);
assert property (@(posedge clk_i) disable iff (!rst_n_i)
fsm_q_i == 3'd3 && !xfer_ready_i |=> fsm_q_i == 3'd3);
assert property (@(posedge clk_i) disable iff (!rst_n_i)
rsp_valid_i |-> rsp_beat_i == 2'd0 && rsp_last_i);
endmodule
bind ribp2apb rib2apb_sva #(
bind rib2apb rib2apb_sva #(
.NSLV(NSLV)
) u_rib2apb_sva (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.psel_comb_i (s_psel_comb),
.psel_q_i (s_psel_q),
.rib_ready_i (ribp.ready),
.fsm_q_i (s_fsm_q),
.rsp_valid_i (rib.rsp_valid),
.rsp_beat_i (rib.rsp_beat),
.rsp_last_i (rib.rsp_last),
.xfer_ready_i(s_xfer_ready)
);
-1
View File
@@ -40,7 +40,6 @@
/ip/ribp/peripheral/timer.sv
/ip/ribp/serial/uart.sv
/ip/ribp/peripheral/gpio.sv
/ip/ribp/interconnect/ribp2apb.sv
/top/ahbl2ribp.sv
/ip/ribp/interconnect/axi4l2ribp.sv
/ip/ribp/util/async_fifo.sv
+1
View File
@@ -2,6 +2,7 @@
/top/gpio_pad_bridge.sv
/top/ribp2rib.sv
/top/rib2ribp.sv
/top/rib2apb.sv
/top/rib_error_slave.sv
/top/rib2ram.sv
/top/core_wrapper.sv
+50 -22
View File
@@ -34,7 +34,7 @@ module bus_formal_design (
rib_if user_rib ();
rib_if dma_rib ();
rib_if rib ();
ribp_if apb_ribp ();
rib_if apb_rib ();
(* anyseq *)logic f_mgmt_valid;
(* anyseq *)logic [31:0] f_mgmt_addr;
@@ -64,6 +64,9 @@ module bus_formal_design (
logic target_write_done_q;
logic [ 1:0] target_len_q;
logic [ 1:0] target_beat_q;
logic apb_active_q;
logic apb_write_q;
logic apb_write_done_q;
logic [31:0] fault_addr;
logic [ 3:0] fault_wstrb;
logic fault_reserved;
@@ -138,27 +141,52 @@ module bus_formal_design (
end
end
assign apb_ribp.ready = apb_ribp.valid;
assign apb_ribp.rdata = 32'h1234_5678;
assign apb_ribp.resp_err = 1'b0;
assign apb_rib.cmd_ready = ~apb_active_q;
assign apb_rib.w_ready = apb_active_q && apb_write_q && ~apb_write_done_q;
assign apb_rib.rsp_valid = apb_active_q && (~apb_write_q || apb_write_done_q);
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;
assign mgmt_valid = mgmt_ribp.valid;
assign mgmt_addr = mgmt_ribp.addr;
assign mgmt_wstrb = mgmt_ribp.wstrb;
assign mgmt_ready = mgmt_ribp.ready;
assign user_cmd_valid = user_rib.cmd_valid;
assign user_cmd_ready = user_rib.cmd_ready;
assign user_cmd_addr = user_rib.cmd_addr;
assign user_cmd_write = user_rib.cmd_write;
assign user_cmd_len = user_rib.cmd_len;
assign dma_cmd_valid = dma_rib.cmd_valid;
assign dma_cmd_ready = dma_rib.cmd_ready;
assign dma_cmd_addr = dma_rib.cmd_addr;
assign dma_cmd_write = dma_rib.cmd_write;
assign dma_cmd_len = dma_rib.cmd_len;
assign rib_cmd_valid = rib.cmd_valid;
assign rib_cmd_len = rib.cmd_len;
assign apb_valid = apb_ribp.valid;
always_ff @(posedge clk_i) begin
if (!rst_n_i) begin
apb_active_q <= 1'b0;
apb_write_q <= 1'b0;
apb_write_done_q <= 1'b0;
end else begin
if (apb_rib.cmd_valid && apb_rib.cmd_ready) begin
apb_active_q <= 1'b1;
apb_write_q <= apb_rib.cmd_write;
apb_write_done_q <= 1'b0;
end
if (apb_rib.w_valid && apb_rib.w_ready && apb_rib.wlast) begin
apb_write_done_q <= 1'b1;
end
if (apb_rib.rsp_valid && apb_rib.rsp_ready) begin
apb_active_q <= 1'b0;
end
end
end
assign mgmt_valid = mgmt_ribp.valid;
assign mgmt_addr = mgmt_ribp.addr;
assign mgmt_wstrb = mgmt_ribp.wstrb;
assign mgmt_ready = mgmt_ribp.ready;
assign user_cmd_valid = user_rib.cmd_valid;
assign user_cmd_ready = user_rib.cmd_ready;
assign user_cmd_addr = user_rib.cmd_addr;
assign user_cmd_write = user_rib.cmd_write;
assign user_cmd_len = user_rib.cmd_len;
assign dma_cmd_valid = dma_rib.cmd_valid;
assign dma_cmd_ready = dma_rib.cmd_ready;
assign dma_cmd_addr = dma_rib.cmd_addr;
assign dma_cmd_write = dma_rib.cmd_write;
assign dma_cmd_len = dma_rib.cmd_len;
assign rib_cmd_valid = rib.cmd_valid;
assign rib_cmd_len = rib.cmd_len;
assign apb_valid = apb_rib.cmd_valid;
bus u_dut (
.clk_i (clk_i),
@@ -169,7 +197,7 @@ module bus_formal_design (
.user_bus_enable_i(1'b1),
.user_bus_idle_o (user_idle),
.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),
+6 -6
View File
@@ -51,14 +51,14 @@ def source_files(target: str) -> list[Path]:
TOP / "rib2ribp.sv",
SCRIPT_DIR / "rib_adapter_formal.sv",
]
if target == "ribp2apb":
if target == "rib2apb":
return [
COMMON_RTL / "interface/ribp_if.sv",
COMMON_RTL / "interface/apb4_pure_if.sv",
COMMON_RTL / "utils/register.sv",
COMMON_RTL / "utils/edge_det.sv",
INTERCONNECT / "ribp2apb.sv",
SCRIPT_DIR / "ribp2apb_formal.sv",
COMMON_RTL / "utils/spill_register.sv",
TOP / "rib_if.sv",
TOP / "rib2apb.sv",
SCRIPT_DIR / "rib2apb_formal.sv",
]
if target == "sysctrl":
return [
@@ -122,7 +122,7 @@ def parse_args() -> argparse.Namespace:
choices=(
"bus",
"rib_adapter",
"ribp2apb",
"rib2apb",
"sysctrl",
"pll_rcu",
"gpio_user",
+153
View File
@@ -0,0 +1,153 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module formal_apb_slave (
apb4_pure_if.slave apb
);
(* anyseq *)logic f_ready;
(* anyseq *)logic [31:0] f_rdata;
(* anyseq *)logic f_slverr;
assign apb.pready = f_ready;
assign apb.prdata = f_rdata;
assign apb.pslverr = f_slverr;
endmodule
module rib2apb_formal_design (
input logic clk_i,
output logic rst_n_i,
output logic f_past_valid,
output logic rib_cmd_valid,
output logic [31:0] rib_cmd_addr,
output logic rib_cmd_write,
output logic [ 1:0] rib_cmd_len,
output logic rib_cmd_ready,
output logic rib_w_valid,
output logic [31:0] rib_wdata,
output logic [ 3:0] rib_wstrb,
output logic rib_wlast,
output logic rib_w_ready,
output logic rib_rsp_valid,
output logic [31:0] rib_rdata,
output logic rib_resp_err,
output logic [ 2:0] rib_resp_code,
output logic [ 1:0] rib_rsp_beat,
output logic rib_rsp_last,
output logic rib_rsp_ready,
output logic [ 9:0] psel_comb,
output logic [ 9:0] psel_q,
output logic xfer_ready,
output logic xfer_error,
output logic rsp_input_valid,
output logic rsp_input_ready,
output logic [38:0] rsp_input_data,
output logic [ 2:0] fsm_q
);
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 ();
(* anyseq *)logic f_rib_cmd_valid;
(* anyseq *)logic [31:0] f_rib_cmd_addr;
(* anyseq *)logic f_rib_cmd_write;
(* anyseq *)logic [ 1:0] f_rib_cmd_len;
(* anyseq *)logic f_rib_w_valid;
(* anyseq *)logic [31:0] f_rib_wdata;
(* anyseq *)logic [ 3:0] f_rib_wstrb;
(* anyseq *)logic f_rib_wlast;
(* anyseq *)logic f_rib_rsp_ready;
assign rib.cmd_valid = f_rib_cmd_valid;
assign rib.cmd_addr = f_rib_cmd_addr;
assign rib.cmd_write = f_rib_cmd_write;
assign rib.cmd_len = f_rib_cmd_len;
assign rib.w_valid = f_rib_w_valid;
assign rib.wdata = f_rib_wdata;
assign rib.wstrb = f_rib_wstrb;
assign rib.wlast = f_rib_wlast;
assign rib.rsp_ready = f_rib_rsp_ready;
assign rib_cmd_valid = rib.cmd_valid;
assign rib_cmd_addr = rib.cmd_addr;
assign rib_cmd_write = rib.cmd_write;
assign rib_cmd_len = rib.cmd_len;
assign rib_cmd_ready = rib.cmd_ready;
assign rib_w_valid = rib.w_valid;
assign rib_wdata = rib.wdata;
assign rib_wstrb = rib.wstrb;
assign rib_wlast = rib.wlast;
assign rib_w_ready = rib.w_ready;
assign rib_rsp_valid = rib.rsp_valid;
assign rib_rdata = rib.rdata;
assign rib_resp_err = rib.resp_err;
assign rib_resp_code = rib.resp_code;
assign rib_rsp_beat = rib.rsp_beat;
assign rib_rsp_last = rib.rsp_last;
assign rib_rsp_ready = rib.rsp_ready;
formal_apb_slave u_archinfo_slave (.apb(archinfo));
formal_apb_slave u_rng_slave (.apb(rng));
formal_apb_slave u_uart_slave (.apb(uart));
formal_apb_slave u_pwm_slave (.apb(pwm));
formal_apb_slave u_ps2_slave (.apb(ps2));
formal_apb_slave u_rtc_slave (.apb(rtc));
formal_apb_slave u_wdg_slave (.apb(wdg));
formal_apb_slave u_crc_slave (.apb(crc));
formal_apb_slave u_tmr_slave (.apb(tmr));
formal_apb_slave u_user_ip_slave (.apb(user_ip));
rib2apb u_dut (
.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)
);
assign psel_comb = u_dut.s_psel_comb;
assign psel_q = u_dut.s_psel_q;
assign xfer_ready = u_dut.s_xfer_ready;
assign xfer_error = u_dut.s_xfer_error;
assign rsp_input_valid = u_dut.s_rsp_input_valid;
assign rsp_input_ready = u_dut.s_rsp_input_ready;
assign rsp_input_data = u_dut.s_rsp_input_data;
assign fsm_q = u_dut.s_fsm_q;
initial begin
rst_n_i = 1'b0;
f_past_valid = 1'b0;
end
always_ff @(posedge clk_i) begin
rst_n_i <= 1'b1;
f_past_valid <= 1'b1;
end
endmodule
+113
View File
@@ -0,0 +1,113 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module rib2apb_formal;
localparam logic [2:0] FSM_ENAB = 3'd3;
localparam logic [2:0] FSM_ERR = 3'd5;
localparam logic [2:0] RIB_RESP_OK = 3'd0;
localparam logic [2:0] RIB_RESP_SLVERR = 3'd3;
(* anyseq *) (* gclk *)reg clk_i;
wire rst_n_i;
wire f_past_valid;
wire rib_cmd_valid;
wire [31:0] rib_cmd_addr;
wire rib_cmd_write;
wire [ 1:0] rib_cmd_len;
wire rib_cmd_ready;
wire rib_w_valid;
wire [31:0] rib_wdata;
wire [ 3:0] rib_wstrb;
wire rib_wlast;
wire rib_w_ready;
wire rib_rsp_valid;
wire [31:0] rib_rdata;
wire rib_resp_err;
wire [ 2:0] rib_resp_code;
wire [ 1:0] rib_rsp_beat;
wire rib_rsp_last;
wire rib_rsp_ready;
wire [ 9:0] psel_comb;
wire [ 9:0] psel_q;
wire xfer_ready;
wire xfer_error;
wire rsp_input_valid;
wire rsp_input_ready;
wire [38:0] rsp_input_data;
wire [ 2:0] fsm_q;
rib2apb_formal_design u_design (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.f_past_valid (f_past_valid),
.rib_cmd_valid (rib_cmd_valid),
.rib_cmd_addr (rib_cmd_addr),
.rib_cmd_write (rib_cmd_write),
.rib_cmd_len (rib_cmd_len),
.rib_cmd_ready (rib_cmd_ready),
.rib_w_valid (rib_w_valid),
.rib_wdata (rib_wdata),
.rib_wstrb (rib_wstrb),
.rib_wlast (rib_wlast),
.rib_w_ready (rib_w_ready),
.rib_rsp_valid (rib_rsp_valid),
.rib_rdata (rib_rdata),
.rib_resp_err (rib_resp_err),
.rib_resp_code (rib_resp_code),
.rib_rsp_beat (rib_rsp_beat),
.rib_rsp_last (rib_rsp_last),
.rib_rsp_ready (rib_rsp_ready),
.psel_comb (psel_comb),
.psel_q (psel_q),
.xfer_ready (xfer_ready),
.xfer_error (xfer_error),
.rsp_input_valid(rsp_input_valid),
.rsp_input_ready(rsp_input_ready),
.rsp_input_data (rsp_input_data),
.fsm_q (fsm_q)
);
always @(posedge clk_i) begin
if (f_past_valid && $past(rst_n_i && rib_cmd_valid && !rib_cmd_ready)) begin
assume (rib_cmd_valid);
assume (rib_cmd_addr == $past(rib_cmd_addr));
assume (rib_cmd_write == $past(rib_cmd_write));
assume (rib_cmd_len == $past(rib_cmd_len));
end
if (f_past_valid && $past(rst_n_i && rib_w_valid && !rib_w_ready)) begin
assume (rib_w_valid);
assume (rib_wdata == $past(rib_wdata));
assume (rib_wstrb == $past(rib_wstrb));
assume (rib_wlast == $past(rib_wlast));
end
if (rst_n_i) begin
assert ($onehot0(psel_comb));
if (f_past_valid && $past(rst_n_i && fsm_q == FSM_ENAB && !xfer_ready)) begin
assert (fsm_q == FSM_ENAB);
assert (psel_q == $past(psel_q));
end
if (fsm_q == FSM_ENAB && xfer_ready) begin
assert (rsp_input_valid);
assert (rsp_input_data[38:36] == 3'b100);
assert (rsp_input_data[32] == xfer_error);
assert (rsp_input_data[35:33] == (xfer_error ? RIB_RESP_SLVERR : RIB_RESP_OK));
end
if (fsm_q == FSM_ERR) begin
assert (rsp_input_valid);
assert (rsp_input_data[38:36] == 3'b100);
assert (rsp_input_data[32]);
end
cover (fsm_q == FSM_ENAB && xfer_ready && rsp_input_ready);
end
end
endmodule
-113
View File
@@ -1,113 +0,0 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module formal_apb_slave (
apb4_pure_if.slave apb
);
(* anyseq *)logic f_ready;
(* anyseq *)logic [31:0] f_rdata;
(* anyseq *)logic f_slverr;
assign apb.pready = f_ready;
assign apb.prdata = f_rdata;
assign apb.pslverr = f_slverr;
endmodule
module ribp2apb_formal_design (
input logic clk_i,
output logic rst_n_i,
output logic f_past_valid,
output logic rib_valid,
output logic [31:0] rib_addr,
output logic [31:0] rib_wdata,
output logic [ 3:0] rib_wstrb,
output logic rib_ready,
output logic rib_resp_err,
output logic [ 9:0] psel_comb,
output logic [ 9:0] psel_q,
output logic xfer_ready,
output logic xfer_error,
output logic [ 1:0] fsm_q
);
ribp_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 ();
(* anyseq *)logic f_rib_valid;
(* anyseq *)logic [31:0] f_rib_addr;
(* anyseq *)logic [31:0] f_rib_wdata;
(* anyseq *)logic [ 3:0] f_rib_wstrb;
assign rib.valid = f_rib_valid;
assign rib.addr = f_rib_addr;
assign rib.wdata = f_rib_wdata;
assign rib.wstrb = f_rib_wstrb;
assign rib_valid = rib.valid;
assign rib_addr = rib.addr;
assign rib_wdata = rib.wdata;
assign rib_wstrb = rib.wstrb;
assign rib_ready = rib.ready;
assign rib_resp_err = rib.resp_err;
formal_apb_slave u_archinfo_slave (.apb(archinfo));
formal_apb_slave u_rng_slave (.apb(rng));
formal_apb_slave u_uart_slave (.apb(uart));
formal_apb_slave u_pwm_slave (.apb(pwm));
formal_apb_slave u_ps2_slave (.apb(ps2));
formal_apb_slave u_rtc_slave (.apb(rtc));
formal_apb_slave u_wdg_slave (.apb(wdg));
formal_apb_slave u_crc_slave (.apb(crc));
formal_apb_slave u_tmr_slave (.apb(tmr));
formal_apb_slave u_user_ip_slave (.apb(user_ip));
ribp2apb u_dut (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.ribp (rib),
.archinfo(archinfo),
.rng (rng),
.uart (uart),
.pwm (pwm),
.ps2 (ps2),
.rtc (rtc),
.wdg (wdg),
.crc (crc),
.tmr (tmr),
.user_ip (user_ip)
);
assign psel_comb = u_dut.s_psel_comb;
assign psel_q = u_dut.s_psel_q;
assign xfer_ready = u_dut.s_xfer_ready;
assign xfer_error = u_dut.s_xfer_error;
assign fsm_q = u_dut.s_fsm_q;
initial begin
rst_n_i = 1'b0;
f_past_valid = 1'b0;
end
always_ff @(posedge clk_i) begin
rst_n_i <= 1'b1;
f_past_valid <= 1'b1;
end
endmodule
-75
View File
@@ -1,75 +0,0 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
module ribp2apb_formal;
localparam [1:0] FSM_SETP = 2'd1;
localparam [1:0] FSM_ENAB = 2'd2;
(* anyseq *) (* gclk *)reg clk_i;
wire rst_n_i;
wire f_past_valid;
wire rib_valid;
wire [31:0] rib_addr;
wire [31:0] rib_wdata;
wire [ 3:0] rib_wstrb;
wire rib_ready, rib_resp_err;
wire [9:0] psel_comb;
wire [9:0] psel_q;
wire xfer_ready, xfer_error;
wire [1:0] fsm_q;
ribp2apb_formal_design u_design (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
.f_past_valid(f_past_valid),
.rib_valid (rib_valid),
.rib_addr (rib_addr),
.rib_wdata (rib_wdata),
.rib_wstrb (rib_wstrb),
.rib_ready (rib_ready),
.rib_resp_err(rib_resp_err),
.psel_comb (psel_comb),
.psel_q (psel_q),
.xfer_ready (xfer_ready),
.xfer_error (xfer_error),
.fsm_q (fsm_q)
);
always @(posedge clk_i) begin
if (f_past_valid && $past(rst_n_i && rib_valid && !rib_ready)) begin
assume (rib_valid);
assume (rib_addr == $past(rib_addr));
assume (rib_wdata == $past(rib_wdata));
assume (rib_wstrb == $past(rib_wstrb));
end
if (rst_n_i) begin
assert ($onehot0(psel_comb));
assert ($onehot0(psel_q));
if (rib_ready) begin
assert (xfer_ready);
assert (fsm_q == FSM_ENAB);
assert (rib_resp_err == xfer_error);
end else begin
assert (!rib_resp_err);
end
if (f_past_valid && $past(rst_n_i && fsm_q == FSM_SETP)) begin
assert (psel_q == $past(psel_q));
end
if (f_past_valid && $past(rst_n_i && fsm_q == FSM_ENAB && !xfer_ready)) begin
assert (fsm_q == FSM_ENAB);
assert (psel_q == $past(psel_q));
end
cover (fsm_q == FSM_ENAB && rib_ready);
end
end
endmodule
+1 -1
View File
@@ -5,7 +5,7 @@ that is not part of the software address-map ABI or the package pad map.
The topology generator validates rib RIB and APB target ownership against
`../address_map/memory_map.json` and emits generated SystemVerilog include
files for `ip_ribp_wrapper.sv`, `ip_apb_wrapper.sv`, `ribp2apb.sv`, and
files for `ip_ribp_wrapper.sv`, `ip_apb_wrapper.sv`, `rib2apb.sv`, and
`retrosoc.sv`. The output retains scalar interface instances and ports, so it
does not depend on interface-array support in FPGA or netlist simulation tools.
+10 -10
View File
@@ -22,7 +22,7 @@ FABRIC_PROTOCOLS = {
"user": "rib",
"dma": "rib",
"rib": "rib",
"apb": "ribp",
"apb": "rib",
}
IRQ_GROUP_NAMES = ("ribp", "apb")
IRQ_VECTOR_WIDTH = 32
@@ -657,7 +657,7 @@ def render_apb_declarations(targets: list[ApbTarget]) -> str:
[
"// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit.",
f" localparam int NSLV = {count};",
" logic [NSLV-1:0] s_psel_comb, s_psel_d, s_psel_q;",
" logic [NSLV-1:0] s_psel_comb, s_psel_q;",
"",
]
)
@@ -668,13 +668,13 @@ def render_apb_request_routes(targets: list[ApbTarget]) -> str:
for target in targets:
lines.extend(
[
f" assign {target.name}.paddr = ribp.addr;",
f" assign {target.name}.paddr = s_addr_q;",
f" assign {target.name}.pprot = '0;",
f" assign {target.name}.psel = s_xfer_valid && `SOC_ADDR_IS_{target.region}(ribp.addr);",
f" assign {target.name}.psel = s_xfer_valid && s_psel_q[{target.slot}];",
f" assign {target.name}.penable = s_fsm_q == FSM_ENAB;",
f" assign {target.name}.pwrite = |ribp.wstrb;",
f" assign {target.name}.pwdata = ribp.wdata;",
f" assign {target.name}.pstrb = ribp.wstrb;",
f" assign {target.name}.pwrite = s_write_q;",
f" assign {target.name}.pwdata = s_wdata_q;",
f" assign {target.name}.pstrb = s_wstrb_q;",
"",
]
)
@@ -684,7 +684,7 @@ def render_apb_request_routes(targets: list[ApbTarget]) -> str:
def render_apb_select_routes(targets: list[ApbTarget]) -> str:
lines = ["// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit."]
lines.extend(
f" assign s_psel_comb[{target.slot}] = `SOC_ADDR_IS_{target.region}(ribp.addr);"
f" assign s_psel_comb[{target.slot}] = `SOC_ADDR_IS_{target.region}(rib.cmd_addr);"
for target in targets
)
return "\n".join(lines) + "\n"
@@ -736,7 +736,7 @@ def render_bus_fabric_connections(links: list[FabricLink]) -> str:
"user": "user_rib",
"dma": "dma_rib",
"rib": "rib",
"apb": "apb_ribp",
"apb": "apb_rib",
}
interfaces = {link.name: link.interface for link in links}
lines = ["// Generated by rtl/mini/integration/generate_soc_topology.py; do not edit."]
@@ -905,7 +905,7 @@ def generate(topology_path: Path, memory_map_path: Path, output_dir: Path) -> No
)
atomic_write(
rtl_dir / "soc_ip_apb_wrapper_fabric.svh",
render_fabric_connection(fabric_links, "apb", "ribp"),
render_fabric_connection(fabric_links, "apb", "rib"),
)
atomic_write(rtl_dir / "soc_gpio_alt_bindings.svh", render_gpio_bindings(gpio_functions))
atomic_write(rtl_dir / "soc_irq_config.svh", render_irq_config(irq_vector_width, irq_groups))
+1 -1
View File
@@ -50,7 +50,7 @@
{"name": "user", "interface": "u_user_rib_if", "protocol": "rib"},
{"name": "dma", "interface": "u_dma_rib_if", "protocol": "rib"},
{"name": "rib", "interface": "u_rib_if", "protocol": "rib"},
{"name": "apb", "interface": "u_apb_ribp_if", "protocol": "ribp"}
{"name": "apb", "interface": "u_apb_rib_if", "protocol": "rib"}
],
"apb_targets": [
{"slot": 0, "name": "archinfo", "timed_interface": "u_archinfo_apb_if", "pure_interface": "u_archinfo_apb_pure_if", "region": "APB_ARCHINFO"},
+6 -6
View File
@@ -6,7 +6,7 @@ FORMAL_SOLVER_DIR := $(FORMAL_DIR)/bin
FORMAL_SOLVER_WRAPPER := $(FORMAL_SOLVER_DIR)/bitwuzla
FORMAL_DEPTH ?= 20
FORMAL_TIMEOUT ?= 60
FORMAL_TARGETS := bus rib_adapter ribp2apb sysctrl pll_rcu gpio_user
FORMAL_TARGETS := bus rib_adapter rib2apb sysctrl pll_rcu gpio_user
FORMAL_FILELIST_GENERATOR := $(RTL_PATH)/formal/generate_formal_filelist.py
FORMAL_SBY_GENERATOR := $(RTL_PATH)/formal/generate_sby_config.py
FORMAL_RESULT_GENERATOR := $(RTL_PATH)/formal/formal_results.py
@@ -14,8 +14,8 @@ FORMAL_SOURCE_FILES := $(RTL_PATH)/formal/bus_formal.sv \
$(RTL_PATH)/formal/bus_formal_props.sv \
$(RTL_PATH)/formal/rib_adapter_formal.sv \
$(RTL_PATH)/formal/rib_adapter_formal_props.sv \
$(RTL_PATH)/formal/ribp2apb_formal.sv \
$(RTL_PATH)/formal/ribp2apb_formal_props.sv \
$(RTL_PATH)/formal/rib2apb_formal.sv \
$(RTL_PATH)/formal/rib2apb_formal_props.sv \
$(RTL_PATH)/formal/sysctrl_formal.sv \
$(RTL_PATH)/formal/sysctrl_formal_props.sv \
$(RTL_PATH)/formal/pll_rcu_formal.sv \
@@ -27,8 +27,8 @@ FORMAL_SOURCE_FILES := $(RTL_PATH)/formal/bus_formal.sv \
$(RTL_PATH)/top/rib_if.sv \
$(RTL_PATH)/top/rib2ram.sv \
$(RTL_PATH)/top/rib2ribp.sv \
$(RTL_PATH)/top/rib2apb.sv \
$(RTL_PATH)/top/ribp2rib.sv \
$(ROOT_PATH)/rtl/ip/ribp/interconnect/ribp2apb.sv \
$(ROOT_PATH)/rtl/ip/ribp/interconnect/ribp_regslice.sv \
$(ROOT_PATH)/rtl/ip/ribp/peripheral/gpio.sv \
$(ROOT_PATH)/rtl/ip/ribp/peripheral/pll_ctrl_if.sv \
@@ -117,7 +117,7 @@ formal-bus: $(FORMAL_DIR)/bus/.stamp | manifest
formal-rib-adapter: $(FORMAL_DIR)/rib_adapter/.stamp | manifest
formal-ribp2apb: $(FORMAL_DIR)/ribp2apb/.stamp | manifest
formal-rib2apb: $(FORMAL_DIR)/rib2apb/.stamp | manifest
formal-sysctrl: $(FORMAL_DIR)/sysctrl/.stamp | manifest
@@ -131,4 +131,4 @@ formal-doctor:
formal-clean:
python3 $(ROOT_PATH)/scripts/clean.py --root $(ROOT_PATH) --path $(FORMAL_DIR)
.PHONY: formal formal-bus formal-rib-adapter formal-ribp2apb formal-sysctrl formal-pll-rcu formal-gpio-user formal-doctor formal-clean
.PHONY: formal formal-bus formal-rib-adapter formal-rib2apb formal-sysctrl formal-pll-rcu formal-gpio-user formal-doctor formal-clean
+24 -34
View File
@@ -18,13 +18,13 @@ module bus (
`ifdef HAVE_SRAM_IF
ram_if.master ram,
`endif
ribp_if.slave mgmt_ribp,
rib_if.slave user_rib,
rib_if.slave dma_rib,
ribp_if.slave mgmt_ribp,
rib_if.slave user_rib,
rib_if.slave dma_rib,
input logic user_bus_enable_i,
output logic user_bus_idle_o,
rib_if.master rib,
ribp_if.master apb_ribp,
rib_if.master rib,
rib_if.master apb_rib,
input logic perf_enable_i,
input logic perf_clear_i,
output logic fault_valid_o,
@@ -56,7 +56,6 @@ module bus (
rib_if u_mgmt_rib_if ();
rib_if u_mstr_rib_if ();
rib_if u_apb_rib_if ();
rib_if u_ram_rib_if ();
rib_if u_fault_rib_if ();
@@ -97,13 +96,6 @@ module bus (
.rib (u_mgmt_rib_if)
);
rib2ribp u_apb_rib2ribp (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.rib (u_apb_rib_if),
.ribp (apb_ribp)
);
rib_error_slave u_fault_slave (
.clk_i (clk_i),
.rst_n_i (rst_n_i),
@@ -368,10 +360,10 @@ module bus (
assign rib.cmd_addr = u_mstr_rib_if.cmd_addr;
assign rib.cmd_write = u_mstr_rib_if.cmd_write;
assign rib.cmd_len = u_mstr_rib_if.cmd_len;
assign u_apb_rib_if.cmd_valid = s_apb_sel;
assign u_apb_rib_if.cmd_addr = u_mstr_rib_if.cmd_addr;
assign u_apb_rib_if.cmd_write = u_mstr_rib_if.cmd_write;
assign u_apb_rib_if.cmd_len = u_mstr_rib_if.cmd_len;
assign apb_rib.cmd_valid = s_apb_sel;
assign apb_rib.cmd_addr = u_mstr_rib_if.cmd_addr;
assign apb_rib.cmd_write = u_mstr_rib_if.cmd_write;
assign apb_rib.cmd_len = u_mstr_rib_if.cmd_len;
assign u_ram_rib_if.cmd_valid = s_ram_sel;
assign u_ram_rib_if.cmd_addr = u_mstr_rib_if.cmd_addr;
assign u_ram_rib_if.cmd_write = u_mstr_rib_if.cmd_write;
@@ -386,7 +378,7 @@ module bus (
if (s_ribp_sel) begin
u_mstr_rib_if.cmd_ready = rib.cmd_ready;
end else if (s_apb_sel) begin
u_mstr_rib_if.cmd_ready = u_apb_rib_if.cmd_ready;
u_mstr_rib_if.cmd_ready = apb_rib.cmd_ready;
end else if (s_ram_sel) begin
u_mstr_rib_if.cmd_ready = u_ram_rib_if.cmd_ready;
end else if (s_fault_sel) begin
@@ -424,15 +416,13 @@ module bus (
assign rib.rsp_ready = s_mstr_lock_q && s_cmd_accepted_q && (s_target_q == TARGET_RIBP) ?
u_mstr_rib_if.rsp_ready : 1'b0;
assign u_apb_rib_if.w_valid = s_mstr_lock_q && s_cmd_accepted_q &&
(s_target_q == TARGET_APB) ?
u_mstr_rib_if.w_valid : 1'b0;
assign u_apb_rib_if.wdata = u_mstr_rib_if.wdata;
assign u_apb_rib_if.wstrb = u_mstr_rib_if.wstrb;
assign u_apb_rib_if.wlast = u_mstr_rib_if.wlast;
assign u_apb_rib_if.rsp_ready = s_mstr_lock_q && s_cmd_accepted_q &&
(s_target_q == TARGET_APB) ?
u_mstr_rib_if.rsp_ready : 1'b0;
assign apb_rib.w_valid = s_mstr_lock_q && s_cmd_accepted_q &&
(s_target_q == TARGET_APB) ? u_mstr_rib_if.w_valid : 1'b0;
assign apb_rib.wdata = u_mstr_rib_if.wdata;
assign apb_rib.wstrb = u_mstr_rib_if.wstrb;
assign apb_rib.wlast = u_mstr_rib_if.wlast;
assign apb_rib.rsp_ready = s_mstr_lock_q && s_cmd_accepted_q &&
(s_target_q == TARGET_APB) ? u_mstr_rib_if.rsp_ready : 1'b0;
assign u_ram_rib_if.w_valid = s_mstr_lock_q && s_cmd_accepted_q &&
(s_target_q == TARGET_RAM) ?
@@ -473,13 +463,13 @@ module bus (
u_mstr_rib_if.rsp_last = rib.rsp_last;
end
TARGET_APB: begin
u_mstr_rib_if.w_ready = s_cmd_accepted_q && u_apb_rib_if.w_ready;
u_mstr_rib_if.rsp_valid = s_cmd_accepted_q && u_apb_rib_if.rsp_valid;
u_mstr_rib_if.rdata = u_apb_rib_if.rdata;
u_mstr_rib_if.resp_err = u_apb_rib_if.resp_err;
u_mstr_rib_if.resp_code = u_apb_rib_if.resp_code;
u_mstr_rib_if.rsp_beat = u_apb_rib_if.rsp_beat;
u_mstr_rib_if.rsp_last = u_apb_rib_if.rsp_last;
u_mstr_rib_if.w_ready = s_cmd_accepted_q && apb_rib.w_ready;
u_mstr_rib_if.rsp_valid = s_cmd_accepted_q && apb_rib.rsp_valid;
u_mstr_rib_if.rdata = apb_rib.rdata;
u_mstr_rib_if.resp_err = apb_rib.resp_err;
u_mstr_rib_if.resp_code = apb_rib.resp_code;
u_mstr_rib_if.rsp_beat = apb_rib.rsp_beat;
u_mstr_rib_if.rsp_last = apb_rib.rsp_last;
end
TARGET_RAM: begin
u_mstr_rib_if.w_ready = s_cmd_accepted_q && u_ram_rib_if.w_ready;
+3 -3
View File
@@ -22,7 +22,7 @@ module ip_apb_wrapper (
input logic clk_aud_i,
input logic rst_aud_n_i,
input logic tmr_capch_i,
ribp_if.slave ribp,
rib_if.slave rib,
uart_if.dut uart,
pwm_if.dut pwm,
ps2_if.dut ps2,
@@ -62,10 +62,10 @@ module ip_apb_wrapper (
// Generated IRQ ownership and core-vector bit assignments are topology checked.
`include "soc_apb_irq_bindings.svh"
ribp2apb u_ribp2apb (
rib2apb u_rib2apb (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.ribp (ribp),
.rib (rib),
`include "soc_apb_connections.svh"
);
+177
View File
@@ -0,0 +1,177 @@
// Copyright (c) 2026 Yuchi Miao <miaoyuchi@ict.ac.cn>
// retroSoC is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
`include "mmap_define.svh"
`include "rib_defs.svh"
module rib2apb (
// verilog_format: off
input logic clk_i,
input logic rst_n_i,
rib_if.slave rib,
`include "soc_apb_ports.svh"
// verilog_format: on
);
localparam logic [2:0] FSM_CMD = 3'd0;
localparam logic [2:0] FSM_WDATA = 3'd1;
localparam logic [2:0] FSM_SETP = 3'd2;
localparam logic [2:0] FSM_ENAB = 3'd3;
localparam logic [2:0] FSM_DROP_WDATA = 3'd4;
localparam logic [2:0] FSM_ERR = 3'd5;
localparam int RSP_WIDTH = 39;
logic [31:0] s_rd_data;
logic s_xfer_valid, s_xfer_ready, s_xfer_error;
logic [2:0] s_fsm_d, s_fsm_q;
logic [31:0] s_addr_q, s_wdata_q;
logic [3:0] s_wstrb_q;
logic s_write_q;
logic [2:0] s_error_code_d, s_error_code_q;
logic s_cmd_hdshk, s_w_hdshk, s_rsp_hdshk;
logic s_psel_valid;
logic s_rsp_input_valid, s_rsp_input_ready;
logic [RSP_WIDTH-1:0] s_rsp_input_data, s_rsp_output_data;
// Registered slave-select one-hot and APB response mux.
`include "soc_apb_declarations.svh"
assign s_cmd_hdshk = rib.cmd_valid && rib.cmd_ready;
assign s_w_hdshk = rib.w_valid && rib.w_ready;
assign rib.cmd_ready = (s_fsm_q == FSM_CMD) && !rib.rsp_valid;
assign rib.w_ready = (s_fsm_q == FSM_WDATA) || (s_fsm_q == FSM_DROP_WDATA);
assign s_xfer_valid = (s_fsm_q == FSM_SETP) || (s_fsm_q == FSM_ENAB);
// Generated APB routing uses the latched RIB request and selected target.
`include "soc_apb_request_routes.svh"
`include "soc_apb_select_routes.svh"
`include "soc_apb_response_mux.svh"
assign s_psel_valid = |s_psel_comb;
assign s_rsp_input_valid = ((s_fsm_q == FSM_ENAB) && s_xfer_ready) || (s_fsm_q == FSM_ERR);
assign s_rsp_input_data = (s_fsm_q == FSM_ENAB) ?
{1'b1, 2'd0, s_xfer_error ? `RIB_RESP_SLVERR : `RIB_RESP_OK, s_xfer_error,
s_write_q ? 32'd0 : s_rd_data} :
{1'b1, 2'd0, s_error_code_q, 1'b1, 32'd0};
assign s_rsp_hdshk = s_rsp_input_valid && s_rsp_input_ready;
spill_register #(
.DATA_WIDTH(RSP_WIDTH),
.BYPASS (1'b0)
) u_rsp_spill_register (
.clk_i (clk_i),
.rst_n_i(rst_n_i),
.flush_i(1'b0),
.valid_i(s_rsp_input_valid),
.ready_o(s_rsp_input_ready),
.data_i (s_rsp_input_data),
.valid_o(rib.rsp_valid),
.ready_i(rib.rsp_ready),
.data_o (s_rsp_output_data)
);
assign rib.rdata = s_rsp_output_data[31:0];
assign rib.resp_err = s_rsp_output_data[32];
assign rib.resp_code = s_rsp_output_data[35:33];
assign rib.rsp_beat = s_rsp_output_data[37:36];
assign rib.rsp_last = s_rsp_output_data[38];
always_comb begin
s_fsm_d = s_fsm_q;
s_error_code_d = s_error_code_q;
unique case (s_fsm_q)
FSM_CMD: begin
if (s_cmd_hdshk) begin
if (rib.cmd_len != `RIB_LEN_INCR1) begin
s_error_code_d = `RIB_RESP_BURSTERR;
s_fsm_d = rib.cmd_write ? FSM_DROP_WDATA : FSM_ERR;
end else if (!s_psel_valid) begin
s_error_code_d = `RIB_RESP_DECERR;
s_fsm_d = rib.cmd_write ? FSM_DROP_WDATA : FSM_ERR;
end else begin
s_fsm_d = rib.cmd_write ? FSM_WDATA : FSM_SETP;
end
end
end
FSM_WDATA: begin
if (s_w_hdshk) begin
if (rib.wlast) begin
s_fsm_d = FSM_SETP;
end else begin
s_error_code_d = `RIB_RESP_BURSTERR;
s_fsm_d = FSM_ERR;
end
end
end
FSM_SETP: s_fsm_d = FSM_ENAB;
FSM_ENAB: begin
if (s_xfer_ready && s_rsp_input_ready) s_fsm_d = FSM_CMD;
end
FSM_DROP_WDATA: begin
if (s_w_hdshk && rib.wlast) s_fsm_d = FSM_ERR;
end
FSM_ERR: begin
if (s_rsp_hdshk) s_fsm_d = FSM_CMD;
end
default: s_fsm_d = FSM_CMD;
endcase
end
dffr #(3) u_fsm_dffr (
clk_i,
rst_n_i,
s_fsm_d,
s_fsm_q
);
dffer #(32) u_addr_dffer (
clk_i,
rst_n_i,
s_cmd_hdshk,
rib.cmd_addr,
s_addr_q
);
dffer #(1) u_write_dffer (
clk_i,
rst_n_i,
s_cmd_hdshk,
rib.cmd_write,
s_write_q
);
dffer #(32) u_wdata_dffer (
clk_i,
rst_n_i,
s_w_hdshk && (s_fsm_q == FSM_WDATA),
rib.wdata,
s_wdata_q
);
dffer #(4) u_wstrb_dffer (
clk_i,
rst_n_i,
s_w_hdshk && (s_fsm_q == FSM_WDATA),
rib.wstrb,
s_wstrb_q
);
dffr #(3) u_error_code_dffr (
clk_i,
rst_n_i,
s_error_code_d,
s_error_code_q
);
dffr #(NSLV) u_psel_dffr (
clk_i,
rst_n_i,
s_cmd_hdshk ? s_psel_comb : s_psel_q,
s_psel_q
);
endmodule
+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: