Toady we are going to explain how to do time division multiple in VHDL language. This project will display a simple method to do the 7 segment multiplexing in VHDL language for Nexys 3 FPGA development board. To further understand the code you may want to look into our previous FPGA LED blinking example, where we explained how the onboard LED can be accessed in VHDL and Verilog and how we can use the onboard clock to generate the required amount of timing delays. In today’s example we are extending that example code to display numbers on the on board 7 segment displays. Here is the circuit diagram of that Nexys 3 FPGA board.
As you can see in this diagram that 4 7 segment displays are attached to the Spartan 6 FPGA and you can also check the respective pins in the circuit diagram.
Single Digit up counter in VHDL
First of all let’s look into the single digit 7 segment display counter code in the VHDL which will count from 0 to 9 and only use one digit. This will not do any kind of multiplexing but give you a general idea of what the 7 segment decoder look like when implemented in VHDL.
entity sevensegment_ex01 is
Port ( anodes : out STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC;
cathods : out STD_LOGIC_VECTOR (7 downto 0));
end sevensegment_ex01;
architecture Behavioral of sevensegment_ex01 is
signal digit0 : std_logic_vector (7 downto 0);
signal counter : natural range 0 to 9 := 0;
signal clk_counter : natural range 0 to 50000000 := 0;
begin
process(clk)
begin
if rising_edge(clk) then
clk_counter <= clk_counter + 1;
if clk_counter >= 50000000 then
clk_counter <= 0;
if counter > 8 then
counter <= 0;
else
counter <= counter +1;
end if;
end if;
end if;
end process;
process(counter)
begin
case counter is
when 0 => cathods <= "11000000"; --0
when 1 => cathods <= "11111001"; --1
when 2 => cathods <= "10100100"; --2
when 3 => cathods <= "10110000"; --3
when 4 => cathods <= "10011001"; --4
when 5 => cathods <= "10010010"; --5
when 6 => cathods <= "10000010"; --6
when 7 => cathods <= "11111000"; --7
when 8 => cathods <= "10000000"; --8
when 9 => cathods <= "10010000"; --9
end case;
end process;
anodes <= "1110";
--cathods <= digit0;
end Behavioral;
Code language: VHDL (vhdl)
7 segment Multiplexing
Now let’s try to extend this code and try to implement a multiplexer. Which could be accomplished by with the process which is clock dependent but this time the clock is very fast. We will provide 1 millisecond clock source to refresh every digit. To generate this clock we will use the on board 100MHz clock input so we need to wait for 10000 clocks. We can achieve this division by adding a signal of type natural range 0 to 10000 :=0; Here is the complete source code.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity sevensegment_ex01 is
Port ( anodes : out STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC;
cathods : out STD_LOGIC_VECTOR (7 downto 0));
end sevensegment_ex01;
architecture Behavioral of sevensegment_ex01 is
signal digit0 : std_logic_vector (7 downto 0);
signal anodeval : std_logic_vector (3 downto 0);
signal counter : natural range 0 to 9 := 0;
signal clk_counter : natural range 0 to 100000 := 0;
signal digit_number : natural range 0 to 4 :=0;
begin
process(clk)
begin
if rising_edge(clk) then
clk_counter <= clk_counter + 1;
if clk_counter >= 100000 then
clk_counter <= 0;
digit_number <= digit_number +1;
if digit_number >=4 then
digit_number <=0;
end if;
end if;
end if;
end process;
process(digit_number)
begin
case digit_number is
when 0 => anodeval <= "1110";
when 1 => anodeval <= "1101";
when 2 => anodeval <= "1011";
when 3 => anodeval <= "0111";
when 4 => anodeval <= "1111";
end case;
end process;
process(digit_number)
begin
case digit_number is
when 0 => counter <= 1;
when 1 => counter <= 2;
when 2 => counter <= 3;
when 3 => counter <= 4;
when 4 => counter <= 0;
end case;
end process;
--
process(counter)
begin
case counter is
when 0 => cathods <= "11000000"; --0
when 1 => cathods <= "11111001"; --1
when 2 => cathods <= "10100100"; --2
when 3 => cathods <= "10110000"; --3
when 4 => cathods <= "10011001"; --4
when 5 => cathods <= "10010010"; --5
when 6 => cathods <= "10000010"; --6
when 7 => cathods <= "11111000"; --7
when 8 => cathods <= "10000000"; --8
when 9 => cathods <= "10010000"; --9
end case;
end process;
anodes <= anodeval;
--cathods <= digit0;
end Behavioral;
Code language: VHDL (vhdl)
Here is the ucf
file which describe the on board pins mapping to spartan 6 FPGA.
NET "anodes<0>" LOC = "N16";
NET "anodes<1>" LOC = "N15";
NET "anodes<2>" LOC = "P18";
NET "anodes<3>" LOC = "P17";
NET "clk" LOC = V10;
NET "cathods<0>" LOC = "T17" ;
NET "cathods<1>" LOC = "T18" ;
NET "cathods<2>" LOC = "U17" ;
NET "cathods<3>" LOC = "U18" ;
NET "cathods<4>" LOC = "M14" ;
NET "cathods<5>" LOC = "N14" ;
NET "cathods<6>" LOC = "L14" ;
NET "cathods<7>" LOC = "M13" ;
Code language: JavaScript (javascript)