ai-in-ci-cd
An AI review step inside a self-hosted pipeline. A push to GitLab starts a job on a runner in another machine; the runner lints, simulates and synthesizes the design, then hands the diff to a local Qwen3.8 model, and the findings come back as a comment on the merge request. Three ordinary machines, no cloud service, and no line of RTL leaves the network.
- lint
- simulation
- synthesis
- ai-review
What runs where #
The pipeline is split across machines a small team usually already has, or can add without a data-centre budget. Each one does one job, and they only talk to each other.
gitlab-server
Self-hosted GitLab holds the repositories and the merge requests. When a change is pushed it creates a pipeline and queues its jobs; at the end it shows the results and the review comment where the engineers already work.
- GitLab CE
- merge requests
- job artifacts
runner
A separate machine with gitlab-runner and the open-source FPGA tools. It
checks out the change, runs lint, simulation and synthesis, collects the diff and the
logs, and asks the model for a review. Vendor tools can live here too when licences allow.
- Verilator
- Icarus Verilog
- Yosys
- Docker or shell executor
model-server
Qwen3.8 served on a GPU workstation behind an OpenAI-compatible API. It receives the diff, the tool reports and the team's written rules, and answers with structured findings. The firewall gives it no route to the internet.
- Qwen3.8
- OpenAI-compatible API
- no outbound traffic
The pipeline file #
The AI step is one more job in .gitlab-ci.yml. It only runs once the
deterministic checks have passed, so the model reviews a design that already builds and
simulates, and its output is a comment, never a merge.
stages: [lint, sim, synth, review] lint: stage: lint tags: [fpga] script: - verilator --lint-only -Wall rtl/*.v sim: stage: sim tags: [fpga] script: - make -C tb sim # iverilog + vvp, self-checking testbenches synth: stage: synth tags: [fpga] script: - yosys -s scripts/synth.ys | tee synth.log ai-review: stage: review tags: [fpga] rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" variables: LLM_URL: http://gpu-01.lan:8000/v1 # internal address only LLM_MODEL: qwen3.8 script: - git diff origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME... -- rtl tb > change.diff - ai-review --diff change.diff --rules docs/rtl_rules.md --logs synth.log --post-to-mr artifacts: paths: [review/]
Why it suits a small team #
The code stays in-house
Model, runner and repository are on your machines. Customer IP and NDAs are not a reason to stay away from AI.
No per-seat subscriptions
One GPU workstation serves the whole team's pipelines. The cost is the hardware and the power, not a licence per engineer.
Reviews that never get skipped
Every merge request gets a first pass against the team's own rules, so the human reviewer starts from the questions that matter.
Built from open pieces
GitLab, gitlab-runner, open FPGA tools and an open-weights model. Nothing is locked to one vendor, and the team can maintain it.
Lint, 128 simulation checks and synthesis pass. Two notes on the change:
rtl/uart_tx.v:57— the parity bit is computed fromtx_shiftafter the first shift. Compute it fromtx_datawhentx_startis accepted.tb/tb_uart_tx.v— odd parity is never exercised. A test case is attached to the job artifacts.Model: qwen3.8 on gpu-01 · rules:
docs/rtl_rules.md· 41 s