Verilog Modules, Ports, Wires, and Regs
A Verilog design is built from modules. A module has ports on the outside and signals inside. Once this feels natural, larger FPGA projects become much less mysterious.
Learning Objectives
You will learn to:
- write a clean module header;
- choose port directions and widths;
- understand
wire,reg, andlogic; - instantiate one module inside another;
- avoid width and connection mistakes.
Module Skeleton
module module_name (
input wire clk,
input wire rst,
input wire [3:0] data_in,
output wire [3:0] data_out
);
// internal logic here
endmodule
The bracket range [3:0] means a 4-bit bus. Bit 3 is the most significant bit. Bit 0 is the least significant bit.
Wires
Use wire for signals driven by continuous assignments or by another module output.
wire both_on;
assign both_on = sw0 & sw1;
If two different things drive the same wire, you probably have a bug unless you are intentionally building tri-state behavior at an I/O boundary.
Regs and Logic
Old Verilog uses reg for signals assigned inside always blocks:
reg [7:0] count;
SystemVerilog commonly uses logic:
logic [7:0] count;
The word reg does not always mean a flip-flop. A reg assigned in a combinational always @* block can synthesize into LUT logic. A reg assigned in always @(posedge clk) usually synthesizes into flip-flops.
Module Instantiation
Create a small reusable block:
module majority3 (
input wire a,
input wire b,
input wire c,
output wire y
);
assign y = (a & b) | (a & c) | (b & c);
endmodule
Use it in a top module:
module top (
input wire sw0,
input wire sw1,
input wire sw2,
output wire led
);
majority3 u_majority (
.a(sw0),
.b(sw1),
.c(sw2),
.y(led)
);
endmodule
Named port connections are easier to review than positional connections.
Width Rules
wire [7:0] a;
wire [3:0] b;
wire [7:0] y;
assign y = a + b;
This can be valid, but you should know how b is extended. Beginners should make width conversions explicit when the design matters.
Exercise
Write a module nibble_swap:
- input:
din[7:0] - output:
dout[7:0] - behavior: upper nibble and lower nibble are swapped
Expected mapping:
dout[7:4] = din[3:0]
dout[3:0] = din[7:4]
Then instantiate it in a top module.
Common Mistakes
- Forgetting bus widths in module ports.
- Connecting ports by position and accidentally swapping signals.
- Assigning to a
wireinside analwaysblock. - Assuming
regalways means a physical register. - Ignoring synthesis warnings about width truncation or extension.
Summary
Modules are the reusable blocks of Verilog design. Ports define the boundary; wires and regs/logics define internal connections and assigned values. Clean module boundaries make simulation, synthesis, and review much easier.
Next: Combinational Logic in Verilog.
Further Reading
- Verilator warnings for width and port mismatches
- Yosys Verilog frontend notes
- FPGA vendor coding templates