--*********************************************************** --File: seven segment controller for Lab 6 -- 7_segment_controller.vhd -- --Purpose: To introduce students to a control -- section for the seven segment LEDs -- on a spartan XL prototyping board. -- More comments from the original author -- follow. This is your first case of -- software reuse. This controller -- is very handy for displaying information -- on the seven segment displays. We -- are only using a portion of the entire -- code but it is easier to import and use -- the entire project than to create it -- from scratch. It also gives you the -- opportunity to see another style of -- coding and comments. -- --Created: 07/01/02 CK and JM -- --*********************************************************** -- -- -- Purpose: -- Produces firing pattern for 4 digit 7 segment LED display connected in a -- NPN MUX fashion. -- -- The bellow figure shows the numbering of the segments: -- _ _ _ _ -- | _ | | _ | | _ | | _ | -- | _ | | _ | | _ | | _ | -- 0 1 2 3 -- -- Below is the common lettering scheme for 7 segment displays. -- _A_ -- | | -- F B -- | | -- -G- -- | | -- E C -- | | -- -D- -- Input to the segments are provided through SSEG_#_H (where # is 0-3) of -- type std_logic_vector( 6 downto 0 ). The standard 4 digit 7 segment -- display also has 4 decimal places, which are activated through DP_#_H -- (where # is 0-3) of type std_logic. -- -- Since the refresh rate for most LED displays is 60Hz to 3kHz (check with -- manufacturer's data sheet) we need to slow down the clock frequency. -- The generic statements in the entity declaration are used to define the -- counter width (COUNTER_WIDTH) and the fall count (FALL_COUNT). The COUNTER_WIDTH -- is used to define the number of bits in the clock conversion counter. -- The FALL_COUNT is used to determine when the converted clock signal will -- fall with respect to the clock conversion count. The below equation shows -- how to determine FALL_COUNT. -- -- Ratio of system to convert count = [(System clock rate)/((Refresh rate)*4)] -- -- Next find an n such that: -- -- 2^n >= Ratio of system to convert count -- -- This n is your COUNTER_WIDTH. The FALL_COUNT can be obtained by 2^n/2. -- -- Output to the physical display device is accomplished through,.. -- 1) SBASE_H of type std_logic_vector( 3 downto 0 ) which is used to drive base -- of NPN transistors -- 2) SSEG_OUT_H of type std_logic_vector( 6 downto 0 ) which is used to drive -- drive the individual segments in a seven segment display. -- 3) DP_OUT_H type std_logic which is ued to enable the decimal point LED. -- -- Timing/Placement Issues: -- This entity is designed to work with minimal place and route constraints. -- -- -- Flexability: -- This code is targeted for a 4 digit 7 segment LED display using -- NPN MUX style hookup. ------------------------------------------------------------------------------------------------ -- LIBRARIES/PACKAGES ------------------------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ------------------------------------------------------------------------------------------------ -- GENERIC/ENTITY ------------------------------------------------------------------------------------------------ entity SEGMENT7_CONTROLLER is generic ( COUNTER_WIDTH : natural := 12; -- Used to set number of bits in counter FALL_COUNT : natural := 2048 -- Used to set the fall count of the clock ); port ( CLK : in std_logic; -- Input for system clock RST_H : in std_logic; -- Global reset -- SSEG_0_H : in std_logic_vector( 3 downto 0 ); -- Segment 0 input DP_0_H : in std_logic; -- Segment 0 decimal point input -- SSEG_1_H : in std_logic_vector( 3 downto 0 ); -- Segment 1 input DP_1_H : in std_logic; -- Segment 1 decimal point input -- SSEG_2_H : in std_logic_vector( 3 downto 0 ); -- Segment 2 input DP_2_H : in std_logic; -- Segment 2 decimal point input -- SSEG_3_H : in std_logic_vector( 3 downto 0 ); -- Segment 3 input DP_3_H : in std_logic; -- Segment 3 decimal point input -- SBASE_OUT_H : out std_logic_vector( 3 downto 0 ); -- Segment enable output -- SSEG_OUT_H : out std_logic_vector( 6 downto 0 ); -- LED enable output DP_OUT_H : out std_logic -- Decimal point LED enable output ); end entity SEGMENT7_CONTROLLER; ------------------------------------------------------------------------------------------------ -- ARCHITECTURE ------------------------------------------------------------------------------------------------ architecture BEHAVIORAL of SEGMENT7_CONTROLLER is -- Signal definitions -- COUNT_CLOCK counts the number of rising edge pulses from the system clock -- CLK_CONV_H is high below the FALL_COUNT and low above. signal COUNT_CLOCK : std_logic_vector( COUNTER_WIDTH - 1 downto 0 ); signal CLK_CONV_H : std_logic; signal DIGIT_INNER_H : std_logic_vector( 3 downto 0 ); -- Used to MUX output to LEDs signal SBASE_INNER_H : std_logic_vector( 3 downto 0 ); -- Used to select digit input -- This is how Xilinx does states if we wish to force a "one-hot" coding methodology,.. -- modifiy it to your synthesis tool and hardware target. type STATE_TYPE is (S0, S1, S2, S3); -- Definition attribute ENUM_ENCODING : string; -- Augment ENUM_ENCODING for type string attribute ENUM_ENCODING of STATE_TYPE : type is "0001 0010 0100 1000"; -- Bind STATE_TYPE -- to literal. -- Signals using STATE_TYPE signal CR_STATE, NX_STATE : STATE_TYPE; begin -- Process used to count the number of clock cycles -- seen. Note: on some parts this can be removed, -- because the input clock buffer has division and -- multiplication functionality,.. flavor to your parts -- taste COUNT_CLOCK_PROC : process ( RST_H, CLK ) begin if RST_H = '1' then COUNT_CLOCK <= ( others => '0'); elsif rising_edge( CLK ) then COUNT_CLOCK <= COUNT_CLOCK + 1; end if; end process; -- Output a converted clock signal, this signal -- is very unstable, because its output is determined -- by a comparitor. See above note. CLK_CONV_H <= '1' when COUNT_CLOCK < FALL_COUNT else '0'; -- To make a clean converted clock signal we sample -- CLK_CONV_H every rising_edge. See above, above note. SEG_COUNT_PROC : process( RST_H, CLK ) variable LAST_H : std_logic; -- Used to detect change in CLK_CONV_H begin if RST_H = '1' then LAST_H := '0'; CR_STATE <= S0; elsif rising_edge( CLK ) then if CLK_CONV_H /= LAST_H then CR_STATE <= NX_STATE; end if; LAST_H := CLK_CONV_H; end if; end process; -- Selects the which digit to refresh BASE_SELECT_PROC : process (CR_STATE) begin case CR_STATE is when S0 => SBASE_INNER_H <= "0001"; NX_STATE <= S1; when S1 => SBASE_INNER_H <= "0010"; NX_STATE <= S2; when S2 => SBASE_INNER_H <= "0100"; NX_STATE <= S3; when S3 => SBASE_INNER_H <= "1000"; NX_STATE <= S0; end case; end process; -- Output inner SBASE to output port SBASE_OUT_H <= SBASE_INNER_H; -- MUX to select with digit to select with SBASE_INNER_H select DIGIT_INNER_H <= SSEG_0_H when "0001", SSEG_1_H when "0010", SSEG_2_H when "0100", SSEG_3_H when "1000", SSEG_0_H when others; -- Decoder for 4 bit binary number to 7 segment display. -- Depending on how the target LED display is hooked up -- an inversion of the below selection assigments may need -- to be changed. The line sigment of the seven segment -- display map as follows: -- "ABCDEFG" with DIGIT_INNER_H select SSEG_OUT_H <= "0000001" when X"0", "1001111" when X"1", "0010010" when X"2", "0000110" when X"3", "1001100" when X"4", "0100100" when X"5", "0100000" when X"6", "0001111" when X"7", "0000000" when X"8", "0000100" when X"9", "0001000" when X"A", "1100000" when X"B", "0110001" when X"C", "1000010" when X"D", "0110000" when X"E", "0111000" when X"F", "1111111" when others; -- MUX to select decimal point -- not use in lab 6 with SBASE_INNER_H select DP_OUT_H <= not DP_0_H when "0001", not DP_1_H when "0010", not DP_2_H when "0100", not DP_3_H when "1000", '1' when others; end architecture BEHAVIORAL; -- End of file