Merge tdk_new and Ti375 Efinity support

Keep the current GPS software and Genesys2/VCU118 flows while integrating Ti375C529 Efinity, flash, programming, and debug support. Add board-specific SPI NOR profiles and persistent GPS flash layouts across all three boards.
This commit is contained in:
onur
2026-08-13 01:28:46 +03:00
33 changed files with 2434 additions and 180 deletions
+2
View File
@@ -7,6 +7,7 @@
# Generated build outputs.
/out/
/soc/out/
/hardware/generated/
/soc/software/*/build/
/soc/software/gps_system/tests/test_*
!/soc/software/gps_system/tests/test_*.c
@@ -21,6 +22,7 @@ clockInfo.txt
/targets/fpga/*/out/logs/
/targets/fpga/*/out/reports/
/targets/fpga/*/out/build/checkpoints/
/targets/fpga/vcu118/out/
# Python runtime caches and privacy-sensitive raw board captures.
__pycache__/
+10 -4
View File
@@ -10,8 +10,8 @@ FPGA_BOARD ?= vcu118
endif
FPGA_TARGET_DIR := targets/fpga/$(FPGA_BOARD)
.PHONY: help doctor soc-hw fpga-rtl fpga-bitstream fpga-elf-flash-image fpga-mcs fpga-flash-app fpga-flash fpga-flash-bitstream fpga-flash-mcs fpga-flash-all fpga-program fpga-debug-openocd fpga-debug-load fpga-uart fpga-config asic-rtl asic-sim clean
.PHONY: fpga_rtl fpga_bitstream fpga_elf_flash_image fpga_mcs fpga_flash_app fpga_flash fpga_flash_bitstream fpga_flash_mcs fpga_flash_all fpga_program fpga_debug_openocd fpga_debug_load fpga_uart fpga_config
.PHONY: help doctor soc-hw fpga-rtl fpga-bitstream fpga-elf-flash-image fpga-mcs fpga-flash-app fpga-flash fpga-flash-bitstream fpga-flash-mcs fpga-flash-all fpga-program fpga-detect fpga-debug-openocd fpga-debug-load fpga-uart fpga-config asic-rtl asic-sim clean
.PHONY: fpga_rtl fpga_bitstream fpga_elf_flash_image fpga_mcs fpga_flash_app fpga_flash fpga_flash_bitstream fpga_flash_mcs fpga_flash_all fpga_program fpga_detect fpga_debug_openocd fpga_debug_load fpga_uart fpga_config
help:
@printf '%s\n' \
@@ -19,11 +19,12 @@ help:
' make doctor # check local JDK/Mill/CIRCT and RISC-V tools' \
' make soc-hw # emit shared SoC FIRRTL through FPGA config' \
' make fpga-rtl # emit selected FPGA SystemVerilog and wrapper' \
' make fpga-bitstream # run selected FPGA Vivado bitstream flow' \
' make fpga-bitstream # run selected board vendor bitstream flow' \
' make fpga-elf-flash-image' \
' # build APP ELF and board flash-format app image' \
' make fpga-mcs # generate combined bitstream + app MCS/BIN' \
' make fpga-program # program selected FPGA SRAM' \
' make fpga-detect # run selected board USB/JTAG detection target' \
' make fpga-flash-app # build flash-format app image and program app flash region' \
' make fpga-flash # alias for fpga-flash-app' \
' make fpga-flash-bitstream' \
@@ -39,7 +40,7 @@ help:
' make asic-sim # run ASIC-style Questa sanity simulation' \
'' \
'Config:' \
' FPGA_BOARD=$(FPGA_BOARD) # vcu118 or genesys2' \
' FPGA_BOARD=$(FPGA_BOARD) # vcu118, genesys2, or ti375c529' \
' UART_BAUD=460800 # FPGA firmware and host listener default' \
' GPS_ESKF_ENABLE=1 # gps_system: 1 ESKF, 0 GPS-only' \
' IMU_SENSOR=auto # gps_system: auto, tdk, st or stm' \
@@ -49,6 +50,7 @@ help:
' make -C hardware/soc help' \
' make -C targets/fpga/vcu118 help' \
' make -C targets/fpga/genesys2 help' \
' make -C targets/fpga/ti375c529 help' \
' make -C targets/asic/rocket help'
doctor:
@@ -72,6 +74,9 @@ fpga-mcs:
fpga-program:
$(MAKE) -C $(FPGA_TARGET_DIR) program-fpga
fpga-detect:
$(MAKE) -C $(FPGA_TARGET_DIR) detect
fpga-flash-app fpga-flash:
$(MAKE) -C $(FPGA_TARGET_DIR) program-flash
@@ -106,6 +111,7 @@ fpga_flash_bitstream: fpga-flash-bitstream
fpga_flash_mcs: fpga-flash-mcs
fpga_flash_all: fpga-flash-all
fpga_program: fpga-program
fpga_detect: fpga-detect
fpga_debug_openocd: fpga-debug-openocd
fpga_debug_load: fpga-debug-load
fpga_uart: fpga-uart
+139 -8
View File
@@ -1,6 +1,7 @@
# Rocket Project
Bu agac VCU118/Genesys2 FPGA ve ASIC-style Rocket akislari icin sade proje duzenidir.
Bu agac VCU118, Genesys2 ve Ti375C529 FPGA akislari ile ASIC-style Rocket
akisi icin sade proje duzenidir.
Upstream Rocket-Chip kaynaklari daginik kok klasorlerde tutulmaz; gerekli
upstream kaynaklar `hardware/upstream/rocket-chip/` altindadir.
@@ -22,6 +23,7 @@ hardware/
soc/software/ Bootloader, BSP, uygulamalar, flash image tool
targets/fpga/vcu118/ VCU118 build/programlama akisi
targets/fpga/genesys2/ Genesys2 build/programlama akisi
targets/fpga/ti375c529/ Ti375C529 Efinity build/programlama akisi
targets/asic/rocket/ ASIC wrapper/filelist/sim akisi
setup_tools.sh /tools/soc-tools host araci kurulum betigi
```
@@ -209,6 +211,7 @@ make -C hardware/fpga/vcu118/rtl help
make -C hardware/sim/fpga/vcu118 help
make -C targets/fpga/vcu118 help
make -C targets/fpga/genesys2 help
make -C targets/fpga/ti375c529 help
make -C targets/asic/rocket help
```
@@ -219,6 +222,7 @@ FPGA karti kok Makefile'dan `FPGA_BOARD` ile secilir:
```sh
make FPGA_BOARD=vcu118 fpga-config
make FPGA_BOARD=genesys2 fpga-config
make FPGA_BOARD=ti375c529 fpga-config
```
Top-level `BOARD=...` alias'i da desteklenir. Orneklerde Genesys2 kullanilir:
@@ -232,7 +236,7 @@ Yanlislikla underscore kullanilmasi durumunda yaygin FPGA hedefleri icin
alias'lar da vardir (`fpga_program`, `fpga_debug_openocd` gibi).
`fpga-config` secilen kartin clock, flash, UART, DTIM ve RF ayarlarini
gosterir. RF kaynagi `RF_INPUT_MODE` ile secilir:
gosterir. Genesys2 ve VCU118'de RF kaynagi `RF_INPUT_MODE` ile secilir:
```text
RF_INPUT_MODE=pmod Varsayilan. Harici 4-bit RF data + RF clock PMOD'dan gelir.
@@ -270,10 +274,19 @@ VCU118 icin ayrilan bos PMOD0/J52 pinleri:
VCU118'in U41 level shifter'i PMOD header tarafini 3.3 V'a cevirir. Mevcut
standart PMOD SPI pinleri degistirilmemistir:
Ti375C529, PMOD0/J13'te RF veri ve saatinden arta kalan uc pini kullanir:
| MAX2771 sinyali | FPGA yonu | Ti375C529 PMOD | FPGA pini | Elektrik standardi |
|---|---|---|---|---|
| `SCLK` | cikis | `J13.1` | `G15` | 3.3_V_LVCMOS |
| `CSN` | cikis | `J13.8` | `A11` | 3.3_V_LVCMOS |
| `SDATA` | yazmada cikis, okumada giris | `J13.9` | `A13` | 3.3_V_LVCMOS |
| Kart | Standart PMOD SPI CSN/MOSI/MISO/SCLK | MAX2771 CSN/SDATA/SCLK |
|---|---|---|
| Genesys2 | `JC1/JC2/JC3/JC4` | `JB3/JB4/JB2` |
| VCU118 | `J53.1/J53.3/J53.5/J53.7` | `J52.6/J52.8/J52.4` |
| Ti375C529 | `J14.1/J14.2/J14.3/J14.4` | `J13.8/J13.9/J13.1` |
MAX2771 register varsayilanlarini yazip tek-hat `SDATA` uzerinden geri okuyarak
dogrulayan bare-metal uygulama:
@@ -286,10 +299,14 @@ Test MAX2771 register `0x0`-`0xA` icerigini veri sayfasindaki degerlerle
degistirir. EVKIT uzerindeki MAX32625 kontrolcusunun seri hatlari test boyunca
high-Z olmali ve EVKIT GUI ayni anda kullanilmamalidir.
Ti375C529 Efinity wrapper'i su anda yalniz harici PMOD RF girisini kullanir;
bu kartta `RF_INPUT_MODE=pmod` birakilmalidir. `generated` ve `ethernet`
yollari Ti375C529 wrapper'ina henuz uygulanmamistir.
Top-level FPGA wrapper'lar elle yazilmaz; `targets/fpga/*/tools/gen_*_wrapper.py`
scriptleri tarafindan uretilir. Bu yuzden RF secimi RTL `ifdef` ile degil,
generator parametresi ile yapilir. `make rtl` ve Vivado `build.tcl` ayni
`RF_INPUT_MODE` degerini wrapper generator'a gecirir.
scriptleri tarafindan uretilir. Genesys2 ve VCU118'de RF secimi RTL `ifdef`
ile degil, generator parametresi ile yapilir. `make rtl` ve Vivado `build.tcl`
ayni `RF_INPUT_MODE` degerini wrapper generator'a gecirir.
Varsayilan `pmod` modunda Ethernet RF IP/RTL okunmaz ve top'ta Ethernet PHY
portlari olusmaz. Ethernet RF akisi gerektiginde:
@@ -321,11 +338,23 @@ uzerinden 1.8 V bank/LVCMOS18:
rf_data_pmod[1] AW15 PMOD0_2 J52.5 LVCMOS18 3.3 V
rf_data_pmod[2] AV15 PMOD0_3 J52.7 LVCMOS18 3.3 V
rf_data_pmod[3] AV16 PMOD0_4 J52.2 LVCMOS18 3.3 V
Ti375C529 PMOD0/J13, connector ve FPGA tarafi 3.3 V:
port FPGA pin PMOD pin FPGA resource FPGA I/O
rf_clk A12 J13.10 GPIOR_95_CLK12 3.3_V_LVCMOS
rf_data[0] G16 J13.2 GPIOR_89 3.3_V_LVCMOS
rf_data[1] F16 J13.3 GPIOR_90 3.3_V_LVCMOS
rf_data[2] F17 J13.4 GPIOR_91 3.3_V_LVCMOS
rf_data[3] G17 J13.7 GPIOR_92 3.3_V_LVCMOS
```
VCU118'de disaridan PMOD header'a 3.3 V seviye verilir. FPGA U1 package
pinlerine dogrudan 3.3 V uygulanmaz; o tarafta XDC `LVCMOS18` kullanir.
Ti375C529'de AX2771 `rf_clk` hatti mutlaka J13 pin 10'a baglanmalidir. Bu pin
global-clock girisidir. J13 pin 1 / G15 (`GPIOR_88_PLLIN1`) MAX2771 `SCLK`
cikisidir; dedicated fabric GCLK olmadigi icin RF saati oradan alinmaz.
PMOD SPI portu her RF modunda aktiftir ve ayri MMIO register block olarak
`0x10015000` adresindedir. Kart uzerindeki konfig flash SPI'si `0x10014000`
adresinde kalir. Yazilim driver'i single/quad calisma modunu `ctrl.bit2`
@@ -351,6 +380,15 @@ uzerinden 1.2 V bank/LVCMOS12:
pmod_spi_sck P30 PMOD1_3 J53.7 SCK LVCMOS12 3.3 V
pmod_spi_dq[2] P29 PMOD1_4 J53.2 LVCMOS12 3.3 V
pmod_spi_dq[3] L31 PMOD1_5 J53.4 LVCMOS12 3.3 V
Ti375C529 PMOD1/J14, connector ve FPGA tarafi 3.3 V:
port FPGA pin PMOD pin FPGA resource FPGA I/O
pmod_spi_csn B12 J14.1 GPIOR_96_CLK13 3.3_V_LVCMOS
pmod_spi_dq[0] C14 J14.2 MOSI GPIOR_97 3.3_V_LVCMOS
pmod_spi_dq[1] C13 J14.3 MISO GPIOR_98 3.3_V_LVCMOS
pmod_spi_sck C12 J14.4 SCK GPIOR_99 3.3_V_LVCMOS
pmod_spi_dq[2] D12 J14.7 GPIOR_100 3.3_V_LVCMOS
pmod_spi_dq[3] F12 J14.8 GPIOR_101_PLLIN1 3.3_V_LVCMOS
```
Sensorden gelen external interrupt hatti SPI'dan bagimsizdir. `pmod_irq`
@@ -365,8 +403,16 @@ Genesys2:
VCU118:
port FPGA pin PMOD pin FPGA I/O PMOD header level
pmod_irq M31 PMOD1_6 J53.6 LVCMOS12 3.3 V
Ti375C529:
port FPGA pin PMOD pin FPGA resource FPGA I/O
pmod_irq D13 J14.9 GPIOR_102 3.3_V_LVCMOS
gps_pps E13 J14.10 GPIOR_103 3.3_V_LVCMOS
```
Ti375C529'de `gps_pps` J14.10 uzerinden cikan 3.3 V PPS sinyalidir;
`pmod_irq` ise J14.9 uzerinden FPGA'ya girer.
Bu pinler mod bazli companion XDC dosyalarinda tutulur:
`hardware/fpga/genesys2/constraints/genesys2_pmod_rf.xdc`,
`hardware/fpga/vcu118/constraints/vcu118_pmod_rf.xdc`,
@@ -375,13 +421,47 @@ Bu pinler mod bazli companion XDC dosyalarinda tutulur:
`hardware/fpga/genesys2/constraints/genesys2_pmod_irq.xdc`,
`hardware/fpga/vcu118/constraints/vcu118_pmod_irq.xdc`,
`hardware/fpga/genesys2/constraints/genesys2_ethernet.xdc` ve
`hardware/fpga/vcu118/constraints/vcu118_ethernet.xdc`.
`hardware/fpga/vcu118/constraints/vcu118_ethernet.xdc`. Ti375C529 pinleri,
I/O standartlari, PLL'ler ve hard-JTAG baglantisi tek Efinity interface
scriptinde tutulur:
`hardware/fpga/ti375c529/constraints/ti375c529_rocket.isf`.
### Ti375C529 kart uzeri baglantilar
Ti375C529 development kit'te Rocket sistem saati kart uzerindeki 100 MHz
osilatorden, GPS isleme saatleri ise AX2771'in J13.10 uzerindeki
16.367981 MHz RF saatinden uretilir. SW3 active-low Rocket resetidir. FTDI
UART varsayilan olarak 460800 baud ve mevcut Linux enumeration'inda
`/dev/ttyUSB2` kullanir. Birden fazla kart veya farkli enumeration icin
`UART_PORT=...` ve `FTDI_URL=...` ile override edilebilir.
Lower 512-Mbit konfig flash'i kart icinde su pinlere baglidir; PMOD'a kablo
cekilmez:
```text
port FPGA pin FPGA resource
flash_csn A7 GPIOB_N_38 / SSL_N
flash_sck G6 GPIOB_P_39 / CCK
flash_dq[0] H4 GPIOB_N_40 / CDI0
flash_dq[1] H5 GPIOB_P_40 / CDI1
flash_dq[2] G5 GPIOB_N_39 / CDI2
flash_dq[3] B7 GPIOB_P_38 / CDI3
```
Efinity `JTAG_USER1`, mevcut Rocket DMI tunnel protokolunu kullanir. Host
OpenOCD build'inde `riscv set_bscan_tunnel_ir` destegi bulunmalidir; Efinity
ile gelen OpenOCD yerine uyumlu host OpenOCD kullanilir. OpenOCD 0.12 icin
gerekli host yamasi
`targets/fpga/ti375c529/flow/debug/openocd-0.12-ti375-bscan.patch`
dosyasindadir. Ayrintili Efinity, clock, JTAG ve dogrulama notlari icin
`targets/fpga/ti375c529/README.md` dosyasina bakin.
## FPGA Flash ve MCS Akislari
Bu hedefler kok Makefile'dan secilen karta yonlenir. Genesys2 icin
`BOARD=genesys2`, VCU118 icin `BOARD=vcu118` kullanilir. `APP` verilmezse
varsayilan uygulama `hello_uart` olur.
`BOARD=genesys2`, VCU118 icin `BOARD=vcu118`, Ti375C529 icin
`BOARD=ti375c529` kullanilir. `APP` verilmezse varsayilan uygulama
`hello_uart` olur.
Sadece ELF'i derleyip bootloader'in okuyacagi flash-format app imajina cevirmek:
@@ -478,6 +558,57 @@ flash size: 32 MiB
interface: SPIx4
```
### Ti375C529 Efinity build ve flash
Efinity varsayilan olarak `/tools/efinix/efinity` altinda aranir. Farkli bir
kurulum `EFINITY_HOME=/path/to/efinity` ile secilebilir. Build, SRAM'e gecici
programlama ve kart tespiti kokten su sekilde yapilir:
```sh
make FPGA_BOARD=ti375c529 fpga-config
make FPGA_BOARD=ti375c529 fpga-bitstream
make -C targets/fpga/ti375c529 detect
make FPGA_BOARD=ti375c529 fpga-program
```
Ti375C529'de repository genelindeki `fpga-mcs` hedef adi korunur fakat cikti
Xilinx MCS/BIN degil, Efinity raw HEX'tir. Lower 512-Mbit flash yerlesimi:
```text
configuration offset: 0x00000000
app offset: 0x00800000
flash size: 64 MiB
interface: active-x1 configuration / user-mode quad SPI
```
Konfig ve uygulama imajlarini uretmek ve programlamak icin:
```sh
make FPGA_BOARD=ti375c529 APP=hello_uart fpga-mcs
make FPGA_BOARD=ti375c529 APP=hello_uart fpga-flash-app
make FPGA_BOARD=ti375c529 fpga-flash-bitstream
make FPGA_BOARD=ti375c529 APP=hello_uart fpga-flash-mcs
```
Ciktilar:
```text
targets/fpga/ti375c529/out/bitstream/ti375c529_rocket.bit
targets/fpga/ti375c529/out/bitstream/ti375c529_rocket.hex
targets/fpga/ti375c529/out/flash/ti375c529_rocket.hex
targets/fpga/ti375c529/out/flash/ti375c529_rocket.json
```
Flash programlama Efinity'nin Ti375'e uygun JTAG-to-SPI bridge'ini gecici
olarak yukler. Gercek persistent boot testi icin programlamadan sonra karta
power-cycle uygulanmalidir. GDB ile DTIM'e yukleme ve UART dinleme:
```sh
make FPGA_BOARD=ti375c529 fpga-debug-openocd
make FPGA_BOARD=ti375c529 APP=hello_uart fpga-debug-load
make FPGA_BOARD=ti375c529 fpga-uart
```
## GPS Reset Davranisi
OpenOCD/GDB `monitor reset` yolu Rocket debug module `ndmreset` sinyalini
@@ -0,0 +1,235 @@
# Efinity Interface Configuration for the Ti375C529 development kit.
# Pin assignments follow the kit user guide and the Efinity 2025.2 device DB.
# Board I/O bank voltages. Keep these aligned with the Efinix out-of-box
# Ti375C529 development-kit project.
design.set_device_property("2A", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("2A", "2A_MODE_SEL", "2A")
design.set_device_property("2A", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("2B", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("2B", "2B_MODE_SEL", "2B")
design.set_device_property("2B", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("2C", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("2C", "2C_MODE_SEL", "2C")
design.set_device_property("2C", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("2D", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("2D", "2D_MODE_SEL", "2D")
design.set_device_property("2D", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("2E", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("2E", "2E_MODE_SEL", "2E")
design.set_device_property("2E", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("4A_4B", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("4A_4B", "4A_4B_MODE_SEL", "4A_4B")
design.set_device_property("4A_4B", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("4C", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("4C", "4C_MODE_SEL", "4C")
design.set_device_property("4C", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("4D", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("4D", "4D_MODE_SEL", "4D")
design.set_device_property("4D", "VOLTAGE", "1.8", "IOBANK")
design.set_device_property("BL2_BL3", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("BL2_BL3", "BL2_MODE_SEL", "BL2")
design.set_mode_sel_name("BL2_BL3", "BL3_MODE_SEL", "BL3")
design.set_device_property("BL2_BL3", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("BR0", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("BR0", "BR0_MODE_SEL", "BR0")
design.set_device_property("BR0", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("BR3_BR4", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("BR3_BR4", "BR3_MODE_SEL", "BR3")
design.set_mode_sel_name("BR3_BR4", "BR4_MODE_SEL", "BR4")
design.set_device_property("BR3_BR4", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("TL1_TL5", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("TL1_TL5", "TL1_MODE_SEL", "TL1")
design.set_mode_sel_name("TL1_TL5", "TL5_MODE_SEL", "TL5")
design.set_device_property("TL1_TL5", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("TR0", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("TR0", "TR0_MODE_SEL", "TR0")
design.set_device_property("TR0", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("TR1", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("TR1", "TR1_MODE_SEL", "TR1")
design.set_device_property("TR1", "VOLTAGE", "3.3", "IOBANK")
design.set_device_property("TR2", "DYNAMIC_VOLTAGE", "0", "IOBANK")
design.set_mode_sel_name("TR2", "TR2_MODE_SEL", "TR2")
design.set_device_property("TR2", "VOLTAGE", "3.3", "IOBANK")
# External GPIO.
design.create_input_gpio("reset_n")
design.set_property("reset_n", "PULL_OPTION", "WEAK_PULLUP")
design.create_input_gpio("uart_rx")
design.create_output_gpio("uart_tx")
# Lower 512-Mbit configuration flash. After active configuration completes,
# these dedicated SPI pins become fabric GPIO and are driven by Rocket's MMIO
# SPI controller so the BootROM can read the application region.
design.create_output_gpio("flash_sck")
design.create_output_gpio("flash_csn")
design.create_inout_gpio("flash_dq", 3, 0)
# The AX2771 sample clock is routed to J13 pin 10 / GPIOR_95_CLK12 so it
# enters the fabric through a dedicated global-clock input instead of being
# promoted from normal GPIO routing by the placer.
design.create_input_clock_gpio("rf_clk")
design.create_input_gpio("rf_data", 3, 0)
design.create_output_gpio("pmod_spi_sck")
design.create_output_gpio("pmod_spi_csn")
design.create_inout_gpio("pmod_spi_dq", 3, 0)
design.create_input_gpio("pmod_irq")
design.create_output_gpio("max2771_spi_sclk")
design.create_output_gpio("max2771_spi_csn")
design.create_inout_gpio("max2771_spi_sdata")
design.create_output_gpio("gps_pps")
design.create_output_gpio("led", 4, 0)
# The two PMOD headers, FTDI UART, reset switch, 100 MHz oscillator, and
# LED9/LED10 use the development kit's 3.3 V banks. GPIOs otherwise default
# to 1.8 V LVCMOS, so state these assignments explicitly.
design.set_property("reset_n", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("uart_rx", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("uart_tx", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("flash_sck", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_csn", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_dq[0]", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_dq[1]", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_dq[2]", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_dq[3]", "IO_STANDARD", "1.8_V_LVCMOS")
design.set_property("flash_csn", "PULL_OPTION", "WEAK_PULLUP")
design.set_property("flash_dq[0]", "PULL_OPTION", "WEAK_PULLUP")
design.set_property("flash_dq[1]", "PULL_OPTION", "WEAK_PULLUP")
design.set_property("flash_dq[2]", "PULL_OPTION", "WEAK_PULLUP")
design.set_property("flash_dq[3]", "PULL_OPTION", "WEAK_PULLUP")
design.set_property("rf_clk", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("rf_data[0]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("rf_data[1]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("rf_data[2]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("rf_data[3]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_sck", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_csn", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_dq[0]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_dq[1]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_dq[2]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_spi_dq[3]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("pmod_irq", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("max2771_spi_sclk", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("max2771_spi_csn", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("max2771_spi_sdata", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("gps_pps", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("led[0]", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("led[1]", "IO_STANDARD", "3.3_V_LVCMOS")
# Rocket/fabric clock: 100 MHz board oscillator -> 100 MHz GCLK.
design.create_block("fabric_pll", "PLL")
design.gen_pll_ref_clock("fabric_pll", pll_res="PLL_BL0", refclk_src="EXTERNAL", refclk_name="board_clk_100", ext_refclk_no="1")
design.set_property("board_clk_100", "IO_STANDARD", "3.3_V_LVCMOS")
design.set_property("fabric_pll", "REFCLK_FREQ", "100", "PLL")
design.set_property("fabric_pll", "CLKOUT0_PIN", "fabric_clk", "PLL")
design.set_property("fabric_pll", "CLKOUT0_CONN_TYPE", "gclk", "PLL")
design.set_property("fabric_pll", "LOCKED_PIN", "fabric_pll_locked", "PLL")
design.auto_calc_pll_clock("fabric_pll", {"CLKOUT0_FREQ": "100.0", "CLKOUT0_PHASE": "0"})
# RF-coherent GPS processing clocks. The AX2771's 16.367981 MHz clock enters
# the fabric on J13 pin 10 / A12 (GPIOR_95_CLK12) and drives the same two-stage
# clock chain used by the Xilinx targets:
# RF -> ~55.55556 MHz -> 100 MHz acquisition / 125 MHz tracking.
design.create_block("gps_ref_pll", "PLL")
design.gen_pll_ref_clock("gps_ref_pll", pll_res="PLL_TR0", refclk_src="CORE")
design.set_property("gps_ref_pll", "CORE_CLK_PIN", "rf_clk", "PLL")
design.set_property("gps_ref_pll", "REFCLK_FREQ", "16.367981", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_EN", "1", "PLL")
design.set_property("gps_ref_pll", "CLKOUT0_PIN", "gps_ref_clk_gen", "PLL")
design.set_property("gps_ref_pll", "CLKOUT0_CONN_TYPE", "gclk", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_PIN", "gps_ref_feedback", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_CONN_TYPE", "gclk", "PLL")
design.set_property("gps_ref_pll", "LOCKED_PIN", "gps_ref_pll_locked", "PLL")
design.set_property("gps_ref_pll", "FEEDBACK_MODE", "LOCAL", "PLL")
design.set_property("gps_ref_pll", "FEEDBACK_CLK", "CLK1", "PLL")
design.set_property("gps_ref_pll", "FRACTIONAL_MODE_EN", "1", "PLL")
design.set_property("gps_ref_pll", "FRACTIONAL_COEFFICIENT", "10715375", "PLL")
design.set_property("gps_ref_pll", "M", "4", "PLL")
design.set_property("gps_ref_pll", "N", "1", "PLL")
design.set_property("gps_ref_pll", "O", "1", "PLL")
design.set_property("gps_ref_pll", "CLKOUT0_DIV", "42", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_DIV", "35", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_PDIV", "5", "PLL")
design.set_property("gps_ref_pll", "CLKOUT1_SDIV", "30", "PLL")
design.calc_pll_clock("gps_ref_pll")
design.create_block("gps_domain_pll", "PLL")
design.gen_pll_ref_clock("gps_domain_pll", pll_res="PLL_TR1", refclk_src="CORE")
design.set_property("gps_domain_pll", "CORE_CLK_PIN", "gps_ref_clk_gen", "PLL")
design.set_property("gps_domain_pll", "REFCLK_FREQ", "55.55555593", "PLL")
design.set_property("gps_domain_pll", "CLKOUT3_EN", "1", "PLL")
design.set_property("gps_domain_pll", "CLKOUT4_EN", "1", "PLL")
design.set_property("gps_domain_pll", "CLKOUT0_PIN", "gps_domain_feedback", "PLL")
design.set_property("gps_domain_pll", "CLKOUT0_CONN_TYPE", "gclk", "PLL")
design.set_property("gps_domain_pll", "CLKOUT3_PIN", "gps_acq_clk_gen", "PLL")
design.set_property("gps_domain_pll", "CLKOUT3_CONN_TYPE", "gclk", "PLL")
design.set_property("gps_domain_pll", "CLKOUT4_PIN", "gps_trck_clk_gen", "PLL")
design.set_property("gps_domain_pll", "CLKOUT4_CONN_TYPE", "gclk", "PLL")
design.set_property("gps_domain_pll", "LOCKED_PIN", "gps_domain_pll_locked", "PLL")
design.set_property("gps_domain_pll", "FEEDBACK_MODE", "LOCAL", "PLL")
design.set_property("gps_domain_pll", "FEEDBACK_CLK", "CLK0", "PLL")
design.set_property("gps_domain_pll", "M", "2", "PLL")
design.set_property("gps_domain_pll", "N", "1", "PLL")
design.set_property("gps_domain_pll", "O", "2", "PLL")
design.set_property("gps_domain_pll", "CLKOUT0_DIV", "18", "PLL")
design.set_property("gps_domain_pll", "CLKOUT3_DIV", "20", "PLL")
design.set_property("gps_domain_pll", "CLKOUT4_DIV", "16", "PLL")
design.calc_pll_clock("gps_domain_pll")
# Hard JTAG USER1 exposes the TAP handshake at the FPGA core boundary.
design.create_block("rocket_jtag", "JTAG")
design.set_property("rocket_jtag", "NAME", "rocket_jtag", "JTAG")
design.set_property("rocket_jtag", "RESOURCE", "JTAG_USER1", "JTAG")
design.set_property("rocket_jtag", "CAPTURE", "jtag_CAPTURE", "JTAG")
design.set_property("rocket_jtag", "DRCK", "jtag_DRCK", "JTAG")
design.set_property("rocket_jtag", "RESET", "jtag_RESET", "JTAG")
design.set_property("rocket_jtag", "RUNTEST", "jtag_RUNTEST", "JTAG")
design.set_property("rocket_jtag", "SEL", "jtag_SEL", "JTAG")
design.set_property("rocket_jtag", "SHIFT", "jtag_SHIFT", "JTAG")
design.set_property("rocket_jtag", "TCK", "jtag_TCK", "JTAG")
design.set_property("rocket_jtag", "TDI", "jtag_TDI", "JTAG")
design.set_property("rocket_jtag", "TMS", "jtag_TMS", "JTAG")
design.set_property("rocket_jtag", "UPDATE", "jtag_UPDATE", "JTAG")
design.set_property("rocket_jtag", "TDO", "jtag_TDO", "JTAG")
design.assign_resource("rocket_jtag", "JTAG_USER1", "JTAG")
# Package assignments.
design.assign_pkg_pin("board_clk_100", "U4")
design.assign_pkg_pin("reset_n", "U19")
design.assign_pkg_pin("uart_rx", "E10")
design.assign_pkg_pin("uart_tx", "E9")
# Lower configuration flash U47: CDI0..3, CCK, and SSL_N. These assignments
# match Efinix's Ti375C529 JTAG-to-SPI loader reference design.
design.assign_pkg_pin("flash_dq[0]", "H4")
design.assign_pkg_pin("flash_dq[1]", "H5")
design.assign_pkg_pin("flash_dq[2]", "G5")
design.assign_pkg_pin("flash_dq[3]", "B7")
design.assign_pkg_pin("flash_sck", "G6")
design.assign_pkg_pin("flash_csn", "A7")
# PMOD0/J13 RF input plus the independent MAX2771 three-wire control bus.
# J13 pin 10 is the header's dedicated GCLK-capable RF-clock input.
design.assign_pkg_pin("max2771_spi_sclk", "G15")
design.assign_pkg_pin("max2771_spi_csn", "A11")
design.assign_pkg_pin("max2771_spi_sdata", "A13")
design.assign_pkg_pin("rf_clk", "A12")
design.assign_pkg_pin("rf_data[0]", "G16")
design.assign_pkg_pin("rf_data[1]", "F16")
design.assign_pkg_pin("rf_data[2]", "F17")
design.assign_pkg_pin("rf_data[3]", "G17")
# PMOD1/J14 SPI + interrupt + PPS.
design.assign_pkg_pin("pmod_spi_csn", "B12")
design.assign_pkg_pin("pmod_spi_dq[0]", "C14")
design.assign_pkg_pin("pmod_spi_dq[1]", "C13")
design.assign_pkg_pin("pmod_spi_sck", "C12")
design.assign_pkg_pin("pmod_spi_dq[2]", "D12")
design.assign_pkg_pin("pmod_spi_dq[3]", "F12")
design.assign_pkg_pin("pmod_irq", "D13")
design.assign_pkg_pin("gps_pps", "E13")
# User LEDs LED9..LED13.
design.assign_pkg_pin("led[0]", "V4")
design.assign_pkg_pin("led[1]", "U6")
design.assign_pkg_pin("led[2]", "L18")
design.assign_pkg_pin("led[3]", "R20")
design.assign_pkg_pin("led[4]", "E19")
@@ -0,0 +1,8 @@
# AX2771 sample clock on PMOD J13. The 100/125 MHz GPS clocks generated by the
# two Efinity PLLs are frequency-related to this input; the Rocket fabric clock
# comes from the independent on-board 100 MHz oscillator.
create_clock -period 61.09495 -name rf_clk [get_ports {rf_clk}]
# The FTDI adapter is normally run at 1 MHz. Constraining the hard-TAP fabric
# interface to 10 MHz leaves margin if the debug adapter speed is increased.
create_clock -period 100.000 -name jtag_TCK [get_ports {jtag_TCK}]
@@ -0,0 +1,10 @@
# Efinity's generated .pt.sdc is read before this file and defines the fabric
# and PLL-output clocks. The Rocket oscillator, AX2771-derived GPS clocks, and
# hard-TAP JTAG clock are independent domains.
set_clock_groups -asynchronous \
-group [get_clocks {fabric_clk}] \
-group [get_clocks {rf_clk}] \
-group [get_clocks {gps_ref_clk_gen}] \
-group [get_clocks {gps_acq_clk_gen}] \
-group [get_clocks {gps_trck_clk_gen}] \
-group [get_clocks {jtag_TCK}]
+18
View File
@@ -0,0 +1,18 @@
.PHONY: help all shell generated clean
help:
@echo "Ti375C529 RTL targets:"
@echo " make shell # list hand-written FPGA shell RTL"
@echo " make generated # generate Rocket SystemVerilog and Efinix wrapper"
@echo " make clean # remove generated wrapper/verilog"
all: generated
shell:
@find . -type f -name '*.sv' -print | sort
generated:
@$(MAKE) -C ../../../../targets/fpga/ti375c529 rtl
clean:
rm -rf ../../../generated/ti375c529-soc-verilog ../../../../targets/fpga/ti375c529/out/build/generated
+9 -3
View File
@@ -14,12 +14,15 @@ GPS_DEBUG_LEVEL ?= 1
GPS_ESKF_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
GPS_EPHEMERIS_FLASH_BASE ?= 0x01fe0000
GPS_NAV_CONTEXT_ENABLE ?= 1
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x01fc0000
IMU_SENSOR ?= auto
BSP_UART_CLOCK_HZ ?= 100000000
BSP_UART_BAUDRATE ?= 460800
GPS_SYSTEM_UART_BAUDRATE ?= 460800
BSP_CLINT_TIMEBASE_HZ ?= 1000000
BSP_SPI_FLASH_PROFILE ?= 1
GPS_SYSTEM_CLINT_TIMEBASE_HZ ?= 500000
GPS_SYSTEM_IMU_PUBLISH_EVERY_N_SAMPLES ?= 5
# BSP_DTIM_* mirrors the FPGA DTIM_* knobs and is used by C code plus linker scripts.
@@ -51,9 +54,12 @@ help:
@echo " GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)"
@echo " GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)"
@echo " GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)"
@echo " GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)"
@echo " GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)"
@echo " GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)"
@echo " IMU_SENSOR=$(IMU_SENSOR)"
@echo " BSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)"
@echo " BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)"
@echo " GPS_SYSTEM_CLINT_TIMEBASE_HZ=$(GPS_SYSTEM_CLINT_TIMEBASE_HZ)"
@echo " GPS_SYSTEM_IMU_PUBLISH_EVERY_N_SAMPLES=$(GPS_SYSTEM_IMU_PUBLISH_EVERY_N_SAMPLES)"
@echo " BSP_DTIM_BASE=$(BSP_DTIM_BASE)"
@@ -62,7 +68,7 @@ help:
all: bootloader hello
bootloader:
@make -C bootloader TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/bootloader" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
@make -C bootloader TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/bootloader" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
hello:
@make -C hello_uart TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/hello_uart" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
@@ -77,11 +83,11 @@ steval-mki217v1-test:
@make -C steval_mki217v1_test TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/steval_mki217v1_test" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
gps-system:
@make -C gps_system TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/gps_system" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(GPS_SYSTEM_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(GPS_SYSTEM_CLINT_TIMEBASE_HZ)" IMU_CORRECTED_PUBLISH_EVERY_N_SAMPLES="$(GPS_SYSTEM_IMU_PUBLISH_EVERY_N_SAMPLES)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
@make -C gps_system TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/gps_system" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(GPS_SYSTEM_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(GPS_SYSTEM_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" IMU_CORRECTED_PUBLISH_EVERY_N_SAMPLES="$(GPS_SYSTEM_IMU_PUBLISH_EVERY_N_SAMPLES)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
app:
@test -d "$(APP)"
@make -C "$(APP)" TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/$(APP)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
@make -C "$(APP)" TOOLCHAIN="$(TOOLCHAIN)" BUILD_DIR="$(OUT_DIR)/$(APP)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(BSP_DTIM_BASE)" BSP_DTIM_SIZE="$(BSP_DTIM_SIZE)" all
flash-image: app
@mkdir -p "$(FLASH_DIR)"
+5 -1
View File
@@ -14,12 +14,14 @@ MARCH ?= rv64imafdc_zicsr_zifencei
MABI ?= lp64d
BSP_UART_CLOCK_HZ ?= 100000000
BSP_UART_BAUDRATE ?= 460800
BSP_CLINT_TIMEBASE_HZ ?= 1000000
BSP_SPI_FLASH_PROFILE ?= 1
BSP_DTIM_BASE ?= 0x80000000
BSP_DTIM_SIZE ?= 0x00100000
CONFIG_STAMP := $(BUILD_DIR)/build_config.txt
# C uses BSP_DTIM_* for bounds checks; linker uses __dtim_* for RAM origin/length.
CFLAGS := -march=$(MARCH) -mabi=$(MABI) -mcmodel=medany -Os -ffreestanding -fno-builtin -fno-common -Wall -Wextra -I$(BSP_DIR)/include -DAPP_FLASH_OFFSET=$(APP_FLASH_OFFSET)UL -DBSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)UL -DBSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)UL -DBSP_DTIM_BASE=$(BSP_DTIM_BASE)UL -DBSP_DTIM_SIZE=$(BSP_DTIM_SIZE)UL
CFLAGS := -march=$(MARCH) -mabi=$(MABI) -mcmodel=medany -Os -ffreestanding -fno-builtin -fno-common -Wall -Wextra -I$(BSP_DIR)/include -DAPP_FLASH_OFFSET=$(APP_FLASH_OFFSET)UL -DBSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)UL -DBSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)UL -DBSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)UL -DBSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE) -DBSP_DTIM_BASE=$(BSP_DTIM_BASE)UL -DBSP_DTIM_SIZE=$(BSP_DTIM_SIZE)UL
LDFLAGS := -T linker.ld -nostdlib -static -Wl,--gc-sections -Wl,--defsym=__dtim_base=$(BSP_DTIM_BASE) -Wl,--defsym=__dtim_size=$(BSP_DTIM_SIZE) -Wl,-Map,$(BUILD_DIR)/$(TARGET).map
SRCS := start.S main.c
@@ -42,6 +44,8 @@ $(CONFIG_STAMP): FORCE | $(BUILD_DIR)
'MABI=$(MABI)' \
'BSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)' \
'BSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)' \
'BSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)' \
'BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
'BSP_DTIM_BASE=$(BSP_DTIM_BASE)' \
'BSP_DTIM_SIZE=$(BSP_DTIM_SIZE)' > "$$tmp"; \
if ! cmp -s "$$tmp" "$@"; then mv "$$tmp" "$@"; else rm "$$tmp"; fi
+50 -9
View File
@@ -17,17 +17,27 @@
#define FLASH_CMD_WRITE_DISABLE 0x04u
#define FLASH_CMD_WRITE_ENABLE 0x06u
#define FLASH_CMD_READ_CONFIG 0x35u
#define FLASH_CMD_CLEAR_STATUS 0x30u
#define FLASH_CMD_RESET 0xf0u
#define FLASH_CMD_READ_4B 0x13u
#define FLASH_CMD_PROGRAM_4B 0x12u
#define FLASH_CMD_ERASE_4B 0xdcu
#define FLASH_STATUS_WIP (1u << 0)
#define FLASH_STATUS_WEL (1u << 1)
#define FLASH_STATUS_E_ERR (1u << 5)
#define FLASH_STATUS_P_ERR (1u << 6)
#define FLASH_STATUS_ERROR (FLASH_STATUS_E_ERR | FLASH_STATUS_P_ERR)
#define FLASH_STATUS_WIP (1u << 0)
#define FLASH_STATUS_WEL (1u << 1)
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
#define FLASH_CMD_CLEAR_STATUS 0x30u
#define FLASH_CMD_RESET 0xf0u
#define FLASH_STATUS_ERROR ((1u << 5) | (1u << 6))
#elif BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_MT25QU01G
#define FLASH_CMD_RESET_ENABLE 0x66u
#define FLASH_CMD_RESET_MEMORY 0x99u
#define FLASH_CMD_READ_FLAG_STATUS 0x70u
#define FLASH_CMD_CLEAR_FLAG_STATUS 0x50u
#define FLASH_FLAG_STATUS_ERROR ((1u << 1) | (1u << 4) | (1u << 5))
#elif BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_IS25WP512M
#define FLASH_CMD_RESET_ENABLE 0x66u
#define FLASH_CMD_RESET_MEMORY 0x99u
#endif
#define FLASH_RESET_DELAY_US 300u
#define FLASH_PROGRAM_TIMEOUT_US 100000u
@@ -104,6 +114,7 @@ static bool flash_wait_complete(uint32_t timeout_us)
do {
status = bsp_spi_flash_read_status();
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
if ((status & FLASH_STATUS_ERROR) != 0u) {
/* S25FL-S deliberately holds WIP high after a program/erase error
* until CLSR is issued. Clear the latched failure so a later request
@@ -111,7 +122,15 @@ static bool flash_wait_complete(uint32_t timeout_us)
flash_cmd(FLASH_CMD_CLEAR_STATUS);
return false;
}
#endif
if ((status & FLASH_STATUS_WIP) == 0u) {
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_MT25QU01G
uint8_t flags = flash_read_register(FLASH_CMD_READ_FLAG_STATUS);
if ((flags & FLASH_FLAG_STATUS_ERROR) != 0u) {
flash_cmd(FLASH_CMD_CLEAR_FLAG_STATUS);
return false;
}
#endif
return true;
}
} while ((bsp_read64(BSP_CLINT_MTIME) - start) < timeout_ticks);
@@ -121,11 +140,20 @@ static bool flash_wait_complete(uint32_t timeout_us)
static bool flash_write_enable(void)
{
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
flash_cmd(FLASH_CMD_CLEAR_STATUS);
#elif BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_MT25QU01G
flash_cmd(FLASH_CMD_CLEAR_FLAG_STATUS);
#endif
flash_cmd(FLASH_CMD_WRITE_ENABLE);
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
return (bsp_spi_flash_read_status() &
(FLASH_STATUS_WIP | FLASH_STATUS_WEL | FLASH_STATUS_ERROR)) ==
FLASH_STATUS_WEL;
#else
return (bsp_spi_flash_read_status() &
(FLASH_STATUS_WIP | FLASH_STATUS_WEL)) == FLASH_STATUS_WEL;
#endif
}
static bool flash_verify(uint32_t flash_addr, const uint8_t *expected,
@@ -156,7 +184,12 @@ void bsp_spi_flash_init(void)
void bsp_spi_flash_reset(void)
{
spi_select(0);
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
flash_cmd(FLASH_CMD_RESET);
#else
flash_cmd(FLASH_CMD_RESET_ENABLE);
flash_cmd(FLASH_CMD_RESET_MEMORY);
#endif
flash_delay_us(FLASH_RESET_DELAY_US);
}
@@ -179,7 +212,11 @@ uint8_t bsp_spi_flash_read_status(void)
uint8_t bsp_spi_flash_read_config(void)
{
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
return flash_read_register(FLASH_CMD_READ_CONFIG);
#else
return 0u;
#endif
}
void bsp_spi_flash_read(uint32_t flash_addr, void *dst, uint32_t len)
@@ -202,9 +239,13 @@ void bsp_spi_flash_read(uint32_t flash_addr, void *dst, uint32_t len)
bool bsp_spi_flash_erase_sector(uint32_t flash_addr)
{
if ((flash_addr & (BSP_SPI_FLASH_SECTOR_SIZE - 1u)) != 0u ||
!flash_range_valid(flash_addr, BSP_SPI_FLASH_SECTOR_SIZE) ||
!flash_range_valid(flash_addr, BSP_SPI_FLASH_SECTOR_SIZE)
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
||
((flash_addr >= (BSP_SPI_FLASH_SIZE - (2u * BSP_SPI_FLASH_SECTOR_SIZE))) &&
((bsp_spi_flash_read_config() & BSP_SPI_FLASH_CONFIG_TBPARM) != 0u))) {
((bsp_spi_flash_read_config() & BSP_SPI_FLASH_CONFIG_TBPARM) != 0u))
#endif
) {
return false;
}
if (!flash_wait_complete(FLASH_PROGRAM_TIMEOUT_US) || !flash_write_enable()) {
+21 -2
View File
@@ -4,10 +4,29 @@
#include <stdbool.h>
#include <stdint.h>
#define BSP_SPI_FLASH_SIZE 0x02000000UL
#define BSP_SPI_FLASH_PROFILE_S25FL256S 1
#define BSP_SPI_FLASH_PROFILE_MT25QU01G 2
#define BSP_SPI_FLASH_PROFILE_IS25WP512M 3
#ifndef BSP_SPI_FLASH_PROFILE
#define BSP_SPI_FLASH_PROFILE BSP_SPI_FLASH_PROFILE_S25FL256S
#endif
#if BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_S25FL256S
#define BSP_SPI_FLASH_SIZE 0x02000000UL
#define BSP_SPI_FLASH_JEDEC_ID 0x00010219UL
#elif BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_MT25QU01G
#define BSP_SPI_FLASH_SIZE 0x08000000UL
#define BSP_SPI_FLASH_JEDEC_ID 0x0020bb21UL
#elif BSP_SPI_FLASH_PROFILE == BSP_SPI_FLASH_PROFILE_IS25WP512M
#define BSP_SPI_FLASH_SIZE 0x04000000UL
#define BSP_SPI_FLASH_JEDEC_ID 0x009d701aUL
#else
#error "Unsupported BSP_SPI_FLASH_PROFILE"
#endif
#define BSP_SPI_FLASH_PAGE_SIZE 256UL
#define BSP_SPI_FLASH_SECTOR_SIZE 0x00010000UL
#define BSP_SPI_FLASH_JEDEC_ID 0x00010219UL
#define BSP_SPI_FLASH_CONFIG_TBPARM (1u << 2)
void bsp_spi_flash_init(void);
+3 -1
View File
@@ -15,12 +15,13 @@ MABI ?= lp64d
BSP_UART_CLOCK_HZ ?= 100000000
BSP_UART_BAUDRATE ?= 460800
BSP_CLINT_TIMEBASE_HZ ?= 1000000
BSP_SPI_FLASH_PROFILE ?= 1
BSP_DTIM_BASE ?= 0x80000000
BSP_DTIM_SIZE ?= 0x00100000
CONFIG_STAMP := $(BUILD_DIR)/build_config.txt
# C sees BSP_DTIM_* while ld sees __dtim_*; both come from the same Makefile knobs.
CFLAGS ?= -march=$(MARCH) -mabi=$(MABI) -mcmodel=medany -Os -ffreestanding -fno-builtin -fno-common -Wall -Wextra -I$(BSP_DIR)/include -DBSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)UL -DBSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)UL -DBSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)UL -DBSP_DTIM_BASE=$(BSP_DTIM_BASE)UL -DBSP_DTIM_SIZE=$(BSP_DTIM_SIZE)UL
CFLAGS ?= -march=$(MARCH) -mabi=$(MABI) -mcmodel=medany -Os -ffreestanding -fno-builtin -fno-common -Wall -Wextra -I$(BSP_DIR)/include -DBSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)UL -DBSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)UL -DBSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)UL -DBSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE) -DBSP_DTIM_BASE=$(BSP_DTIM_BASE)UL -DBSP_DTIM_SIZE=$(BSP_DTIM_SIZE)UL
LDFLAGS ?= -T $(LINKER_SCRIPT) -nostartfiles -static -Wl,--gc-sections -Wl,--defsym=__dtim_base=$(BSP_DTIM_BASE) -Wl,--defsym=__dtim_size=$(BSP_DTIM_SIZE) -Wl,-Map,$(BUILD_DIR)/$(TARGET).map
LDLIBS ?= -Wl,--start-group -lc -lgcc -Wl,--end-group
@@ -47,6 +48,7 @@ $(CONFIG_STAMP): FORCE | $(BUILD_DIR)
'BSP_UART_CLOCK_HZ=$(BSP_UART_CLOCK_HZ)' \
'BSP_UART_BAUDRATE=$(BSP_UART_BAUDRATE)' \
'BSP_CLINT_TIMEBASE_HZ=$(BSP_CLINT_TIMEBASE_HZ)' \
'BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
'BSP_DTIM_BASE=$(BSP_DTIM_BASE)' \
'BSP_DTIM_SIZE=$(BSP_DTIM_SIZE)' \
'GPS_DEBUG=$(GPS_DEBUG)' \
+4
View File
@@ -102,7 +102,9 @@ GPS_EPHEMERIS_FLASH_ENABLE ?= 1
GPS_EPHEMERIS_STORE_MAX_SLOTS ?= 0
GPS_EPHEMERIS_FLASH_FORCE_FORMAT ?= 0
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
GPS_EPHEMERIS_FLASH_BASE ?= 0x01fe0000
GPS_NAV_CONTEXT_ENABLE ?= 1
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x01fc0000
GPS_PPS_STATUS_LOG_INTERVAL ?= 10
GPS_PPS_DOPPLER_PREDICTOR_ENABLE ?= 1
GPS_PPS_DOPPLER_PREDICTOR_AB_UPDATES ?= 0
@@ -123,7 +125,9 @@ CFLAGS += $(IMU_BACKEND_CFLAG) \
-DGPS_EPHEMERIS_STORE_MAX_SLOTS=$(GPS_EPHEMERIS_STORE_MAX_SLOTS)u \
-DGPS_EPHEMERIS_FLASH_FORCE_FORMAT=$(GPS_EPHEMERIS_FLASH_FORCE_FORMAT) \
-DGPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL) \
-DGPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)UL \
-DGPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE) \
-DGPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)UL \
-DGPS_PPS_STATUS_LOG_INTERVAL=$(GPS_PPS_STATUS_LOG_INTERVAL) \
-DGPS_PPS_DOPPLER_PREDICTOR_ENABLE=$(GPS_PPS_DOPPLER_PREDICTOR_ENABLE) \
-DGPS_PPS_DOPPLER_PREDICTOR_AB_UPDATES=$(GPS_PPS_DOPPLER_PREDICTOR_AB_UPDATES)
@@ -144,10 +144,9 @@
* 20 ms navigation bit; at a few ppm the 15 minute bound leaves
* roughly two orders of magnitude of margin, and broadcast
* ephemeris validity caps reuse well before that anyway. */
/* Persistent ephemeris cache. The Genesys2 image places the
* bitstream at 0 and the application at 0x01800000 on a 32 MiB
* S25FL256S, so the last two 64 KiB sectors are free. Keeping the
* store at the very top leaves the application region free to grow. */
/* Persistent ephemeris cache. Board Makefiles place this store in
* two reserved 64 KiB sectors near the top of the selected flash.
* The defaults describe the 32 MiB Genesys2 layout. */
#ifndef GPS_EPHEMERIS_FLASH_ENABLE
#define GPS_EPHEMERIS_FLASH_ENABLE 1
#endif
@@ -170,8 +169,8 @@
/*
* Persistent navigation context (almanac, ionosphere model, last
* position) in the two 64 KiB sectors immediately below the
* ephemeris store. The application image lives at 0x01800000 and
* is far smaller than the gap.
* ephemeris store. Board Makefiles override both bases together for
* larger flash devices.
*/
#ifndef GPS_NAV_CONTEXT_FLASH_BASE
#define GPS_NAV_CONTEXT_FLASH_BASE 0x01FC0000UL
@@ -16,6 +16,30 @@
#include <math.h>
#include <string.h>
#if (GPS_EPHEMERIS_FLASH_ENABLE == 1)
_Static_assert((GPS_EPHEMERIS_FLASH_BASE % BSP_SPI_FLASH_SECTOR_SIZE) == 0u,
"ephemeris flash base must be sector aligned");
_Static_assert(GPS_EPHEMERIS_FLASH_BASE <=
(BSP_SPI_FLASH_SIZE - (2u * BSP_SPI_FLASH_SECTOR_SIZE)),
"ephemeris store exceeds selected flash");
#endif
#if (GPS_NAV_CONTEXT_ENABLE == 1)
_Static_assert((GPS_NAV_CONTEXT_FLASH_BASE % BSP_SPI_FLASH_SECTOR_SIZE) == 0u,
"navigation context flash base must be sector aligned");
_Static_assert(GPS_NAV_CONTEXT_FLASH_BASE <=
(BSP_SPI_FLASH_SIZE - (2u * BSP_SPI_FLASH_SECTOR_SIZE)),
"navigation context store exceeds selected flash");
#endif
#if ((GPS_EPHEMERIS_FLASH_ENABLE == 1) && (GPS_NAV_CONTEXT_ENABLE == 1))
_Static_assert((GPS_NAV_CONTEXT_FLASH_BASE +
(2u * BSP_SPI_FLASH_SECTOR_SIZE) <=
GPS_EPHEMERIS_FLASH_BASE) ||
(GPS_EPHEMERIS_FLASH_BASE +
(2u * BSP_SPI_FLASH_SECTOR_SIZE) <=
GPS_NAV_CONTEXT_FLASH_BASE),
"persistent flash stores overlap");
#endif
typedef enum {
GPS_ISR_EVENT_ACQ_DONE = 0,
GPS_ISR_EVENT_TRK_STATUS
+11 -2
View File
@@ -72,7 +72,10 @@ GPS_DEBUG_LEVEL ?= 1
GPS_ESKF_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
GPS_EPHEMERIS_FLASH_BASE ?= 0x01fe0000
GPS_NAV_CONTEXT_ENABLE ?= 1
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x01fc0000
BSP_SPI_FLASH_PROFILE ?= 1
IMU_SENSOR ?= auto
FLASH_MCS ?= $(OUT_DIR)/flash/genesys2_rocket.mcs
@@ -180,7 +183,10 @@ help:
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
' IMU_SENSOR=$(IMU_SENSOR)' \
' UART_PORT=$(UART_PORT)' \
' ETH_RF_IFACE=$(ETH_RF_IFACE)' \
@@ -222,17 +228,20 @@ fpga-config:
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
' IMU_SENSOR=$(IMU_SENSOR)' \
' ETH_RF_IFACE=$(ETH_RF_IFACE)' \
' ETH_RF_INPUT=$(ETH_RF_INPUT)' \
' ETH_RF_SAMPLE_FORMAT=$(ETH_RF_SAMPLE_FORMAT)'
software:
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
$(APP_ELF): FORCE
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" app
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" app
chisel: software
@cd "$(REPO_DIR)"
@@ -1,24 +0,0 @@
#-----------------------------------------------------------
# Vivado v2025.2 (64-bit)
# SW Build 6299465 on Fri Nov 14 12:34:56 MST 2025
# IP Build 6300035 on Fri Nov 14 10:48:45 MST 2025
# SharedData Build 6298862 on Thu Nov 13 04:50:51 MST 2025
# Start of session at: Tue Jul 7 01:14:33 2026
# Process ID : 505349
# Current directory : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream
# Command line : vivado
# Log file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.log
# Journal file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.jou
# Running On : onur
# Platform : Ubuntu
# Operating System : Ubuntu 22.04.5 LTS
# Processor Detail : AMD Ryzen 7 7800X3D 8-Core Processor
# CPU Frequency : 4199.900 MHz
# CPU Physical cores : 12
# CPU Logical cores : 12
# Host memory : 22112 MB
# Swap memory : 2147 MB
# Total Virtual : 24260 MB
# Available Virtual : 20472 MB
#-----------------------------------------------------------
start_gui
@@ -1,118 +0,0 @@
#-----------------------------------------------------------
# Vivado v2025.2 (64-bit)
# SW Build 6299465 on Fri Nov 14 12:34:56 MST 2025
# IP Build 6300035 on Fri Nov 14 10:48:45 MST 2025
# SharedData Build 6298862 on Thu Nov 13 04:50:51 MST 2025
# Start of session at: Tue Jul 7 01:14:33 2026
# Process ID : 505349
# Current directory : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream
# Command line : vivado
# Log file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.log
# Journal file : /home/onur/Desktop/tmp/rocket-chip/targets/fpga/genesys2/out/bitstream/vivado.jou
# Running On : onur
# Platform : Ubuntu
# Operating System : Ubuntu 22.04.5 LTS
# Processor Detail : AMD Ryzen 7 7800X3D 8-Core Processor
# CPU Frequency : 4199.900 MHz
# CPU Physical cores : 12
# CPU Logical cores : 12
# Host memory : 22112 MB
# Swap memory : 2147 MB
# Total Virtual : 24260 MB
# Available Virtual : 20472 MB
#-----------------------------------------------------------
start_gui
Sourcing tcl script '/home/onur/.Xilinx/Vivado/Vivado_init.tcl'
Configured Digilent board repo: /home/onur/.local/share/digilent-vivado-boards/new/board_files
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_3eg:part0:1.0 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-3eg/B.0/board.xml as part xczu3eg-sfvc784-1-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_3eg:part0:1.1 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-3eg/D.0/board.xml as part xczu3eg-sfvc784-1-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part digilentinc.com:gzu_5ev:part0:1.1 available at /home/onur/.local/share/digilent-vivado-boards/new/board_files/genesys-zu-5ev/C.0/board.xml as part xczu5ev-sfvc784-1-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:emb-plus-vpr-4616:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/emb-plus-vpr-4616/1.0/board.xml as part xcve2302-sfva784-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:emb-plus-vpr-4616:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/emb-plus-vpr-4616/1.1/board.xml as part xcve2302-sfva784-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24c:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24c/1.0/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24c:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24c/1.1/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k24i:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k24i/1.0/board.xml as part xck24-ubva530-2lvi-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.2/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.3/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26c:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26c/1.4/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.2/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.3/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:k26i:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/k26i/1.4/board.xml as part xck26-sfvc784-2lvi-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu105:part0:1.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu105/1.6/board.xml as part xcku040-ffva1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu105:part0:1.7 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu105/1.7/board.xml as part xcku040-ffva1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu116:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu116/1.4/board.xml as part xcku5p-ffvb676-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu116:part0:1.5 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu116/1.5/board.xml as part xcku5p-ffvb676-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kcu1500:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kcu1500/1.2/board.xml as part xcku115-flvb2104-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kd240_som:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kd240_som/1.0/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kd240_som:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kd240_som/1.1/board.xml as part xck24-ubva530-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kr260_som:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kr260_som/1.0/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kr260_som:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kr260_som/1.1/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.2/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.3/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:kv260_som:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/kv260_som/1.4/board.xml as part xck26-sfvc784-2lv-c specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:scu35:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/scu35/1.0/board.xml as part xcsu35p-sbvb625-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:v80:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/v80/1.0/board.xml as part xcv80-lsva4737-2mhp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:2.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/2.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.0/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.1/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.3/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190:part0:3.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190/production/3.4/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.0/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.1/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.2/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vck190_newl:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vck190_newl/production/1.3/board.xml as part xcvc1902-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu108:part0:1.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu108/1.6/board.xml as part xcvu095-ffva2104-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu108:part0:1.7 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu108/1.7/board.xml as part xcvu095-ffva2104-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu110:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu110/1.4/board.xml as part xcvu190-flgc2104-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.0/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.3/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu118:part0:2.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu118/2.4/board.xml as part xcvu9p-flga2104-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu128:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu128/production/1.0/board.xml as part xcvu37p-fsvh2892-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu129:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu129/production/1.0/board.xml as part xcvu29p-fsga2577-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vcu1525:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vcu1525/1.3/board.xml as part xcvu9p-fsgd2104-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.0/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.1/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek280:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek280/production/1.2/board.xml as part xcve2802-vsvh1760-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385/1.0/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385/1.1/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vek385_1:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vek385_2/1.0/board.xml as part xc2ve3858-ssva2112-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vermeo_t1_mpsoc:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vermeo_t1_mpsoc/1.0/board.xml as part xczu19eg-ffvd1760-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vermeo_t1_rfsoc:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vermeo_t1_rfsoc/1.0/board.xml as part xczu21dr-ffvd1156-2l-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.0/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.1/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vhk158:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vhk158/production/1.2/board.xml as part xcvh1582-vsva3697-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:2.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/2.2/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.0/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.1/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.2/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180/production/3.3/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180_newl:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180_newl/production/1.0/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vmk180_newl:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vmk180_newl/production/1.1/board.xml as part xcvm1802-vsva2197-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.0/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.1/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk120:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk120/production/1.2/board.xml as part xcvp1202-vsva2785-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.0/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.1/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vpk180:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vpk180/production/1.2/board.xml as part xcvp1802-lsvc4072-2mp-e-s specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vrk160:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vrk160/1.0/board.xml as part xcvr1602-vsva2488-2mp-e-s-es1 specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:vrk160:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/vrk160/1.1/board.xml as part xcvr1602-vsva2488-2mp-e-s-es1 specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu102:part0:3.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu102/3.3/board.xml as part xczu9eg-ffvb1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu102:part0:3.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu102/3.4/board.xml as part xczu9eg-ffvb1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu104:part0:1.1 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu104/1.1/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.4/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.5 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.5/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu106:part0:2.6 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu106/2.6/board.xml as part xczu7ev-ffvc1156-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.2 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.2/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.3 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.3/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu111:part0:1.4 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu111/1.4/board.xml as part xczu28dr-ffvg1517-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu1275:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu1275/1.0/board.xml as part xczu29dr-ffvf1760-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu1285:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu1285/1.0/board.xml as part xczu39dr-ffvf1760-2-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu208:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu208/production/2.0/board.xml as part xczu48dr-fsvg1517-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu208ld:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu208ld/production/2.0/board.xml as part xczu58dr-fsvg1517-2-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu216:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu216/production/2.0/board.xml as part xczu49dr-ffvf1760-2-e specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu216ld:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu216ld/production/2.0/board.xml as part xczu59dr-ffvf1760-2-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu670:part0:2.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu670/2.0/board.xml as part xczu67dr-fsve1156-2-i specified in board_part file is either invalid or not available
WARNING: [Board 49-26] cannot add Board Part xilinx.com:zcu670ld:part0:1.0 available at /tools/Xilinx/2025.2/data/xhub/boards/XilinxBoardStore/boards/Xilinx/zcu670ld/1.0/board.xml as part xczu57dr-fsve1156-2-i specified in board_part file is either invalid or not available
exit
INFO: [Common 17-206] Exiting Vivado at Tue Jul 7 01:14:42 2026...
+12
View File
@@ -0,0 +1,12 @@
/out/
/flow/efinity/ti375c529_rocket.isf
/flow/efinity/ti375c529_rocket.peri.xml
/flow/efinity/ti375c529_rocket.pt.sdc
/flow/efinity/ti375c529_rocket.pt.rpt
/flow/efinity/ti375c529_rocket.pinout.*
/flow/efinity/ti375c529_rocket.interface.csv
/flow/efinity/ti375c529_rocket_template.v
/flow/efinity/outflow/
/flow/efinity/work_pnr/
/flow/efinity/work_syn/
/flow/efinity/RUNPNR_*
+438
View File
@@ -0,0 +1,438 @@
SHELL := /bin/bash
.SHELLFLAGS := -euo pipefail -c
.ONESHELL:
FPGA_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
REPO_DIR := $(abspath $(FPGA_DIR)/../../..)
SOC_SW_DIR := $(REPO_DIR)/soc/software
SOC_OUT_DIR := $(REPO_DIR)/soc/out
HW_DIR := $(REPO_DIR)/hardware
HW_GENERATED_DIR := $(HW_DIR)/generated
GPS_SYSTEM_DIR ?= $(HW_DIR)/external/gps/rtl
FLOW_DIR := $(FPGA_DIR)/flow/efinity
DEBUG_DIR := $(FPGA_DIR)/flow/debug
TOOL_SCRIPT_DIR := $(FPGA_DIR)/tools
OUT_DIR := $(FPGA_DIR)/out
LOG_DIR := $(OUT_DIR)/logs
include $(REPO_DIR)/tools/project.mk
BOARD ?= ti375c529
DEVICE ?= Ti375C529
TIMING_MODEL ?= C4
SOC_CLK_HZ ?= 100000000
GPS_ACQ_CLK_HZ ?= 100000000
GPS_TRCK_CLK_HZ ?= 125000000
GPS_RF_CLK_HZ ?= 16367981
RF_INPUT_MODE ?= pmod
UART_PORT ?= /dev/ttyUSB2
UART_BAUD ?= 460800
OPENOCD ?= $(shell command -v openocd)
OPENOCD_ADAPTER_SPEED ?= 1000
GDB_HOST ?= localhost
GDB_PORT ?= 3333
GDB ?= $(firstword $(wildcard /tools/toolchain/bin/riscv64-unknown-elf-gdb) $(CROSS)gdb)
# Leave empty for Efinity's board-profile auto-detection. Boards without an
# FTDI serial number require a bus/device-qualified URL, which changes after
# re-enumeration; users with multiple boards can override this explicitly.
FTDI_URL ?=
BSP_UART_CLOCK_HZ ?= $(SOC_CLK_HZ)
BSP_UART_BAUDRATE ?= $(UART_BAUD)
BSP_CLINT_TIMEBASE_HZ ?= 1000000
DTIM_BASE ?= 0x80000000
DTIM_SIZE ?= 0x00100000
# The compressed Ti375 configuration currently occupies about 5.2 MB.
# Keep the application on a 64-KiB boundary with ample growth margin.
APP_FLASH_OFFSET ?= 0x00800000
FLASH_SIZE ?= 0x04000000
GPS_DEBUG ?= 1
GPS_DEBUG_LEVEL ?= 4
GPS_ESKF_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
GPS_EPHEMERIS_FLASH_BASE ?= 0x03fe0000
GPS_NAV_CONTEXT_ENABLE ?= 1
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x03fc0000
BSP_SPI_FLASH_PROFILE ?= 3
IMU_SENSOR ?= auto
app ?=
ifneq ($(strip $(app)),)
APP ?= $(app)
else
APP ?= hello_uart
endif
FIRRTL_DIR ?= $(HW_GENERATED_DIR)/ti375c529-soc
VERILOG_DIR ?= $(HW_GENERATED_DIR)/ti375c529-soc-verilog
WRAPPER := $(OUT_DIR)/build/generated/ti375c529_rocket_top.sv
GPS_EFINITY_DIR := $(OUT_DIR)/build/generated/gps_efinity
SOURCE_LIST := $(OUT_DIR)/build/efinity_sources.f
PROJECT_XML := $(FLOW_DIR)/ti375c529_rocket.xml
INTERFACE_SOURCE := $(HW_DIR)/fpga/ti375c529/constraints/ti375c529_rocket.isf
INTERFACE_SCRIPT := $(FLOW_DIR)/ti375c529_rocket.isf
BIT_FILE ?= $(OUT_DIR)/bitstream/ti375c529_rocket.bit
CONFIG_HEX ?= $(OUT_DIR)/bitstream/ti375c529_rocket.hex
APP_ELF ?= $(SOC_OUT_DIR)/software/$(APP)/$(APP).elf
APP_FLASH_IMAGE ?= $(SOC_OUT_DIR)/flash/$(APP).flash.bin
FLASH_DIR := $(OUT_DIR)/flash
FLASH_REGION_DIR := $(FLASH_DIR)/regions
APP_HEX ?= $(FLASH_REGION_DIR)/app.hex
FLASH_HEX ?= $(FLASH_DIR)/ti375c529_rocket.hex
FLASH_MANIFEST ?= $(FLASH_DIR)/ti375c529_rocket.json
FLASH_LOADER ?= $(EFINITY_HOME)/pgm/fli/titanium/u006A0A79.bit
FLASH_VERIFY ?= onchipx2
OPENOCD_CFG ?= $(DEBUG_DIR)/openocd_ti375c529_bscan.cfg
GDB_LOAD_SCRIPT ?= $(DEBUG_DIR)/gdb_load_and_run.gdb
GDB_ATTACH_SCRIPT ?= $(DEBUG_DIR)/gdb_attach.gdb
.PHONY: help all fpga-config detect software chisel rtl soc interface map bitstream \
program-fpga debug-openocd debug-load debug-gdb uart-listen \
flash-image flash-regions program-flash program-flash-elf \
program-flash-bitstream program-flash-regions program-flash-all \
program-flash-combined program-flash-loader program-app program-bitstream \
clean clean-sw clean-fpga FORCE
help:
@printf '%s\n' \
'Ti375C529 Efinity targets:' \
' make detect Scan USB and read the Ti375 JTAG IDCODE' \
' make software Build the Rocket boot ROM and selected RV64 app' \
' make chisel Emit Rocket FIRRTL with the existing FPGA config' \
' make rtl Emit split SystemVerilog, Efinix shell, and file list' \
' make interface Generate Efinity pin/PLL/JTAG interface data' \
' make map Run Efinity synthesis only' \
' make bitstream Run the complete Efinity flow' \
' make program-fpga Load BIT_FILE into Ti375 SRAM over JTAG' \
' make flash-image Generate combined Lower-flash Efinity HEX' \
' make program-flash Program only the application flash region' \
' make program-flash-bitstream' \
' Program only the configuration region' \
' make program-flash-combined' \
' Program configuration + application HEX' \
' make debug-openocd Start Rocket DMI/GDB server through JTAG_USER1' \
' make debug-load Load APP ELF into DTIM through GDB' \
' make uart-listen Listen to FTDI UART interface 2' \
' make fpga-config Print resolved tools, clocks, files, and USB config'
all: bitstream
fpga-config:
@printf '%s\n' \
'Ti375C529 FPGA config:' \
' EFINITY_HOME=$(EFINITY_HOME)' \
' EFX_RUN=$(EFX_RUN)' \
' EFX_PGM=$(EFX_PGM)' \
' OPENOCD=$(OPENOCD)' \
' GDB=$(GDB)' \
' DEVICE=$(DEVICE)' \
' TIMING_MODEL=$(TIMING_MODEL)' \
' SOC_CLK_HZ=$(SOC_CLK_HZ)' \
' GPS_ACQ_CLK_HZ=$(GPS_ACQ_CLK_HZ)' \
' GPS_TRCK_CLK_HZ=$(GPS_TRCK_CLK_HZ)' \
' GPS_RF_CLK_HZ=$(GPS_RF_CLK_HZ)' \
' RF_INPUT_MODE=$(RF_INPUT_MODE)' \
' BIT_FILE=$(BIT_FILE)' \
' CONFIG_HEX=$(CONFIG_HEX)' \
' FLASH_HEX=$(FLASH_HEX)' \
' APP_FLASH_OFFSET=$(APP_FLASH_OFFSET)' \
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
' FLASH_LOADER=$(FLASH_LOADER)' \
' FTDI_URL=$(FTDI_URL)' \
' UART_PORT=$(UART_PORT)' \
' UART_BAUD=$(UART_BAUD)'
detect:
@set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
"$(EFX_PGM)" --scan_usb
software:
@$(MAKE) -C "$(SOC_SW_DIR)" \
TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" \
APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" \
BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" \
BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
GPS_SYSTEM_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" \
BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" \
GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" \
GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" \
GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" \
GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" \
GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" \
GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" \
GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" \
BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" \
IMU_SENSOR="$(IMU_SENSOR)" \
bootloader flash-image
$(APP_ELF): FORCE
@$(MAKE) -C "$(SOC_SW_DIR)" \
TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" \
BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" \
BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
GPS_SYSTEM_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" \
BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" \
BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" \
GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" \
GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" \
GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" \
GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" \
GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" \
GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" \
GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" \
BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" \
IMU_SENSOR="$(IMU_SENSOR)" app
chisel: software
@cd "$(REPO_DIR)"
"$(MILL)" -i 'rocketchip[6.7.0].assembly'
rm -rf "$(FIRRTL_DIR)"
mkdir -p "$(FIRRTL_DIR)"
"$(JAVA_HOME)/bin/java" \
-DROCKET_DTIM_BASE="$(DTIM_BASE)" \
-DROCKET_DTIM_SIZE="$(DTIM_SIZE)" \
-DROCKET_SOC_CLOCK_HZ="$(SOC_CLK_HZ)" \
-jar out/rocketchip/6.7.0/assembly.dest/out.jar \
--dir "$(FIRRTL_DIR)" \
--top freechips.rocketchip.fpga.VCU118RocketSystem \
--config freechips.rocketchip.fpga.VCU118RocketConfig
rtl: chisel
@cd "$(REPO_DIR)"
rm -rf "$(VERILOG_DIR)"
mkdir -p "$(VERILOG_DIR)" "$(dir $(WRAPPER))"
$(FIRTOOL_ENV) "$(FIRTOOL)" \
"$(FIRRTL_DIR)/VCU118RocketSystem.fir" \
--split-verilog -o "$(VERILOG_DIR)" \
--preserve-aggregate=none \
--disable-annotation-unknown \
--disable-all-randomization \
--strip-debug-info
find "$(VERILOG_DIR)" -maxdepth 1 -type f \( -name '*.sv' -o -name '*.v' \) \
-printf './%f\n' | sort > "$(VERILOG_DIR)/filelist.f"
perl -0pi -e 's/^([ \t]*)if \([^\n]*\)\n[ \t]*assert__[^\n]*:\s*assert\([^\n]*\);\n//mg; s/^[ \t]*assert__[^\n]*:\s*assert\([^\n]*\);\n//mg' "$(VERILOG_DIR)"/*.sv
python3 "$(TOOL_SCRIPT_DIR)/prepare_efinity_rtl.py" \
--verilog-dir "$(VERILOG_DIR)" \
--gps-source-dir "$(GPS_SYSTEM_DIR)" \
--gps-output-dir "$(GPS_EFINITY_DIR)"
python3 "$(TOOL_SCRIPT_DIR)/gen_ti375c529_wrapper.py" \
--rocket-top "$(VERILOG_DIR)/VCU118RocketSystem.sv" \
--out "$(WRAPPER)"
: > "$(SOURCE_LIST)"
while IFS= read -r rel; do
rel="$${rel#./}"
printf '%s\n' "$(VERILOG_DIR)/$$rel" >> "$(SOURCE_LIST)"
done < "$(VERILOG_DIR)/filelist.f"
printf '%s\n' "$(HW_DIR)/upstream/rocket-chip/src/main/resources/vsrc/plusarg_reader.v" >> "$(SOURCE_LIST)"
while IFS= read -r rel; do
[[ -z "$$rel" || "$$rel" == \#* ]] && continue
case "$$rel" in
trck_src/xil_fifo.sv|trck_src/pulp_fifo/top.sv) continue ;;
acq_src/acq_nco_carr.sv)
printf '%s\n' "$(GPS_EFINITY_DIR)/acq_nco_carr.sv" >> "$(SOURCE_LIST)"
continue ;;
acq_src/twiddle_ram.sv)
printf '%s\n' "$(GPS_EFINITY_DIR)/twiddle_ram.sv" >> "$(SOURCE_LIST)"
continue ;;
trck_src/NCO_carr.sv)
printf '%s\n' "$(GPS_EFINITY_DIR)/NCO_carr.sv" >> "$(SOURCE_LIST)"
continue ;;
esac
printf '%s\n' "$(GPS_SYSTEM_DIR)/$$rel" >> "$(SOURCE_LIST)"
done < "$(GPS_SYSTEM_DIR)/filelist.f"
printf '%s\n' "$(HW_DIR)/ip/max2771_spi/rtl/max2771_spi_engine.sv" >> "$(SOURCE_LIST)"
# Efinix JTAG_USER1 has the same two-bit TDO lead-in as the Kintex-7
# BSCANE2 path, so use the Genesys2-aligned Rocket DMI tunnel.
printf '%s\n' "$(HW_DIR)/fpga/genesys2/rtl/rocket_bscan_dmi_tunnel.sv" >> "$(SOURCE_LIST)"
$(MAKE) -C "$(FPGA_DIR)" "$(INTERFACE_SCRIPT)"
soc: rtl
$(INTERFACE_SCRIPT): $(INTERFACE_SOURCE)
cp "$<" "$@"
interface: $(INTERFACE_SCRIPT)
@mkdir -p "$(LOG_DIR)"
cd "$(FLOW_DIR)"
# Efinity prefers a matching generated .peri.xml over the source .isf.
# Remove it so pin/PLL changes in the checked-in interface script are applied.
rm -f "$(FLOW_DIR)/ti375c529_rocket.peri.xml"
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow interface --un_flow \
--pt_opts "peri_scripts=$(INTERFACE_SCRIPT)" 2>&1 | tee "$(LOG_DIR)/interface.log"
map: rtl interface
@mkdir -p "$(LOG_DIR)"
cd "$(FLOW_DIR)"
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee "$(LOG_DIR)/map.log"
bitstream: rtl interface
@mkdir -p "$(LOG_DIR)" "$(dir $(BIT_FILE))"
cd "$(FLOW_DIR)"
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
: > "$(LOG_DIR)/full.log"
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow map 2>&1 | tee -a "$(LOG_DIR)/full.log"
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow pnr --work_dir work_pnr 2>&1 | tee -a "$(LOG_DIR)/full.log"
python3 "$(EFX_RUN)" "$(PROJECT_XML)" --flow pgm --work_dir work_pnr 2>&1 | tee -a "$(LOG_DIR)/full.log"
generated_bit="$$(find "$(FLOW_DIR)/outflow" "$(OUT_DIR)" -type f -name 'ti375c529_rocket.bit' 2>/dev/null | head -n 1)"
if [[ -z "$$generated_bit" ]]; then
echo "Efinity completed without a discoverable ti375c529_rocket.bit" >&2
exit 1
fi
if [[ "$$generated_bit" != "$(BIT_FILE)" ]]; then
cp "$$generated_bit" "$(BIT_FILE)"
fi
generated_hex="$$(find "$(FLOW_DIR)/outflow" "$(OUT_DIR)" -type f -name 'ti375c529_rocket.hex' ! -path '$(FLASH_DIR)/*' 2>/dev/null | head -n 1)"
if [[ -z "$$generated_hex" ]]; then
echo "Efinity completed without a discoverable ti375c529_rocket.hex" >&2
exit 1
fi
if [[ "$$generated_hex" != "$(CONFIG_HEX)" ]]; then
cp "$$generated_hex" "$(CONFIG_HEX)"
fi
printf 'Bitstream: %s\nConfiguration HEX: %s\n' "$(BIT_FILE)" "$(CONFIG_HEX)"
program-fpga:
@if [[ ! -f "$(BIT_FILE)" ]]; then
echo "Missing bitstream: $(BIT_FILE)" >&2
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
exit 1
fi
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
ftdi_args=()
if [[ -n "$(FTDI_URL)" ]]; then
ftdi_args+=(--url "$(FTDI_URL)")
fi
"$(EFX_PGM)" --mode jtag "$${ftdi_args[@]}" "$(BIT_FILE)"
debug-openocd:
@"$(OPENOCD)" \
-c "set ADAPTER_SPEED $(OPENOCD_ADAPTER_SPEED)" \
-c "gdb_port $(GDB_PORT)" \
-f "$(OPENOCD_CFG)"
debug-load: $(APP_ELF)
@"$(GDB)" -q "$(APP_ELF)" \
-ex "set confirm off" \
-ex "set pagination off" \
-ex "target extended-remote $(GDB_HOST):$(GDB_PORT)" \
-x "$(GDB_LOAD_SCRIPT)"
debug-gdb: $(APP_ELF)
@"$(GDB)" -q "$(APP_ELF)" \
-ex "set confirm off" \
-ex "set pagination off" \
-ex "target extended-remote $(GDB_HOST):$(GDB_PORT)" \
-x "$(GDB_ATTACH_SCRIPT)"
uart-listen:
@stty -F "$(UART_PORT)" "$(UART_BAUD)" cs8 -cstopb -parenb -ixon -ixoff raw
@cat "$(UART_PORT)"
flash-image: flash-regions
flash-regions: software
@if [[ ! -f "$(CONFIG_HEX)" ]]; then
echo "Missing Efinity configuration HEX: $(CONFIG_HEX)" >&2
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
exit 1
fi
mkdir -p "$(FLASH_DIR)" "$(FLASH_REGION_DIR)"
python3 "$(TOOL_SCRIPT_DIR)/make_flash_hex.py" \
--config-hex "$(CONFIG_HEX)" \
--app-bin "$(APP_FLASH_IMAGE)" \
--app-offset "$(APP_FLASH_OFFSET)" \
--flash-size "$(FLASH_SIZE)" \
--nav-context-offset "$(GPS_NAV_CONTEXT_FLASH_BASE)" \
--ephemeris-offset "$(GPS_EPHEMERIS_FLASH_BASE)" \
--combined-hex "$(FLASH_HEX)" \
--app-hex "$(APP_HEX)" \
--manifest "$(FLASH_MANIFEST)"
program-flash-loader:
@if [[ ! -f "$(FLASH_LOADER)" ]]; then
echo "Missing Ti375 JTAG-to-SPI loader: $(FLASH_LOADER)" >&2
exit 1
fi
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
ftdi_args=()
if [[ -n "$(FTDI_URL)" ]]; then
ftdi_args+=(--url "$(FTDI_URL)")
fi
"$(EFX_PGM)" --mode jtag "$${ftdi_args[@]}" "$(FLASH_LOADER)"
program-flash program-flash-elf program-app: flash-regions
@$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
ftdi_args=()
if [[ -n "$(FTDI_URL)" ]]; then
ftdi_args+=(--url "$(FTDI_URL)")
fi
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
--verify_method "$(FLASH_VERIFY)" --address "$(APP_FLASH_OFFSET)" \
"$${ftdi_args[@]}" "$(APP_HEX)"
program-flash-bitstream program-bitstream:
@if [[ ! -f "$(CONFIG_HEX)" ]]; then
echo "Missing Efinity configuration HEX: $(CONFIG_HEX)" >&2
echo "Run: make -C $(FPGA_DIR) bitstream" >&2
exit 1
fi
$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
ftdi_args=()
if [[ -n "$(FTDI_URL)" ]]; then
ftdi_args+=(--url "$(FTDI_URL)")
fi
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
--verify_method "$(FLASH_VERIFY)" --address 0 \
"$${ftdi_args[@]}" "$(CONFIG_HEX)"
program-flash-regions program-flash-all program-flash-combined: flash-image
@$(MAKE) -C "$(FPGA_DIR)" program-flash-loader
set +u
source "$(EFINITY_SETUP)" >/dev/null 2>&1
set -u
ftdi_args=()
if [[ -n "$(FTDI_URL)" ]]; then
ftdi_args+=(--url "$(FTDI_URL)")
fi
"$(EFX_PGM)" --mode jtag_bridge --jtag_bridge_mode all \
--verify_method "$(FLASH_VERIFY)" --address 0 \
"$${ftdi_args[@]}" "$(FLASH_HEX)"
clean-sw:
@$(MAKE) -C "$(SOC_SW_DIR)" clean
clean-fpga:
rm -rf "$(OUT_DIR)" "$(FIRRTL_DIR)" "$(VERILOG_DIR)"
rm -f "$(INTERFACE_SCRIPT)" \
"$(FLOW_DIR)/ti375c529_rocket.peri.xml" \
"$(FLOW_DIR)/ti375c529_rocket.pt.sdc" \
"$(FLOW_DIR)/ti375c529_rocket.pt.rpt"
clean: clean-fpga
FORCE:
+175
View File
@@ -0,0 +1,175 @@
# 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 Efinity under `/tools/efinix/efinity`. Override
`EFINITY_HOME` when another installation is required.
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 |
+12
View File
@@ -0,0 +1,12 @@
Board name: Efinix Titanium Ti375 C529 Development Kit
Official link: https://www.efinixinc.com/products-devkits-titaniumti375c529.html
FPGA device: Ti375C529
Efinity family: Titanium
Efinity timing model: C4
Initial soft-Rocket flow clocks:
SoC/fabric: 100 MHz from the on-board 100 MHz oscillator
GPS RF: external AX2771 PMOD0/J13 clock, nominally 16.367981 MHz
GPS acquisition: 100 MHz, PLL-derived from the GPS RF clock
GPS tracking: 125 MHz, PLL-derived from the GPS RF clock
@@ -0,0 +1 @@
monitor halt
@@ -0,0 +1,13 @@
monitor halt
monitor reset halt
set $mie = 0
set $mstatus = 0x6000
set {unsigned long long}0x02004000 = 0xffffffffffffffff
load
set $mie = 0
set $mstatus = 0x6000
set $sp = (unsigned long)&_stack_top
set $pc = _start
monitor resume
disconnect
quit
@@ -0,0 +1,62 @@
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -127,6 +127,7 @@
static bscan_tunnel_type_t bscan_tunnel_type;
int bscan_tunnel_ir_width; /* if zero, then tunneling is not present/active */
+static int bscan_tunnel_ir_id; /* outer TAP IR used to access the tunnel */
static const uint8_t bscan_zero[4] = {0};
static const uint8_t bscan_one[4] = {1};
@@ -451,8 +452,12 @@
select_idcode.num_bits = target->tap->ir_length;
if (bscan_tunnel_ir_width != 0) {
- assert(target->tap->ir_length >= 6);
- uint32_t ir_user4_raw = 0x23 << (target->tap->ir_length - 6);
+ uint32_t ir_user4_raw = bscan_tunnel_ir_id;
+ /* Preserve the legacy Xilinx USER4 default when no IR was supplied. */
+ if (ir_user4_raw == 0) {
+ assert(target->tap->ir_length >= 6);
+ ir_user4_raw = 0x23 << (target->tap->ir_length - 6);
+ }
h_u32_to_le(ir_user4, ir_user4_raw);
select_user4.num_bits = target->tap->ir_length;
bscan_tunneled_ir_width[0] = bscan_tunnel_ir_width;
@@ -2859,6 +2864,21 @@
return ERROR_OK;
}
+COMMAND_HANDLER(riscv_set_bscan_tunnel_ir)
+{
+ int ir_id = 0;
+
+ if (CMD_ARGC > 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ if (CMD_ARGC == 1)
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], ir_id);
+
+ LOG_INFO("Bscan tunnel IR 0x%x selected", ir_id);
+ bscan_tunnel_ir_id = ir_id;
+ return ERROR_OK;
+}
+
COMMAND_HANDLER(riscv_set_enable_virt2phys)
{
if (CMD_ARGC != 1) {
@@ -3072,6 +3092,14 @@
"1: DATA_REGISTER}"
},
{
+ .name = "set_bscan_tunnel_ir",
+ .handler = riscv_set_bscan_tunnel_ir,
+ .mode = COMMAND_ANY,
+ .usage = "[value]",
+ .help = "Specify the outer JTAG TAP IR used to access the BSCAN tunnel. "
+ "The default remains the Xilinx FPGA USER4 instruction."
+ },
+ {
.name = "set_enable_virt2phys",
.handler = riscv_set_enable_virt2phys,
.mode = COMMAND_ANY,
@@ -0,0 +1,32 @@
# Rocket debug through the Ti375 hard TAP, JTAG_USER1, and the project's DMI tunnel.
adapter driver ftdi
ftdi vid_pid 0x0403 0x6011
ftdi channel 1
ftdi layout_init 0x08 0x0b
if {![info exists ADAPTER_SPEED]} {
set ADAPTER_SPEED 1000
}
adapter speed $ADAPTER_SPEED
jtag newtap ti375 fpga -expected-id 0x006A0A79 -irlen 5 -ircapture 0x5 -irmask 0xF
target create rocket.cpu riscv -chain-position ti375.fpga -coreid 0
# The outer Ti375 USER1 instruction is 0x08. The inner tunnel implements the
# same 5-bit Rocket DTM IR and framing used by the Xilinx targets.
riscv set_ir dtmcs 0x10
riscv set_ir dmi 0x11
riscv use_bscan_tunnel 5 0
# Ti375 requires an OpenOCD build with the upstream configurable outer BSCAN
# instruction support. Keep the catch only so older builds produce a readable
# diagnostic before their legacy Xilinx-specific BSCAN path rejects this TAP.
if {[catch {riscv set_bscan_tunnel_ir 8}]} {
echo "OpenOCD lacks 'riscv set_bscan_tunnel_ir'; Ti375 requires that command"
}
riscv set_reset_timeout_sec 10
riscv set_command_timeout_sec 10
init
halt
@@ -0,0 +1,328 @@
# Ti375C529 Efinity flow notes
This directory contains the Efinity project for the Ti375C529 development kit.
The port keeps the same RV64 Rocket/GPS subsystem used by the Genesys2 and
VCU118 targets. Only the FPGA shell, clocks, pin constraints, programming flow,
and JTAG transport are vendor-specific. The hardened RV32 subsystem in the
Ti375 device is not used.
## What was added
- Added `ti375c529` to the root FPGA board selection and build targets.
- Added Efinity 2025.2 discovery through `EFINITY_HOME`; the current installation
is `/tools/efinix/efinity/2025.2`.
- Added a generated Ti375 wrapper around `VCU118RocketSystem` so the existing
Rocket, DTIM, UART, GPS acquisition, tracking, PPS, and SPI logic is reused.
- Added the Efinity XML project, interface script, SDC constraints, PLLs, pin
assignments, and JTAG programming target.
- Added FTDI UART operation at 460800 baud. On the current host it enumerates as
`/dev/ttyUSB2`.
- Added host OpenOCD/GDB debug through the Ti375 hard TAP and `JTAG_USER1`.
- Added Efinity-specific generated-RTL rewrites for Rocket's store-data path and
the GPS acquisition/tracking lookup tables that Efinity 2025.2 mis-elaborates.
## Clock structure
The Rocket fabric and GPS processing clocks have separate sources:
- The on-board 100 MHz oscillator drives the fabric PLL and the 100 MHz Rocket
system clock.
- AX2771 `rf_clk` enters through the dedicated global-clock input at J13 pin 10
/ package pin A12 (`GPIOR_95_CLK12`). It is the raw AFE sample clock and feeds
the GPS PLL chain. J13 pins 1, 8, and 9 carry the MAX2771 control bus; pin 1
/ G15 is a PLL input, not a dedicated fabric GCLK input.
- The GPS PLL chain generates 100 MHz acquisition and 125 MHz tracking clocks.
- Acquisition and tracking reset release is gated by the relevant PLL lock
signals.
The four AX2771 data bits use J13 pins 2, 3, 4, and 7, corresponding to package
pins G16, F16, F17, and G17. The AX2771 clock must be jumpered to J13 pin 10.
## Efinity synthesis adaptation
This adaptation does **not** modify Rocket's native/upstream Chisel sources or
the shared GPS SystemVerilog. The normal Chisel and `firtool` stages run first
and emit SystemVerilog into `hardware/generated/ti375c529-soc-verilog/`.
Immediately afterward,
`targets/fpga/ti375c529/tools/prepare_efinity_rtl.py` patches the generated
Ti375 `Rocket.sv` and writes Efinity-only GPS replacements under
`targets/fpga/ti375c529/out/build/generated/gps_efinity/`. The Ti375 source-list
recipe substitutes those generated copies for exactly these three shared GPS
files:
- `acq_src/acq_nco_carr.sv`
- `trck_src/NCO_carr.sv`
- `acq_src/twiddle_ram.sv`
All other GPS RTL remains shared. Efinity consumes the replacements; Genesys2
and VCU118 continue to consume the original GPS files. Deleting either
generated directory and running `make FPGA_BOARD=ti375c529 fpga-rtl` repeats
the same deterministic generation and substitution.
### Rocket store-data path
The CIRCT-generated `Rocket.sv` contains this block-local packed temporary for
store-data byte-lane replication:
```systemverilog
automatic logic [3:0][63:0] _GEN_24 = ...;
mem_reg_rs2 <= _GEN_24[ex_reg_mem_size];
```
Vivado synthesizes this construct correctly. Efinity 2025.2 reports `_GEN_24`
as `VDB-1002: net does not have a driver`, leaving Rocket store data at zero.
This initially looked like a Debug Module failure because abstract GPR/CSR
reads execute a hart instruction that stores the result into Debug Module data
registers. DMI was working, but OpenOCD received zeros and reported the
misleading result `misa=0`.
`../../tools/prepare_efinity_rtl.py` replaces only that generated expression
with an equivalent explicit `case` for byte, half-word, word, and double-word
stores. The script runs automatically after `firtool`; generated RTL is not
edited by hand. After the rewrite, the Rocket `VDB-1002` warning disappears
from the current synthesis run. `ti375c529_rocket.warn.log` is reused by
Efinity and can contain entries from older runs, so the generated source and
the final warning block should be checked together.
The same Efinity limitation also affected the four-entry packed atomic-operation
LUT emitted into generated `TLAtomicAutomata_pbus.sv` and
`TLAtomicAutomata_cbus.sv`. Those `_GEN_4`/`_GEN_13` temporaries select the
TileLink atomic ALU operation; they are unrelated to GPS acquisition but could
break software atomics. The post-generation script rewrites both to an
equivalent four-way `case`. Questa confirmed all four index mappings, and their
`VDB-1002` diagnostics disappear from the current single-run `map.out`.
The exact paths are:
- Generated failing/fixed source:
`hardware/generated/ti375c529-soc-verilog/Rocket.sv`
- Generated TileLink atomic sources:
`hardware/generated/ti375c529-soc-verilog/TLAtomicAutomata_pbus.sv` and
`hardware/generated/ti375c529-soc-verilog/TLAtomicAutomata_cbus.sv`
- Efinity synthesis warning log:
`targets/fpga/ti375c529/flow/efinity/outflow/ti375c529_rocket.warn.log`
- Deterministic repair:
`targets/fpga/ti375c529/tools/prepare_efinity_rtl.py`
- Invocation point:
`targets/fpga/ti375c529/Makefile`, in the `rtl` recipe immediately after
`firtool`
### GPS lookup-table paths
The original acquisition carrier NCO is
`hardware/external/gps/rtl/acq_src/acq_nco_carr.sv`. It initializes the
frequency and pull-in arrays with whole-package-array assignments and builds
its sine table in an `initial` loop using `$sin`. Efinity 2025.2 reports the
loop variable as never assigned and the three arrays as undriven. Stand-alone
post-map comparison confirmed that this is functional, not cosmetic: the
unpatched Efinity netlist produced incorrect sine/cosine samples in all 18,040
tested production-parameter cycles.
The generated Ti375 copy replaces the frequency, pull-in, sine, and cosine
reads with constant functions generated from `definitions.sv`. Questa compared
41 frequency bins, 11 pull-in bins, and 40 cycles per combination: all 18,040
RTL samples and all 18,040 Efinity post-map samples matched the original RTL.
The current full-project synthesis no longer reports the acquisition arrays or
its `$sin` loop as undriven.
The separate tracking carrier NCO is
`hardware/external/gps/rtl/trck_src/NCO_carr.sv`. Its
`sinwav_lut = TRCK_SINWAV_LUT` package-array initializer triggers the same
Efinity `VDB-1002` behavior. The Ti375 copy uses an exact 128-entry constant
function generated from `TRCK_SINWAV_LUT`. Questa matched every table entry at
RTL and then matched 5,000 Efinity post-map cycles while visiting all 128
addresses.
The acquisition FFT twiddle source is
`hardware/external/gps/rtl/acq_src/twiddle_ram.sv`. Its whole-array
`COS_ROM_ARRAY` and `SIN_ROM_ARRAY` assignments are converted only for Ti375 to
two generated, exactly 15-bit-wide `$readmemb` files. Efinity infers 30
`EFX_RAM10` blocks with embedded INIT data. Efinity still emits its generic
`sin_rom/cos_rom does not have a driver` elaboration warning for this recognized
ROM form, but this one is demonstrably benign: Questa matched all 8,192 RTL
addresses and all 8,192 addresses in the Efinity post-map RAM netlist. Check
the current `ti375c529_rocket.map.out` for a single run; the `.warn.log` and
`.info.log` files retain records from older builds and can otherwise make fixed
source paths look current.
## JTAG and OpenOCD
Ti375 and the Xilinx boards expose the same inner Rocket DTM protocol, but the
outer FPGA TAP is different:
| Item | Xilinx flow | Ti375 flow |
|---|---|---|
| Outer TAP IR width | Xilinx-specific | 5 bits |
| User instruction | legacy USER4 handling | `JTAG_USER1 = 0x08` |
| Inner DTM IR width | 5 bits | 5 bits |
| DTMCS / DMI IR | `0x10` / `0x11` | `0x10` / `0x11` |
The host OpenOCD must therefore implement:
```text
riscv set_bscan_tunnel_ir 8
```
A fixed OpenOCD pathname is **not** required. The target Makefile evaluates
`command -v openocd`, so the first compatible patched host binary in `PATH` is
used. Another compatible build can be selected without changing files:
```bash
make FPGA_BOARD=ti375c529 fpga-debug-openocd OPENOCD=/path/to/openocd
```
The original `/usr/local/bin/openocd` 0.12 build assumes the Xilinx USER4
instruction and asserts that the outer TAP IR is at least six bits. It cannot
drive the Ti375 5-bit TAP unchanged. `../debug/openocd-0.12-ti375-bscan.patch`
adds the configurable outer instruction to OpenOCD 0.12. The OpenOCD shipped
with Efinity is not required by this flow.
Apply the patch 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
```
The selected paths can be checked with:
```bash
make FPGA_BOARD=ti375c529 fpga-config
command -v openocd
strings "$(command -v openocd)" | grep set_bscan_tunnel_ir
```
The line `Disabling abstract command reads/writes from CSRs` is informational,
not a failure. OpenOCD falls back to Rocket's Program Buffer for CSR access.
## GDB selection
Software is still compiled with the medany toolchain. That toolchain does not
contain GDB, so the debug target deliberately selects:
```text
/tools/toolchain/bin/riscv64-unknown-elf-gdb
```
This can also be overridden with `GDB=/path/to/riscv64-unknown-elf-gdb`.
## Build, program, and debug
From the repository root:
```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
```
Start the host OpenOCD server in one terminal:
```bash
make FPGA_BOARD=ti375c529 fpga-debug-openocd
```
Load and run an application, then monitor UART, from another terminal:
```bash
make FPGA_BOARD=ti375c529 fpga-debug-load APP=hello_uart
make FPGA_BOARD=ti375c529 fpga-uart
```
## Persistent Lower-flash boot
The kit has Lower and Upper 512-Mbit SPI NOR devices. This port intentionally
uses one MCS-like combined layout in the Lower ISSI IS25WP512 because Efinity's
command-line `jtag_bridge` mode directly addresses that flash:
| Offset | Image |
|---:|---|
| `0x00000000` | Compressed, active-x1 FPGA configuration |
| `0x00800000` | Rocket boot header followed by the application payload |
| `0x03FC0000` | Persistent navigation context (two 64-KiB sectors) |
| `0x03FE0000` | Persistent ephemeris cache (two 64-KiB sectors) |
The application offset is 64-KiB-sector aligned and leaves roughly 3.2 MB
between the current 5,190,596-byte configuration and the firmware region.
`spi_low_power_mode=off` is embedded in the configuration so the Lower flash
stays available when Rocket enters user mode.
Rocket's existing MMIO SPI controller is connected to the configuration pins
after configuration completes:
```text
spi_sck/spi_csn/spi_dq_* -> A7/G6/H4/H5/G5/B7 -> Lower flash U47
```
Generate the configuration, per-application, and combined raw Efinity HEX
files:
```bash
make FPGA_BOARD=ti375c529 fpga-bitstream
make FPGA_BOARD=ti375c529 fpga-mcs APP=hello_uart
```
Outputs are:
- `out/bitstream/ti375c529_rocket.hex`: configuration region
- `out/flash/regions/app.hex`: application region
- `out/flash/ti375c529_rocket.hex`: combined image
- `out/flash/ti375c529_rocket.json`: offsets, sizes, and SHA-256 manifest
Program only the application, only the configuration, or the combined image:
```bash
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
```
The Makefile first loads Efinity's device-matched bridge
`/tools/efinix/efinity/2025.2/pgm/fli/titanium/u006A0A79.bit`, then uses
`jtag_bridge` programming with on-chip verification. A fixed Efinity install
path is not required; `FLASH_LOADER` is derived from `EFINITY_HOME` and can be
overridden.
After bridge programming, the FPGA still contains the bridge design. Power
cycle the kit for a true active-flash boot, or use `fpga-program` to load the
normal design immediately and test the BootROM/application flash path.
## On-board verification
The completed flow was checked on the connected Ti375C529 kit with AX2771
attached:
- Efinity interface, map, PNR, and programming-image stages passed.
- Final patched timing passed with WNS `+0.101 ns` and WHS `+0.021 ns`.
- The Ti375 JTAG IDCODE was read as `0x006a0a79`.
- OpenOCD found one RV64 hart and read `misa=0x800000000080112d`.
- A raw Program Buffer GPR/store test returned `0x5a` through DMI.
- `/tools/toolchain/bin/riscv64-unknown-elf-gdb` loaded 40,880 bytes into DTIM.
- `hello_uart` printed the expected Rocket/DTIM/UART messages at 460800 baud.
- The persistent image passed with setup slack `+0.094 ns` and hold slack
`+0.021 ns`.
- The Lower flash was detected as ISSI IS25WP512, JEDEC `0x9d701a`.
- The combined 8,429,552-byte HEX completed erase, write, readback, and verify.
- BootROM read the payload at `0x00800040`, verified CRC `0xed3bbdf5`, copied
40,880 bytes into DTIM, and ran `hello_uart` without GDB.
- A full board power cycle then configured Ti375 from Lower flash. Host OpenOCD
found the RV64 hart through `JTAG_USER1`; its PC was at
`0x8000017e <_exit>` after `hello_uart` returned, and GDB `compare-sections`
matched the complete ELF `.text` range in DTIM. This confirms cold boot of
both hardware and software without a volatile JTAG/GDB load.
## Relevant files
- `ti375c529_rocket.xml`: Efinity project definition.
- `ti375c529_rocket.isf`: generated/copy of the checked-in interface script.
- `../../../../../hardware/fpga/ti375c529/constraints/`: source interface and SDC
constraints.
- `../../tools/gen_ti375c529_wrapper.py`: Efinix board-shell generator.
- `../../tools/prepare_efinity_rtl.py`: deterministic Rocket and GPS
Efinity-only RTL generation/rewrite.
- `../../tools/make_flash_hex.py`: validated Efinity raw-HEX image builder.
- `../debug/openocd_ti375c529_bscan.cfg`: Ti375 hard-TAP/OpenOCD configuration.
- `../debug/openocd-0.12-ti375-bscan.patch`: host OpenOCD 0.12 compatibility
patch.
@@ -0,0 +1,71 @@
<efx:project xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="ti375c529_rocket" description="RV64 Rocket and GPS on the Ti375C529 development kit" sw_version="2025.2.288.2.10" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd" last_run_state="pass" last_run_flow="bitstream" last_change="1785370142" config_result_in_sync="sync" design_ood="sync" place_ood="sync" route_ood="sync">
<efx:device_info>
<efx:family name="Titanium" />
<efx:device name="Ti375C529" />
<efx:timing_model name="C4" />
</efx:device_info>
<efx:design_info def_veri_version="verilog_2k" def_vhdl_version="vhdl_2008" unified_flow="true">
<efx:top_module name="ti375c529_rocket_top" />
<efx:design_file name="../../out/build/generated/ti375c529_rocket_top.sv" version="default" library="default" />
<efx:design_file name="../../out/build/efinity_sources.f" version="na" library="default" />
<efx:top_vhdl_arch name="" />
</efx:design_info>
<efx:constraint_info>
<efx:sdc_file name="../../../../../hardware/fpga/ti375c529/constraints/ti375c529_rocket.sdc" />
<efx:sdc_file name="outflow/ti375c529_rocket.pt.sdc" />
<efx:sdc_file name="../../../../../hardware/fpga/ti375c529/constraints/ti375c529_rocket_clock_groups.sdc" />
<efx:inter_file name="" />
</efx:constraint_info>
<efx:isf_info>
<efx:isf_file name="ti375c529_rocket.isf" />
</efx:isf_info>
<efx:sim_info />
<efx:misc_info />
<efx:ooc_info />
<efx:ip_info />
<efx:synthesis tool_name="efx_map">
<efx:param name="work_dir" value="../../out/build/work_syn" value_type="e_string" />
<efx:param name="write_efx_verilog" value="on" value_type="e_bool" />
<efx:param name="blackbox-error" value="1" value_type="e_option" />
<efx:param name="hdl-compile-unit" value="1" value_type="e_option" />
<efx:param name="infer-clk-enable" value="3" value_type="e_option" />
<efx:param name="infer-sync-set-reset" value="1" value_type="e_option" />
<efx:param name="mode" value="speed" value_type="e_option" />
<efx:param name="retiming" value="1" value_type="e_option" />
<efx:param name="seq_opt" value="1" value_type="e_option" />
<efx:param name="use-logic-for-small-mem" value="64" value_type="e_integer" />
<efx:param name="use-logic-for-small-rom" value="64" value_type="e_integer" />
<efx:param name="max_threads" value="-1" value_type="e_integer" />
<efx:param name="include" value="../../../../../hardware/external/gps/rtl/trck_src/pulp_fifo" value_type="e_string" />
<efx:param name="include" value="../../out/build/generated/gps_efinity" value_type="e_string" />
</efx:synthesis>
<efx:place_and_route tool_name="efx_pnr">
<efx:param name="work_dir" value="work_pnr" value_type="e_string" />
<efx:param name="seed" value="2" value_type="e_integer" />
<efx:param name="placer_effort_level" value="2" value_type="e_option" />
<efx:param name="max_threads" value="-1" value_type="e_integer" />
<efx:param name="beneficial_skew" value="on" value_type="e_option" />
<efx:param name="print_critical_path" value="10" value_type="e_integer" />
</efx:place_and_route>
<efx:bitstream_generation tool_name="efx_pgm">
<efx:param name="mode" value="active" value_type="e_option" />
<efx:param name="width" value="1" value_type="e_option" />
<efx:param name="enable_roms" value="smart" value_type="e_option" />
<efx:param name="bitstream_compression" value="on" value_type="e_bool" />
<efx:param name="spi_low_power_mode" value="off" value_type="e_bool" />
<efx:param name="release_tri_then_reset" value="on" value_type="e_bool" />
<efx:param name="generate_bit" value="on" value_type="e_bool" />
<efx:param name="generate_hex" value="on" value_type="e_bool" />
<efx:param name="jtag_usercode" value="0x52564B54" value_type="e_string" />
</efx:bitstream_generation>
<efx:debugger>
<efx:param name="work_dir" value="../../out/build/work_dbg" value_type="e_string" />
<efx:param name="auto_instantiation" value="off" value_type="e_bool" />
<efx:param name="profile" value="NONE" value_type="e_string" />
</efx:debugger>
<efx:security>
<efx:param name="enable_bitstream_encrypt" value="off" value_type="e_bool" />
<efx:param name="enable_bitstream_auth" value="off" value_type="e_bool" />
<efx:param name="randomize_iv_value" value="on" value_type="e_bool" />
</efx:security>
</efx:project>
@@ -0,0 +1,276 @@
#!/usr/bin/env python3
"""Generate the Efinix Ti375 board shell around the shared Rocket subsystem."""
import argparse
import re
from pathlib import Path
def width_bits(width):
if not width:
return 1
match = re.fullmatch(r"\[(\d+):(\d+)\]", width.strip())
if not match:
raise ValueError(f"unsupported width: {width}")
return abs(int(match.group(1)) - int(match.group(2))) + 1
def parse_ports(verilog_path):
text = Path(verilog_path).read_text()
module_name = Path(verilog_path).stem
start = text.index(f"module {module_name}(")
end = text.index(");", start)
header = re.sub(r"//.*", "", text[start:end])
pieces = re.split(r"\b(input|output)\b", header)[1:]
ports = []
for direction, body in zip(pieces[0::2], pieces[1::2]):
body = body.replace("\n", " ")
body = re.split(r"\b(input|output)\b", body)[0]
default_width = ""
width_match = re.match(r"\s*(\[[^\]]+\])\s*(.*)", body)
if width_match:
default_width = width_match.group(1)
rest = width_match.group(2)
else:
rest = body
for item in rest.split(","):
item = item.strip()
if not item:
continue
item_match = re.match(r"(\[[^\]]+\])\s*(\w+)$", item)
if item_match:
width, name = item_match.groups()
else:
width = default_width
name = item.split()[-1]
if re.fullmatch(r"\w+", name):
ports.append((direction, width, name))
return ports
def const_for(width):
bits = width_bits(width)
return "1'b0" if bits == 1 else f"{bits}'d0"
def is_clock(name):
return name.endswith("_clock") or name == "debug_clock"
def is_reset(name):
return name.endswith("_reset") or name == "debug_reset"
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--rocket-top", required=True)
parser.add_argument("--out", required=True)
args = parser.parse_args()
ports = parse_ports(args.rocket_top)
port_by_name = {name: (direction, width) for direction, width, name in ports}
required = {
"uart_rxd", "uart_txd",
"spi_sck", "spi_csn", "spi_dq_i", "spi_dq_o", "spi_dq_oe",
"pmod_spi_sck", "pmod_spi_csn",
"pmod_spi_dq_i", "pmod_spi_dq_o", "pmod_spi_dq_oe",
"max2771_spi_sclk", "max2771_spi_csn",
"max2771_spi_sdata_i", "max2771_spi_sdata_o",
"max2771_spi_sdata_oe",
"pmod_irq", "gps_acq_clk", "gps_trck_clk",
"gps_rf_clk", "gps_rf_data", "gps_pps",
}
missing = sorted(required - port_by_name.keys())
if missing:
raise RuntimeError(f"Rocket top is missing required Ti375 ports: {', '.join(missing)}")
passthrough = {
"pmod_spi_sck", "pmod_spi_csn",
"max2771_spi_sclk", "max2771_spi_csn",
"pmod_irq", "gps_pps",
}
def decl(width, name):
return f" wire {width + ' ' if width else ''}{name};"
assigns = []
for direction, width, name in ports:
if direction != "input" or name in passthrough:
continue
if name.startswith("debug_clockeddmi_dmi_req"):
continue
if name in {
"debug_clockeddmi_dmi_resp_ready",
"debug_clockeddmi_dmiClock",
"debug_clockeddmi_dmiReset",
}:
continue
if name == "resetctrl_hartIsInReset_0":
value = "soc_reset"
elif name == "debug_reset":
value = "fabric_reset"
elif is_reset(name):
value = "soc_reset"
elif name == "gps_acq_clk":
value = "gps_acq_clk_gen"
elif name == "gps_trck_clk":
value = "gps_trck_clk_gen"
elif name in {"gps_rf_clk", "gps_afe_clk"}:
value = "rf_clk"
elif name == "gps_rf_data":
value = "rf_data"
elif is_clock(name):
value = "fabric_clk"
elif name == "debug_dmactiveAck":
value = "debug_dmactive"
elif name == "uart_rxd":
value = "uart_rx"
elif name == "spi_dq_i":
value = "flash_dq_IN"
elif name == "pmod_spi_dq_i":
value = "pmod_spi_dq_IN"
elif name == "max2771_spi_sdata_i":
value = "max2771_spi_sdata_IN"
elif name == "interrupts":
value = "2'b00"
else:
value = const_for(width)
assigns.append(f" assign {name} = {value};")
port_map = ",\n".join(f" .{name}({name})" for _, _, name in ports)
internal_decls = "\n".join(
decl(width, name) for _, width, name in ports if name not in passthrough
)
content = f"""`timescale 1ns/1ps
module ti375c529_rocket_top (
(* syn_peri_port = 0 *) input wire fabric_clk,
(* syn_peri_port = 0 *) input wire fabric_pll_locked,
(* syn_peri_port = 0 *) input wire board_clk_100,
(* syn_peri_port = 0 *) input wire gps_ref_clk_gen,
(* syn_peri_port = 0 *) input wire gps_acq_clk_gen,
(* syn_peri_port = 0 *) input wire gps_trck_clk_gen,
(* syn_peri_port = 0 *) input wire gps_domain_feedback,
(* syn_peri_port = 0 *) input wire gps_ref_pll_locked,
(* syn_peri_port = 0 *) input wire gps_domain_pll_locked,
(* syn_peri_port = 0 *) input wire reset_n,
(* syn_peri_port = 0 *) input wire uart_rx,
(* syn_peri_port = 0 *) output wire uart_tx,
(* syn_peri_port = 0 *) output wire flash_sck,
(* syn_peri_port = 0 *) output wire flash_csn,
(* syn_peri_port = 0 *) input wire [3:0] flash_dq_IN,
(* syn_peri_port = 0 *) output wire [3:0] flash_dq_OUT,
(* syn_peri_port = 0 *) output wire [3:0] flash_dq_OE,
(* syn_peri_port = 0 *) input wire rf_clk,
(* syn_peri_port = 0 *) input wire [3:0] rf_data,
(* syn_peri_port = 0 *) output wire pmod_spi_sck,
(* syn_peri_port = 0 *) output wire pmod_spi_csn,
(* syn_peri_port = 0 *) input wire [3:0] pmod_spi_dq_IN,
(* syn_peri_port = 0 *) output wire [3:0] pmod_spi_dq_OUT,
(* syn_peri_port = 0 *) output wire [3:0] pmod_spi_dq_OE,
(* syn_peri_port = 0 *) input wire pmod_irq,
(* syn_peri_port = 0 *) output wire max2771_spi_sclk,
(* syn_peri_port = 0 *) output wire max2771_spi_csn,
(* syn_peri_port = 0 *) input wire max2771_spi_sdata_IN,
(* syn_peri_port = 0 *) output wire max2771_spi_sdata_OUT,
(* syn_peri_port = 0 *) output wire max2771_spi_sdata_OE,
(* syn_peri_port = 0 *) output wire gps_pps,
(* syn_peri_port = 0 *) input wire jtag_CAPTURE,
(* syn_peri_port = 0 *) input wire jtag_DRCK,
(* syn_peri_port = 0 *) input wire jtag_RESET,
(* syn_peri_port = 0 *) input wire jtag_RUNTEST,
(* syn_peri_port = 0 *) input wire jtag_SEL,
(* syn_peri_port = 0 *) input wire jtag_SHIFT,
(* syn_peri_port = 0 *) input wire jtag_TCK,
(* syn_peri_port = 0 *) input wire jtag_TDI,
(* syn_peri_port = 0 *) input wire jtag_TMS,
(* syn_peri_port = 0 *) input wire jtag_UPDATE,
(* syn_peri_port = 0 *) output wire jtag_TDO,
(* syn_peri_port = 0 *) output wire [4:0] led
);
wire gps_clock_locked = gps_ref_pll_locked & gps_domain_pll_locked;
wire pll_ready_async = fabric_pll_locked & gps_clock_locked & reset_n;
(* async_reg = "true" *) reg [2:0] pll_ready_sync = 3'b000;
reg [15:0] reset_shift = 16'hffff;
always @(posedge fabric_clk) begin
pll_ready_sync <= {{pll_ready_sync[1:0], pll_ready_async}};
if (!pll_ready_sync[2])
reset_shift <= 16'hffff;
else
reset_shift <= {{reset_shift[14:0], 1'b0}};
end
wire fabric_reset = reset_shift[15];
reg [31:0] heartbeat = 32'd0;
always @(posedge fabric_clk) begin
if (fabric_reset)
heartbeat <= 32'd0;
else
heartbeat <= heartbeat + 32'd1;
end
{internal_decls}
wire soc_reset = fabric_reset | debug_ndreset;
rocket_bscan_dmi_tunnel u_rocket_dmi_tunnel (
.tck(jtag_TCK),
.reset(fabric_reset | jtag_RESET),
.bscan_capture(jtag_CAPTURE),
.bscan_sel(jtag_SEL),
.bscan_shift(jtag_SHIFT),
.bscan_tdi(jtag_TDI),
.bscan_update(jtag_UPDATE),
.bscan_tdo(jtag_TDO),
.dmi_clock(debug_clockeddmi_dmiClock),
.dmi_reset(debug_clockeddmi_dmiReset),
.dmi_req_ready(debug_clockeddmi_dmi_req_ready),
.dmi_req_valid(debug_clockeddmi_dmi_req_valid),
.dmi_req_addr(debug_clockeddmi_dmi_req_bits_addr),
.dmi_req_data(debug_clockeddmi_dmi_req_bits_data),
.dmi_req_op(debug_clockeddmi_dmi_req_bits_op),
.dmi_resp_ready(debug_clockeddmi_dmi_resp_ready),
.dmi_resp_valid(debug_clockeddmi_dmi_resp_valid),
.dmi_resp_data(debug_clockeddmi_dmi_resp_bits_data),
.dmi_resp_resp(debug_clockeddmi_dmi_resp_bits_resp)
);
assign pmod_spi_dq_OUT = pmod_spi_dq_o;
assign pmod_spi_dq_OE = pmod_spi_dq_oe;
assign max2771_spi_sdata_OUT = max2771_spi_sdata_o;
assign max2771_spi_sdata_OE = max2771_spi_sdata_oe;
assign flash_sck = spi_sck;
assign flash_csn = spi_csn;
assign flash_dq_OUT = spi_dq_o;
assign flash_dq_OE = spi_dq_oe;
assign uart_tx = uart_txd;
// The kit LEDs are active-low. Show heartbeat, PLL locks, reset release,
// and debug-module activity from LED13 down to LED9.
assign led = ~{{heartbeat[25], gps_clock_locked, fabric_pll_locked,
~fabric_reset, debug_dmactive}};
{chr(10).join(assigns)}
(* syn_preserve = 1 *)
{Path(args.rocket_top).stem} u_rocket (
{port_map}
);
// These hard-TAP outputs are intentionally unused by the DMI framing logic.
wire _unused_hard_signals = jtag_DRCK ^ jtag_RUNTEST ^ jtag_TMS ^
board_clk_100 ^ gps_ref_clk_gen ^
gps_domain_feedback;
endmodule
"""
output = Path(args.out)
output.parent.mkdir(parents=True, exist_ok=True)
output.write_text(content)
if __name__ == "__main__":
main()
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""Build Efinity raw-HEX images for Ti375C529 persistent Rocket boot."""
import argparse
import hashlib
import json
import re
from pathlib import Path
HEX_BYTE = re.compile(r"[0-9a-fA-F]{2}")
def parse_int(value):
return int(value, 0)
def read_raw_hex(path):
data = bytearray()
with path.open() as source:
for line_number, line in enumerate(source, 1):
value = line.strip()
if not HEX_BYTE.fullmatch(value):
raise SystemExit(
f"{path}:{line_number}: expected one hexadecimal byte per line"
)
data.append(int(value, 16))
return bytes(data)
def write_raw_hex(path, chunks):
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w") as output:
for chunk in chunks:
for value in chunk:
output.write(f"{value:02X}\n")
def sha256(data):
return hashlib.sha256(data).hexdigest()
def main():
parser = argparse.ArgumentParser(
description="Combine an Efinity configuration HEX and Rocket app image"
)
parser.add_argument("--config-hex", type=Path, required=True)
parser.add_argument("--app-bin", type=Path, required=True)
parser.add_argument("--app-offset", type=parse_int, required=True)
parser.add_argument("--flash-size", type=parse_int, default=0x04000000)
parser.add_argument("--nav-context-offset", type=parse_int, required=True)
parser.add_argument("--ephemeris-offset", type=parse_int, required=True)
parser.add_argument("--combined-hex", type=Path, required=True)
parser.add_argument("--app-hex", type=Path, required=True)
parser.add_argument("--manifest", type=Path, required=True)
args = parser.parse_args()
config = read_raw_hex(args.config_hex)
app = args.app_bin.read_bytes()
app_end = args.app_offset + len(app)
if args.app_offset & 0xFFFF:
raise SystemExit("application offset must be aligned to a 64-KiB sector")
if len(config) > args.app_offset:
raise SystemExit(
f"configuration image (0x{len(config):x} bytes) overlaps application "
f"at 0x{args.app_offset:x}"
)
if app_end > args.flash_size:
raise SystemExit(
f"application ends at 0x{app_end:x}, beyond flash size 0x{args.flash_size:x}"
)
reserved_size = 2 * 0x10000
if args.nav_context_offset + reserved_size > args.ephemeris_offset:
raise SystemExit("navigation context overlaps ephemeris flash region")
if args.ephemeris_offset + reserved_size > args.flash_size:
raise SystemExit("ephemeris flash region exceeds device capacity")
if app_end > args.nav_context_offset:
raise SystemExit(
f"application ends at 0x{app_end:x}, overlapping persistent data at "
f"0x{args.nav_context_offset:x}"
)
padding_size = args.app_offset - len(config)
write_raw_hex(args.app_hex, (app,))
write_raw_hex(args.combined_hex, (config, bytes([0xFF]) * padding_size, app))
manifest = {
"format": "Efinity raw HEX (one byte per line)",
"flash": "Ti375C529 lower SPI NOR (U47)",
"flash_size": f"0x{args.flash_size:08x}",
"configuration": {
"source": str(args.config_hex),
"offset": "0x00000000",
"size": len(config),
"sha256": sha256(config),
},
"application": {
"source": str(args.app_bin),
"offset": f"0x{args.app_offset:08x}",
"size": len(app),
"sha256": sha256(app),
},
"navigation_context": {
"offset": f"0x{args.nav_context_offset:08x}",
"size": reserved_size,
},
"ephemeris_cache": {
"offset": f"0x{args.ephemeris_offset:08x}",
"size": reserved_size,
},
"combined": {
"image": str(args.combined_hex),
"programmed_length": app_end,
},
}
args.manifest.parent.mkdir(parents=True, exist_ok=True)
args.manifest.write_text(json.dumps(manifest, indent=2) + "\n")
print(f"configuration: 0x00000000..0x{len(config) - 1:08x}")
print(f"application: 0x{args.app_offset:08x}..0x{app_end - 1:08x}")
print(f"combined HEX: {args.combined_hex}")
if __name__ == "__main__":
main()
@@ -0,0 +1,316 @@
#!/usr/bin/env python3
"""Apply small, deterministic Efinity synthesis adaptations to generated RTL."""
from __future__ import annotations
import argparse
import math
import re
from pathlib import Path
ROCKET_STORE_DATA = """ else begin
automatic logic [3:0][63:0] _GEN_24 =
{{ex_rs_1}, {{2{ex_rs_1[31:0]}}}, {{4{ex_rs_1[15:0]}}}, {{8{ex_rs_1[7:0]}}}};
mem_reg_rs2 <= _GEN_24[ex_reg_mem_size];
end"""
EFINITY_STORE_DATA = """ else begin
// Efinity 2025.2 leaves the block-local packed automatic array above
// undriven (VDB-1002). Spell out the byte-lane replication instead.
case (ex_reg_mem_size)
2'h0: mem_reg_rs2 <= {8{ex_rs_1[7:0]}};
2'h1: mem_reg_rs2 <= {4{ex_rs_1[15:0]}};
2'h2: mem_reg_rs2 <= {2{ex_rs_1[31:0]}};
default: mem_reg_rs2 <= ex_rs_1;
endcase
end"""
ATOMIC_LUT_DECLARATION = re.compile(
r"^(?P<indent>\s*)automatic logic \[3:0\]\[3:0\] (?P<name>_GEN_[0-9]+) "
r"= '\{4'hC, 4'h8, 4'hE, 4'h6\};$",
re.MULTILINE,
)
NCO_ROM_START = '(*rom_style = "distributed" *) logic [PH_ACC_WL-1 : 0] freq_word_arr'
NCO_ROM_END = "logic [PH_ACC_WL-1 : 0] sin_phase, cos_phase;"
def parse_integer_parameter(text: str, name: str) -> int:
match = re.search(rf"\bparameter\s+{re.escape(name)}\s*=\s*([0-9]+)\s*;", text)
if match is None:
raise RuntimeError(f"could not find integer parameter {name}")
return int(match.group(1))
def parse_sv_integer(token: str) -> tuple[int, int | None]:
token = token.strip().replace("_", "")
match = re.fullmatch(r"(-)?([0-9]+)'([dDhHbB])([0-9a-fA-F]+)", token)
if match is not None:
sign, width_text, radix_text, digits = match.groups()
radix = {"d": 10, "h": 16, "b": 2}[radix_text.lower()]
value = int(digits, radix)
if sign:
value = -value
return value, int(width_text)
if re.fullmatch(r"-?[0-9]+", token):
return int(token), None
raise RuntimeError(f"unsupported SystemVerilog integer literal: {token!r}")
def parse_array_parameter(text: str, name: str) -> list[tuple[int, int | None]]:
match = re.search(
rf"\bparameter\s+\[[^\]]+\]\s+{re.escape(name)}\s*\[[^\]]+\]\s*=\s*\{{(.*?)\}}\s*;",
text,
re.DOTALL,
)
if match is None:
raise RuntimeError(f"could not find array parameter {name}")
return [parse_sv_integer(token) for token in match.group(1).split(",") if token.strip()]
def sv_case_function(
name: str,
input_width: str,
output_width: str,
values: list[int],
literal_width: int,
) -> str:
lines = [
f"function automatic logic [{output_width}-1 : 0] {name};",
f" input logic [{input_width}-1 : 0] index;",
" begin",
" case (index)",
]
for index, value in enumerate(values):
literal = f"-{literal_width}'sd{-value}" if value < 0 else f"{literal_width}'d{value}"
lines.append(f" {index}: {name} = {literal};")
lines.extend(
[
f" default: {name} = '0;",
" endcase",
" end",
"endfunction",
]
)
return "\n".join(lines)
def round_sv_real(value: float) -> int:
"""Match real-to-integral assignment rounding used by SystemVerilog."""
return math.floor(value + 0.5) if value >= 0 else math.ceil(value - 0.5)
def build_nco_rom_functions(definitions: str) -> str:
phase_width = parse_integer_parameter(definitions, "ACQ_NCO_PH_ACC_WL")
sine_integer_bits = parse_integer_parameter(definitions, "ACQ_SIN_IL")
sine_fraction_bits = parse_integer_parameter(definitions, "ACQ_SIN_FL")
lut_address_width = parse_integer_parameter(definitions, "ACQ_SIN_LUT_DEPTH_WL")
freq_values = [value for value, _ in parse_array_parameter(definitions, "FREQ_WORD_ARRAY")]
pullin_values = [value for value, _ in parse_array_parameter(definitions, "PULLIN_FREQ_WORD_ARRAY")]
sine_width = sine_integer_bits + sine_fraction_bits
sine_values = [
round_sv_real(
math.sin(2.0 * math.pi * index / (1 << lut_address_width))
* (1 << sine_fraction_bits)
)
for index in range(1 << lut_address_width)
]
return "\n\n".join(
[
"// Efinity 2025.2 mis-elaborates the original initial/$sin ROMs.\n"
"// These constant functions are generated from definitions.sv for Ti375 only.",
sv_case_function(
"efinity_freq_word", "FREQ_BIN_WL", "PH_ACC_WL", freq_values, phase_width
),
sv_case_function(
"efinity_pullin_word", "NUM_PULLIN_WL", "PH_ACC_WL", pullin_values, phase_width
),
sv_case_function(
"efinity_sine", "LUT_DEPTH_WL", "ACQ_SIN_IL + ACQ_SIN_FL", sine_values, sine_width
),
]
)
def rewrite_acquisition_nco(source: Path, destination: Path, definitions: str) -> None:
text = source.read_text(encoding="utf-8")
start = text.find(NCO_ROM_START)
end = text.find(NCO_ROM_END, start)
if start < 0 or end < 0:
raise RuntimeError(f"could not locate acquisition NCO ROM block in {source}")
text = text[:start] + build_nco_rom_functions(definitions) + "\n\n" + text[end:]
old_sum = (
"freq_word_arr[freq_bin_idx_i] + "
"pullin_freq_word_arr[pullin_freq_bin_idx_i]"
)
new_sum = (
"efinity_freq_word(freq_bin_idx_i) + "
"efinity_pullin_word(pullin_freq_bin_idx_i)"
)
if text.count(old_sum) != 2:
raise RuntimeError(f"expected two NCO phase increments in {source}")
text = text.replace(old_sum, new_sum)
if text.count("sinwav_lut[truncated_sin_phase]") != 1:
raise RuntimeError(f"expected one sine ROM read in {source}")
if text.count("sinwav_lut[truncated_cos_phase]") != 1:
raise RuntimeError(f"expected one cosine ROM read in {source}")
text = text.replace("sinwav_lut[truncated_sin_phase]", "efinity_sine(truncated_sin_phase)")
text = text.replace("sinwav_lut[truncated_cos_phase]", "efinity_sine(truncated_cos_phase)")
destination.write_text(text, encoding="utf-8")
def rewrite_tracking_nco(source: Path, destination: Path, definitions: str) -> None:
text = source.read_text(encoding="utf-8")
declaration = (
'(*rom_style = "distributed" *) logic [SIN_IL-1 : -SIN_FL] '
"sinwav_lut [0 : 2**LUT_DEPTH_WL-1];"
)
values = [value for value, _ in parse_array_parameter(definitions, "TRCK_SINWAV_LUT")]
expected_entries = parse_integer_parameter(definitions, "NUM_TRCK_SINWAV_LUT")
if len(values) != expected_entries:
raise RuntimeError(
f"expected {expected_entries} tracking sine entries, got {len(values)}"
)
function = (
"// Efinity 2025.2 leaves the original package-array initialized ROM undriven.\n"
"// This Ti375-only constant function preserves the exact definitions.sv values.\n"
+ sv_case_function(
"efinity_tracking_sine",
"LUT_DEPTH_WL",
"SIN_IL + SIN_FL",
values,
parse_integer_parameter(definitions, "TRCK_CARR_NCO_SIN_WL"),
)
)
if text.count(declaration) != 1:
raise RuntimeError(f"expected one tracking sine ROM declaration in {source}")
text = text.replace(declaration, function)
initializer = """initial begin
sinwav_lut = TRCK_SINWAV_LUT;
end
"""
if text.count(initializer) != 1:
raise RuntimeError(f"expected one tracking sine ROM initializer in {source}")
text = text.replace(initializer, "")
if text.count("sinwav_lut[accum_truncated_sin]") != 1:
raise RuntimeError(f"expected one tracking sine ROM read in {source}")
if text.count("sinwav_lut[accum_truncated_cos]") != 1:
raise RuntimeError(f"expected one tracking cosine ROM read in {source}")
text = text.replace(
"sinwav_lut[accum_truncated_sin]", "efinity_tracking_sine(accum_truncated_sin)"
)
text = text.replace(
"sinwav_lut[accum_truncated_cos]", "efinity_tracking_sine(accum_truncated_cos)"
)
destination.write_text(text, encoding="utf-8")
def write_mem_file(path: Path, entries: list[tuple[int, int | None]], width: int) -> None:
mask = (1 << width) - 1
path.write_text(
# Binary keeps each row exactly TWIDDLE_WIDTH bits. A hexadecimal row
# would round 15 bits up to four digits and Efinity warns about a
# spurious 16-to-15-bit truncation even though the value is correct.
"".join(f"{value & mask:0{width}b}\n" for value, _ in entries),
encoding="ascii",
)
def rewrite_twiddle_rom(source: Path, destination: Path) -> None:
text = source.read_text(encoding="utf-8")
old = """initial begin
cos_rom = COS_ROM_ARRAY;
sin_rom = SIN_ROM_ARRAY;
end"""
new = """initial begin
// Generated Ti375 files are resolved through Efinity's memory-init include path.
$readmemb("ti375_twiddle_cos_15.mem", cos_rom);
$readmemb("ti375_twiddle_sin_15.mem", sin_rom);
end"""
if text.count(old) != 1:
raise RuntimeError(f"expected one twiddle ROM initializer in {source}")
destination.write_text(text.replace(old, new), encoding="utf-8")
def prepare_gps_rtl(source_dir: Path, output_dir: Path) -> None:
definitions_path = source_dir / "common" / "definitions.sv"
definitions = definitions_path.read_text(encoding="utf-8")
output_dir.mkdir(parents=True, exist_ok=True)
rewrite_acquisition_nco(
source_dir / "acq_src" / "acq_nco_carr.sv",
output_dir / "acq_nco_carr.sv",
definitions,
)
rewrite_tracking_nco(
source_dir / "trck_src" / "NCO_carr.sv",
output_dir / "NCO_carr.sv",
definitions,
)
rewrite_twiddle_rom(
source_dir / "acq_src" / "twiddle_ram.sv",
output_dir / "twiddle_ram.sv",
)
cos_entries = parse_array_parameter(definitions, "COS_ROM_ARRAY")
sin_entries = parse_array_parameter(definitions, "SIN_ROM_ARRAY")
expected_entries = parse_integer_parameter(definitions, "NUM_TWIDDLE_ROM_IDX")
if len(cos_entries) != expected_entries or len(sin_entries) != expected_entries:
raise RuntimeError(
f"expected {expected_entries} twiddle entries, got "
f"cos={len(cos_entries)} sin={len(sin_entries)}"
)
write_mem_file(output_dir / "ti375_twiddle_cos_15.mem", cos_entries, 15)
write_mem_file(output_dir / "ti375_twiddle_sin_15.mem", sin_entries, 15)
def rewrite_rocket_store_data(path: Path) -> None:
text = path.read_text(encoding="utf-8")
if EFINITY_STORE_DATA in text:
return
if text.count(ROCKET_STORE_DATA) != 1:
raise RuntimeError(f"expected one Rocket store-data array in {path}")
path.write_text(text.replace(ROCKET_STORE_DATA, EFINITY_STORE_DATA), encoding="utf-8")
def rewrite_tilelink_atomic_lut(path: Path) -> None:
text = path.read_text(encoding="utf-8")
if "// Avoid Efinity VDB-1002 on the block-local packed LUT." in text:
return
match = ATOMIC_LUT_DECLARATION.search(text)
if match is None:
raise RuntimeError(f"expected one TileLink atomic packed LUT in {path}")
if ATOMIC_LUT_DECLARATION.search(text, match.end()) is not None:
raise RuntimeError(f"expected only one TileLink atomic packed LUT in {path}")
indent = match.group("indent")
temporary = match.group("name")
old_read = f"{indent}cam_a_0_lut <= {temporary}[auto_in_a_bits_param[1:0]];"
new_read = f"""{indent}// Avoid Efinity VDB-1002 on the block-local packed LUT.
{indent}case (auto_in_a_bits_param[1:0])
{indent} 2'h0: cam_a_0_lut <= 4'h6;
{indent} 2'h1: cam_a_0_lut <= 4'hE;
{indent} 2'h2: cam_a_0_lut <= 4'h8;
{indent} default: cam_a_0_lut <= 4'hC;
{indent}endcase"""
if text.count(old_read) != 1:
raise RuntimeError(f"expected one TileLink atomic packed LUT read in {path}")
text = text[: match.start()] + text[match.end() + 1 :]
text = text.replace(old_read, new_read)
path.write_text(text, encoding="utf-8")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--verilog-dir", type=Path, required=True)
parser.add_argument("--gps-source-dir", type=Path, required=True)
parser.add_argument("--gps-output-dir", type=Path, required=True)
args = parser.parse_args()
rewrite_rocket_store_data(args.verilog_dir / "Rocket.sv")
rewrite_tilelink_atomic_lut(args.verilog_dir / "TLAtomicAutomata_pbus.sv")
rewrite_tilelink_atomic_lut(args.verilog_dir / "TLAtomicAutomata_cbus.sv")
prepare_gps_rtl(args.gps_source_dir, args.gps_output_dir)
if __name__ == "__main__":
main()
+14 -2
View File
@@ -69,6 +69,12 @@ FLASH_FORCE ?= 0
GPS_DEBUG ?= 1
GPS_DEBUG_LEVEL ?= 4
GPS_ESKF_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_ENABLE ?= 1
GPS_EPHEMERIS_FLASH_SEED_INITIAL ?= 1
GPS_EPHEMERIS_FLASH_BASE ?= 0x07fe0000
GPS_NAV_CONTEXT_ENABLE ?= 1
GPS_NAV_CONTEXT_FLASH_BASE ?= 0x07fc0000
BSP_SPI_FLASH_PROFILE ?= 2
IMU_SENSOR ?= auto
FLASH_MCS ?= $(OUT_DIR)/flash/vcu118_rocket.mcs
@@ -213,13 +219,19 @@ fpga-config:
' UART_PORT=$(UART_PORT)' \
' UART_BAUD=$(UART_BAUD)' \
' GPS_ESKF_ENABLE=$(GPS_ESKF_ENABLE)' \
' GPS_EPHEMERIS_FLASH_ENABLE=$(GPS_EPHEMERIS_FLASH_ENABLE)' \
' GPS_EPHEMERIS_FLASH_SEED_INITIAL=$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)' \
' GPS_EPHEMERIS_FLASH_BASE=$(GPS_EPHEMERIS_FLASH_BASE)' \
' GPS_NAV_CONTEXT_ENABLE=$(GPS_NAV_CONTEXT_ENABLE)' \
' GPS_NAV_CONTEXT_FLASH_BASE=$(GPS_NAV_CONTEXT_FLASH_BASE)' \
' BSP_SPI_FLASH_PROFILE=$(BSP_SPI_FLASH_PROFILE)' \
' IMU_SENSOR=$(IMU_SENSOR)'
software:
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" bootloader flash-image
$(APP_ELF): FORCE
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" IMU_SENSOR="$(IMU_SENSOR)" app
@$(MAKE_BIN) -C "$(SOC_SW_DIR)" TOOLCHAIN="$(TOOLCHAIN)" APP="$(APP)" APP_FLASH_OFFSET="$(APP_FLASH_OFFSET)" BSP_UART_CLOCK_HZ="$(BSP_UART_CLOCK_HZ)" BSP_UART_BAUDRATE="$(BSP_UART_BAUDRATE)" BSP_CLINT_TIMEBASE_HZ="$(BSP_CLINT_TIMEBASE_HZ)" BSP_SPI_FLASH_PROFILE="$(BSP_SPI_FLASH_PROFILE)" BSP_DTIM_BASE="$(DTIM_BASE)" BSP_DTIM_SIZE="$(DTIM_SIZE)" GPS_DEBUG="$(GPS_DEBUG)" GPS_DEBUG_LEVEL="$(GPS_DEBUG_LEVEL)" GPS_ESKF_ENABLE="$(GPS_ESKF_ENABLE)" GPS_EPHEMERIS_FLASH_ENABLE="$(GPS_EPHEMERIS_FLASH_ENABLE)" GPS_EPHEMERIS_FLASH_SEED_INITIAL="$(GPS_EPHEMERIS_FLASH_SEED_INITIAL)" GPS_EPHEMERIS_FLASH_BASE="$(GPS_EPHEMERIS_FLASH_BASE)" GPS_NAV_CONTEXT_ENABLE="$(GPS_NAV_CONTEXT_ENABLE)" GPS_NAV_CONTEXT_FLASH_BASE="$(GPS_NAV_CONTEXT_FLASH_BASE)" IMU_SENSOR="$(IMU_SENSOR)" app
chisel: software
@cd "$(REPO_DIR)"
+4
View File
@@ -16,6 +16,10 @@ FIRTOOL ?= $(firstword $(wildcard $(SOC_TOOLS_ROOT)/circt-current/bin/firtool) $
Z3_LIB_DIR ?= $(firstword $(wildcard $(SOC_TOOLS_ROOT)/z3-current/bin) $(wildcard $(PROJECT_TOOLS_DIR)/z3/*/bin))
CIRCT_LIB_DIR ?= $(patsubst %/bin/firtool,%/lib,$(FIRTOOL))
VIVADO ?= $(lastword $(sort $(wildcard /tools/Xilinx/*/Vivado/bin/vivado) $(shell command -v vivado 2>/dev/null)))
EFINITY_HOME ?= $(lastword $(sort $(wildcard /tools/efinix/efinity/*)))
EFINITY_SETUP ?= $(EFINITY_HOME)/bin/setup.sh
EFX_RUN ?= $(EFINITY_HOME)/scripts/efx_run.py
EFX_PGM ?= $(EFINITY_HOME)/pgm/bin/ftdi_pgm.sh
# RISCV_TOOLCHAIN may point either to the toolchain root or its bin directory.
# TOOLCHAIN keeps compatibility with the existing software Makefiles.