JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

From Logic Diagrams to Verilog

Designers do not draw modern chips gate by gate — a single block can hold billions of transistors, far past what any pen or schematic could ever lay out. Instead, they describe the hardware in text and let tools build the picture. In this guide you meet Verilog, the language that does the describing, and the one idea that trips up every newcomer: it is not a programming language. Get that idea right and the rest falls into place.

Why describe hardware in text?

Picture trying to draw a city by placing every brick by hand. That is what a gate-by-gate schematic feels like once a design grows past a few thousand gates — and real chips have billions. Somewhere along the way, drawing pictures stops scaling. You need a way to say *what you want* and let a machine work out the bricks.

That is what an HDL (hardware description language) is for. You write a compact text description — "this block adds two 8-bit numbers," "this one steers traffic between two inputs" — and a synthesis tool turns your words into an actual network of gates. The text is the source of truth; the schematic becomes something the tools draw *for* you, not something you draw *by hand*.

HDL is not a programming language

Here is the idea that trips up every newcomer. In software, lines run one after another. In an HDL like Verilog, the lines describe hardware that all exists at the same time — more like the parts of an orchestra than the steps of a recipe. Writing assign y = a & b; doesn't do an AND once; it lays down a permanent wire that is always computing it.

module and_gate(input a, b, output y);
  assign y = a & b;   // a permanent wire: y is ALWAYS (a AND b)
endmodule
A two-input AND gate. module names a block of hardware; the ports are its pins.

Once that clicks, the order of your assign statements mostly stops mattering. Two assign lines describe two wires; it makes no difference which you write first, because both are live at once. That is the deepest difference between describing hardware and writing a program — and the habit worth building from day one.

Your first module: a gate

A Verilog design is built from modules. A module is a labeled box of hardware: it has a name, a set of ports (its pins, marked input or output), and a body that says how the pins relate. You snap modules together the way you'd plug chips into a board — small boxes inside bigger boxes.

module inverter(input  a,      // one pin in
                output y);     // one pin out
  assign y = ~a;               // y is always NOT a
endmodule
An inverter (NOT gate). The ~ flips the bit; y tracks a forever.

Read that as a description of a part, not a sequence of actions: "here is a box called inverter; it has a pin a coming in and a pin y going out; y is permanently the opposite of a." Power it up and it just holds that relationship — no line ever "runs." Every gate you'll ever need (AND, OR, NOT, XOR) is one operator and one assign away.

Wires, signals & buses

Inside and between modules, values travel on wires. A single wire carries one bit — a 0 or a 1. But you rarely move just one bit; an 8-bit number, a color, an address all need several wires bundled together. That bundle is a bus, and in Verilog you write its width in square brackets.

wire        ready;        // 1 bit
wire [7:0]  data;         // an 8-bit bus: data[7] down to data[0]
wire [7:0]  sum;          // an 8-bit bus carrying the result of a + b
assign      sum = a + b;  // (a and b are 8-bit wires declared elsewhere)
[7:0] means "8 lines, numbered 7 down to 0" — one ribbon cable, eight strands.

Picture a bus as a ribbon cable: many strands taped side by side, moving together as one named thing. data[0] is the least-significant strand, data[7] the most-significant. The width is not decoration — it is physical. A register that stores data[7:0] is eight flip-flops wide, and a wider bus literally means more metal on the chip.

Behavioral vs structural

There are two ways to describe the same hardware, and good designers slide between them. Structural is bottom-up: you name the parts and wire them together by hand, like an assembly diagram. Behavioral is top-down: you state the *behavior you want* and let synthesis invent the gates. Same chip, two altitudes of description.

Take a 2:1 multiplexer — a switch that picks input a or input b depending on a select line sel. Behaviorally, you just state the choice and let the tool build it.

module mux2(input a, b, sel, output y);
  assign y = sel ? b : a;   // sel=1 -> y=b, sel=0 -> y=a
endmodule
A 2:1 mux, behavioral style. You describe the choice, not the gates.

The structural version of that *same* mux would spell out the gates by hand — an inverter, two ANDs, an OR — and wire them up strand by strand. Both descriptions synthesize to the same hardware. The lesson: start behavioral, describing intent, and drop to structural only when you need precise control over the exact gates. Higher altitude first; zoom in only where it pays.