Known Issues & Bring-up Findings

Pitfalls encountered while verifying and bringing up this IP, kept out of the regular guides on purpose. Each entry states the symptom, the cause and the fix/workaround as applied in this repository. SoC-level findings (linker script, UART baud rate, simulator flags of the hatch build) are documented in the hatch repository’s Known issues page instead.

Simulation / testbench

TB race at the OBI port (Verilator --timing)

Task code that drives stimulus with blocking assignments right after a @(posedge clk) resumption executes before the FFs of the same time step. Consequences: double acceptance of requests and missed one-cycle rvalid pulses. Rule (applied in test/tb_qspi_top.sv, to be adopted in new TBs): drive stimulus on negedges only, and check gnt in the request cycle after a #1ps settle.

Yosys fsm pass miscompiles certain FSMs

FSMs whose state register is written in two places of the same process (spi_test_master.sv) were re-encoded incorrectly: RTL sim green, netlist dead (stuck in StIdle). Fix: (* fsm_encoding = "none" *) on the state signals. Diagnosis method that found it: post-synthesis simulation of the yosys netlist with Verilator + cells_sim.v against the same TB (prep netlist OK, synth_xilinx netlist broken → pass bisection).

Synthesis / place & route (openXC7 flow)

yosys needs the slang frontend

read_verilog -sv already fails on parameter string INIT_FILE. Use yosys -m slang with read_slang (the OSS CAD Suite ships slang.so).

nextpnr-xilinx XDC parser is a minimal subset

No set_property -dict { ... }, no whitespace inside { } ([get_ports { x }] → assertion str.back() == '}'), no -waveform. One property per line, [get_ports {x}] without spaces.

create_clock is effectively ignored

nextpnr-xilinx checks timing against its 12 MHz default and reports “PASS” even if the design is slower than the board clock. Read Fmax from the log yourself (make check-fmax in the Makefiles). The FPGA tops here run on half the board clock (50 MHz) for that reason; the hatch SoC top runs at 20 MHz.

LUTRAM (RAM256X1S) cannot be placed

nextpnr-xilinx fails on distributed-RAM primitives. Synthesise with -nolutram; small memories then become FFs — keep model memories small (MEM_ADDR_BITS, loopback uses 1 KiB).

IOBUF / tri-state is non-functional

yosys’ automatic inout lowering produces output-only buffers in this flow (confirmed by an isolation test). All board-to-board lanes are therefore wired unidirectionally (separate a2b/b2a pin groups, see FPGA Test Setups (Arty A7)); nothing in the test setups relies on z states.

This is specific to the yosys/nextpnr-xilinx flow, not a hardware limitation: Vivado’s synthesis handles the standard oe ? drive : 1'bz idiom natively, confirmed both on fpga/vivado/top_model.sv here and on the hatch SoC side (hatch repo, docs/fpga_vivado_flow.md) – real tri-state, fewer wires, FPGA Test Setups (Arty A7) setup 3.

Async-CS constructs do not map

model/s23lc1024.sv uses posedge cs_ni simultaneously as a clock (bus-mode switch) and as an async reset of the shift FFs. On the FPGA this forces CS onto a global clock buffer and a data mux — unroutable, or the slave hangs in CS reset (proven via a bus-spy bitstream: SCK edges arrived, bit_cnt/active stayed 0). On hardware, use the fully synchronous fpga_sram_slave.sv, which oversamples cs/sclk/data with the board clock. The behavioural model remains the simulation reference.

Auto-start pulse lost at configuration

A start pulse fired in the first cycles after configuration is swallowed by the GSR release. top_loopback waits ~10 ms (BOOT_BITS) before starting.

BUFG-promoted pins cannot reach slice data pins

nextpnr promotes CS/SCLK to BUFG clocks; a BUFG net cannot additionally route to slice data inputs (“Unrouteable … BUFGCTRL -> DFFMUX”). The activity LED therefore synchronises SIO0 (a pure data net) instead of CS.

Board / host

openFPGALoader: unable to open ftdi device

udev rules for the Digilent FTDI (0403:6010) missing or not reloaded. Install the rules (usually shipped with the package), re-plug the board, verify with openFPGALoader --scan-usb without sudo.