Skip to content

cpu/cyclonev_hps: Add Intel Cyclone V HPS (hard dual Cortex-A9) support - #2496

Merged
enjoy-digital merged 9 commits into
masterfrom
cyclonev_hps
Jul 6, 2026
Merged

cpu/cyclonev_hps: Add Intel Cyclone V HPS (hard dual Cortex-A9) support#2496
enjoy-digital merged 9 commits into
masterfrom
cyclonev_hps

Conversation

@enjoy-digital

@enjoy-digital enjoy-digital commented Jul 6, 2026

Copy link
Copy Markdown
Owner

This PR adds Intel Cyclone V HPS support as a hardcore CPU (--cpu-type=cyclonev_hps), similar to what is already done for Zynq7000/ZynqMP, targeting boards where the HPS is pre-booted from SD-Card (e.g. MiSTer/DE10-Nano) and where only the Fabric-side bridge interfaces are then required.

Integration:

  • H2F LW AXI3 master used as the LiteX peripheral bus, with the bridge's window-relative addresses extended to ARM physical addresses so that the LiteX memory map matches the ARM's view (CSRs at 0xff20_0000, directly usable from the HPS with devmem//dev/mem).
  • Optional H2F AXI3 master (0xc000_0000, 960MB window) via add_axi_h2f_master() and F2H AXI3 slave via add_axi_f2h_slave() for Fabric -> HPS DDR3/peripherals accesses.
  • F2SDRAM Avalon-MM ports via add_fpga2sdram_port() for direct (higher bandwidth) Fabric -> HPS SDRAM Controller accesses; the port layout is fixed (Port 0: 128-bit, Ports 1/2: 64-bit) to match the configuration applied by MiSTer's Preloader/U-Boot.
  • F2H interrupts (32 IRQs) and Clocks/Resets/Trace/Boot tie-offs.
  • New generic interconnect/avalon Wishbone2AvalonMM bridge (with simulation coverage) to connect the F2SDRAM Avalon-MM ports to the LiteX bus.
  • BIOS/software support files (UART redirected to HPS UART0/16550, configured by the Preloader/U-Boot); the BIOS is only compiled when the target adds rom/sram regions in HPS DDR3, as on Zynq targets.
  • GIC-aware BIOS interrupt support for bare-metal use (BIOS launched from U-Boot with go 0x01000000): Cortex-A9 crt0.S with exception vectors at the image start (VBAR), VFP enable, IRQ-mode stack and AAPCS IRQ trampoline; GIC-390 irq.h (the 32-bit LiteX interrupt mask maps to the F2H IRQs / GIC IDs 72-103 without disturbing other IDs); IAR/EOIR claim-based ISR dispatch in libbase/isr.c.

Implementation notes:

  • The HPS is integrated through direct cyclonev_hps_interface_* atom instantiation (no Qsys/Platform Designer). Port lists were taken from Quartus's WYSIWYG component library and cross-checked against MiSTer's sys framework (which instantiates the same atoms directly); the F2SDRAM atom configuration/wiring replicates MiSTer's generated sys framework.
  • Unused H2F/F2H bridges are explicitly instantiated with port_size_config=unused, as done by MiSTer; the F2SDRAM atom is only instantiated when at least one port is used.
  • The dbg_apb tie-off atom used by MiSTer (Quartus 17) is not instantiated: it is no longer present in recent Quartus releases (23.1) and is not required.

Tested:

  • Full Quartus 23.1 builds on the DE10-Nano target (see companion litex-boards PR), with and without F2SDRAM: 0 errors, bridges/F2SDRAM atoms placed/routed, .rbf produced; BIOS compiles with arm-none-eabi-gcc.
  • Wishbone2AvalonMM simulation test (32/64-bit, base address translation, wait-states, pipelined read latency).
  • GIC/crt0 path verified by building the BIOS with arm-none-eabi-gcc and inspecting the disassembly: vectors at rom base/entry point (0x01000000), GIC Distributor/CPU Interface accesses (ITARGETSR/PMR/CTLRs) inlined in main() through irq_setie(1), exception return sequence — runtime behavior still to be validated on hardware.
  • Softcore DE10-Nano path unchanged/still elaborates.
  • Hardware bring-up on a MiSTer is the next step (CSR access from HPS Linux with devmem, SDRAM access at 0xc000_0000 through the H2F bridge, HPS DDR3 access at 0xd000_0000 through F2SDRAM).

Companion PRs: litex-hub/litex-boards#746 (DE10-Nano target), #2497 (litex_server --devmem for remote litex_cli/litescope accesses from the HPS).

Possible follow-ups: Qsys backend for standalone (non pre-booted) boards.

@enjoy-digital
enjoy-digital merged commit 2470e43 into master Jul 6, 2026
8 checks passed
…ore.

Add the Cyclone V HPS as a hardcore CPU (similar to Zynq7000/ZynqMP):
- H2F LW AXI3 master used as LiteX peripheral bus, with the bridge's
  window-relative addresses extended to ARM physical addresses so that
  the LiteX memory map matches the ARM's view (CSRs at 0xff20_0000).
- Optional H2F AXI3 master (0xc000_0000, 960MB window) through
  add_axi_h2f_master() and F2H AXI3 slave through add_axi_f2h_slave()
  for Fabric -> HPS DDR3/peripherals accesses.
- F2H interrupts (32 IRQs) and Clocks/Resets/Trace/Boot tie-offs.

The HPS is integrated through direct cyclonev_hps_interface_* atom
instantiation (no Qsys/Platform Designer), targeting boards where the
HPS is pre-booted from SD-Card (e.g. MiSTer/DE10-Nano) and where only
the Fabric-side bridge interfaces are then required. Unused H2F/F2H
bridges are explicitly instantiated with port_size_config=unused, as
done by MiSTer.
Similar to Zynq7000 but self-contained (no external BSP):
- system.h: UART redirected to HPS UART0 (16550 at 0xffc02000, already
  configured by the Preloader/U-Boot), cache flush stubs.
- irq.h: Stubs (GIC support will be added later if needed).
- boot-helper.c: Simple jump to address.
- crt0.S: Empty (BIOS is only compiled/linked when the target adds
  rom/sram regions in HPS DDR3, as on Zynq targets).
Hardcore CPU: can't be simulated in the CI boot tests (as Zynq7000/
ZynqMP/EOS-S3).
Wishbone Slave to Avalon-MM Master bridge (Classic single-beat
accesses), complementing the existing AvalonMM2Wishbone bridge. Useful
to connect Avalon-MM Slaves (ex Cyclone V HPS F2SDRAM ports) to the
LiteX bus.

Add simulation coverage against an Avalon-MM RAM model (32/64-bit,
base address translation, wait-states, pipelined read latency).
Add add_fpga2sdram_port() providing direct Avalon-MM ports to the HPS
SDRAM Controller (higher bandwidth than the F2H bridge). The port
layout is fixed (Port 0: 128-bit, Ports 1/2: 64-bit) since it has to
match the configuration applied by the Preloader/U-Boot (applycfg),
here MiSTer's one; the atom configuration/wiring replicates MiSTer's
generated sys framework.

The fpga2sdram atom is only instantiated when at least one port is
used; unused ports are tied-off (Clks driven, commands disabled).
Replace the irq.h stubs and empty crt0.S with a functional (hardware
still to be validated) bare-metal interrupt path for the BIOS when
launched from the Preloader/U-Boot (ex go 0x01000000):
- crt0.S: Cortex-A9 startup with exception vectors placed at the image
  start (VBAR, 32-byte aligned), VFP/NEON enable (BIOS is built
  hard-float), IRQ mode stack, .data copy/.bss clear and an IRQ
  trampoline (AAPCS caller-saved registers + SPSR save/restore) calling
  isr().
- irq.h: GIC-390 (Distributor at 0xfffed000, CPU Interface at
  0xfffec100) implementation of irq_getie/setie/getmask/setmask/
  pending; the 32-bit LiteX interrupt mask maps to the F2H IRQs (GIC
  IDs 72-103), other GIC IDs (HPS peripherals) are not disturbed;
  irq_setie(1) routes the F2H IRQs to CPU0 and enables the Distributor/
  CPU Interface (hooked to the BIOS irq_setmask(0)/irq_setie(1) init).
- libbase/isr.c: cyclonev_hps ISR with GIC IAR/EOIR claim-based
  dispatch to the common interrupt table (F2H IRQ0 <-> LiteX IRQ0).
- core.py: add -D__cyclonev_hps__ to gcc_flags (used by isr.c).

Verified by building the BIOS with arm-none-eabi-gcc and inspecting
the disassembly: vectors at rom base/entry point (0x01000000), GIC
Distributor/CPU Interface accesses (ITARGETSR 0xfffed848-64, PMR,
CTLRs) inlined in main(), exception return sequence (ldm sp!, {..}^).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant