Files

Ti375C529 Rocket FPGA flow

This target keeps the project's RV64 Rocket/GPS subsystem in FPGA fabric and replaces only the Xilinx board shell and build flow with Efinix equivalents. It does not use the Ti375 hardened RV32 subsystem.

Detailed porting, synthesis, clocking, JTAG, and verification notes are in flow/efinity/README.md.

Build and program

make FPGA_BOARD=ti375c529 fpga-config
make FPGA_BOARD=ti375c529 fpga-rtl
make FPGA_BOARD=ti375c529 fpga-bitstream
make FPGA_BOARD=ti375c529 fpga-program

The Makefile auto-discovers versioned Efinity installations under /tools/efinix/efinity, /tools/Efinix/efinity, /opt, the current user's home directory, and tools/local/efinity. Override discovery when required:

make FPGA_BOARD=ti375c529 fpga-bitstream \
  EFINITY_HOME=/path/to/efinity/<version>

fpga-rtl does not require Efinity. The interface, bitstream, and programming targets require a complete Efinity installation containing bin/setup.sh and scripts/efx_run.py; they now stop before hardware elaboration with a direct diagnostic when it is absent. Concurrent Ti375 map or bitstream invocations are rejected because they share generated FIRRTL, SystemVerilog, and Efinity work directories. Efinity is run with unbuffered Python output so map, pnr, and pgm progress remains visible in the terminal and out/logs/full.log.

Programming auto-selects the connected Ti375 development kit. If more than one compatible FTDI device is attached, run make FPGA_BOARD=ti375c529 fpga-detect to list the bus-qualified URLs and pass the selected one as FTDI_URL=....

Volatile JTAG programming and GDB loading into Rocket DTIM remain available. Persistent boot uses the board's Lower 512-Mbit SPI flash with this map:

Region Flash offset Contents
FPGA configuration 0x00000000 Efinity active-mode configuration HEX
Rocket application 0x00800000 Boot header and ELF-derived payload
Navigation context 0x03FC0000 Two 64-KiB journal sectors
Ephemeris cache 0x03FE0000 Two 64-KiB journal sectors

The application starts at 8 MiB because the compressed Ti375 configuration is currently about 5.19 MB; the previous 4 MiB trial offset would overlap it. Generate or program the Efinity raw HEX images with:

make FPGA_BOARD=ti375c529 fpga-mcs APP=hello_uart
make FPGA_BOARD=ti375c529 fpga-flash-app APP=hello_uart
make FPGA_BOARD=ti375c529 fpga-flash-bitstream
make FPGA_BOARD=ti375c529 fpga-flash-mcs APP=hello_uart

fpga-mcs is the repository-wide compatibility target name. For this Efinix board it produces .hex, not Xilinx .mcs. fpga-flash-app changes only the application region; fpga-flash-mcs erases/programs configuration plus the application through Efinity's pre-built JTAG-to-SPI bridge and verifies the readback. Cold boot from this layout was verified by a complete board power cycle: Ti375 configured from flash and Rocket loaded and completed hello_uart from the application region without a JTAG/GDB load.

Debug and load

Use the host OpenOCD build, not the OpenOCD shipped with Efinity. The build must include riscv set_bscan_tunnel_ir; Ti375 uses a 5-bit outer TAP and selects JTAG_USER1 with instruction 0x08. OpenOCD 0.12 can be given that upstream-compatible command with flow/debug/openocd-0.12-ti375-bscan.patch.

Apply it from a clean OpenOCD 0.12 source tree before configuring and building the host tool:

git apply --check /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch
git apply /path/to/gps/targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch

Place the resulting openocd in PATH, or pass its absolute path with OPENOCD=/path/to/openocd.

In one terminal:

make FPGA_BOARD=ti375c529 fpga-debug-openocd

In a second terminal:

make FPGA_BOARD=ti375c529 fpga-debug-load APP=hello_uart
make FPGA_BOARD=ti375c529 fpga-uart

The target deliberately selects /tools/toolchain/bin/riscv64-unknown-elf-gdb when it exists. The medany compiler toolchain is still used to build software, but it is not expected to contain GDB.

Efinity 2025.2 leaves Rocket's block-local packed store-data array undriven (VDB-1002). tools/prepare_efinity_rtl.py rewrites that generated RTL expression as an equivalent explicit case. Without the rewrite, DMI itself works, but GPR/CSR values stored into Debug Module data registers read as zero; OpenOCD consequently reports a misleading misa=0.

The patch is deliberately post-generation: Chisel and firtool first emit the Ti375 SystemVerilog tree, then prepare_efinity_rtl.py modifies only the generated Ti375 Rocket.sv before Efinity synthesis. It does not edit Rocket's native/upstream Chisel sources.

Two equivalent four-entry packed temporaries in the generated pbus/cbus TLAtomicAutomata modules are rewritten for the same reason, preserving the four atomic-operation mappings while removing their VDB-1002 risk.

The same script generates Ti375-only copies of the acquisition carrier NCO, tracking carrier NCO, and FFT twiddle ROM under out/build/generated/gps_efinity/. This avoids Efinity 2025.2 whole-array/initial/$sin elaboration failures without editing the shared GPS RTL. Only the Ti375 source list selects these copies; Genesys2 and VCU118 still use the originals. Detailed source paths, warning interpretation, and Questa RTL/post-map equivalence results are in the Efinity flow notes.

The affected generated source is hardware/generated/ti375c529-soc-verilog/Rocket.sv; Efinity records the original diagnostic in targets/fpga/ti375c529/flow/efinity/outflow/ti375c529_rocket.warn.log. The checked-in repair is targets/fpga/ti375c529/tools/prepare_efinity_rtl.py and runs after every firtool invocation, before Efinity synthesis.

Board connections

PMOD0/J13 carries the GPS RF sampler:

Signal PMOD pin FPGA resource Package pin
rf_clk 10 GPIOR_95_CLK12 A12
rf_data[0] 2 GPIOR_89 G16
rf_data[1] 3 GPIOR_90 F16
rf_data[2] 4 GPIOR_91 F17
rf_data[3] 7 GPIOR_92 G17
max2771_spi_sclk 1 GPIOR_88_PLLIN1 G15
max2771_spi_csn 8 GPIOR_93_PLLIN1 A11
max2771_spi_sdata 9 GPIOR_94 A13

rf_clk must be wired to J13 pin 10. Pin 10 is the PMOD0 header's dedicated 3.3 V global-clock input. J13 pin 1 is used as the MAX2771 serial clock output; using it as the raw AFE clock would make Efinity promote normal GPIO routing into a GBUF and issue an extra-clock-insertion-delay warning.

As on Genesys2 and VCU118, the AX2771 clock is both the raw AFE sample clock and the source of the GPS processing-clock chain. Two Titanium PLLs generate an intermediate 55.5556 MHz clock, then 100 MHz acquisition and 125 MHz tracking clocks. The Rocket fabric uses the independent on-board 100 MHz oscillator.

PMOD1/J14 carries the sensor SPI, interrupt, and PPS:

Signal PMOD pin FPGA resource Package pin
pmod_spi_csn 1 GPIOR_96_CLK13 B12
pmod_spi_dq[0] 2 GPIOR_97 C14
pmod_spi_dq[1] 3 GPIOR_98 C13
pmod_spi_sck 4 GPIOR_99 C12
pmod_spi_dq[2] 7 GPIOR_100 D12
pmod_spi_dq[3] 8 GPIOR_101_PLLIN1 F12
pmod_irq 9 GPIOR_102 D13
gps_pps 10 GPIOR_103 E13

The FTDI UART is /dev/ttyUSB2 on the current Linux enumeration. SW3 is the active-low Rocket reset. JTAG uses Efinix JTAG_USER1 and the existing Rocket DMI tunnel protocol.

The Lower flash user-mode connection is internal to the development kit:

Signal FPGA resource Package pin
flash_csn GPIOB_N_38 / SSL_N A7
flash_sck GPIOB_P_39 / CCK G6
flash_dq[0] GPIOB_N_40 / CDI0 H4
flash_dq[1] GPIOB_P_40 / CDI1 H5
flash_dq[2] GPIOB_N_39 / CDI2 G5
flash_dq[3] GPIOB_P_38 / CDI3 B7