In this post, I will be teaching you how to build a binary to seven segment Verilog module and download it into the Tangnano 9k FPGA board. If you don't have much background on Verilog or FPGA, I suggest reading my post A Beginner's Guide to FPGA Programming using Tang Nano 9k Board and OSS CAD Suite. That will give you enough background so you can easily grasp the concept and follow the steps I will discuss in this post.
Specification
The Verilog module that I'm going to design accepts 4-bit binary input and drives the seven segment LED with the corresponding hex value. The input to output mapping should be as follows:
- Input: 0000 Output: 0
- Input: 0001 Output: 1
- Input: 0010 Output: 2
- Input: 0011 Output: 3
- Input: 0100 Output: 4
- Input: 0101 Output: 5
- Input: 0110 Output: 6
- Input: 0111 Output: 7
- Input: 1000 Output: 8
- Input: 1001 Output: 9
- Input: 1010 Output: A
- Input: 1011 Output: b
- Input: 1100 Output: C
- Input: 1101 Output: d
- Input: 1110 Output: E
- Input: 1111 Output: F
I will also add another 4-bit output to serve as an indicator to reflect the value of the input. The Verilog module should look like the diagram below.
In terms of the decoding logic, the seven segment LED that I have is a common cathode, which means I need to drive logic 1 to the segment I want to turn on. I will discuss the implementation of the decoding logic in the coding portion of this post.
Tang nano 9k has only 2 on-board pushbuttons, therefore it is not enough to be used as our input mechanism. Because of that I will be using the IO pins and connect pushbuttons via breadboard. For the output, I will be using the on-board LEDs for led_ind and IO pins for driving the seven segment LED. The schematic diagram is shown below:
Designing the Verilog Module
Let us first create the module name bin_to_seven_segment and declare the input and output ports. The code should be like this:
Then let us connect the led_ind to bin. By doing this, we will be able to see, the value of bin being displayed using the on-board LEDs. Take note that the on-board LEDs are reversed bias. This means that when the bin is at logic low (pushbutton is not pressed) , the LED will turn on. Subsequently, when we press the pushbutton, the LED on the board will turn off. With this we can easily see the value of bin in the physical board without the need for multimeter or logic analyzer. The code should look like this:
Now, let us code the decoding logic. Let us first create an always block. In Verilog, always block executes the code inside it whenever the trigger is activated. The syntax for the always block is shown below:
In our case, we will make our input port named bin to act as the trigger in the always block. By doing this, every time the value of bin changes the always block will get executed. The code should be like this:
After creating the always block, we will now use the Verilog case statement to implement the decoding logic. The syntax for case statement is as follows:
We use bin as the input to our case statement, this means that we are checking the value of bin and will execute the corresponding action for that specific value. Let us say for example, the value of bin is 4'b0000, we will set seg to be 7'b0111111. If the value of bin is not in the choices, it will go to default. The complete code can be found here.
Running Simulations
I created a simple Verilog testbench to check whether the bin_to_seven_segment module is working. The testbench code is shown below.
Looking into the test bench code, you can see line at line 15, there is a for loop that assigns the value of i to bin. That will enumerate all the possible values of bin starting from 4'b0000 to 4'b1111. Line 18 just prints the value of the input and outputs of the module. If you ran the test bench you can see the following output in your terminal. If you do not know how to run simulations, I suggest reading this first: A Beginner's Guide to FPGA Programming using Tang Nano 9k Board and OSS CAD Suite.
You can use the GTKWave to open the VCD file. In my case, I downloaded a VSCode plugin called surfer to open vcd files directly on the VSCode so it will be seamless. The VCD waveform should look like this:
The value shown in the waveform should be the same of what is on the terminal. The only difference is that the waveform. shows the hex value, you can easily change that in the waveform GUI. Right click on the signal name then change format to binary. If you do that, your waveform will be like this:
Now that we can see that the module is working properly in simulations, we can now define the IO pins we will be going to use and create a CST file. For me, I wired everything up on the breadboard, then identify the FPGA pins I want to use based on the connections I made. You can follow the connections I made or you can choose your own IO pins. The resulting CST file that I have is shown here:
Implementing the Design to FPGA
To implement the design and download the bit file to the tang nano 9k board, you need to run the following commands:
yosys -p "read_verilog bin_to_seven_segment.v; synth_gowin -json bin_to_seven_segment.json"
nextpnr-himbaechel --json bin_to_seven_segment.json --write pnr.json\
--device GW1NR-LV9QN88PC6/I5\
--vopt family=GW1N-9C --vopt\
cst=bin_to_seven_segment.cst
gowin_pack -d GW1N-9C -o pack.fs pnr.json
openFPGALoader -b tangnano9k pack.fs
Validating the Design
Once you downloaded the design, you can check if it is working as expected by pressing the pushbuttons and observing both the seven segment LED and the on-board LED. You can take a look on the video below to see how it would look like:
No comments:
Post a Comment