Maker.io main logo

Introduction to FPGA Part 9 - Phase-Locked Loop (PLL) and Glitches

2022-01-10 | By ShawnHymel

License: Attribution

A field-programmable gate array (FPGA) is a reconfigurable integrated circuit (IC) that lets you implement a wide range of custom digital circuits. Throughout the series, we will examine how an FPGA works as well as demonstrate the basic building blocks of implementing digital circuits using the Verilog hardware description language (HDL).

Many FPGAs use a phase-locked loop (PLL) to increase the internal clock speed. The iCE40 on the IceStick allows you to run up to 275 MHz by setting the internal PLL with the onboard 12 MHz reference clock.

However, you will often find the higher clock speed increases the chances of glitches in your design. A “glitch” is an unintended, spurious signal transition. Sometimes they are benign, such as when a counter is transitioning before you register the output. Other times, they can have a detrimental effect on your design. If your clock speed is fast enough (or your LUT delays are long enough), you might inadvertently register the wrong value.

In the previous tutorial, we saw how to allocate and use the iCE40’s block RAM to store data. This time, we show how to configure the PLL to achieve a faster clock speed and demonstrate how glitches might impact some designs. This tutorial acts as a solution to the challenge posed in the video: we construct a different kind of counter to eliminate glitches in a counter design.

Video

If you have not done so, please watch the following video, which explains the concepts required to complete the challenge.

 

Required Hardware

You will need only the Icarus Verilog simulator and GTKWave waveform viewer for this challenge, as you will be required to simulate gate delays to prove that your design reduces glitches.

Resources

The following datasheets and guides might be helpful as you tackle the challenges:

Challenge

As shown in the video, most basic counter designs will emit glitches while the binary numbers transition from one to another. For example, if you want to add 1 to ‘b0111, you’d need to change 4 bits. The ripple carry counter we showed in the video changes one bit at a time. If there is any gate delay (or more accurately, LUT delay), these transitions will be noticeable on the output of the counter.

However, so long as you register the output value after it has settled, you will not notice any glitches. As you start working with faster clock speeds, such glitches may become apparent.

Your challenge is to build a counter that reduces or eliminates glitches. You must also demonstrate your design by simulating it. Note that any time you use a gate or look-up table (LUT), you should add a 1 ns delay so that you can visualize any transitions or glitches in the waveform viewer.

Solution

Spoilers below! I highly encourage you to try the challenge on your own before comparing your answer to mine. Note that my solution may not be the only way to solve the challenge.

One option is to use a carry-lookahead adder (CLA) design for your counter. This adder computes the carry bits before the sum, which reduces the total amount of delay for the adder to perform its computation. 

Another option is to use a reflected binary code (RBC), which is also called a “Gray code” (named after its inventor, Frank Gray). A Gray code is a reordering of bits in a counter so that only one bit changes at a time. It prevents glitches from appearing during the counting process, and it’s used frequently in digital communications.

Note that for a Gray code to work, you must use exactly 2^n counts (where n is a positive integer). For example, you must use all possible values in 0 through 15 for a 4-bit Gray counter to ensure that only one bit is changing at a time.

Finally, you can use a lookup table or finite state machine (FSM) to guarantee that the output latency of the changing value remains constant. In other words, there will not be any glitches because all of the bits in the counter value update at the same time. The FSM is quite simple for a counter. A 2-bit counter might consist of 4 states that transitions from one to the next each clock cycle: ‘b00 to ‘b01 to ‘b10 to ‘b11.

Here is my implementation that combines a 4-bit Gray code counter with an FSM to ensure that the output update latency remains constant. Note that all code is stored in a testbench, as we induce simulated lookup delays in the FSM.

Copy Code
// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 1 ps

// 4-bit gray code counter FSM
module gray_counter (

// Inputs
input clk,
input rst,

// Outputs
output reg [3:0] count
);

// State machine transitions (with simulated delays)
always @ (posedge clk or posedge rst) begin
if (rst == 1'b1) begin
count <= 0;
end else begin
case (count) // Gray code state
4'b0000: #1 count <= 4'b0001; // 0
4'b0001: #1 count <= 4'b0011; // 1
4'b0011: #1 count <= 4'b0010; // 2
4'b0010: #1 count <= 4'b0110; // 3
4'b0110: #1 count <= 4'b0111; // 4
4'b0111: #1 count <= 4'b0101; // 5
4'b0101: #1 count <= 4'b0100; // 6
4'b0100: #1 count <= 4'b1100; // 7
4'b1100: #1 count <= 4'b1101; // 8
4'b1101: #1 count <= 4'b1111; // 9
4'b1111: #1 count <= 4'b1110; // 10
4'b1110: #1 count <= 4'b1010; // 11
4'b1010: #1 count <= 4'b1011; // 12
4'b1011: #1 count <= 4'b1001; // 13
4'b1001: #1 count <= 4'b1000; // 14
4'b1000: #1 count <= 4'b0000; // 15
default: #1 count <= 4'b0000;
endcase
end
end

endmodule

// Define our testbench
module gray_counter_tb();

// Simulation time: 10000 * 1 ns = 10000 ns
localparam DURATION = 10000;

// Internal signals
wire [3:0] out;

// Internal storage elements
reg clk = 0;
reg rst = 0;

// Generate clock signal: 1 / ((2 * 4.167) * 1 ns) = 119,990,400.77 Hz
always begin
#4.167
clk = ~clk;
end

// Instantiate gray code counter
gray_counter gray (.clk(clk), .rst(rst), .count(out));

// Pulse reset line high at the beginning
initial begin
#10
rst = 1;
#1
rst = 0;
end

// Run simulation (output to .vcd file)
initial begin

// Create simulation output file
$dumpfile("gray-code-counter_tb.vcd");
$dumpvars(0, gray_counter_tb);

// Wait for given amount of time for simulation to complete
#(DURATION)

// Notify and end simulation
$display("Finished!");
$finish;
end

endmodule

The gray_counter module should be straightforward. At each clock cycle, the counter value increments to the next Gray code value as given by the 16 states. While there is some lookup latency (simulated), it should be constant across all values. By using a Gray code, only one bit changes at a time, which makes this design resistant to glitches.

Here is an example of the Gray code in action as a waveform:

Gray code FSM counter

Recommended Reading

The following content might be helpful if you would like to dig deeper:

Introduction to FPGA Part 1 - What is an FPGA?

Introduction to FPGA Part 2 - Toolchain Setup

Introduction to FPGA Part 3 - Getting Started with Verilog

Introduction to FPGA Part 4 - Clocks and Procedural Assignments

Introduction to FPGA Part 5 - Finite State Machine (FSM)

Introduction to FPGA Part 6 - Verilog Modules and Parameters

Introduction to FPGA Part 7 - Verilog Testbenches and Simulation

Introduction to FPGA Part 8 - Memory and Block RAM

Introduction to FPGA Part 10 - Metastability and FIFO

Introduction to FPGA Part 11 - RISC-V Softcore Processor

Introduction to FPGA Part 12 - RISC-V Custom Peripheral

制造商零件编号 ICE40HX1K-STICK-EVN
BOARD EVAL FPGA ICESTICK
Lattice Semiconductor Corporation
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum