Files
gps/targets/fpga/ti375c529/README.md
T

191 lines
7.8 KiB
Markdown

# 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`](flow/efinity/README.md).
## Build and program
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
make FPGA_BOARD=ti375c529 fpga-debug-openocd
```
In a second terminal:
```bash
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 |