
Implementation of 7 segment LED display Controller on FPGA
Hello readers, welcome back.
Β
So far we have discussed a lot about verilog and FPGA Introduction. So letβs implement something. The video tutorial for this has been posted on youtube. You can watch that as well. I have written all the verilog codes in this blog so it will help you.
Β
In this blog we will see how to make a BCD controller. We need a BCD controller to control all the 7-segment displays of the FPGA individually.
Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 7-segment displayΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Total 8 digital signals are required to form a character (or number)
Β
Β
Most FPGAs have multiple 7-segment displays. I have used a FPGA from Spartan 6 family and below is the image for that. All the four 7-seven segment displays share common control wires for signals {A,B,C,D,E,F,G,DP}, so if we switch on all of them then all of them Β will show the same number. We want to display different numbers hence we are designing a system which will help us do that.
Β
Β
Β
The above block diagram shows our approach to implement it. At a particular instant only one of the four 7-segment displays Β will be active and the rest will be inactive and at the next clock cycle the 2nd one will be active and so on. The frequency for updating will be so fast that we won't be able to notice the switching and it will appear as if itβs glowing continuously.
Β
All the verilog code is available here, I will be explaining about the modules one by one.
Modules function
1.Β Digit selectΒ Β
This module takes input a system clock and gives a 2-bit vector output sel which is used to determine which digit will be displayed and which anode will be active.
Β
moduleΒ digit_select(clk,sel);
Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β inputΒ clk;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β outputΒ reg [1:0]sel = 2'b00;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β regΒ [9:0]count = 10'd0;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β regΒ new_clk = 0;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β parameterΒ prescaler = 1000;Β Β Β Β Β Β Β Β // refresh frequency is 50KHz
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β alwaysΒ @(posedgeΒ clk)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β begin
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β if(count == prescaler)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β begin
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β count <= 0;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β new_clk <= ~new_clk;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β end
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β elseΒ count <= count + 1;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β end
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β alwaysΒ @(posedgeΒ new_clk) sel <= sel + 1;
Β
Β
endmodule
Β
Here we take the input clock and generate a new clock of a bit lower frequency (50 KHz). At every positive edge of the new clock we increment the value of sel. Hence we get a total of 4 different states for sel (i.e. 00,01,10,11).
2. Anode selectΒ
This module takes input vector sel and switches on the anode accordingly
Β
moduleΒ anode_controller(sel,anode);
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β input [1:0]sel;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β outputΒ reg [3:0]anode = 4'd0;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β alwaysΒ @(sel)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β begin
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β case(sel)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'd0 : anode = 4'b0001;Β Β Β Β Β Β Β Β //right most
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'd1 : anode = 4'b0010;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'd2 : anode = 4'b0100;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'd3 : anode = 4'b1000;Β Β Β Β Β Β Β Β //left most
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β endcase
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β end
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β
endmodule
Β
For 00 the right most anode is active and for 11 left most and so on.
3. Digit control
This module takes input vector sel and all four digits and outputs a single digit that is to be shown at that moment according to sel value. Note both the anode output and digit should be for same 7-segment display.
Β
Β
moduleΒ digit_control(ones,tens,hundreds,thousands,sel,data);
Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β inputΒ [3:0]ones,tens,hundreds,thousands;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β inputΒ [1:0]sel;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β output regΒ [3:0]data = 4'd0;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β alwaysΒ @(sel)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β begin
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β case(sel)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'b00Β Β Β Β Β Β Β Β :Β Β Β Β Β Β Β Β data = ones;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'b01Β Β Β Β Β Β Β Β :Β Β Β Β Β Β Β Β data = tens;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'b10Β Β Β Β Β Β Β Β :Β Β Β Β Β Β Β Β data = hundreds;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 2'b11Β Β Β Β Β Β Β Β :Β Β Β Β Β Β Β Β data = thousands;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β endcase
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β end
endmodule
Β
Β
4. BCD converter
This module takes input the binary data from the digit control module and outputs the signals for Β {A,B,C,D,E,F,G,DP} to show proper numbers on the 7-segment display.
Β
moduleΒ BCD_convertor(data,out);
Β
Β Β Β Β Β Β Β Β inputΒ [3:0]data;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β output regΒ [7:0]out = 8'd0;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β alwaysΒ @(data)
Β Β Β Β Β Β Β Β begin
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β case(data)
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0000 Β Β Β Β Β Β Β Β Β : out = 8'b00000011;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0001 Β Β Β Β Β Β Β Β : out = 8'b10011111;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0010Β Β Β Β Β Β Β Β : out = 8'b00100101;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0011Β Β Β Β Β Β Β Β : out = 8'b00001101;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0100 Β Β Β Β Β Β Β Β : out = 8'b10011001;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0101 Β Β Β Β Β Β Β Β : out = 8'b01001001;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0110 Β Β Β Β Β Β Β Β : out = 8'b01000001;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b0111 Β Β Β Β Β Β Β Β : out = 8'b00011111;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b1000 Β Β Β Β Β Β Β Β : out = 8'b00000001;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β 4'b1001 Β Β Β Β Β Β Β Β : out = 8'b00001001;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β default Β Β Β Β Β Β Β Β : out = 8'b11111111;
Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β endcase
Β Β Β Β Β Β Β Β end
Β
endmodule
Β
Β
Β
- Finally we combine everything in a top module and then we will upload the code to FPGA to see the desired results.
Β
- Before burning the code into FPGA Β make sure to configure input and output by making a .ucf file.
Β
Β
Β
Β
Β
moduleΒ top(clk,ones,tens,hundreds,thousands,anode,out);
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β inputΒ [3:0]ones,tens,hundreds,thousands;
Β Β Β Β Β Β Β Β inputΒ clk;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β outputΒ [3:0]anode;
Β Β Β Β Β Β Β Β outputΒ [7:0]out;
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β wireΒ [1:0]sel;
Β Β Β Β Β Β Β Β wireΒ [3:0]data;
Β Β Β Β Β Β Β Β digit_select DS(
Β Β Β Β Β Β Β Β .clk(clk),
Β Β Β Β Β Β Β Β .sel(sel)
Β Β Β Β Β Β Β Β );
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β anode_controller AC(
Β Β Β Β Β Β Β Β .sel(sel),
Β Β Β Β Β Β Β Β .anode(anode)
Β Β Β Β Β Β Β Β );
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β digit_control DC(
Β Β Β Β Β Β Β Β .ones(ones),
Β Β Β Β Β Β Β Β .tens(tens),
Β Β Β Β Β Β Β Β .hundreds(hundreds),
Β Β Β Β Β Β Β Β .thousands(thousands),
Β Β Β Β Β Β Β Β .sel(sel),
Β Β Β Β Β Β Β Β .data(data)
Β Β Β Β Β Β Β Β );
Β Β Β Β Β Β Β Β
Β Β Β Β Β Β Β Β BCD_convertor BCD(
Β Β Β Β Β Β Β Β .data(data),
Β Β Β Β Β Β Β Β .out(out)
Β Β Β Β Β Β Β Β );
Β
endmodule
Β
I hope you enjoyed and learned something from this tutorial. Thatβs all for today, we will meet again. Until then explore and try to implement your own ideas. Keep learningβ¦β¦!!!
Β
This blog has been submitted by KRSSG, IIT-Kharagpur under the Robocraze Club Outreach Program.
Author: Anubhav Prasad