Verilog
Describe the hardware that runs AI.
Verilog is a hardware description language (HDL). Instead of instructions for a processor, you describe digital circuits: registers, adders, state machines and whole chips. GPUs, TPUs and every AI accelerator start life as HDL code like Verilog or SystemVerilog before they are turned into silicon or loaded onto an FPGA.
Why learn Verilog?
If you want to understand how a tensor core or AI chip really works, you need to think in hardware, and Verilog is the most common way to do that.
- Real hardware: your code becomes logic gates and wires.
- Parallel by nature: every block runs at the same time, every clock cycle.
- AI chips: accelerators, systolic arrays and FPGA inference engines are designed in HDLs.
Set up and run your first program
Install Icarus Verilog to simulate and GTKWave to view waveforms. Verilator is a fast alternative for larger designs.
sudo apt install iverilog gtkwave
iverilog -o hello hello.v
vvp hellomodule hello;
initial begin
$display("Hello, AI! Welcome to Verilog.");
$finish;
end
endmoduleinitial blocks and $display only work in simulation; real hardware uses modules, wires and registers.Modules and wires
A module is a hardware block with input and output ports. assign creates continuous logic: the output always reflects the inputs, like a wire connected to gates.
module half_adder (
input wire a,
input wire b,
output wire sum,
output wire carry
);
assign sum = a ^ b; // XOR gate
assign carry = a & b; // AND gate
endmoduleVectors and arithmetic
Signals can be multi-bit buses like [7:0] for 8 bits. Arithmetic operators synthesise into adders and multipliers.
module mac8 (
input wire [7:0] a, b, // two 8-bit inputs (INT8)
input wire [15:0] acc_in,
output wire [15:0] acc_out
);
// multiply-accumulate: the core operation of neural networks
assign acc_out = acc_in + a * b;
endmoduleClocks and registers
always @(posedge clk) describes flip-flops that update on each rising clock edge. Use non-blocking assignment <= inside clocked blocks.
module counter (
input wire clk,
input wire rst,
output reg [7:0] count
);
always @(posedge clk) begin
if (rst) count <= 8'd0;
else count <= count + 8'd1;
end
endmoduleState machines
Finite state machines control hardware step by step. A register holds the current state; a case statement picks the next one.
module loader (input wire clk, rst, start, done, output reg busy);
localparam IDLE = 2'd0, LOAD = 2'd1, COMPUTE = 2'd2;
reg [1:0] state;
always @(posedge clk) begin
if (rst) state <= IDLE;
else case (state)
IDLE: if (start) state <= LOAD;
LOAD: state <= COMPUTE;
COMPUTE: if (done) state <= IDLE;
default: state <= IDLE;
endcase
end
always @(*) busy = (state != IDLE);
endmoduleTestbenches
A testbench is a simulation-only module that drives inputs, generates a clock and checks outputs.
module tb;
reg clk = 0, rst = 1;
wire [7:0] count;
counter dut (.clk(clk), .rst(rst), .count(count));
always #5 clk = ~clk; // 10 ns clock
initial begin
$dumpfile("wave.vcd"); $dumpvars(0, tb);
#12 rst = 0;
#100 $display("count = %0d", count);
$finish;
end
endmodule
// iverilog -o sim tb.v counter.v && vvp sim && gtkwave wave.vcdVerilog and AI hardware
AI accelerators are built from huge arrays of multiply-accumulate (MAC) units. Google's TPU uses a systolic array, where data flows between neighbouring MACs each clock cycle, and NVIDIA's tensor cores are dedicated matrix-multiply units. FPGA engineers write Verilog (or use high-level synthesis) to build custom inference engines, and LLMs are now being used to help write and verify HDL.
The essential libraries
A processing element for a systolic array
Each PE multiplies its inputs, adds to its accumulator and passes data to its neighbours on the next cycle.
module pe (
input wire clk, rst,
input wire signed [7:0] a_in, b_in,
output reg signed [7:0] a_out, b_out,
output reg signed [31:0] acc
);
always @(posedge clk) begin
if (rst) begin
acc <= 0; a_out <= 0; b_out <= 0;
end else begin
acc <= acc + a_in * b_in; // MAC
a_out <= a_in; // pass right
b_out <= b_in; // pass down
end
end
endmoduleAn agent that runs hardware simulations
An AI agent can help design hardware if it can run the simulator. This Python agent lets a local model compile and simulate Verilog files with Icarus Verilog and read the results.
import json, subprocess
from openai import OpenAI
def simulate(files):
b = subprocess.run(["iverilog", "-o", "sim", *files], capture_output=True, text=True)
if b.returncode: return "Compile error:\n" + b.stderr
return subprocess.run(["vvp", "sim"], capture_output=True, text=True, timeout=30).stdout
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
tools = [{"type": "function", "function": {"name": "simulate", "description": "Compile and simulate Verilog files",
"parameters": {"type": "object", "properties": {"files": {"type": "array", "items": {"type": "string"}}}, "required": ["files"]}}}]
messages = [{"role": "user", "content": "Simulate tb.v with counter.v and tell me the final count."}]
for _ in range(5):
msg = client.chat.completions.create(model="llama3.1", messages=messages, tools=tools).choices[0].message
messages.append(msg)
if not msg.tool_calls:
print(msg.content); break
for c in msg.tool_calls:
messages.append({"role": "tool", "tool_call_id": c.id, "content": simulate(**json.loads(c.function.arguments))})Run the simulator in a sandbox; the agent should only see the project folder.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.Verilog learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
Verilog cheat sheet
| Task | Syntax |
|---|---|
| Module | module m(input a, output y); endmodule |
| Wire logic | assign y = a & b; |
| Register | always @(posedge clk) q <= d; |
| Bus | wire [7:0] data; |
| Case | case (s) 0: ...; endcase |
| Print (sim) | $display("%d", x); |
Common mistakes
- Use
<=in clocked blocks and=in combinational blocks; mixing them causes simulation/hardware mismatches. - Forgetting a default in combinational logic creates unwanted latches.
- Delays like
#5are ignored by synthesis; they only work in simulation.
Where to go next
- HDLBits — practice online
- ChipVerify — tutorial
- Verilator — simulator
On TensorCore.si: VHDL volume, What is a tensor core?.
Keyboard: [ previous language · ] next language · / search the library