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;