Tools & Productivity

Git for VLSI Engineers

Version control for RTL, SDC, synthesis scripts, and IP blocks. Learn branching strategies, EDA-friendly workflows, and how to never lose a working RTL revision again.

Contents
  1. Why Git for VLSI?
  2. Core Concepts
  3. First-Time Setup
  4. Basic Daily Workflow
  5. Branching & Merging
  6. Stash — Save Work in Progress
  7. History, Blame & Diff
  8. .gitignore for EDA Projects
  9. VLSI-Specific Workflows
  10. Quick Reference
  11. Q&A

1 Why Git for VLSI?

VLSI projects involve dozens of interdependent files — RTL, constraints (SDC), synthesis scripts (TCL), timing reports, UPF, netlists. A single wrong edit to a timing constraint can break a working closure. Git lets you track every change, branch for experiments, and instantly restore any previous state — without copying directories named rtl_backup_v3_FINAL_final2.

2 Core Concepts

Git has four distinct areas where files live:

Working Directory
→ git add →
Staging Area
→ git commit →
Local Repo
→ git push →
Remote Repo

3 First-Time Setup

# Set your identity (appears in every commit)
git config --global user.name "Your Name"
git config --global user.email "you@company.com"

# Set default editor (for commit messages)
git config --global core.editor vim

# Set default branch name to 'main'
git config --global init.defaultBranch main

# Better diff output — shows word-level changes
git config --global diff.wordRegex "[^[:space:]]"

# Colorized output
git config --global color.ui auto

# Store credentials (for HTTPS remotes)
git config --global credential.helper store

# View your config
git config --list

4 Basic Daily Workflow

Starting a Repository

# New project from scratch
git init my_rtl_project
cd my_rtl_project

# Clone an existing remote project
git clone https://github.com/company/chip_top.git
git clone git@internal-server:vlsi/soc_design.git

The Everyday Cycle

# 1. Check current state
git status

# 2. See what changed
git diff                   # unstaged changes
git diff --staged          # staged changes (what will be committed)

# 3. Stage specific files
git add rtl/fifo_ctrl.sv
git add constraints/top.sdc
git add -p                 # interactive: stage specific hunks, not whole files

# 4. Commit with a clear message
git commit -m "Fix CDC synchronizer in fifo_ctrl — 2FF chain missing"

# 5. Push to remote
git push origin main

# 6. Pull latest from teammates
git pull origin main

Writing Good Commit Messages

# Bad — tells you nothing useful later
git commit -m "fix stuff"
git commit -m "update"

# Good — explains WHAT and WHY
git commit -m "Add reset synchronizer to async_fifo — fixes CDC lint error CDC-003"
git commit -m "Update SDC: tighten hold margin on clk_div2 path to 0.1ns"
git commit -m "Refactor APB slave decode — remove redundant mux for synthesis QoR"
Rule of thumb: If you read this commit message in 6 months, will you know why the change was made — not just what changed? If not, add more context.

5 Branching & Merging

Branches are Git's killer feature. Creating a branch for a risky RTL experiment costs nothing — no file copying, no extra disk space. If it doesn't work, delete it. If it works, merge it.

Branch Commands

# List branches (* = current)
git branch

# Create and switch to a new branch
git checkout -b feature/add-pipeline-stage
# Modern syntax:
git switch -c feature/add-pipeline-stage

# Switch between branches
git switch main
git switch feature/add-pipeline-stage

# Delete a branch (after merging)
git branch -d feature/add-pipeline-stage

# Force delete (unmerged)
git branch -D feature/bad-experiment

Merging

# Merge a feature branch into main
git switch main
git merge feature/add-pipeline-stage

# Merge with a commit (no fast-forward) — preserves branch history
git merge --no-ff feature/add-pipeline-stage -m "Merge pipeline stage feature"

Rebase — Clean Linear History

# Rebase feature branch onto latest main
git switch feature/cdc-fix
git rebase main

# Interactive rebase — squash/reorder commits before merging
git rebase -i HEAD~3       # edit last 3 commits
VLSI branching strategy: Use main for tape-out-ready RTL only. All work happens in feature branches (feature/), bug fixes in fix/ branches, and tapeout prep in release/v1.0 branches. Merge to main only after synthesis and lint pass.

Resolving Merge Conflicts

# Git marks conflicts in the file like this:
<<<<<<< HEAD
  assign data_out = fifo_rd_data;       // your version
=======
  assign data_out = pipeline_rd_data;   // incoming version
>>>>>>> feature/pipeline-stage

# Edit the file to keep the correct version, then:
git add rtl/top.sv
git commit                 # completes the merge

# Or abort the merge entirely
git merge --abort

6 Stash — Save Work in Progress

You're mid-way through a CDC fix when your manager asks you to check a synthesis run on the clean branch. Git stash saves your uncommitted changes temporarily so you can switch branches cleanly.

# Save current uncommitted work
git stash
git stash push -m "WIP: cdc synchronizer rework"

# List stashes
git stash list

# Restore the most recent stash
git stash pop

# Restore a specific stash
git stash apply stash@{2}

# Stash including untracked files
git stash -u

# Drop a stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

7 History, Blame & Diff

git log

# Full log
git log

# Compact one-line view (best for orientation)
git log --oneline

# Graph view — see branching visually
git log --oneline --graph --all

# Log for a specific file (track all changes to a constraint file)
git log --oneline constraints/top.sdc

# Search commit messages
git log --oneline --grep="CDC"

# Show changes introduced in each commit
git log -p rtl/fifo_ctrl.sv

# Log since a date
git log --oneline --since="2 weeks ago"

git blame — Who Wrote This?

# Show who last changed each line
git blame rtl/alu.sv

# Blame a specific line range
git blame -L 45,80 rtl/alu.sv

# Show blame ignoring whitespace changes
git blame -w rtl/top.sv
RTL debug use case: A lint tool flags a suspicious signal assignment on line 127. git blame rtl/top.sv immediately shows who added that line, in which commit, and when — giving you the context behind the decision.

git diff

# Diff between two commits
git diff HEAD~1 HEAD rtl/fifo_ctrl.sv

# Diff between two branches
git diff main feature/cdc-fix -- rtl/

# Diff between two tags
git diff v1.2 v1.3 -- constraints/

# Show only file names that changed
git diff --name-only main feature/pipeline

Restore and Reset

# Discard changes to one file (restore from last commit)
git restore rtl/top.sv

# Unstage a file (keep changes in working directory)
git restore --staged rtl/top.sv

# Go back to a previous commit (creates a new commit)
git revert HEAD

# Hard reset to a specific commit — DESTRUCTIVE, loses uncommitted work
git reset --hard abc1234
Warning: git reset --hard permanently discards uncommitted changes. Always run git status and git stash first if you have work in progress.

8 .gitignore for EDA Projects

EDA tools generate massive output directories — simulation waveforms, synthesis databases, log files. These must never be committed. Place this .gitignore at your project root.

# ── Simulation ──────────────────────────────────────────────
work/                  # ModelSim/Questa compiled library
sim_build/
*.wlf                  # Questa waveform files
*.vcd                  # VCD waveform dumps
*.fst
vsim.wlf
transcript
*.ucdb                 # coverage databases

# ── Synthesis (Synopsys DC / Genus) ─────────────────────────
WORK/
alib-52/
*.pvl
*.syn
*.mr
*.svf
DC_SHELL/
work_dir/
mapped/
unmapped/
reports/
*.ddc                  # Design Compiler checkpoint

# ── Cadence ─────────────────────────────────────────────────
.cadence/
cds.lib
hdl.var
xcelium.d/
*.shm/
*.dsn

# ── Vivado / Quartus ────────────────────────────────────────
*.xpr.bak
.Xil/
vivado*.jou
vivado*.log
*.runs/
*.cache/
*.hw/
*.ip_user_files/
db/
incremental_db/

# ── Logs & Temp ─────────────────────────────────────────────
*.log
*.rpt                  # synthesis / timing reports — regenerate, don't commit
*.bak
*.tmp
*.orig
*~
\#*\#

# ── OS / Editor ─────────────────────────────────────────────
.DS_Store
Thumbs.db
*.swp
*.swo
.viminfo
What TO commit: RTL source (.v, .sv, .svh), constraints (.sdc, .upf, .xdc), synthesis scripts (.tcl), testbenches, documentation, and the .gitignore itself. Reports and databases are derived artifacts — regenerate them from the committed source.

9 VLSI-Specific Workflows

Tagging Synthesis Runs

# Tag the exact RTL state used for a synthesis run
git tag -a v2.1-synth-DC-2025-05 -m "DC synthesis run May 2025, WNS=-0.02ns"
git push origin v2.1-synth-DC-2025-05

# Checkout a specific tagged version to reproduce a run
git checkout v2.1-synth-DC-2025-05

Comparing RTL Between Synthesis Runs

# What RTL changed between two synthesis tags?
git diff v2.0-synth v2.1-synth -- rtl/
git diff v2.0-synth v2.1-synth -- constraints/top.sdc

Tracking a File's Full Change History

# Every commit that touched this constraint file
git log --oneline -p constraints/top.sdc

# When was a specific timing exception added?
git log --oneline --all -S "set_multicycle_path" constraints/top.sdc

Working with Large Binary Files (LFS)

# Track large binary files (GDS, LEF, lib) with Git LFS
git lfs install
git lfs track "*.gds"
git lfs track "*.lib"
git lfs track "*.lef"
git add .gitattributes
git commit -m "Track large EDA binary files with Git LFS"

10 Quick Reference

CommandWhat it does
git statusShow what's modified, staged, and untracked
git diffShow unstaged changes line by line
git add -pInteractively stage specific hunks
git commit -m "..."Commit staged changes with message
git log --oneline --graphVisual branch history
git blame file.svShow who last changed each line
git switch -c branchCreate and switch to new branch
git merge branchMerge branch into current
git stash / git stash popSave/restore work in progress
git restore file.svDiscard changes to a file
git tag -a v1.0 -m "..."Create annotated tag for a release
git revert HEADUndo last commit safely (new commit)
git log -S "signal_name"Find when a specific string was added/removed
git diff branch1..branch2Show all changes between two branches

11 Q&A

I committed sensitive IP files accidentally. How do I remove them from history?

Use git filter-repo (preferred) or BFG Repo Cleaner to rewrite history and permanently remove the file from all commits. Then force-push: git push --force-with-lease. Alert all teammates immediately — they must re-clone the repository. Old copies still have the sensitive files. This is why a good .gitignore is critical upfront.

My synthesis team uses Perforce and I want to use Git locally. Can I do both?

Yes — use git-p4, a bridge tool included with Git. You sync from Perforce into a local Git repository, work in Git branches locally, then submit back to Perforce when ready. This lets you use Git's lightweight branching and stash features for local experiments while keeping the team's Perforce workflow intact. Run git p4 clone //depot/chip/rtl/... @all to create a local Git repo mirroring the Perforce depot.

How do I see only the RTL changes between two tapeout tags, excluding log files?

Use pathspec filtering in git diff: git diff v1.0..v1.1 -- '*.sv' '*.v' '*.sdc'. The -- separates git options from pathspecs. You can also use --name-only to see just the list of changed RTL files, then selectively view individual files with git diff v1.0..v1.1 -- rtl/fifo_ctrl.sv.

What's the best way to handle auto-generated netlists — commit them or not?

Generally do not commit auto-generated netlists — they are derived from the RTL source and synthesis scripts, which you do commit. Committing generated files causes noise in diffs, merge conflicts with no human meaning, and bloated repositories. The exception: a formally released gate-level netlist for handoff (to physical design, for example) can be tagged and archived in a separate delivery directory or with Git LFS to preserve the exact artifact for audit purposes.

How do I find exactly when a specific timing constraint was added or removed?

Use git log -S (the "pickaxe" option): git log -S "set_multicycle_path 2 -setup -from clk_a -to clk_b" --oneline constraints/top.sdc. This searches through the diff of every commit and shows only commits where the count of that string changed — meaning it was added or removed. Add -p to see the actual change context.