Time to actually write hardware. First we'll settle the age-old question — Verilog or VHDL? — then dissect a Verilog module piece by piece, and finally write your first real design: a 2-to-1 multiplexer, complete with a testbench you can run in the browser. Every port explained, nothing skipped.
There are two main hardware description languages (HDLs), and beginners always ask which to pick. Both describe hardware and both synthesize to the same gates — the difference is mostly style:
| Verilog | VHDL | |
|---|---|---|
| Feel | concise, C-like | verbose, Ada-like |
| Typing | looser, quicker | strict, more checks |
| Popular in | US, Asia, most industry | Europe, aerospace/defence |
| Lines for a mux | ~5 | ~15 |
For this course we use Verilog — it's shorter, dominant in industry, and runs in our online simulator. (Once you know one, the other is easy to read.) For deeper Verilog, see our Verilog tutorials.
The basic building block in Verilog is the module — one block of hardware. It always has the same skeleton:
module name (...ports...); … endmodule — the wrapper.input (signal coming in) and output (signal going out). A width like [7:0] means 8 bits wide; no width = 1 bit.assign describes combinational logic; always blocks (later) describe clocked logic.A multiplexer (mux) is a digital switch: it picks one of several inputs to pass to the output, chosen by a select line. A 2-to-1 mux chooses between two inputs a and b using sel:
Here's the whole design — five lines. Copy or download it:
// EcrioniX · FPGA from Scratch — your first module: a 2-to-1 multiplexer
module mux2 (
input wire a, // data input 0
input wire b, // data input 1
input wire sel, // select: 0 picks a, 1 picks b
output wire y // output
);
assign y = sel ? b : a; // if sel==1 -> y=b, else y=a
endmodule
| Port | Dir | Width | Meaning |
|---|---|---|---|
| a | input | 1 bit | Data input chosen when sel = 0. |
| b | input | 1 bit | Data input chosen when sel = 1. |
| sel | input | 1 bit | Select line — decides which input passes through. |
| y | output | 1 bit | The output — equals a or b per sel. |
The single line assign y = sel ? b : a; is a ternary: "if sel is 1, y = b, otherwise y = a." assign means this is combinational — y updates instantly whenever an input changes, no clock involved.
A design isn't done until you've verified it. A testbench is a special module with no ports that creates the design, drives its inputs through every case, and prints the results. Here's one for our mux — copy/download and run it alongside mux2.v:
// Testbench for mux2 — drives all input combinations and prints the result.
`timescale 1ns/1ps
module tb_mux2;
reg a, b, sel; // 'reg' = signals we drive from the testbench
wire y; // 'wire' = output we observe
// Instantiate the design under test (DUT), connecting ports by name
mux2 dut (.a(a), .b(b), .sel(sel), .y(y));
integer i;
initial begin
$display(" sel a b | y");
$display(" ---------+--");
for (i = 0; i < 8; i = i + 1) begin
{sel, a, b} = i[2:0]; // walk through all 8 combinations
#1; // wait 1 ns for y to settle
$display(" %b %b %b | %b", sel, a, b, y);
end
$finish;
end
endmodule
Paste both files into the online Verilog simulator and Run. When sel=0, y follows a; when sel=1, y follows b:
sel a b | y ---------+-- 0 0 0 | 0 0 0 1 | 0 0 1 0 | 1 <- sel=0, y follows a 0 1 1 | 1 1 0 0 | 0 1 0 1 | 1 <- sel=1, y follows b 1 1 0 | 0 1 1 1 | 1
If your output matches, congratulations — you've designed, simulated and verified your first piece of hardware. 🎉 Notice the testbench uses reg for signals it drives and wire for the output it watches, and connects ports by name (.a(a)) — habits we'll keep all course.
For contrast, the identical mux in VHDL — notice how much more ceremony it needs. You don't need to write VHDL in this course, just recognise it:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux2 is
port ( a, b, sel : in STD_LOGIC;
y : out STD_LOGIC );
end mux2;
architecture rtl of mux2 is
begin
y <= b when sel = '1' else a;
end rtl;
Think of the design module as the product you're building, and the testbench as the quality-inspector who pokes every button and checks every light before it ships. The inspector (testbench) never goes into the final product — it has no ports and isn't synthesized — but you never ship without it. Design + testbench always travel together.
Verilog (concise, industry-standard) and VHDL (verbose, strict) both describe hardware; we use Verilog. A module = module…endmodule with ports (input/output, optional width) and logic. Your first design, a 2:1 mux, is one line: assign y = sel ? b : a; — and you verify it with a testbench (a port-less module that drives inputs and prints outputs) before ever touching hardware.
input/output, width like [7:0]) + logic.assign = combinational; a 2:1 mux is assign y = sel ? b : a;..a(a)).assign y = sel ? b : a; do?input and output ports? What does [7:0] mean?reg and which are wire, and why?Verilog is concise and C-like (US/Asia/industry); VHDL is verbose and strict (Europe/defence). Both synthesize to the same hardware.
Verilog's basic block — module…endmodule with ports (inputs/outputs) and logic; can be instantiated inside other modules.
A port-less, non-synthesizable module that instantiates your design, applies stimulus and prints/checks outputs in simulation.
A module with inputs a, b, sel and output y, and one line: assign y = sel ? b : a;.
← Back to the full roadmap · Run this in the Verilog simulator →