Skip to content

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

  1. Verilog
  2. Synthesis
  3. Place & Route (Testing & Simulation)
  4. Layout (Libra…converts Verilog to physical layout…outputs GDS files)
  5. GDS File (DRC and LVS checks needed, viewed with Klayout or Magic)
  6. 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).
alt text (from Zero to Asic)

Every digital chip is comprised of 3 layers:

  1. Diffusion (active) = transistor body
  2. Polysilicon = transistor gate
  3. Metal = wires

alt text (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:

  1. Transistor Level > SPICE, MOSFETS, Physics
  2. Gate Level > AND, OR, NOT gates; Netlists; Post-synthesis Structure
  3. RTL Level > Clocked registers, explicit data paths, clear hardware structure (synthesizable…expected by FPGA and ASIC tools)
  4. 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;
alt text

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
alt text

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
alt text

Combinational Logic Coding example: 2-to-1 Multiplexer

alt text

Gate Level Coding
alt text
- 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 circuits

Data Level Coding
alt text
- 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
alt text

  • 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
alt text - 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
alt text

Sequential Logic Coding: 4-bit Counter example
alt text

  • 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. alt text

Non-Blocking used in Shift Register alt text

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
alt text

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.
alt text

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).
alt text

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
alt text

From 01…if 1 encountered > 11 state, if 0 encountered> 10 state
alt text

From 11…if 1 encountered > 01 state, if 0 encountered > 10 state
alt text

From 10…if 1 encountered > 01 state, if 0 encountered > 11 state alt text

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
alt text

  • 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.
    alt text

  • Repeat defining Case Statements for all possible states
    alt text

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

alt text
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.
alt text

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…

  1. Coding
  2. Simulation & Verification
  3. Synthesis & Conversion

alt text
- 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…

  1. Module definition
  2. 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
(NOTE: ChatGPT was used to review and fix coding errors.)

Waveform Viewing

I dropped my Verilog code into the 8bitWaveform website and got this…
alt text

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
(NOTE: ChatGPT was used to write test conditions, review and fix general coding errors.)