In short: Verilog is a hardware description language whose statements describe parallel circuits rather than sequential instructions, and only a disciplined subset of it (the synthesizable subset) can be turned into gates by tools such as Synopsys Design Compiler or Xilinx Vivado.
What Verilog actually is
Verilog HDL was created by Gateway Design Automation in 1984 as a simulation language, was acquired by Cadence, and was standardised as IEEE 1364 in 1995. It was later merged with its richer verification cousin and is now maintained as IEEE 1800 SystemVerilog. The key idea to absorb on day one: Verilog is not a programming language that happens to run on chips. It is a notation for describing structure and behaviour of hardware, which a simulator can execute and a synthesis tool can map to logic.
That dual life explains most interview questions on the topic. The same text file may be read by a simulator (Siemens Questa, Cadence Xcelium, Synopsys VCS) that executes it over simulated time, or by a synthesis tool that tries to infer flip-flops, LUTs and wires from it. The two readers accept different amounts of the language.
Key fact: A module in Verilog is a piece of hardware that exists permanently and is always "on". Instantiating it ten times creates ten physical copies, not ten function calls.
How Verilog models concurrency
A software program has one program counter walking through lines. A chip has thousands of gates switching at once. Verilog reflects this with concurrent constructs: every assign statement, every always block, every initial block and every module instance is a process that starts at time zero and runs in parallel with all the others. Their order in the source file is irrelevant.
Inside a single always block, statements execute in order (like software), but the block as a whole is simply sensitive to events: always @(posedge clk) wakes up only on a rising clock edge, while always @(*) wakes whenever any input changes. A continuous assignment such as assign y = a & b; is like a physical AND gate: change a and y is re-evaluated automatically.
The event-driven simulation model
A simulator cannot literally run everything at once on a CPU, so it uses an event queue. When a signal changes, every process sensitive to it is scheduled. The standard divides each time step into regions: first the active region (blocking assignments and evaluation of right-hand sides), then the NBA (non-blocking assignment) region where <= updates are committed. That two-phase trick is why a shift register written with non-blocking assignments behaves like real flip-flops sampling the same clock edge. We cover the consequences in detail in Blocking vs Non Blocking Verilog.
module shift3 (input clk, input d, output reg q2);
reg q0, q1;
always @(posedge clk) begin
q0 <= d;
q1 <= q0; // sees OLD q0 - a true 3-stage pipeline
q2 <= q1;
end
endmodule
If you replaced <= with =, the simulator would pass d through all three stages in a single edge, collapsing the pipeline into one flip-flop. Real silicon would never do that, which is exactly why this is a favourite interview trap.
Data types and what they become in hardware
Verilog has two broad families: nets (wire) that model physical connections driven by something, and variables (reg) that hold a value between assignments. A reg is not automatically a register; whether it becomes a flip-flop depends on the sensitivity list of the block that drives it. See Reg vs Wire in Verilog for the full rules, and Verilog data types for the four-state logic values (0, 1, X, Z) that make simulation more expressive than silicon.
Four-state logic is itself a simulation-only luxury. In silicon a node is 0 or 1 (or high-impedance on a tri-state bus); "X" is merely the simulator's way of saying "unknown, probably a bug or an uninitialised register".
Simulation subset versus synthesis subset
A testbench needs things hardware cannot do: wait for 10 ns, print a message, read a file, generate random numbers. A synthesizer needs the opposite: constructs that map to a finite network of gates. The overlap is the synthesizable subset.
| Construct | Simulation | Synthesis |
|---|---|---|
#5 a = b; delay | Works | Ignored (warning) |
initial block | Works | FPGA: sets power-up value; ASIC: usually unsupported |
$display, $fopen | Works | Ignored or error |
for loop, fixed bounds | Works | Unrolled into parallel logic |
wait, fork/join | Works | Not supported |
case with X / casex | Works | Risky: sim/synth mismatch |
Key fact: Synthesis tools ignore #delay values, so a design that "works" only because of delays in simulation will fail on silicon. Real timing is set by gate and wire delays, checked later by static timing analysis in tools such as Synopsys PrimeTime or Cadence Tempus.
Classic simulation/synthesis mismatches
- Incomplete
iforcasein combinational logic. If an output is not assigned on every path, synthesis infers a latch. The simulator happily holds the old value; the lint tool should have warned you. - Incomplete sensitivity lists.
always @(a)for logic that also depends onbsimulates wrongly but synthesises as if the list were complete. Usealways @(*)or SystemVerilogalways_comb. - Mixing blocking and non-blocking in one block, giving race conditions in simulation that hardware never shows.
- X-optimism and X-pessimism. An
if (x)on an unknown takes the else branch in simulation, hiding a reset bug that real silicon would expose.
Coding styles: structural, dataflow, behavioural
Verilog can describe the same adder at three abstraction levels. Gate-level or structural code instantiates primitives and sub-modules (see Structural Modeling in Verilog); dataflow uses assign with operators; behavioural uses procedural blocks. Synthesis tools accept all three, but a typical RTL (register-transfer level) design is mostly behavioural for sequential logic and dataflow for simple combinational expressions. Also remember that simulation time resolution comes from the timescale directive, which is meaningless to synthesis but vital to a testbench.
Where Verilog sits in the design flow
An ASIC flow typically runs RTL simulation, logic synthesis (Synopsys Design Compiler or Cadence Genus), place-and-route (Innovus, IC Compiler II), and sign-off. An FPGA flow replaces the last stages with the vendor's implementation tools. Newer approaches such as high-level synthesis generate Verilog from C/C++, but engineers still read and debug the generated RTL. If you want hands-on practice, our CourseTron courses take you from first module to FPGA implementation, and the physical-design side is taught at ChipXpert.
Key fact: Most real-world bugs that survive RTL simulation come from the gap between what you simulated and what was synthesised. Running gate-level simulation and formal equivalence checking closes that gap.
Ready to write synthesizable Verilog? Join the CourseTron FPGA and VLSI courses at coursetron.com/courses and practise on real simulation and synthesis exercises.
Frequently asked questions
Is Verilog a programming language?
No. It is a hardware description language. Its statements describe circuits that exist concurrently, though testbench code can use procedural, software-like constructs that only a simulator understands.
Why is my simulation correct but my FPGA fails?
Common causes are unintended latches, incomplete sensitivity lists, reliance on # delays, uninitialised registers hiding as X in simulation, and unmet timing constraints. Check synthesis warnings first.
Is Verilog still relevant versus VHDL and SystemVerilog?
Yes. SystemVerilog is a superset of Verilog, so Verilog knowledge carries over directly, and Verilog remains extremely common in industry RTL and FPGA work.
Do I need to know synthesis to write Verilog?
Yes, at least conceptually. Writing RTL means picturing the hardware your code will produce; otherwise you will write code that simulates but cannot be built.