| Gate | Symbol (text) | Boolean | Behaviour |
|---|---|---|---|
| NOT | ~a |
Inverts the input | |
| AND | a & b |
1 only when both inputs are 1 | |
| OR | a | b |
1 when at least one input is 1 | |
| NAND | ~(a & b) |
Inverted AND | |
| NOR | ~(a | b) |
Inverted OR | |
| XOR | a ^ b |
1 when inputs differ | |
| XNOR | ~(a ^ b) |
1 when inputs are equal |
These operators appear in SystemVerilog exactly as shown in the Symbol (text) column — so the language and the circuit description are already the same notation.
Seat-belt alert: a car sounds an alarm (
| 0 | × | × | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 0 |
This is a combinational circuit: the output depends only on the current inputs, with no memory of the past.
module seatbelt_alert (
input logic k, // ignition
input logic d, // driver belt
input logic p, // passenger belt
output logic s // alarm
);
assign s = k & (~d | ~p);
endmodule
module/endmodule — the building block of a SystemVerilog designinput/output — the ports of the module, visible from the outsideassign s = ... — continuous assignment
s is permanently wired to this expressions updates instantly (in the model) or within nanoseconds (in real hardware)&, |, ~) are exactly the Boolean operators from the previous slide.logic — the type for almost everything in this course
0, 1, x (unknown), z (undriven)0 and 1These identities let you simplify circuits (fewer gates = smaller, faster hardware):
| Identity | AND form | OR form |
|---|---|---|
| Identity | ||
| Null | ||
| Idempotent | ||
| Complement | ||
| De Morgan | ||
| Distributive |
De Morgan is the most important: it explains why NAND and NOR are universal gates (any function can be built from NAND alone), and why we write ~(a & b) instead of ~a | ~b — they are the same circuit.
A single logic is one wire. A vector is a bundle of wires:
logic [3:0] a; // 4-bit vector: a[3] (MSB) ... a[0] (LSB)
logic [7:0] b; // 8-bit vector
logic [0:3] r; // r[0] is MSB — less common, avoid mixing conventions
Operators apply bitwise across vectors:
logic [3:0] x, y, z;
assign z = x & y; // z[3]=x[3]&y[3], z[2]=x[2]&y[2], ...
assign z = x ^ y; // bitwise XOR: 1 wherever x and y differ
assign z = ~x; // bitwise NOT: inverts every bit
Reduction operators collapse a vector to one bit:
assign all_ones = &x; // 1 only if every bit of x is 1
assign any_one = |x; // 1 if at least one bit of x is 1
assign parity = ^x; // XOR of all bits: 1 if an odd number of 1s
4'b1010 // 4-bit binary = decimal 10
8'hFF // 8-bit hex = 255
12'd2217 // 12-bit decimal
32'hDEAD_BEEF // underscores for readability, ignored by the tool
8'd255 = 255 = 8'b11111111
b = binary, h = hex, d = decimal, o = octal8'hFF = hFF = 255 = 8'b11111111'0 and '1 are width-agnostic: '0 = all-zeros, '1 = all-ones, whatever the context width is.
0 (decimal 0) and '0 (all-zeros, width determined by context), 1 (decimal 1) and '1 (all-ones, width determined by context)x and z are also width-agnostic: 'x = all unknown, 'z = all undriven{a, b} joins two vectors into one — essential for building wider signals:
logic [3:0] hi, lo;
logic [7:0] word;
assign word = {hi, lo}; // hi is bits [7:4], lo is bits [3:0]
assign word = {4'b0000, lo}; // zero-extend lo to 8 bits
assign word = {{4{lo[3]}}, lo}; // sign-extend lo (replicate MSB 4 times)
The {N{expr}} replication syntax is used constantly for sign extension — you will write it dozens of times in Project 1's immediate-reconstruction logic.
Sign extension is the process of increasing the width of a binary number while preserving its value, typically by replicating the most significant bit.
When expressions mix different bit-widths, SystemVerilog silently zero-extends or truncates the shorter operand. This is a frequent source of subtle bugs.
The fix: use N'(expr) to make the intended width explicit:
logic [7:0] a;
logic [3:0] b;
logic [7:0] sum;
assign sum = a + 8'(b); // zero-extend b to 8 bits explicitly
localparam int HALF = 127;
logic [7:0] cnt;
// Without casting, (HALF - 1) is a 32-bit constant; comparison works but
// generates a width-mismatch warning. Cast makes intent clear:
if (cnt == 8'(HALF - 1)) ...
N'(expr) whenever the right-hand side has a different bit-width from the target — especially with localparam arithmetic.'0 extends to all-zeros matching the context width; '1 extends to all-ones.-Wall warnings that hide real bugs.module and_gate (
input logic a,
input logic b,
output logic y
);
assign y = a & b;
endmodule
A module is a black box: visible from the outside only through its ports. Inside can be any logic; the rest of the design does not care.
module and3 (input logic a, b, c, output logic y);
logic ab;
and_gate u0 (.a(a), .b(b), .y(ab)); // named port connections
and_gate u1 (.a(ab), .b(c), .y(y));
endmodule
.port(signal) — always prefer named connections over positional; self-documenting and survives port-order changes.logic ab — an internal signal connecting the two instances, visible only inside and3.Output is 1 when at least 2 of 3 inputs are 1. The Boolean equation (from SOP):
module majority (
input logic a, b, c,
output logic m
);
assign m = (a & b) | (a & c) | (b & c);
endmodule
Equivalently with De Morgan (using only NAND):
assign m = ~(~(a & b) & ~(a & c) & ~(b & c));
Both descriptions produce the same circuit — the synthesis tool picks the implementation.
You need four tools from the OSS CAD Suite (one installer, all platforms):
# Install OSS CAD Suite (Linux/Mac — adjust path for your OS)
# Download from https://github.com/YosysHQ/oss-cad-suite-build/releases
tar -xf oss-cad-suite-*.tgz
source oss-cad-suite/environment # add tools to PATH
# Verify
yosys --version # synthesis
nextpnr-himbaechel --version # place & route
openFPGALoader --version # bitstream upload
verilator --version # simulation (later classes)
Minimal project layout:
project/
src/top.sv ← your SystemVerilog
pins.cst ← pin constraints for the Tang Nano 9K
Makefile ← build rules
To synthesize and load: make load (full Makefile in M01A06; for now, use the Lab 2 starter template).
Lab 2 walks through the full setup step by step — complete it before the next class so you can do Lab 3 on the board.
- LUT = lookup table, implements any combinational function of N inputs
- FF = D flip-flop, registered state
- BRAM = block RAM, on-chip memory, inferred from
logicarrays
See M01A06 for the full primitives table.
// pins.cst (excerpt — Tang Nano 9K)
IO_LOC "btn[0]" 3; // push button 0
IO_LOC "btn[1]" 4; // push button 1
IO_LOC "led[0]" 10; // LED 0 (active-low: 0 = ON)
IO_LOC "led[1]" 11;
IO_LOC "led[2]" 13;
module btn_logic (
input logic [1:0] btn, // active-low: 0 when pressed
output logic [5:0] led // active-low: 0 = ON
);
logic b0, b1;
assign b0 = ~btn[0]; // invert: b0=1 when button 0 pressed
assign b1 = ~btn[1];
assign led[0] = ~(b0 & b1); // LED 0 on when BOTH pressed
assign led[1] = ~(b0 | b1); // LED 1 on when EITHER pressed
assign led[2] = ~(b0 ^ b1); // LED 2 on when they DIFFER
assign led[3] = ~b0; // LED 3 mirrors button 0
assign led[4] = ~b1; // LED 4 mirrors button 1
assign led[5] = ~(b0 | b1); // LED 5 = OR again
endmodule
make load (Yosys → nextpnr → openFPGALoader) and press the buttons. You are observing real combinational hardware — no CPU, no code.Combinational Building Blocks: multiplexers, decoders, comparators — and always_comb and case in SystemVerilog, the tools for describing more complex combinational logic cleanly.
REVIEW: circuit diagram of two AND gates (u0, u1) instantiated inside and3
REVIEW: tarefa de instructor — extrair starter templates dos labs da implementação de referência e publicar como GitHub Classroom template repository (não é conteúdo de slide)