eSC-V is a 5-stage pipelined RV32I Zicsr Zicfilp Smcfiss Smpmpind RISC-V SoC implemented entirely in VHDL. It is designed to provide hardware-enforced Control-Flow Integrity (CFI) for bare-metal, M-mode microcontrollers. To protect against Return-Oriented Programming (ROP) and Jump-Oriented Programming (JOP) , the core integrates the Zicfilp extension for forward-edge protection and the draft Smcfiss and Smpmpind extensions to enforce a hardware shadow stack.
The SoC has a dual-port unified memory controller that synthesizes to BRAM, a UART for communication, and has been verified against Sail and Spike formal models using the RISC-V Compatibility Framework (RISCOF).
The complete tooling is open source, and the FPGA used is the Tang Primer 20K, running at 60 MHz with an open-source (reverse-engineered) bitstream. Nix is used to keep the development environment consistent and to manage the custom GCC toolchain required for compiling the CFI extensions.
eSC-V/
├── constraints/ # FPGA constraint files
│ └── fpga.cst
├── docs/ # Documentation and diagrams
│ ├── dev_docs/
│ ├── pipeline.png
│ └── specifications/
├── software/ # Software and firmware
│ ├── apps
│ ├── common
│ ├── drivers
│ ├── Makefile
│ └── tests
├── src/ # VHDL module implementations
│ ├── core.vhd
│ ├── soc.vhd
│ ├── IF_stage/
│ ├── ID_stage/
│ ├── EX_stage/
│ └── ...
├── tb/ # Testbench files
│ ├── tb_soc.vhd
│ └── tb_soc_riscof.vhd
├── verification/ # Verification frameworks
│ └── riscof/
├── Makefile # Build and simulation commands
├── flake.nix # Nix development environment
└── README.md # Project documentation
Here is the rewritten Usage section of your README, updated to reflect the unified cfi testing structure and the new exploit script arguments.
From the project root, enter the Nix development shell. The Makefile handles building software, simulation, and synthesis directly without needing to change directories.
nix developThe build system will automatically compile the selected software variant before running simulation or synthesis.
Standard Applications:
ascii-tetris(Default): A Tetris game playable over UART.pong-c: A Pong game playable over UART.libc: Functional tests for newlib functions likeprintf.
Security Validation:
cfi: A unified, vulnerable C program designed to test both backward-edge protection (shadow stack / ROP) and forward-edge protection (landing pads / JOP).
# Run with ASCII Tetris (default)
make run
# Run with specific software
make run pong-c
make run libc
# View waveforms
make viewNote: For custom hardware constraints, modify
constraints/fpga.cst.
# Program with Tetris (default)
make program
# Program with a specific application
make program pong-c
# Program with the vulnerable CFI test program
make program cfiTo validate hardware-enforced Control Flow Integrity (CFI), a proof-of-concept exploit environment is provided. The cfi variant contains a vulnerable_function() that accepts UART input without bounds checking and prints the address of an unreachable win_function().
Steps:
CFI protections can be disabled individually by commenting out
-D__ENABLE_ZICFILP__or-D__ENABLE_SMCFISS__insoftware/tests/cfi/Makefile.
- Build and program the FPGA with the vulnerable target:
make program cfi- Run the exploit script: The exploit script supports testing for both Jump-Oriented Programming (JOP) and Return-Oriented Programming (ROP) vulnerabilities. JOP is the default test and is executed first.
Note: If the ROP test is selected, the script will automatically input a dummy JOP string first to bypass the initial check before executing the ROP payload._
# Test JOP (Forward-edge / Landing Pads)
python3 scripts/exploit.py --exploit jop
# Test ROP (Backward-edge / Shadow Stack)
python3 scripts/exploit.py --exploit rop- Observe the Results:
- Without CFI: The exploit succeeds, redirecting control flow to
win_function(). - With CFI Enabled: The hardware traps the violation and outputs a fatal crash report over UART.
- Without CFI: The exploit succeeds, redirecting control flow to
- 5 Stage Pipeline
- Core
- Memory Controller
- UART
- SoC
- Architectural Verification with RISCOF
- Bootstrap C
- Bootstrap libC
- Tetris
- Pong
- Zicfilp
- Smpmpind
- Smcfiss
- Bootloader
- Wishbone Interconnect
- DDR3 controller
- Cache
- ASCII Doom
- Branch Prediction Unit
Install Nix using the Determinate Systems installer:
curl -fsSL https://install.determinate.systems/nix | sh -s -- install --determinateFork the repository at github.com/ethycS0/eSC-V, then clone your fork:
git clone git@github.com:your_github_username/eSC-V.git
cd eSC-VEnter the development environment (required for each terminal session):
nix developPlace implementations in src/ and testbenches in tb/ . Use the Makefile to build and test:
make run TB=tb_module # Run simulation
make view # View waveformsClean generated files before committing. I personally use this awesome formatter to format code and comments before committing.
make clean
git add .
git commit -m "feat: implement module"
git push origin mainOpen a pull request from your fork on GitHub with a clear description of your changes.
