Implementation of 7 segment LED display Controller on FPGA

Hello readers, welcome back.

So far we have discussed a lot about verilog and FPGA. 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 :-

  • 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).

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

  • 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

  • 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

Leave a comment

Please note, comments must be approved before they are published