This is an old revision of the document!


Check out our full list of Verilog based projects!

Verilog® HDL: Project 2

Using switches to control LEDs

Project Overview

The goal of this project is to take the simple example from Project 1 and program our FPGA with it so that we can control a single LED with a single switch. Then, we'll take the same program and expand it to have multiple switches control multiple LEDs. Brave users will be challenged (with some guidance) at the end to do the same thing with some external components.

A list of the previous projects can be found here.

This project presumes you are using an FPGA development board that has external slide switches and LEDs built into the board, much like the Digilent system boards. However, the project can be easily modified to accommodate different types of external inputs (buttons instead of switches) or to use external I/O components rather than embedded components. If you have any questions after reading through the project, please feel free to post them on the Digilent Forum where an engineer will be happy to assist you.

Some Background Information

The digital circuit we are building from Project 1 is called led_sw. With this project, the FPGA is receiving an input signal, in this case from an embedded switch, that can be logic high, '1', or logic low, '0'. The input is then passed directly to an embedded LED that shows the corresponding logic by being “on” (a logic high) or “off” (a logic low). Both the embedded switch and LED are connected to their own ports on the FPGA and are specified in the constraint file (for Vivado, this is the XDC file) –link needed FIXME

Relooking at the Simple Example HDL

The code shown in the Simple Example from Project 1 that we will break down was as follows:

'timescale 1ns/1ps

module led_sw(
output led,
input sw
);
assign led = sw;

endmodule

The timescale portion 'timescale 1ns/1ps provides a base time length followed by a minimum time resolution. Generally speaking, this is only used during simulation and if delays are specifically implemented into the HDL, of which we are doing neither, but is a required part of Verilog modules nevertheless.

The module portion

module led_sw(
output led,
input sw
);

names and defines the number of inputs and outputs that we are creating on our custom “black box” (so-to-speak).

The assign portion assign led = sw; defines what our “black box” actually does. Multiple assign statements can be used as needed, as well as other ways of defining what our “black box” does (which we will get to in a later tutorial).

The endmodule is the keyword that signals the end of us defining what our module (our black box) does. Other modules could then be created with their own set of inputs and outputs, assign statements, and of course endmodule's.

Timescale

This timescale is required for all Verilog projects to synthesize correctly. If you had multiple types of delays, multiple timescales may be listed.

Module

In a schematic capture environment, a graphical symbol defines a given logic circuit by showing a “bounding box” as well as input and output connections. In Verilog, this same concept is used, only the bounding box must be explicitly typed into the text editor, starting with “module” and ending with the phrase “endmodule”.

The module block (as shown in the image) gives the circuit a name (“led_sw” for readibility, it could have been called “myFirstModule123abc”) and defines all input and output ports, effectively playing the same role as a symbol in a schematic environment. The module is closed by an “endmodule” statement, and all the statement between module declaration and “endmodule” describes the functionality of the module, i.e., the internal circuit connection of the module.

In terms of syntax, the inputs and outputs of the named module are enclosed by a set of parenthesis '()' with a semicolon ';', with a comma ',' between each set of inputs/outputs. If a set of inputs/outputs is actually a bus (an array), a set of square brackets '[]' is used around a range of numbers in the form [MSB:LSB]. No special syntax is needed to end the module, just the word “endmodule”.

Input, Output, and Bus

Whenever you are writing a Verilog module, the first thing to do is to define the input and output signals. In the example in Fig. 1, there is one input signal “sw” coming from the onboard switch SW0, and one output signal “led” connected to LED0. How did we choose the names “sw” and “led”? They came from the XDC file. need link to XDC file page description

Note, however, that input and output can be a group of wires as well. We call these groupings a bus. To declare the input or output as a bus, we need to provide the CAD tools with the index of the most significant bit (MSB) of the bus and the index of the least significant bit (LSB) of the bus. For example, the following code defines an 8-bit wide bus “sw”, where the left-most bit (MSB) has the index 7 and the right-most bit (LSB) has the index 0, with a colon ':' separating the two numbers.

  input [7:0] sw  

Indexing a bus in Verilog is similar to indexing an array in the C language. For example, if we want to index the second bit of sw bus declared above, we will use sw[1]. No semicolon is used while listing the various inputs and outputs that are used.

Assign

The assign statement in the example above assigns the signal value on the net “sw” to the net “led”. In implementation, it creates a wire that connects the input port sw to the output port led.

An assign statement can also be used to assign one signal of a bus to one signal of another bus. For example, if we declared sw as an 8-bit wide bus and LED as an 8-bit wide bus, and we want to use second switch to control fourth LED, the code will be:

module led_sw(
output [7:0] led,
input [7:0] sw
);
assign led[3] = sw[1];
...
endmodule

At the end of each assign statement (can be more than one line long), a semicolon ';' is required.

Important Takeaways from Project 2

tags to be added via the tag> and double curly braces around everything
learn programmable-logic software tutorial vivado verilog