You already know Boolean logic, state machines, and binary arithmetic cold. The hard part of learning Verilog for someone with your background isn't the syntax — it's unlearning one habit: reading code as a sequence of steps that happen one after another.
A C or Python program is a recipe: the CPU has one instruction pointer, and it executes statements in order, one at a time. Verilog describes something structurally different — a piece of physical hardware. A circuit has no instruction pointer. Every gate, flip-flop, and wire in a real chip exists simultaneously and reacts continuously to whatever is happening around it. Verilog's job is to describe that circuit, so most of a Verilog file describes things that are all "running" — really, all physically existing and reacting — at the same time, forever, not a sequence of steps.
This is why Verilog is called a Hardware Description Language (HDL) rather than a programming language. You're not telling a machine what to do step by step. You're describing what hardware should exist and how its pieces are wired together and behave.
Click Step through software repeatedly to see one line execute at a time. Click Power on hardware to see all four blocks become active simultaneously — that's the circuit these same four operations would become in silicon.
Both sides compute the same four things. The software column is what you're used to: one line finishes
before the next starts. The hardware column is what Verilog is actually describing: four independent
pieces of logic — an adder, a comparator, a state register, a decoder — that all exist as separate
circuitry and are all "on" continuously. The adder doesn't wait its turn. It's a physical block of gates
that's always computing a + b, whether or not anything downstream is looking at the answer
yet.
A Verilog file is normally processed by two different kinds of tools, and it helps to know which job is happening when, because they don't always treat your code the same way.
| Tool | What it does | Cares about |
|---|---|---|
| Simulator e.g. Icarus Verilog, ModelSim, Verilator |
Executes your design as a program, advancing a virtual clock, so you can check the design behaves correctly before it ever touches real hardware. | Correct behavior over time. Will happily run code that could never be built as a real circuit. |
| Synthesis tool e.g. Yosys, Vivado, Quartus |
Reads a subset of Verilog and produces a netlist — an actual list of gates and flip-flops and how they're wired — targeting an FPGA or ASIC. | Only constructs that map to real gates. Rejects or warns on anything it can't turn into hardware. |
This split matters immediately: some Verilog is synthesizable (it describes real hardware) and some is simulation-only (it's scaffolding that helps you test the design — printing messages, generating a clock signal, forcing values onto wires — but could never exist as silicon). You'll write both kinds. The code that describes your circuit must be synthesizable; the code that exercises and checks that circuit — the testbench, which you'll meet properly in Lesson 6 — is simulation-only and is never synthesized.
If a function is software's unit of structure, a module is hardware's. A module is a named, reusable block with a fixed interface (a set of input and output wires) and an implementation inside. Here's the shape, with details deferred to Lesson 2:
module and_gate(
input a,
input b,
output y
);
assign y = a & b;
endmodule
The crucial difference from a function: calling a function in software means "pause here, go run that
code, come back." Instantiating a module means "there is now a physical copy of this
circuit, permanently wired in, running all the time." If you instantiate and_gate three
times in a design, you get three distinct AND gates on the chip — not one piece of logic invoked three
times.
Inside a module you'll write two broad flavors of description, covered in depth in Lessons 3 and 4:
assign, and one style of
always block) — "this wire is always equal to this expression," like the adder and
decoder above.always block) —
"on every rising edge of the clock, update this piece of memory," like the state register above.Both are still concurrent with everything else in the design. The clocked block doesn't "pause" the combinational logic around it — it's simply describing a different kind of hardware element (memory) that only changes at specific moments, sitting right alongside logic that's continuously live.
assign statements in a Verilog module, one on line 4 and one on line 20. What can you conclude about their execution order?assign statements in one Verilog module. Convince yourself these are the same kind of
object — a static structure that exists all at once — described two different ways. That mental
substitution is the single biggest unlock for reading Verilog fluently.
New terms from this lesson — HDL, module, synthesizable, testbench, netlist — are collected with fuller definitions in the glossary.