# Big Sur Silicon RTL samples

Three SystemVerilog reference designs with self-checking testbenches. Each sample can be used on its own.

The [bare-metal C driver sample](firmware/README.md) uses the AXI4-Lite SPI peripheral’s register map and runs a loopback test against the same RTL in Verilator.

| Sample | Design focus | Verification |
| --- | --- | --- |
| [Round-robin bus arbiter](#round-robin-bus-arbiter) | Parameterized arbitration and stable grants under backpressure | Full contention, wraparound, stalls, and deterministic randomized requests across 1, 3, 4, and 5 requesters |
| [AXI4-Lite register bank and SPI master](#axi4-lite-register-bank-and-spi-master) | Independent AXI channels, byte strobes, and a register-controlled SPI peripheral | Channel arrival order, read and write backpressure, invalid accesses, and full-duplex SPI pin timing |
| [Asynchronous dual-clock FIFO](#asynchronous-dual-clock-fifo) | Gray-code pointer synchronization and clock-domain-local flags | Full and empty behavior, data ordering across wraparound, reset while full, and both faster-write and faster-read clock configurations |

## Run the checks

Run these targets from this directory.

```sh
make test        # Icarus Verilog and vvp
make lint        # Verilator
make synth       # Generic synthesis and netlist checks with Yosys
```

The testbenches stop on the first mismatch or timeout. Build products go in `build/`.

## Round-robin bus arbiter

[RTL](rtl/round_robin_arbiter.sv) · [Testbench](tb/tb_round_robin_arbiter.sv)

Set `REQUESTERS` to the number of inputs, with a minimum of one. Each input holds its request and payload until its one-hot grant is accepted at a rising clock edge with `grant_valid && grant_ready`. Use the grant to select data in the surrounding bus logic.

The scan starts at the next priority index and wraps at the actual requester count. When the output stalls, the arbiter holds the selected grant. Priority advances only after an accepted grant. A continuously asserted request can be preceded by at most `REQUESTERS - 1` other accepted grants. Drive the active-low reset for at least one rising clock edge. The first priority after reset is requester zero.

The scan is a simple combinational implementation. For a large requester count or a tight clock budget, check the arbitration path after synthesis and placement.

## AXI4-Lite register bank and SPI master

[AXI/register RTL](rtl/axil_spi.sv) · [SPI RTL](rtl/spi_master_mode0.sv) · [Testbench](tb/tb_axil_spi.sv)

The peripheral uses a 32-bit AXI4-Lite interface. Write address and write data are buffered independently, so either can arrive first. The interface allows one outstanding read and one outstanding write. Responses remain stable until accepted. Deassert `aresetn` synchronously to `aclk`. The register map uses aligned byte offsets from the peripheral base. Connect the address inputs to local offsets when mapping the block at a nonzero system address. Apply any access policy in the interconnect. [Arm AMBA AXI specification](https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/IHI0022H_amba_axi_protocol_spec.pdf)

| Offset | Register | Access | Behavior |
| --- | --- | --- | --- |
| `0x00` | STATUS | Read, write-one-to-clear | Bit 0 is busy. Bit 1 latches completion. Write bit 1 in byte lane 0 to clear it. |
| `0x04` | DIVIDER | Read/write | Bits 15:0 give ACLK cycles per SPI half period. Reset value is 2. A write that would make the divider zero returns `SLVERR`. |
| `0x08` | TXDATA | Write | Writing byte lane 0 starts a frame using bits 7:0 and clears the previous completion. A start while busy returns `SLVERR`. |
| `0x0C` | RXDATA | Read | Bits 7:0 hold the byte received in the most recently completed frame. Reset value is zero. |

Byte strobes affect only the lanes implemented by each writable register. Unsupported addresses and access directions return `SLVERR`. An accepted divider change during a frame takes effect on the next frame.

The SPI engine transfers one eight-bit, MSB-first frame per start using active-low chip select and mode 0. It drives chip select and SCK from registers, presents MOSI before each rising edge, and captures MISO at the corresponding sampling event. SCK runs at `ACLK / (2 × DIVIDER)` during a frame. Chip select stays asserted for a half period after the final falling edge. Check the external device’s chip-select spacing and board-level I/O timing when integrating the peripheral. [Microchip SPI transfer modes](https://onlinedocs.microchip.com/oxy/GUID-DE09DA5A-1CBB-49A8-9DA0-B2EB94E57E56-en-US-11/GUID-67490DA2-F73A-42D5-889A-2AF016ADDFE3.html)

## Asynchronous dual-clock FIFO

[RTL](rtl/async_fifo.sv) · [Testbench](tb/tb_async_fifo.sv)

Set `DATA_WIDTH` to the word width and `ADDR_WIDTH` to the address width. Both must be at least one. Capacity is exactly `2 ** ADDR_WIDTH` words.

A write is accepted on a rising `wr_clk` edge when `wr_en && !wr_full`. A read is accepted on a rising `rd_clk` edge when `rd_en && !rd_empty`. The accepted word appears in the registered `rd_data` with `rd_valid` after that read edge. Back-to-back reads can keep `rd_valid` high. Sample full only in the write domain and empty and valid only in the read domain. A common active-low reset flushes the FIFO, with synchronous release in each domain.

Binary pointers address dual-port storage. Registered Gray pointers cross through two synchronizer stages, and each domain generates its own full or empty flag. Flag release can lag remote activity by a few local clock cycles while the pointer propagates. Reset clears pointers and flags, and `rd_valid` qualifies the read data. [Clifford Cummings, asynchronous FIFO design](https://www.researchgate.net/profile/Clifford-Cummings/publication/252160343_Simulation_and_Synthesis_Techniques_for_Asynchronous_FIFO_Design/links/54bfe9720cf28eae4a66418a/Simulation-and-Synthesis-Techniques-for-Asynchronous-FIFO-Design.pdf)

For a specific target, review dual-port RAM inference and apply the device toolchain’s delay and skew constraints to both Gray-pointer crossings. Check those paths and the reset synchronizers in the target CDC and timing reports. The supplied checks cover RTL behavior and generic synthesis. Target-specific timing closure, metastability analysis, and physical hardware validation remain integration work. [AMD Vivado CDC constraints](https://docs.amd.com/r/en-US/ug903-vivado-using-constraints/Constraining-Asynchronous-Signals)
