HDLC for a 7-Segment LED Display

Michael Smit


Table of Contents

License
Overview
The LED display
Displaying a Single Digit
Displaying 4 Digits
Dividing Down the Clock

License

This document is licensed under a Creative Commons license.

Overview

In this article we describe how to write HDLC for displaying numbers on a 7-bit LED display. This example was done on a Spartan III Xilinx development board but a variation should work with any 7-bit display. To compile the VHDL I used the Xilinx WebPack tool.

The LED display

A standard 7 segment led display has 7 LEDs arranged in the shape of an eight. Each led is driven by an individual input. By turning on various segments the display can show all 10 numerical digits as well as the letters A-F.

The Xilinx development board display has 4 identical digits, each of which shares the same 7 input wires. In this case driving the signal low lights the led while driving it high turns the led off.

In order to select a particular digit the display also has a 4-bit selector input. By rapidly changing the selector input and the 7-bit segment inputs you can display a 4 digit number.

Displaying a Single Digit

Displaying a single digit is fairly straight forward. To do this we will develop a entity called led_mux. This entity will take in a 4-bit number and output 7 bits corresponding to the 7 LEDs on the 7 segment LED display.

Table 1. 7 bit led codes

NumberCode
0x010000000
0x11111001
0x20100100
0x30110000
0x40011001
0x50010010
0x06000010
0x71111000
0x80000000
0x80010000
0X0001000
0CB0000011
0xx1000110
0CD0100001
0Xe0000110
0CF0001110

Obviously all we need here is a multiplexer.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity led_mux is
    Port ( DIGIT_IN : in  STD_LOGIC_VECTOR (3 downto 0);
           LED_OUT : out  STD_LOGIC_VECTOR (6 downto 0));
end led_mux;

architecture Behavioral of led_mux is


begin
with DIGIT_IN SELect
LED_OUT<= "1111001" when "0001",   --1
         "0100100" when "0010",   --2
         "0110000" when "0011",   --3
         "0011001" when "0100",   --4
         "0010010" when "0101",   --5
         "0000010" when "0110",   --6
         "1111000" when "0111",   --7
         "0000000" when "1000",   --8
         "0010000" when "1001",   --9
         "0001000" when "1010",   --A
         "0000011" when "1011",   --b
         "1000110" when "1100",   --C
         "0100001" when "1101",   --d
         "0000110" when "1110",   --E
         "0001110" when "1111",   --F
         "1000000" when "0000",
			"1100011" when others;   --0

end Behavioral;

Displaying 4 Digits

Displaying 2 full bytes is slightly more complicated but not by much. Basically what we need to do is rapidly switch between each of the four digits in the display.

The led_persist entity take in 4 sets of 7-bit led inputs as well as a clock and outputs a 4-bit digit selector and a 7 bit led segment selector. This is slightly more complicated than the led multiplexer, but not by much. In this case we need a counter and a multiplexer.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity led_persist is
    Port ( CLOCK_IN : in  STD_LOGIC;
           LED3_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED2_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED1_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED0_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED_OUT : out  STD_LOGIC_VECTOR (6 downto 0);
           LED_SELECT_OUT : out  STD_LOGIC_VECTOR (3 downto 0));
end led_persist;

architecture Behavioral of led_persist is

signal count:std_logic_vector(1 downto 0) := "00";
begin

process (CLOCK_IN)
begin
if(CLOCK_IN = '1') and CLOCK_IN'event then
	count <= count + 1;
end if;
end process;

with count select
LED_OUT <= LED0_IN when "00",
			  LED1_IN when "01",
			  LED2_IN when "10",
			  LED3_IN when others;

with count select
LED_SELECT_OUT <= "0111" when "00",
						"1011" when "01",
						"1101" when "10",
						"1110" when others;

end Behavioral;

Dividing Down the Clock

All you have to do now, is create 4 led_mux entities and one led_persist entity, hook it up to a clock and the 7 segment led display and you're golden. Unfortunately there is one hitch. The Spartan III development kit comes with a 50MHz clock. If you try an run the led_persist entity at that rate the LED display will not be able to refresh fast enough to keep up.

Unfortunately the documentation doesn't tell you how fast to go, so it's a bit of trail an error. As it turns out dividing down by 2^15 about does it.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity led_display is
    Port ( CLOCK_IN : in  STD_LOGIC;
           LED_OUT : out  STD_LOGIC_VECTOR (6 downto 0);
           LED_SELECT_OUT : out  STD_LOGIC_VECTOR (3 downto 0));
end led_display;

architecture Behavioral of led_display is
component led_mux is
    Port ( DIGIT_IN : in  STD_LOGIC_VECTOR (3 downto 0);
           LED_OUT : out  STD_LOGIC_VECTOR (6 downto 0));
end component;

component led_persist is
    Port ( CLOCK_IN : in  STD_LOGIC;
           LED3_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED2_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED1_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED0_IN : in  STD_LOGIC_VECTOR (6 downto 0);
           LED_OUT : out  STD_LOGIC_VECTOR (6 downto 0);
           LED_SELECT_OUT : out  STD_LOGIC_VECTOR (3 downto 0));
end component;

signal led0, led1, led2, led3: std_logic_vector (6 downto 0);

signal led_clock: std_logic;
signal led_clock_count: std_logic_vector(15 downto 0) := "0000000000000000";
begin


process (CLOCK_IN)
begin
if(CLOCK_IN = '1') and CLOCK_IN'event then
	led_clock_count <= led_clock_count + 1;
end if;
end process;

mux1:led_mux
port map("0000", led0);
mux2:led_mux
port map("0001", led1);
mux3:led_mux
port map("0010", led2);
mux4:led_mux
port map("0100", led3);

persist:led_persist
port map(led_clock, led3, led2, led1, led0, LED_OUT, LED_SELECT_OUT);

led_clock <= led_clock_count(15);

end Behavioral;