Your First Module & Testbench
Modules, ports and assign, then a testbench that drives the inputs and prints the outputs.
Everything in Verilog lives in a module: a block of hardware with input and output ports, like a chip with pins. To check a module you write a second module, the testbench, which has no ports: it creates signals, connects them to the module and changes them over time.
A real module: two gates
module and_or ( ... ); opens the module and lists its ports.
input wire a means a is an input of 1 bit.
assign y_and = a & b; creates an AND gate driving y_and.
endmodule closes the module.
The testbench
reg a, b; are the testbench's own variables, assigned inside initial.
and_or dut (.a(a), ...) places one copy (an instance) of the module and connects its ports by name.
{a, b} = i; assigns the two low bits of i to a and b at once (concatenation on the left).
$dumpfile/$dumpvars record every signal into wave.vcd for a waveform viewer.
and_or dut (a, b, y_or, y_and);
and_or dut (.a(a), .b(b), .y_and(y_and), .y_or(y_or));
Positional connection depends on the order of the ports in the module header; swapping two outputs is silent. Named connection (.port(signal)) is order-independent and is the standard in real projects.
module tb; wire a, b; initial a = 1; // error module tb; reg a, b; initial a = 1;
Signals assigned inside initial or always blocks must be reg (variables). Wires can only be driven by assign or by a module output.
Why does a testbench module have no ports?
It is the top of the simulation: it creates every signal itself, so nothing outside it needs to connect to it.
What does $finish do, and what happens without it?
It ends the simulation. Without it, a testbench with a free-running clock (always #5 clk = ~clk) would simulate forever.
What does {a, b} = 2; set a and b to?
2 is binary 10, so a = 1 and b = 0: the concatenation {a, b} receives the value with a as the most significant bit.