Session 5 > RTL Design & Verification¶
Class Notes¶
Lots of great information shared during the class. Andreas Olofsson went through a bunch of definitions and tips-and-tricks useful for successfully creating and verifying an RTL design. I don’t understand most of it (yet), but I appreciate the structured way Andreas presented the information.
- Flip-Flops = good. Latches should be avoided
- Verilog is the tool to use for creating RTL designs
- Verilog Data Types = wire, reg, integer, parameter
- Number Formats - 8-bit = binary, hex, decimal, octal
- Number Formats - 4-bit = value, unknown, high-impedance
Combinational Logic
- AND y = a & b
- OR y = a | b
- XOR y = a ^ b
- NOT y = ~a
- Arithmatic sum = a + b
- Conditional y = sel ? a:b //if sel then a else b
Sequential Logic
- Blocking Operator =
- Non-blocking Operator <= (use inside ‘always @(posedge clk)’ blocks)
Finite State Logic
A circuit that moves between states based on inputs.
Testbench is verilog code that tests Verilog designs. Use faster clocks than the target hardware to speed up simulation.
# testbench example
`timescale 1ns/1ps
module my_module_tb;
// Inputs are reg (we drive them)
reg clk, rst_n, data_in;
// Outputs are wire (DUT drives them)
wire data_out;
// Instantiate Device Under Test
my_module dut (
.clk(clk),
.rst_n(rst_n),
.data_in(data_in),
.data_out(data_out)
);
// Clock generation
always #10 clk = ~clk; // 50 MHz (20ns period)
// Test stimulus
initial begin
$dumpfile("waves.vcd");
$dumpvars(0, my_module_tb);
// Initialize
clk = 0;
rst_n = 0;
data_in = 0;
// Reset
#40 rst_n = 1;
// Test cases
#20 data_in = 1;
#20 data_in = 0;
#200 $finish;
end
endmodule
Terminology¶
Design Process
- Verilog
- Synthesis
- Place & Route (Testing & Simulation)
- Layout (Libra…converts Verilog to physical layout…outputs GDS files)
- GDS File (DRC and LVS checks needed, viewed with Klayout or Magic)
- Chip Fabrication
(ChatGPT)
The Tiny Tapeout Flow
- module.v
- Yosys (synthesis)
- OpenLane (place & route)
- sky130 Standard Cells
- GDS Layout generated
- Merged with all other designs
- Taped out to silicon
(ChatGPT)
GDS = Graphic Data System. The final layout file used to manufacture an integrated circuit. It contains the exact geometric shapes that define every layer of the chip. Stores polygons and shapes, not circuits.
- Transistor geometries
- Metal interconnect routing
- Vias between layers
- Diffusion regions
- Contacts
- Layer assignments
- Heirachy of cells
Layer 1 > Diffusion
Layer 2 > Polysilicon
Layer 3 > Metal 1
Layer 4 > Metal 2
Layer 5 > Vias
(ChatGPT)
Diffusion Layer = The Diffusion Layer is the region of silion where the chip fabrication process changes the doping of the silicon so it becomes electrically conductive. Where transistors actually live. It forms the Source and Drain regions of MOSFET transistors (the Polysilicon makes up the gate).
(from Zero to Asic)
Every digital chip is comprised of 3 layers:
- Diffusion (active) = transistor body
- Polysilicon = transistor gate
- Metal = wires
(from Zero to Asic)
Diffusion is where current can flow in silicon.
Graphics were done in Siliwiz
(ChatGPT)
RTL = Register Transfer Level. A way of desribing digital hardware in terms of Registers, Cominational Logic, data movements between registers, clock-driven behavior. Not transistor description. Not describing physics. Describing “On this clock edge, move this data into this register”. Or “When the clock rises, A + B gets stored into sum” where ‘A + B’ is Combinational Logic and ‘sum’ is the register. Data transfers between registers, controlled by clocked logic. The bridge between logical thinking, synthesizable hardware, and physical implementation. An RTL is designed, tools convert it to gates, PDKs turns gates into transistors. (ChatGPT)
# Example RTL in Verilog
module adder_reg (
input wire clk,
input wire [7:0] A,
input wire [7:0] B,
output reg [7:0] sum
);
always @(posedge clk) begin
sum <= A + B;
end
endmodule
In terms of abstraction from lowest to highest levels:
- Transistor Level > SPICE, MOSFETS, Physics
- Gate Level > AND, OR, NOT gates; Netlists; Post-synthesis Structure
- RTL Level > Clocked registers, explicit data paths, clear hardware structure (synthesizable…expected by FPGA and ASIC tools)
- Behavior Modeling Level > …very abstract, describes what should happen, not how hardware is structured.
//Behavioral Example
if (state == IDLE)
state = RUN;
Registers = storage elements, usually Flip-Flops (ChatGPT)
Combinational Logic = digital logic where the output depends on only the current inputs. No memory. No clock. No history. Built from logic gates like AND, OR, NOT, NAND, NOR, XOR. Like a calculator, enter numbers > compute > output results. The keyword ‘assign’ describes Combinational Logic in Verilog. (ChatGPT)
Sequential Logic = Flip-flops, Registers, Latches, Counters, State Machines. Has clock, memory, and output depends on past inputs (stored state). Like a notebook, stores previous values. (ChatGPT)
// Sequential Logic Example > Flip-Flop
always @(posedge clk)
Q <= D;
D Input registers as Q Output at the next clock edge (either Rising or Falling).
Finite State Machine = a digital system that has a finite number of states, is in exactly one state at a time, changes based current state and current inputs, and updates on a clock edge. An FSM is a circuit that remembers where i9t is and decides where to go next. Example states, IDLE, RUN, DONE. Stores current state in the State Register. Determines the next state using Next-State Logic (combinational). Determines outputs with Output Logic depending on the type of FSM. Moore Machine outputs depend only on current state. Mealy Machine Outputs depend on state AND inputs. State register is a bank of Flip-Flops. The machine moves forward one step. Used in UART controllers, SPI interfaces, Traffic Lights, Vending Machines, CPU control units, Protocol handlers. (ChatGPT)
// State encoding example
localparam IDLE = 2'b00,
RUN = 2'b01,
DONE = 2'b10;
reg [1:0] state;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
end
else begin
case (state)
IDLE: if (start) state <= RUN;
RUN: if (count == 0) state <= DONE;
DONE: state <= IDLE;
default: state <= IDLE;
endcase
end
end
Research¶
Learning Verilog¶
Verilog, a hardware description coding language…used instead of having to draw a ton of logic gates and circuit connections by hand.
I studied Verilog programming by watching The best way to start learning Verilog.
- Verilog coding can be done in differnt levels of abstraction: Gate Level, Dataflow Level, Behavior Level
Combinational vs Sequential Logic coding
Combinational Logic Coding example: 2-to-1 Multiplexer¶
Gate Level Coding
- Gate Level coding mostly involves conection descriptions of instantiatable logic gate circuit modules that has a specific function
- Gate Level code is fine for smaller circuits, but impractical for larger circuitsData Level Coding
- formulas are written to describe data flow paths and relationships between different paths
- “like a boolean logical sentence”
- “efficient but cryptic”
- commenters of the video did note however that the expression is incorrect and should be adjusted to
out1 = (~B&A)|(X&B)
Behavioral Level Coding
![]()
- procedural block, such as an ‘always block’, describes how a circuit functions…not its hardware connections or how data flows.
- The most efficient but abstract level
- Relies on the compiler to build internal logic connections
Comparing 3 Coding Styles
- programmed into an Cyclone 5 FPGA development board
Sequential Logic¶
Made up of Combinational Logic, but has memory, current/next states and a timing clock
Sequential Logic Coding: 4-bit Counter example
![]()
- Uses ‘D-Type Flip-Flop’, very important for sequential logic…a 1-clock cycle memory element…the output Q registers only on the positive (Rising) edge of a clock cycle (specified with ‘posedge clk’ in the code)
- …Combinational Logic is used to increment
- …the concept of Current and Next State is used
- …and Non-blocking assignment (‘<=’) is what makes the code Sequential
Blocking vs Non-Blocking
- Blocking > evaluation and assignment of value for 2 sides (left and right sides) of an expression occurs simultaneously (usually used for Combinational Logic)
- Non-Blocking > there is separation between left and right side assignment. The right side evaluation is immediate but assignment to the left hand side waits…until all evaluation of the right side is completed.
Non-Blocking used in Shift Register
It was a really good tutorial and it seems the Visual Electric channel offers other tutorial videos relevant to this Microelectronics course!
State Machine and Testbenches¶
Another great tutorial by Visual Electric on State Machines & Testbenches in Verilog
Finite State Machines has a fixed number of STATES, an INPUT which triggers a transition between states, and an OUTPUT. Each STATE has a unique identifier and specific state definitions.
Moore Machine Example
Moore Machine the Output is a function of the Current State. Logs Output on the next clock cycle edge. Separates State Transition Logic from Output Logic.
Mealy Machine depends on the Current State and the Next Input, the Output can update quicker than in a Moore Machine. Logs output immediately.

A Pair Detector State Machine. Looks for pairs of 1s in a stream of ones and zeroes. Different states are defined, each with specific STATE identifiers (00, 01, 01, 11) and OUTPUT value (0 or 1). In this model only when a pair of 1s is detected, is the Output 1. That is, we only want to log a TRUE output when we have 1 pairs (not 0 pairs).
After determining the Current State (what is its identifier), the machine then decides which Next State to move to. Depending on if the INPUT is 1 or 0, it moves to the next state that corresponding to TRUE or FALSE conditions.
From 00…if 1 encountered > 01 state, if 0 encountered > 10 state
From 01…if 1 encountered > 11 state, if 0 encountered> 10 state
From 11…if 1 encountered > 01 state, if 0 encountered > 10 state
From 10…if 1 encountered > 01 state, if 0 encountered > 11 state
Here is a live demo from the YouTube tutorial:
Having this diagram to map out the different states and their relationships is valuable to the next step…writing code.
Coding the Moore State Machine in Verilog
4 States needs a 2-bit register to encode the unique numbers of the states (i.e. 00, 01, 10, 11) and store them. I think the syntax works like this…
- ‘reg’ = a register type variable
- [1:0] = specifies 2-bit, with 1 being the Most Significant Bit (MSB) followed by 0 being the Least Significant Bit (LSB) after the colon
is followed by 2 values in square brackets that defines the Least Significant Bit first then the M
- Specify recording of outputs at the positive edge of a clock pulse
-
Define a Case Statement encapsulated within Begin and End statements. The case has a name (2’b00) and a conditional statement (if(inbits) state…). Note that Non-Blocking ‘<=’ is used to indicate Sequential Logic.
-
Repeat defining Case Statements for all possible states

-
Finish the cases with endcase and end code with end.

The full Verilog code for Moore Machine:
// Moore Machine by Visual Electric
module pair_detect(clk, inbits, detect, reset); //module name and 4 ports
input clk; //clock input, synchronizes the circuit
input inbits; //input bit stream
input reset; //state machine reset input, value = 1 returns to starting state
output reg detect; //output register (updated in always block)
reg[1:0] state; //2-bit register for 4 possible states
initial //initial state definition
begin
state = 2'b00; //initial state is state 00
end
//State Transition Logic
always@(posedge clk or posedge reset) //block runs when clock or reset rises
begin
if(reset)
state <= 2'b00; //if reset is TRUE, state = 00
else
begin
case(state) //case statement, checks Current State to decide Next State
2'b00: //00 case
begin
if (inbits) state <= 2'b01; //if TRUE, go to state 01
else state <= 2'b10; //if FALSE, go to state 10
end
2'b01: //01 case
begin
if (inbits) state <= 2'b11; //if TRUE, go to state 11
else state <= 2'b10; //if FALSE, go to state 10
end
2'b10: //10 case
begin
if (inbits) state <= 2'b01; //if TRUE, go to state 01
else state <= 2'b11; //if FALSE, go to state 11
end
2'b11: //11 case
begin
if (inbits) state <= 2'b01; //if TRUE, go to state 01
else state <= 2'b10; //if FALSE, go to state 10
end
endcase
end
end
//Output Logic
always@(posedge clk or posedge reset) //output depends on the state, not on the input
begin
if (reset)
detect <= 0; //if TRUE, resets the output
else if (state == 2'b11)
detect <= 1; //if state 11 is TRUE, 1 to output register
else detect <= 0; //if state 11 is FALSE, 1 to output register
end
endmodule
Testbench the Moore Machine¶
Instantiates the Pair-Detect module, and tests it with a random stream of 0s and 1s.
‘tb’ means ‘testbench’
//Pair-Detect Testbench by Visual Electric
`timescale 10ns/100ps //time unit = 10ns/time precision = 100ps
module testbench; //module name
//testbench signals: reg driven by procedural blocks (initial, always),
//wire driven by continuous connection (module ports)
reg clk_tb;
reg reset_tb;
reg inbits_tb;
wire detect;
reg [4:0] d; //optional, d wasn't used: 5-bit register (0, 1, 2, 3, 4)
//set initial values for signals
initial
begin
clk_tb = 1'b0;
reset_tb = 1'b0;
inbits_tb = 1'b0;
d = 5'b0;
end
//Initialize signals
initial
begin
reset_tb = 1'b1;
#15 reset_tb = 1'b0;
end
always
begin
#10 clk_tb = ~clk_tb; //toggle every 10 time units
end
initial //stream of random 0s and 1s...once
begin
#20;
inbits_tb = 1; #20; //...with 200ns delay
inbits_tb = 0; #20;
inbits_tb = 1; #20;
inbits_tb = 0; #20;
inbits_tb = 0; #20;
inbits_tb = 1; #20;
inbits_tb = 1; #20;
inbits_tb = 0; #20;
inbits_tb = 1; #20;
inbits_tb = 0; #20;
inbits_tb = 1; #20;
inbits_tb = 0; #20;
inbits_tb = 0; #20;
inbits_tb = 0; #20;
inbits_tb = 1; #20;
inbits_tb = 1; #20;
inbits_tb = 0; #20;
inbits_tb = 1; #20;
#50 $finish;
end
pair_detect pair_detect_inst(
.clk (clk_tb),
.inbits (inbits_tb),
.detect (detect),
.reset (reset_tb)
);
endmodule
Poking around the Tiny Tapeout site, I found a browser based Verilog editor and tester called 8-Bit Workshop. It looks promising with a code editor and waveform generator.
![]()
I think I will try to use this to do my homework.
I have come to understand that I am a slow learner. Understanding new and difficult concepts does not come quickly for me. While I believe that I am on the verge of understanding…the pieces are still floating disconnected in my mind, not quite well understood yet and certainly is not congealing into something rational or logical to me.
Since ‘practice makes perfect’, I am going to watch another video tutorial to complete my homework called.Mastering Verilog in 1 Hour. Brute force repetition will be my path to mastering these concepts.
Understanding Verilog (again)
The video is very detailed and it was good to hear the same concepts and ideas repeated once again, hopefully to be hard coded into my brain. I learned:
- Verilog is a Hardware Description Language…modeling digital (not analog too?) systems by coding its functionality and structure.
- Verilog allows simulationa and verification of designs (functioning as expected) before implementation.
- Verilog allows for synthesis, converting high-level design description into gate-level representation that can be implemented on FPGA hardware or fabricated as an ASIC.
So…
- Coding
- Simulation & Verification
- Synthesis & Conversion

- Start by defining a module (Verilog’s basic building block)
- The module must have a name and a list of INPUT and OUTPUT ports
- This is followed by port declarations where the ports are specified as INPUT or OUTPUT
- Next are any parameter declarations or constants to be used
- After, any sub-modules would be included
- Then, the main bulk of the code will be Logic description for Hardware
- Lastly…pairing it with an endmodule command at the very bottom.
So…
- Module definition
- Interface specifications
Assignment Work¶
[x] Write Verilog for your project’s core module (aim for 10-30 lines to start)
[ ] Integrate with any provided library modules (e.g., debounce, UART, PWM) — create a top-level wrapper
[x] Simulate with a testbench and examine waveforms in GTKWave
[ ] Run linter (verilator –lint-only) and fix any warnings
A Verilog Project > LED ON & OFF¶
I enjoyed learning about Finite State Machines, so I will write a simple State Machine Verilog code assuming the following scenario:
- A 2-state machine that describes the function of 2 buttons and an LED
- If Button A is pressed > LED turns ON
- If Button B is pressed > LED turns OFF
- If no button is pressed > LED remains in the last state
module hello_world_FSM (
input clk,
input reset, //for power ON after power OFF
input ON,
input OFF,
output reg led
);
reg[0:0] state; //1-bit state
//Initial State
initial
begin
state = 1'b0;
end
//State Transition Logic - Sequential Logic (flip-flops)
always @(posedge clk or posedge reset)
begin
if(reset)
state <= 1'b0;
else
begin
case(state)
1'b0: //LED Off
begin
if (ON) state <= 1'b1;
else state <= 1'b0;
end
1'b1: //LED On
begin
if (OFF) state <= 1'b0;
else state <= 1'b1;
end
endcase
end
end
//Output Logic - Combinational Logic (logic gates)
always @(*) //'*' to specify block run whenver ANY input used inside the block changes
begin
case(state)
1'b0: led = 0;
1'b1: led = 1;
endcase
end
endmodule
Waveform Viewing¶
I dropped my Verilog code into the 8bitWaveform website and got this…
Not understanding the interface for the website, I asked ChatGPT for instructions and was told to…
Reduce my Verilog program to this and save as design.v
module hello_world_FSM (
input clk,
input reset,
input ON,
input OFF,
output reg led
);
always @(posedge clk or posedge reset) begin
if (reset)
led <= 0;
else if (ON)
led <= 1;
else if (OFF)
led <= 0;
end
endmodule
Testbenching the Verilog Code¶
Using the Moore Machine tutorial code as a reference, I wrote this testbench for my LED ON-OFF project.
//Testbench for LED ON-OFF Project
`timescale 10ns/100ps //10ns increments, 100ps resolution
module testbench;
reg clk_tb;
reg reset_tb;
reg ON_tb;
reg OFF_tb;
wire led_tb;
initial
begin
clk_tb = 1'b0;
reset_tb = 1'b0;
ON_tb = 1'b0;
OFF_tb = 1'b0;
end
initial
begin
reset_tb = 1'b1;
#15 reset_tb = 1'b0;
end
always
begin
#10 clk_tb = ~clk_tb;
end
initial
begin
#30;
// Press ON (one clock-long pulse)
ON_tb = 1'b1;
#20;
ON_tb = 1'b0;
// Wait a bit
#40;
// Press OFF (one clock-long pulse)
OFF_tb = 1'b1;
#20;
OFF_tb = 1'b0;
// Try pressing ON again
#40;
ON_tb = 1'b1;
#20;
ON_tb = 1'b0;
// Edge case: press both at same time
// (Your FSM will pick based on current state logic: OFF wins only in ON state, ON wins only in OFF state)
#40;
ON_tb = 1'b1;
OFF_tb = 1'b1;
#20;
ON_tb = 1'b0;
OFF_tb = 1'b0;
// End simulation
#80;
$finish;
end
//pairs program ports with testbench ports
hello_world_FSM hello_world_FSM_inst (
.clk (clk_tb),
.reset (reset_tb),
.ON (ON_tb),
.OFF (OFF_tb),
.led (led_tb)
);
//Waveform dump for GTKWave
initial
begin
$dumpfile("hello_world_FSM_tb.vcd");
$dumpvars(0, testbench);
end
endmodule
(from Zero to Asic)

- programmed into an Cyclone 5 FPGA development board