Skip to main content

Seven Segment LED Multiplexing Circuit in Verilog

The seven segment LED circuit uses seven different and individual LED's to display a hexadecimal symbol. It has 7 wires to control the individual LED's one wire to control the decimal point and one enable wire. The demo board I am using here consists of four such 7-segment LED's(As do any other demo board). To reduce the number of wires a multiplexing circuit is used to control the display. Using the multiplexing circuit the number of wires required to light up all 4 displays are reduced from 32 to 12 (8 data bits and 4 enable bits). All bits here are active low, such that to enable them a '0' is required. For example the figure below shows how to display a 3 on the seven segment.

The multiplexing circuit can take 4 inputs and have only one output. But the inputs should be displayed on the output fast enough to fool the viewer into thinking all outputs are enabled individually and simultaneously. This is achieved by having an enable signal that changes so fast that it appears that all displays are on simultaneously. The refreshing rate of the enable signal should be around 1000Hz to achieve this desired effect. Since the BASYS2 board has a 50Mhz clock and if an 18 bit counter is used and only the 2 MSB's are used to generate the enable signal then the refreshing rate of an individual enable bit will be 50MHz/(2^16) which comes to about 800 Hz.

Once the multiplexing is done the next code block is always the data bits for the seven segment. This is usually a case statement which encodes the hexadecimal digits into binary format. Since the LED's here are active low the segments that need to be enabled must be low.

The code for the LED multiplexing is shown below:

module sevenseg(
 input clock, reset,
 input in0, in1, in2, in3,  //the 4 inputs for each display
 output a, b, c, d, e, f, g, dp, //the individual LED output for the seven segment along with the digital point
 output [3:0] an   // the 4 bit enable signal
 );

localparam N = 18;

reg [N-1:0]count; //the 18 bit counter which allows us to multiplex at 1000Hz

always @ (posedge clock or posedge reset)
 begin
  if (reset)
   count <= 0;
  else
   count <= count + 1;
 end

reg [6:0]sseg; //the 7 bit register to hold the data to output
reg [3:0]an_temp; //register for the 4 bit enable

always @ (*)
 begin
  case(count[N-1:N-2]) //using only the 2 MSB's of the counter 
   
   2'b00 :  //When the 2 MSB's are 00 enable the fourth display
    begin
     sseg = in0;
     an_temp = 4'b1110;
    end
   
   2'b01:  //When the 2 MSB's are 01 enable the third display
    begin
     sseg = in1;
     an_temp = 4'b1101;
    end
   
   2'b10:  //When the 2 MSB's are 10 enable the second display
    begin
     sseg = in2;
     an_temp = 4'b1011;
    end
    
   2'b11:  //When the 2 MSB's are 11 enable the first display
    begin
     sseg = in3;
     an_temp = 4'b0111;
    end
  endcase
 end
assign an = an_temp;


reg [6:0] sseg_temp; // 7 bit register to hold the binary value of each input given

always @ (*)
 begin
  case(sseg)
   4'd0 : sseg_temp = 7'b1000000; //to display 0
   4'd1 : sseg_temp = 7'b1111001; //to display 1
   4'd2 : sseg_temp = 7'b0100100; //to display 2
   4'd3 : sseg_temp = 7'b0110000; //to display 3
   4'd4 : sseg_temp = 7'b0011001; //to display 4
   4'd5 : sseg_temp = 7'b0010010; //to display 5
   4'd6 : sseg_temp = 7'b0000010; //to display 6
   4'd7 : sseg_temp = 7'b1111000; //to display 7
   4'd8 : sseg_temp = 7'b0000000; //to display 8
   4'd9 : sseg_temp = 7'b0010000; //to display 9
   default : sseg_temp = 7'b0111111; //dash
  endcase
 end
assign {g, f, e, d, c, b, a} = sseg_temp; //concatenate the outputs to the register, this is just a more neat way of doing this.
// I could have done in the case statement: 4'd0 : {g, f, e, d, c, b, a} = 7'b1000000; 
// its the same thing.. write however you like it

assign dp = 1'b1; //since the decimal point is not needed, all 4 of them are turned off


endmodule


Comments

  1. Hi, I copied pasted the source to the *.v
    created the *.ucf
    Here is my ucf:
    NET "reset" LOC = "a7";

    # Pin assignment for 7-segment displays
    NET "a" LOC = "l14" ;
    NET "b" LOC = "h12" ;
    NET "c" LOC = "n14" ;
    NET "d" LOC = "n11" ;
    NET "e" LOC = "p12" ;
    NET "f" LOC = "l13" ;
    NET "g" LOC = "m12" ;
    NET "dp" LOC = "n13" ;

    NET "in0" LOC = "k14";
    NET "in1" LOC = "m13";
    NET "in2" LOC = "j12";
    NET "in3" LOC = "f12";

    # Pin assignment for clock
    NET "clock" LOC = "b8";

    But it's doing nothing?
    How can work it? thanks :)

    ReplyDelete
  2. The code above is not a stand alone module. It is to be used within or connected to another module. In your ucf file you linked the in0 - in3 registers but in this code there is no data coming to them. The reason it does not work is that it has nothing to display.

    Check out this post to get an idea of how to use this within another module: http://simplefpga.blogspot.co.uk/2012/07/00-to-99-two-digit-decimal-counter-via.html

    ReplyDelete
  3. Hello, i am using a DE1 altera board and dont know how to assign the pins after using mux.
    Could you help out? Thank you

    ReplyDelete
    Replies
    1. You have to use the ucf file for your board. That will give you pin assignment info. Google it. It's easily available.

      Delete
  4. Please explain me why did you use 18 bit register for count

    ReplyDelete
    Replies
    1. I mentioned the reason for that in the text explanation. Below I have copied the relevant part again:

      The refreshing rate of the enable signal should be around 1000Hz to achieve this desired effect. Since the BASYS2 board has a 50Mhz clock and if an 18 bit counter is used and only the 2 MSB's are used to generate the enable signal then the refreshing rate of an individual enable bit will be 50MHz/(2^16) which comes to about 800 Hz.

      Delete
  5. Hello..I am trying to implement this in spartan 3e but the lcd interfacing is totally different in spartan 3e ..can you please give me some direction on how to multiplex lcd in spartan 3e?

    regards
    rahul

    ReplyDelete
    Replies
    1. Hi Rahul. Interfacing an LCD is different that multiplexing the seven segment display. Please refer to your board handbook for that if its an onboard LCD

      Delete
  6. define all inputs
    as a vector [4:0]
    ie, input [4:0]in0;
    input [4:0]in1;
    and same for in2 and in3.
    and also change the vector [6:0]sseg to [4:0]. should be the same as input vectors.
    It work fine afterthen

    ReplyDelete
  7. hi, what pin do i assignment the output "an" to and in0/1/2/3 to? Thanks in advance

    ReplyDelete

Post a Comment

Popular posts from this blog

To Code a Stopwatch in Verilog

The stopwatch coded here will be able to keep time till 10 minutes. It will be a 4 digit stopwatch counting from 0:00:0 till 9:59:9. The right most digit will be incremented every 0.1 second, when it reaches 9 it will increment the middle two digits, which represent the second count. When it reaches 59 seconds it will increment the right most minute display. The stopwatch will be in the format M:SS:D. How to Create an Accurate Delay in Verilog: To make the stop watch an accurate device we need to be able to produce an accurate 0.1 second delay. I have already explained how to do this before in my decimal counter in verilog post. But since it is of great importance to the design will be explained in more detail here. Since we know that the BASYS2 (the one I am using, yours may be different) has a 50 MHz clock which means that the clock cycle is repeated 50M times in one second. So to create a 0.1 second delay we multiply the clock with the required time: 50MHz * 0.1 sec = ...

Random Number Generator in Verilog | FPGA

In verilog a random number can be generated by using the $random keyword but that works only for simulation purposes and cannot be implemented. So when we need a random number for implementation i.e. in hardware it can be achieved using an LFSR (Liner Feedback Shift Register). An LFSR is simply a shift register with some of its bits (known as taps) XOR'd with themselves to create a feedback term. When implementing an LFSR it's width and it's repeatability must be kept under consideration .An N-bit LFSR will be able to generate (2**N) - 1 random bits before it starts repeating. For example a 30 bit LFSR will have 1073741823 random states before repeating, so for most practical purposes this can be considered true random. In an LFSR the MSB will always be the feedback point also the main thing to take care of while coding an LFSR is to know which bits are the taps (to be selected for XOR ). This is confusing as the taps are different for different size registers. For e...