Add FPGA project workspace layout
This commit is contained in:
@@ -13,20 +13,20 @@ See ROADMAP.md for the full phased plan.
|
|||||||
|
|
||||||
- Language: SystemVerilog (not Verilog). Use SV features: packages, structs, enums,
|
- Language: SystemVerilog (not Verilog). Use SV features: packages, structs, enums,
|
||||||
always_comb, always_ff, logic (not reg/wire).
|
always_comb, always_ff, logic (not reg/wire).
|
||||||
- All inter-stage signals are defined as structs in `rtl/pkg/rv32_pkg.sv`. Always
|
- All inter-stage signals are defined as structs in `FPGA/rtl/pkg/rv32_pkg.sv`.
|
||||||
import this package. When adding new functionality, extend the existing structs
|
Always import this package. When adding new functionality, extend the existing
|
||||||
rather than adding loose wires.
|
structs rather than adding loose wires.
|
||||||
- Module naming: `rv32_<block>` (e.g., `rv32_alu`, `rv32_decode`, `rv32_regfile`).
|
- Module naming: `rv32_<block>` (e.g., `rv32_alu`, `rv32_decode`, `rv32_regfile`).
|
||||||
- File naming: one module per file, filename matches module name.
|
- File naming: one module per file, filename matches module name.
|
||||||
- Testbenches: `tb/tb_<module>.sv`. Use Vivado simulator.
|
- Testbenches: `FPGA/tb/tb_<module>.sv`. Use Vivado simulator.
|
||||||
- Clock: single clock domain, active rising edge, signal named `clk`. Target
|
- Clock: single clock domain, active rising edge, signal named `clk`. Target
|
||||||
frequency: 50 MHz (derived from the Arty's 100 MHz oscillator via MMCM/2).
|
frequency: 50 MHz (derived from the Arty's 100 MHz oscillator via MMCM/2).
|
||||||
- Reset: synchronous active-high, signal named `rst`. The Arty's `CK_RST` button
|
- Reset: synchronous active-high, signal named `rst`. The Arty's `CK_RST` button
|
||||||
is active-low; the top-level wraps it through a 2-FF synchronizer and inverts
|
is active-low; the top-level wraps it through a 2-FF synchronizer and inverts
|
||||||
to produce the internal `rst`. The rest of the design only sees synchronous
|
to produce the internal `rst`. The rest of the design only sees synchronous
|
||||||
active-high.
|
active-high.
|
||||||
- BRAM init files: `mem/*.mem` in hex format, one 32-bit word per line.
|
- BRAM init files: `FPGA/mem/*.mem` in hex format, one 32-bit word per line.
|
||||||
- Firmware source: `fw/` directory. Built with `riscv64-unknown-elf-gcc`
|
- Firmware source: `Software/fw/` directory. Built with `riscv64-unknown-elf-gcc`
|
||||||
(multilib build required). March string evolves with the implemented ISA:
|
(multilib build required). March string evolves with the implemented ISA:
|
||||||
- Phase 8 (pre-CSR bare-metal): `-march=rv32im -mabi=ilp32`
|
- Phase 8 (pre-CSR bare-metal): `-march=rv32im -mabi=ilp32`
|
||||||
- Phase 12+ (CSRs/Zifencei decoded): `-march=rv32im_zicsr_zifencei -mabi=ilp32`
|
- Phase 12+ (CSRs/Zifencei decoded): `-march=rv32im_zicsr_zifencei -mabi=ilp32`
|
||||||
@@ -37,18 +37,35 @@ See ROADMAP.md for the full phased plan.
|
|||||||
## Directory Structure
|
## Directory Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
rtl/ — synthesizable source
|
FPGA/ — everything that ends up on the FPGA
|
||||||
pkg/ — packages (rv32_pkg.sv)
|
rtl/ — synthesizable source
|
||||||
core/ — CPU core modules (ALU, M unit, decoder, regfile, datapath)
|
pkg/ — packages (rv32_pkg.sv)
|
||||||
periph/ — peripherals (UART, timer, PLIC, etc.)
|
core/ — CPU core modules (ALU, M unit, decoder, regfile, datapath)
|
||||||
top/ — top-level and SoC integration
|
periph/ — peripherals (UART, timer, PLIC, etc.)
|
||||||
tb/ — testbenches (tb_<module>.sv)
|
top/ — top-level and SoC integration
|
||||||
mem/ — BRAM init files (.mem)
|
tb/ — testbenches (tb_<module>.sv)
|
||||||
fw/ — firmware source (C, assembly, linker scripts)
|
constraints/ — Vivado XDC constraint files
|
||||||
constraints/ — Vivado XDC constraint files
|
mem/ — BRAM init files (.mem)
|
||||||
docs/ — block diagrams, notes
|
vivado/ — Vivado project workspace (regenerated, not committed)
|
||||||
|
only create_project.tcl is committed; .xpr and
|
||||||
|
*.runs / *.cache / *.hw / *.sim / *.gen / *.srcs /
|
||||||
|
*.ip_user_files are git-ignored
|
||||||
|
Software/ — software that runs on the CPU
|
||||||
|
fw/ — bare-metal firmware, crt0, linker scripts (Phase 8+)
|
||||||
|
bios/ — BIOS / monitor + ELF loader (Phase 9, 10)
|
||||||
|
kernel/ — tiny custom kernel, later Linux artifacts (Phase 11, 19, 20)
|
||||||
|
Docs/ — block diagrams, architectural notes
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The Vivado project lives in `FPGA/vivado/`, not at the repo root. The `.xpr`
|
||||||
|
itself is **not** committed — `create_project.tcl` is the source of truth, and
|
||||||
|
each developer regenerates the project locally with
|
||||||
|
`vivado -mode batch -source FPGA/vivado/create_project.tcl`. RTL and testbench
|
||||||
|
files are added to the project as **references** to `../rtl/...` and
|
||||||
|
`../tb/...` so the actual source of truth stays in version control. All
|
||||||
|
generated state (`*.xpr`, `*.runs/`, `*.cache/`, `*.hw/`, `*.sim/`,
|
||||||
|
`*.ip_user_files/`, `*.gen/`, `*.srcs/`) is git-ignored.
|
||||||
|
|
||||||
## ISA Target
|
## ISA Target
|
||||||
|
|
||||||
End target: **RV32IMA + Zicsr + Zifencei + M/S/U privilege + Sv32** (Linux-capable).
|
End target: **RV32IMA + Zicsr + Zifencei + M/S/U privilege + Sv32** (Linux-capable).
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Docs/
|
||||||
|
|
||||||
|
Architectural notes and the Phase 0.2 block diagram. The diagram is the
|
||||||
|
visual source of truth for the datapath — draw on paper first, then capture a
|
||||||
|
digital copy here (e.g. `block-diagram.drawio` exported to SVG/PNG) once it
|
||||||
|
stabilizes. Update it whenever a stage-boundary struct or bus instance changes.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/
|
||||||
|
|
||||||
|
Everything that ends up on the FPGA: SystemVerilog source, testbenches,
|
||||||
|
constraints, memory init files, and the Vivado project.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/constraints/
|
||||||
|
|
||||||
|
Vivado XDC constraint files: pin assignments for the Arty A7, clock
|
||||||
|
definitions, and timing constraints.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/mem/
|
||||||
|
|
||||||
|
BRAM init files (`.mem`) in hex format, one 32-bit word per line. Loaded by
|
||||||
|
`$readmemh` into instruction/data BRAM at elaboration.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/rtl/
|
||||||
|
|
||||||
|
Synthesizable SystemVerilog source. One module per file, filename matches
|
||||||
|
module name (e.g. `rv32_alu.sv`).
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/rtl/core/
|
||||||
|
|
||||||
|
CPU core modules: ALU, M unit, decoder, register file, fetch, LSU, datapath,
|
||||||
|
and (later) CSR file and MMU. Module names follow `rv32_<block>`.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/rtl/periph/
|
||||||
|
|
||||||
|
Memory-mapped peripherals: UART (Phase 7), CLINT timer (Phase 13), PLIC
|
||||||
|
(Phase 14), and any future devices. Each peripheral is a slave on the D-bus.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/rtl/pkg/
|
||||||
|
|
||||||
|
Shared SystemVerilog packages — the type contract for the design.
|
||||||
|
`rv32_pkg.sv` (enums, stage-boundary structs, bus payloads) lives here.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# FPGA/rtl/top/
|
||||||
|
|
||||||
|
Top-level modules and SoC integration: clock/reset wrapping (MMCM, reset
|
||||||
|
synchronizer), bus arbitration, address decode, and the board-level top that
|
||||||
|
maps to the Arty A7 pins.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# FPGA/tb/
|
||||||
|
|
||||||
|
SystemVerilog testbenches, one per module under test. Naming: `tb_<module>.sv`.
|
||||||
|
Run with the Vivado simulator (xsim).
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Vivado-generated project state. The committed source of truth is
|
||||||
|
# create_project.tcl — everything below (including the .xpr itself, which
|
||||||
|
# embeds machine-specific paths) is regenerated by running that script.
|
||||||
|
|
||||||
|
# The project file itself — regenerated from create_project.tcl
|
||||||
|
*.xpr
|
||||||
|
|
||||||
|
# Project-wide generated directories (named after the .xpr basename)
|
||||||
|
*.cache/
|
||||||
|
*.hw/
|
||||||
|
*.sim/
|
||||||
|
*.runs/
|
||||||
|
*.ip_user_files/
|
||||||
|
*.gen/
|
||||||
|
*.srcs/
|
||||||
|
|
||||||
|
# Vivado scratch / temp
|
||||||
|
.Xil/
|
||||||
|
xsim.dir/
|
||||||
|
|
||||||
|
# Logs, journals, autosave backups
|
||||||
|
*.jou
|
||||||
|
*.log
|
||||||
|
*.str
|
||||||
|
*.backup.*
|
||||||
|
*.wdb
|
||||||
|
*.pb
|
||||||
|
vivado*.jou
|
||||||
|
vivado*.log
|
||||||
|
|
||||||
|
# Webtalk telemetry
|
||||||
|
webtalk*.jou
|
||||||
|
webtalk*.log
|
||||||
|
usage_statistics_webtalk.*
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# FPGA/vivado/
|
||||||
|
|
||||||
|
The Vivado project workspace. The committed source of truth is
|
||||||
|
`create_project.tcl`; the project file (`FPGA-Core.xpr`) and all of Vivado's
|
||||||
|
generated state (`*.runs/`, `*.cache/`, `*.hw/`, `*.sim/`, `*.ip_user_files/`,
|
||||||
|
`*.gen/`, `*.srcs/`) are git-ignored — `.xpr` files embed machine-specific
|
||||||
|
paths and are regenerated locally.
|
||||||
|
|
||||||
|
RTL and testbench files are added to the project as **references** to
|
||||||
|
`../rtl/...` / `../tb/...` so the actual source of truth stays in version
|
||||||
|
control, not inside the project file.
|
||||||
|
|
||||||
|
To generate the project, run from the repo root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
vivado -mode batch -source FPGA/vivado/create_project.tcl
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open the resulting `FPGA/vivado/FPGA-Core.xpr` in the Vivado GUI.
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# create_project.tcl — generate FPGA/vivado/FPGA-Core.xpr
|
||||||
|
#
|
||||||
|
# Usage (from the repo root):
|
||||||
|
# vivado -mode batch -source FPGA/vivado/create_project.tcl
|
||||||
|
#
|
||||||
|
# Or from inside FPGA/vivado/:
|
||||||
|
# vivado -mode batch -source create_project.tcl
|
||||||
|
#
|
||||||
|
# Then open the resulting .xpr in the Vivado GUI. To regenerate from scratch,
|
||||||
|
# delete FPGA-Core.xpr and its sibling *.cache / *.runs / *.hw / *.sim /
|
||||||
|
# *.ip_user_files / *.gen directories, then re-run.
|
||||||
|
|
||||||
|
set script_dir [file normalize [file dirname [info script]]]
|
||||||
|
set fpga_dir [file normalize "$script_dir/.."]
|
||||||
|
set proj_name "FPGA-Core"
|
||||||
|
set part "xc7a100tcsg324-1"
|
||||||
|
|
||||||
|
if {[file exists "$script_dir/$proj_name.xpr"]} {
|
||||||
|
puts "Project already exists: $script_dir/$proj_name.xpr"
|
||||||
|
puts "Delete it (and its sibling *.cache, *.runs, ... dirs) first."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
create_project $proj_name $script_dir -part $part
|
||||||
|
|
||||||
|
set_property target_language Verilog [current_project]
|
||||||
|
set_property simulator_language Mixed [current_project]
|
||||||
|
|
||||||
|
# RTL and testbenches are added as references (not copied) so the source of
|
||||||
|
# truth stays in git, not inside the .xpr. Passing a directory makes Vivado
|
||||||
|
# recursively pick up all HDL files under it.
|
||||||
|
add_files "$fpga_dir/rtl"
|
||||||
|
add_files -fileset sim_1 "$fpga_dir/tb"
|
||||||
|
|
||||||
|
set xdc_files [glob -nocomplain "$fpga_dir/constraints/*.xdc"]
|
||||||
|
if {[llength $xdc_files] > 0} {
|
||||||
|
add_files -fileset constrs_1 $xdc_files
|
||||||
|
}
|
||||||
|
|
||||||
|
update_compile_order -fileset sources_1
|
||||||
|
update_compile_order -fileset sim_1
|
||||||
|
|
||||||
|
puts "Created $script_dir/$proj_name.xpr"
|
||||||
@@ -50,7 +50,19 @@ Requires:
|
|||||||
- `riscv-tests` (for compliance verification from Phase 8.5)
|
- `riscv-tests` (for compliance verification from Phase 8.5)
|
||||||
- Serial terminal (minicom/picocom/PuTTY) at 115200 8N1
|
- Serial terminal (minicom/picocom/PuTTY) at 115200 8N1
|
||||||
|
|
||||||
Open `FPGA-Core.xpr` in Vivado. Synthesis and implementation target the xc7a100tcsg324-1.
|
FPGA sources (RTL, testbenches, constraints, BRAM init files, and the Vivado
|
||||||
|
project script) live under `FPGA/`. Software that runs on the core (firmware,
|
||||||
|
BIOS, kernels) lives under `Software/`. The Vivado project itself is **not**
|
||||||
|
committed — generate it from the script and then open it:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
vivado -mode batch -source FPGA/vivado/create_project.tcl
|
||||||
|
# then open FPGA/vivado/FPGA-Core.xpr in the Vivado GUI
|
||||||
|
```
|
||||||
|
|
||||||
|
Synthesis and implementation target the xc7a100tcsg324-1. RTL sources in
|
||||||
|
`FPGA/rtl/` and testbenches in `FPGA/tb/` are added to the project as
|
||||||
|
references — do not let Vivado copy them in.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Software/
|
||||||
|
|
||||||
|
Software that runs on the CPU: bare-metal firmware, BIOS, and kernels.
|
||||||
|
Built with the RISC-V GCC toolchain (`riscv64-unknown-elf-gcc`). The `march`
|
||||||
|
string evolves with the implemented ISA — see `CLAUDE.md`.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Software/bios/
|
||||||
|
|
||||||
|
BIOS / monitor: an interactive ROM program that talks over UART to peek/poke
|
||||||
|
memory, dump registers, and load programs into RAM. Includes the ELF loader.
|
||||||
|
|
||||||
|
**Phases:** 9 (BIOS monitor), 10 (ELF loader over UART).
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Software/fw/
|
||||||
|
|
||||||
|
Bare-metal firmware: `crt0.S`, linker script, and the first C programs that
|
||||||
|
run on the CPU. Also where `riscv-tests` integration lives.
|
||||||
|
|
||||||
|
**Phases:** 8 (GCC toolchain, first C program, `riscv-tests`).
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Software/kernel/
|
||||||
|
|
||||||
|
Kernels that run on the core. Starts as a tiny custom kernel for learning
|
||||||
|
trap/scheduling/syscalls; later hosts the Linux device tree, OpenSBI, and
|
||||||
|
mainline Linux build artifacts.
|
||||||
|
|
||||||
|
**Phases:** 11 (tiny kernel), 19 (Linux boot contract), 20 (Linux).
|
||||||
@@ -37,7 +37,7 @@ state stored, what changes each clock, what can wait, and what happens on an exc
|
|||||||
|
|
||||||
## Tooling And Testing
|
## Tooling And Testing
|
||||||
|
|
||||||
- Keep the diagram in `docs/` and update it when interfaces change.
|
- Keep the diagram in `Docs/` and update it when interfaces change.
|
||||||
- Compare waveform signal names against the diagram after each integration phase.
|
- Compare waveform signal names against the diagram after each integration phase.
|
||||||
- Use the diagram as a checklist when adding ILA probes.
|
- Use the diagram as a checklist when adding ILA probes.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user