Home
Welcome
Information


FPGA projects
Basic
Music box
LED displays
Pong game
R/C servos
Text LCD module
Quadrature decoder
PWM and one-bit DAC
Debouncer
Crossing clock domains
External contributions

Interfaces
RS-232
JTAG
I2C
EPP
SPI
PCI
PCI Express
10BASE-T

Advanced
Digital oscilloscope
Graphic LCD panel
Direct Digital Synthesis
CNC steppers
Spoc CPU core

Hands-on
A simple oscilloscope


FPGA introduction
What are FPGAs?
How FPGAs work
Internal RAM
FPGA pins
Clocks and global lines
Download cables
Configuration
Learn more

FPGA software
Design software
Pin assignment
Design-entry/HDL
Simulation/HDL
Synthesis and P&R

FPGA electronic
SMD technology
Crystals and oscillators

HDL info
HDL tutorials
Verilog tips
VHDL tips

Quick-start guides
ISE
Quartus

Site
News
FPGA links
HDL tutorials
Forum


7-segments LED displays

Now that we know how to drive an individual LED, let's try a 7-segment display.
The 7-segments display

The 7-segments display consists of 8 LEDs (let's not forget the dot) aggregated as shown below.

Each segment is created using a separate LED, typically named "A" to "G", plus DP for the dot. So a 7-segments display consists of 8 LEDs.

Now, the LEDs are not wired separately. To save a few pins in the 7-segments display, either the anodes or the cathodes are tied together, so that only 9 pins are required out of the display. Here's a typical "common-cathode" display:

Such a display requires at least 9 pins. It is often made in 10 pins packages (and the common signal is available on 2 pins).
Now, to drive such a display from an FPGA, the straighforward solution is to use 8 IOs.

Using such arrangement, here's how to display the digit '2'.
module LED_7seg(segA, segB, segC, segD, segE, segF, segG, segDP);
output segA, segB, segC, segD, segE, segF, segG, segDP;

assign {segA, segB, segC, segD, segE, segF, segG, segDP} = 8'b11011010;   // light the leds to display '2'
endmodule

Now that wasn't too hard.
Decimal counter
Let's try a decimal counter.
module LED_7seg(clk, segA, segB, segC, segD, segE, segF, segG, segDP);
input clk;
output segA, segB, segC, segD, segE, segF, segG, segDP;

// cnt is used as a prescaler
reg [23:0] cnt;
always @(posedge clk) cnt<=cnt+24'h1;
wire cntovf = &cnt;

// BCD is a counter that counts from 0 to 9
reg [3:0] BCD;
always @(posedge clk) if(cntovf) BCD <= (BCD==4'h9 ? 4'h0 : BCD+4'h1);

reg [7:0] SevenSeg;
always @(*)
case(BCD)
    4'h0: SevenSeg = 8'b11111100;
    4'h1: SevenSeg = 8'b01100000;
    4'h2: SevenSeg = 8'b11011010;
    4'h3: SevenSeg = 8'b11110010;
    4'h4: SevenSeg = 8'b01100110;
    4'h5: SevenSeg = 8'b10110110;
    4'h6: SevenSeg = 8'b10111110;
    4'h7: SevenSeg = 8'b11100000;
    4'h8: SevenSeg = 8'b11111110;
    4'h9: SevenSeg = 8'b11110110;
    default: SevenSeg = 8'b00000000;
endcase

assign {segA, segB, segC, segD, segE, segF, segG, segDP} = SevenSeg;
endmodule
Smooth counter
Finally let's try a "smooth" counter (fades each digit into then next).
module LED_7seg(clk, segA, segB, segC, segD, segE, segF, segG, segDP);
input clk;
output segA, segB, segC, segD, segE, segF, segG, segDP;

reg [23:0] cnt;
always @(posedge clk) cnt<=cnt+24'h1;
wire cntovf = &cnt;

reg [3:0] BCD_new, BCD_old;
always @(posedge clk) if(cntovf) BCD_new <= (BCD_new==4'h9 ? 4'h0 : BCD_new+4'h1);
always @(posedge clk) if(cntovf) BCD_old <= BCD_new;

reg [4:0] PWM;
wire [3:0] PWM_input = cnt[22:19];
always @(posedge clk) PWM <= PWM[3:0]+PWM_input;
wire [3:0] BCD = (cnt[23] | PWM[4]) ? BCD_new : BCD_old;

reg [7:0] SevenSeg;
always @(*)
case(BCD)
    4'h0: SevenSeg = 8'b11111100;
    4'h1: SevenSeg = 8'b01100000;
    4'h2: SevenSeg = 8'b11011010;
    4'h3: SevenSeg = 8'b11110010;
    4'h4: SevenSeg = 8'b01100110;
    4'h5: SevenSeg = 8'b10110110;
    4'h6: SevenSeg = 8'b10111110;
    4'h7: SevenSeg = 8'b11100000;
    4'h8: SevenSeg = 8'b11111110;
    4'h9: SevenSeg = 8'b11110110;
    default: SevenSeg = 8'b00000000;
endcase

assign {segA, segB, segC, segD, segE, segF, segG, segDP} = SevenSeg;
endmodule

Nice, isn't it?
Sorry you have to build it if you want to see it.



>>> NEXT: LED multiplexing >>>



This page was last updated on August 09 2006.