Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/vivado-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# .github/workflows/vivado-build.yml
#
# Vivado FPGA Build — gf16_heartbeat_uart_top
# Target: xc7a100tfgg676-1 (QMTech Wukong V1)
#
# Runs on a self-hosted runner with Vivado 2023.2 installed locally.
# The runner must carry labels: [self-hosted, linux, vivado].
# Configure XILINX_VIVADO in the runner's environment (see SETUP_RUNNER.md).

name: Vivado FPGA Build

on:
push:
branches:
- feat/vivado-ci
pull_request:
types: [labeled]
workflow_dispatch:

jobs:
build-bitstream:
# Only run PR builds when the "build:vivado" label is attached.
# Push and workflow_dispatch runs always proceed.
if: >
github.event_name != 'pull_request' ||
contains(github.event.pull_request.labels.*.name, 'build:vivado')

name: Build .bit (Vivado 2023.2)
runs-on: [self-hosted, linux, vivado]
timeout-minutes: 30

steps:
# ── 1. Checkout ──────────────────────────────────────────────────────────
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1

# ── 2. Vivado on PATH ────────────────────────────────────────────────────
#
# XILINX_VIVADO must be set in the runner's systemd unit or .env file,
# e.g.: XILINX_VIVADO=/opt/Xilinx/Vivado/2023.2
#
# We extend PATH here rather than sourcing settings64.sh to avoid
# polluting the environment with every Vivado variable (and because
# .sh files are disallowed in this repository).
- name: Add Vivado to PATH
run: echo "$XILINX_VIVADO/bin" >> "$GITHUB_PATH"
env:
XILINX_VIVADO: ${{ env.XILINX_VIVADO }}

# ── 3. Vivado batch build ────────────────────────────────────────────────
- name: Run Vivado build
working-directory: fpga/vivado/uart
run: >
vivado
-mode batch
-nojournal
-nolog
-source build.tcl
env:
XILINX_VIVADO: ${{ env.XILINX_VIVADO }}

# ── 4. Upload artefacts ──────────────────────────────────────────────────
- name: Upload bitstream and reports
uses: actions/upload-artifact@v4
with:
name: vivado-output-${{ github.sha }}
path: |
fpga/vivado/uart/build/output/gf16_heartbeat_uart_top.bit
fpga/vivado/uart/build/output/utilization.rpt
fpga/vivado/uart/build/output/timing.rpt
if-no-files-found: error
retention-days: 30

# ── 5. SHA-256 summary ───────────────────────────────────────────────────
- name: Write SHA-256 to step summary
run: |
BIT=fpga/vivado/uart/build/output/gf16_heartbeat_uart_top.bit
SHA=$(sha256sum "$BIT" | awk '{print $1}')
echo "## Bitstream" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Field | Value |" >> "$GITHUB_STEP_SUMMARY"
echo "|-------|-------|" >> "$GITHUB_STEP_SUMMARY"
echo "| File | \`gf16_heartbeat_uart_top.bit\` |" >> "$GITHUB_STEP_SUMMARY"
echo "| SHA-256 | \`$SHA\` |" >> "$GITHUB_STEP_SUMMARY"
echo "| Commit | \`${{ github.sha }}\` |" >> "$GITHUB_STEP_SUMMARY"
62 changes: 62 additions & 0 deletions fpga/vivado/uart/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Dockerfile — self-hosted GitHub Actions runner base image
#
# Does NOT install Vivado. Vivado is expected to be bind-mounted from the
# host at /tools/Xilinx (or /opt/Xilinx) at container start, matching a
# typical self-hosted setup where the installer was run once on bare metal.
#
# Build:
# docker build -t ghactions-vivado-runner .
#
# Run example (Vivado on host at /opt/Xilinx):
# docker run --rm \
# -v /opt/Xilinx:/opt/Xilinx:ro \
# -e XILINX_VIVADO=/opt/Xilinx/Vivado/2023.2 \
# -e RUNNER_TOKEN=<token> \
# ghactions-vivado-runner
#
# The RUNNER_TOKEN must be obtained fresh from:
# https://github.com/<owner>/<repo>/settings/actions/runners/new

FROM ubuntu:22.04

LABEL org.opencontainers.image.description="GitHub Actions self-hosted runner base for Vivado (Vivado volume-mounted from host)"

ENV DEBIAN_FRONTEND=noninteractive

# Runtime dependencies required by Vivado on Ubuntu 22.04.
# libtinfo5 is not in 22.04 main repos; libncurses5 pulls it transitively
# via the compat package. Install both to be safe.
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
git \
jq \
libc6 \
libglib2.0-0 \
libgtk2.0-0 \
libncurses5 \
libstdc++6 \
libtinfo5 \
libxext6 \
libxrender1 \
libxtst6 \
locales \
sudo \
unzip \
&& rm -rf /var/lib/apt/lists/*

# Generate en_US.UTF-8 locale (Vivado log parser expects it)
RUN locale-gen en_US.UTF-8
ENV LANG=en_US.UTF-8

# Create a non-root runner user
RUN useradd -m -s /bin/bash runner && \
echo "runner ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER runner
WORKDIR /home/runner

# The entrypoint should configure and start the Actions runner.
# Configuration is left to the operator (token rotation, repo URL, labels).
# See SETUP_RUNNER.md for details.
CMD ["/bin/bash"]
84 changes: 84 additions & 0 deletions fpga/vivado/uart/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# fpga/vivado/uart — Vivado CI

Continuous integration pipeline for building the `gf16_heartbeat_uart_top`
bitstream via Vivado 2023.2 on a self-hosted GitHub Actions runner.

## Contents

| File | Purpose |
|------|---------|
| `build.tcl` | Vivado batch build script — synth → opt → place → route → write_bitstream |
| `vivado-build.yml` | GitHub Actions workflow (copy to `.github/workflows/`) |
| `Dockerfile` | Optional base image for containerised runner (Vivado volume-mounted from host) |
| `SETUP_RUNNER.md` | Step-by-step guide: install Vivado, register runner, configure labels |
| `README.md` | This file |
| `SUMMARY.md` | What was scaffolded and what you need to do next |

## Quick Start

### Prerequisites

- A Linux machine with **Vivado 2023.2 Standard Edition** installed
(see `SETUP_RUNNER.md` for download and licence instructions)
- GitHub Actions self-hosted runner registered to this repo
with labels `self-hosted`, `linux`, `vivado`
- `XILINX_VIVADO=/opt/Xilinx/Vivado/2023.2` in the runner's environment

### Repository layout expected by the build

```
fpga/
vsa/
gf16_dot4.v ← shared GF(2^4) dot-product module
uart/
build.tcl ← this directory
gf16_heartbeat_uart_top.v
gf16_heartbeat_uart_top.xdc
build/output/ ← created by build.tcl
gf16_heartbeat_uart_top.bit
utilization.rpt
timing.rpt
```

### Trigger a build

**Via push:** any push to `feat/vivado-ci` triggers the workflow automatically.

**Via UI:** Actions → *Vivado FPGA Build* → *Run workflow*.

**Via PR:** attach the label `build:vivado` to a pull request.

### Workflow file placement

Copy (or symlink) `vivado-build.yml` to `.github/workflows/vivado-build.yml`
in the repository root before merging.

---

## Reference Design

The **current working heartbeat bitstream** (no UART) is:

```
fpga/vivado/gf16_heartbeat_top.bit
```

It was built from `gf16_heartbeat_top.v` + `gf16_heartbeat_top.xdc` against
the same xc7a100tfgg676-1 target and is already confirmed functional on the
QMTech Wukong V1 board.

The UART variant (`gf16_heartbeat_uart_top`) extends that design with a
115200-baud TX telemetry output on pin K20.

---

## Target

| Parameter | Value |
|-----------|-------|
| FPGA | xc7a100tfgg676-1 |
| Board | QMTech Wukong V1 |
| Top module | `gf16_heartbeat_uart_top` |
| Clock | CFGMCLK ≈ 65 MHz (STARTUPE2) |
| UART TX pin | K20 (115200 8N1) |
| Tool | Vivado 2023.2 Standard Edition |
Loading
Loading