VHDL Source Code -- MuxDisp.vhd

-- MUXDISP.VHD					Chuck McManis 19-Mar-2001
--
-- This then is some VHDL to drive 8 digits of display with only 16 lines on the
-- FPGA. Our circuit consists of 8 lines going to all 8 of the seven segment
-- displays, and then 8 lines going to a Toshiba darlington current sink that
-- "enables" each digit by grounding the common cathode pin for that digit.
-- If you turn on more than one, you get more than one digit lit. Fun yes?
-- Just don't over draw the current on the FPGA!
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity MUXDISP is
    Port ( mux_clk : in std_logic; 	-- Multiplexing clock for display
           rst : in std_logic; 		-- Reset pin
	   data : in std_logic_vector(31 downto 0); -- Eight 4 bit digits.
	   blank : in std_logic_vector(7 downto 0); -- Eight blank inputs
	   dps : in std_logic_vector(7 downto 0);
	   test : in std_logic; 	-- Blank and test pins
           display : out std_logic_vector(6 downto 0); -- Segment output
	   dpo : out std_logic; -- decimal point output.
           digits : out std_logic_vector(7 downto 0)); -- digit selectors
end MUXDISP;

architecture behavioral of MUXDISP is

    -- I use the previously defined hex_display component as the means
    -- to drive the segment pins.
    COMPONENT hex_display
    PORT(
	test : IN std_logic;
	blank : IN std_logic;
	data : IN std_logic_vector(3 downto 0);          
	segs : OUT std_logic_vector(6 downto 0)
	);
    END COMPONENT;

    -- Remember the 'looper' project? Guess what, we do that again :-)
    signal selector : std_logic_vector (7 downto 0);
    signal cur_digit : std_logic_vector (3 downto 0);
	 signal cur_blank : std_logic;

begin
    u1: hex_display PORT MAP( test => test, blank => cur_blank,
		data => cur_digit, segs => display);

	 cur_blank <= blank(0) when selector = "10000000" else
	 		blank(1) when selector = "01000000" else
			blank(2) when selector = "00100000" else
			blank(3) when selector = "00010000" else
			blank(4) when selector = "00001000" else
			blank(5) when selector = "00000100" else
			blank(6) when selector = "00000010" else
			blank(7);

    -- Generate what appears to be the continuous display of 8 digits
    -- by lighting each digit up in sequence. If you can get all 8
    -- digits on at least once every 100 milleseconds, then they will
    -- look continuous. Just don't pick a multiple of 60hz!
    -- On the SPARTAN2 board 'mux_clk' is 24Mhz
    gen_display: process (rst, mux_clk) is
	variable d_clk : unsigned(13 downto 0);
    begin
	if (rst = '0') then
	    selector <= "10000000";
	    d_clk := "00000000000000";
	elsif rising_edge(mux_clk) then
	    -- each time the count "rolls over" switch to the next
	    -- digit. With 14 bits that is a count of 16384 and a
	    -- freq of 1.465Khz, divided by 8 means each digit is
	    -- illuminated 183 times/sec. (plenty fast)
	    if (d_clk = 0) then
		-- select the next digit to display
		selector <= selector(0) & selector(7 downto 1);
	    end if;
	    d_clk := d_clk + 1; -- now keep counting up
	end if;
    end process;

    -- At this point the selector value is rotating around like the looper
    -- did, but this time it is enabling each digit in the display in turn.
    -- We use the value of the selector to decide which bit of data to put
    -- on the cur_digit lines (which feed the hex_display decoder)
    cur_digit <= data(31 downto 28) when selector = "00000001" else
		 data(27 downto 24) when selector = "00000010" else
		 data(23 downto 20) when selector = "00000100" else
		 data(19 downto 16) when selector = "00001000" else
		 data(15 downto 12) when selector = "00010000" else
		 data(11 downto  8) when selector = "00100000" else
		 data( 7 downto  4) when selector = "01000000" else
		 data( 3 downto  0);

	 dpo <= dps(7) when selector = "00000001" else
	 		dps(6) when selector = "00000010" else
			dps(5) when selector = "00000100" else
			dps(4) when selector = "00001000" else
			dps(3) when selector = "00010000" else
			dps(2) when selector = "00100000" else
			dps(1) when selector = "01000000" else
			dps(0);

    -- further, we need to wire the selector value to the 'digits' output.
    digits <= selector;

end behavioral;