A reusable, configurable template for FPGA development with Verilog, Xilinx Vivado, and VS Code. Designed for CMOD A7 but easily adaptable to other boards.
- π― Centralized Configuration: Single
config.tclfile to configure all project settings - π€ Automated Build System: PowerShell and TCL scripts for synthesis, implementation, and programming
- πΎ Non-Volatile Flash Support: Program configuration memory so design persists after power cycle
- π¦ Multi-Board Support: Easy switching between FPGA boards
- π§ VS Code Integration: Tasks for one-click builds and programming
- π Example Projects: LED blinker, switch display, and reaction game included
- π Private Project Folder: Keep personal projects private with
src_main/(git-ignored)
.
βββ .github/
β βββ copilot-instructions.md # GitHub Copilot instructions
βββ .vscode/
β βββ extensions.json # Recommended VS Code extensions
β βββ settings.json # Workspace settings
β βββ tasks.json # Build tasks
βββ src/ # π Template examples (public)
β βββ blink.v # Example: LED blink module
β βββ switch_display.v # Example: Switch to LED mapping
β βββ reaction_game.v # Example: Reaction game
βββ src_main/ # π YOUR PROJECTS (git-ignored, private)
β βββ README.md # Instructions for personal projects
βββ constraints/
β βββ cmod_a7.xdc # Pin constraints for CMOD A7
βββ testbench/
β βββ (simulation testbenches)
βββ scripts/
β βββ config.tcl # βοΈ PROJECT CONFIGURATION (edit this!)
β βββ build.tcl # Vivado synthesis & implementation
β βββ program.tcl # FPGA programming script
β βββ flash.tcl # Non-volatile configuration flash programming
β βββ build.ps1 # PowerShell automation script
βββ build/ # Generated artifacts (git-ignored)
βββ .gitignore
βββ TEMPLATE_GUIDE.md # Template usage guide
βββ README.md
-
Xilinx Vivado ML Edition (2023.1 or later)
- Download from Xilinx website
- Install with CMOD A7 board support
-
VS Code Extensions (Auto-recommended)
- mshr-h.veriloghdl - Verilog HDL/SystemVerilog syntax highlighting
- teros-technology.teroshdl - Advanced HDL support, linting, and documentation
-
CMOD A7 Board (or compatible)
- Default:
xc7a35tcpg236-1 - Connect via USB (provides both power and JTAG)
- Default:
- Clone or download this project
- Open the folder in VS Code
- Install recommended extensions when prompted
- Configure your project by editing
scripts/config.tcl:set PROJECT_NAME "my_project" set TOP_MODULE "my_top_module" set SOURCE_FILES [list "my_top_module.v"]
- Update Vivado path in
scripts/build.ps1if needed (default:C:\Xilinx\Vivado\2023.1\bin\vivado.bat)
π See TEMPLATE_GUIDE.md for detailed configuration options
This template uses a dual-folder approach to let you maintain public template examples while keeping your personal projects private:
-
src/- Template examples (public, tracked in git)- Contains reference designs:
blink.v,switch_display.v,reaction_game.v, etc. - These files are shared publicly as examples for others to learn from
- Contains reference designs:
-
src_main/- Your personal projects (private, git-ignored)- All files here are automatically excluded from git
- Place your custom Verilog projects here
- Build system is pre-configured to use this folder
-
Create your Verilog files in
src_main/:# Copy a template example to get started Copy-Item src\blink.v src_main\my_project.v
-
Edit
scripts/config.tcl:set PROJECT_NAME "my_project" set TOP_MODULE "my_top" set SOURCE_FILES [list "my_project.v"] # Or use "*.v" to include all files in src_main/
-
Build and program normally - everything already points to
src_main/
To build and test template examples from src/:
- Temporarily edit
scripts/build.tclline 4: changesrc_mainback tosrc - Update
config.tclto reference the template module - Build and test
- Switch back to
src_mainfor your personal work
π‘ Tip: Your personal projects in
src_main/will never be pushed to GitHub, keeping your work private while you maintain and share the template!
Use this sequence for reliable bring-up:
- Build the design (
buildorBuild FPGA Design). - Program volatile SRAM (
programorProgram FPGA) and verify behavior on hardware. - If verification passes, flash configuration memory (
flashorFlash FPGA (Non-Volatile)). - Power-cycle the board and confirm auto-boot from flash.
-
Build the design:
- Press
Ctrl+Shift+Bor run task:Terminal > Run Build Task - Builds synthesis, implementation, and generates bitstream
- Press
-
Program the FPGA:
- Press
Ctrl+Shift+PβTasks: Run TaskβProgram FPGA - Programs the connected CMOD A7 board
- Press
-
Flash configuration memory (non-volatile):
- Press
Ctrl+Shift+PβTasks: Run TaskβFlash FPGA (Non-Volatile) - Writes bitstream into external configuration flash (boots after power cycle)
- Press
-
Build and Program:
- Run task:
Build and Program FPGA - Does both in one step
- Run task:
-
Build and Flash:
- Run task:
Build and Flash FPGA - Builds bitstream, then flashes configuration memory
- Run task:
-
Clean build artifacts:
- Run task:
Clean Build
- Run task:
# Build only
.\scripts\build.ps1 -Action build
# Program only (requires existing build)
.\scripts\build.ps1 -Action program
# Build and program
.\scripts\build.ps1 -Action all
# Flash only (non-volatile, persists after power cycle)
.\scripts\build.ps1 -Action flash
# Build and flash
.\scripts\build.ps1 -Action allflash
# Clean build directory
.\scripts\build.ps1 -Action clean
# Specify custom Vivado path
.\scripts\build.ps1 -Action build -VivadoPath "C:\Xilinx\Vivado\2023.2\bin\vivado.bat"# Run synthesis and implementation
vivado -mode batch -source scripts/build.tcl
# Program FPGA
vivado -mode batch -source scripts/program.tcl
# Flash non-volatile configuration memory
vivado -mode batch -source scripts/flash.tclprogramwrites the FPGA SRAM image only; configuration is lost after power-off.flashwrites the external configuration memory; FPGA reloads design automatically on next boot.all= build + volatile program.allflash= build + non-volatile flash.
- Follow Verilog-2001 standard
- Use non-blocking assignments (
<=) for sequential logic - Use blocking assignments (
=) for combinational logic - Add meaningful comments
- Keep modules focused and reusable
The included src/blink.v demonstrates:
- Clock divider for 12MHz input clock
- Simple counter-based state machine
- Active-low reset handling
- LED output control
-
Edit
scripts/config.tcl(this is the ONLY file you need to edit!):set PROJECT_NAME "my_new_project" set TOP_MODULE "my_top_module" set SOURCE_FILES [list "my_top_module.v"] # Or use all .v files: set SOURCE_FILES "*.v"
-
Create
.vfiles insrc/directory -
Add pin constraints in
constraints/directory -
Build and program using the workflow below
π‘ No need to edit build scripts! All configuration is centralized in
config.tcl
Key pins configured in constraints/cmod_a7.xdc:
| Signal | Pin | Description |
|---|---|---|
| clk | L17 | 12 MHz system clock |
| rst_n | A18 | Button 0 (reset) |
| led | A17 | RGB LED (blue channel) |
See constraint file for complete pinout including:
- RGB LED channels (R, G, B)
- Buttons (BTN0, BTN1)
- Pmod header JA pins
Create testbenches in testbench/ directory:
`timescale 1ns / 1ps
module blink_tb;
reg clk, rst_n;
wire led;
blink uut (
.clk(clk),
.rst_n(rst_n),
.led(led)
);
initial begin
clk = 0;
forever #41.67 clk = ~clk; // 12MHz
end
initial begin
rst_n = 0;
#100 rst_n = 1;
#100000 $finish;
end
endmoduleAfter building, find reports in build/:
timing_summary.rpt- Timing analysisutilization.rpt- Resource utilizationpower.rpt- Power estimation
Update the path in scripts/build.ps1:
$VivadoPath = "C:\Xilinx\Vivado\YOUR_VERSION\bin\vivado.bat"- Install Xilinx USB Cable drivers
- Check Device Manager for "Digilent USB Device"
- Try different USB port/cable
- Check Verilog syntax
- Verify module names match between files
- Review
build/*.logfiles
- Check
timing_summary.rpt - Add timing constraints in XDC file
- Optimize critical paths
See TEMPLATE_GUIDE.md for comprehensive documentation on:
- Configuration options
- Example project setups
- Multi-board support
- Troubleshooting
This project is licensed under the MIT License - see the LICENSE file for details.
Free to use for educational and commercial purposes.
Feel free to submit issues, fork the repository, and create pull requests for improvements.
Created by Gavin Tan SUTD-EPD Made for SUTD Engineering Product Development Digital Systems Lab (Year 2026)