Es werden BCD- oder HEX-Nibbles in Signale für eine 7-Segment-Anzeige dekodiert. 4 Nibbles werden zeitmultiplex auf einer 4-Ziffern-Anzeige dargestellt.
Die 4 Nibbles werden zuerst auf ein Nibble multiplext, welches anschließend dekodiert wird. Man kann es auch umgekehrt machen, dann braucht man allerdings 4 Dekoder und einen 7 bit breiten Multiplexer.
Für seven_segment_decoder kann je nach Bedarf der BCD- oder der HEX-Decoder instantiiert werden.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity sseg_test is Port ( clk : in STD_LOGIC; sw : in STD_LOGIC_VECTOR (7 downto 0); an : out STD_LOGIC_VECTOR (3 downto 0); seg : out STD_LOGIC_VECTOR (6 downto 0); dp : out STD_LOGIC); end sseg_test; architecture default of sseg_test is signal inverse: unsigned(7 downto 0); signal en: std_logic_vector(3 downto 0); signal v: std_logic_vector(3 downto 0); begin inverse <= not unsigned(sw); display_multiplexer: entity timemux_4x4 port map( clk => clk, reset => '0', d0 => sw(3 downto 0), d1 => sw(7 downto 4), d2 => std_logic_vector(inverse(3 downto 0)), d3 => std_logic_vector(inverse(7 downto 4)), lo_en => en, q => v); seven_segment_decoder: entity bcd_to_7seg port map(bcd => unsigned(v), seg => seg); dp <= en(2); an <= en; end default;
Die Eingänge sind an die Schiebeschaltern SW0 bis SW7 gelegt, die 7 Signale für die Segmente und das für den Punkt an die gemeinsamen Kathoden der Anzeige, die Aktivierung jeder Ziffer and die 4 Anoden der Anzeige und der Takt wird vom Onboard-50MHz-Signal gespeist.
# clock pin for Nexys 2 Board NET "clk" LOC = "B8"; # Bank = 0, Pin name = IP_L13P_0/GCLK8, Type = GCLK, Sch name = GCLK0 # 7 segment display NET "seg<0>" LOC = "L18"; # Bank = 1, Pin name = IO_L10P_1, Type = I/O, Sch name = CA NET "seg<1>" LOC = "F18"; # Bank = 1, Pin name = IO_L19P_1, Type = I/O, Sch name = CB NET "seg<2>" LOC = "D17"; # Bank = 1, Pin name = IO_L23P_1/HDC, Type = DUAL, Sch name = CC NET "seg<3>" LOC = "D16"; # Bank = 1, Pin name = IO_L23N_1/LDC0, Type = DUAL, Sch name = CD NET "seg<4>" LOC = "G14"; # Bank = 1, Pin name = IO_L20P_1, Type = I/O, Sch name = CE NET "seg<5>" LOC = "J17"; # Bank = 1, Pin name = IO_L13P_1/A6/RHCLK4/IRDY1, Type = RHCLK/DUAL, Sch name = CF NET "seg<6>" LOC = "H14"; # Bank = 1, Pin name = IO_L17P_1, Type = I/O, Sch name = CG NET "dp" LOC = "C17"; # Bank = 1, Pin name = IO_L24N_1/LDC2, Type = DUAL, Sch name = DP NET "an<0>" LOC = "F17"; # Bank = 1, Pin name = IO_L19N_1, Type = I/O, Sch name = AN0 NET "an<1>" LOC = "H17"; # Bank = 1, Pin name = IO_L16N_1/A0, Type = DUAL, Sch name = AN1 NET "an<2>" LOC = "C18"; # Bank = 1, Pin name = IO_L24P_1/LDC1, Type = DUAL, Sch name = AN2 NET "an<3>" LOC = "F15"; # Bank = 1, Pin name = IO_L21P_1, Type = I/O, Sch name = AN3 # Switches NET "sw<0>" LOC = "G18"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW0 NET "sw<1>" LOC = "H18"; # Bank = 1, Pin name = IP/VREF_1, Type = VREF, Sch name = SW1 NET "sw<2>" LOC = "K18"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW2 NET "sw<3>" LOC = "K17"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW3 NET "sw<4>" LOC = "L14"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW4 NET "sw<5>" LOC = "L13"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW5 NET "sw<6>" LOC = "N17"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW6 NET "sw<7>" LOC = "R17"; # Bank = 1, Pin name = IP, Type = INPUT, Sch name = SW7 NET "clk" TNM_NET = clk; TIMESPEC TS_clk = PERIOD "clk" 20 ns HIGH 50%;
Dieser Dekoder kann statt dem HEX-Dekoder verwendet werden, wenn man keine hexadezimalen Ziffern benötigt und man auf (ganz leicht) geringeren Ressourcenverbrauch hin optimieren möchte.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity bcd_to_7seg is Port ( bcd : in unsigned (3 downto 0); seg : out STD_LOGIC_VECTOR (6 downto 0)); end bcd_to_7seg; architecture default of bcd_to_7seg is begin with bcd select seg <= "1000000" when "0000", "1111001" when "0001", "0100100" when "0010", "0110000" when "0011", "0011001" when "0100", "0010010" when "0101", "0000010" when "0110", "1111000" when "0111", "0000000" when "1000", "0010000" when "1001", "-------" when others; end default;
Hier sind zusätzlich zu den dekadischen die hexadezimalen Ziffern A, b, C, d, E und F implementiert.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity hex_to_7seg is Port ( hex : in unsigned (3 downto 0); seg : out STD_LOGIC_VECTOR (6 downto 0)); end hex_to_7seg; architecture default of hex_to_7seg is begin with hex select seg <= "1000000" when "0000", "1111001" when "0001", "0100100" when "0010", "0110000" when "0011", "0011001" when "0100", "0010010" when "0101", "0000010" when "0110", "1111000" when "0111", "0000000" when "1000", "0010000" when "1001", "0001000" when "1010", "0000011" when "1011", "1000110" when "1100", "0100001" when "1101", "0000110" when "1110", "0001110" when "1111", "-------" when others; end default;
Der Multiplexer teilt zuerst den Takt durch 2^DIVIDER_SHIFT, und erhöht bei Überlauf einen 2-bit-Zähler (beides in einem Signalvektor zusammengefasst).
Je nach Zählerstand wird dann das entsprechende low-aktive Enable-Signal gesetzt (entspricht einem 1-aus-4-Dekoder) und einer der Eingangsvektoren auf den Ausgang geschaltet (entspricht einem 4 bit breiten 4-zu-1-Multiplexer).
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity timemux_4x4 is Port ( clk : in STD_LOGIC; reset : in std_logic; d0 : in STD_LOGIC_VECTOR (3 downto 0); d1 : in STD_LOGIC_VECTOR (3 downto 0); d2 : in STD_LOGIC_VECTOR (3 downto 0); d3 : in STD_LOGIC_VECTOR (3 downto 0); lo_en : out STD_LOGIC_VECTOR (3 downto 0); q : out STD_LOGIC_VECTOR (3 downto 0)); end timemux_4x4; architecture default of timemux_4x4 is constant DIVIDER_SHIFT: natural := 16; signal combined: unsigned(DIVIDER_SHIFT+1 downto 0); signal counter: unsigned(1 downto 0); begin process (clk, reset) begin if reset = '1' then combined <= (others => '0'); elsif rising_edge(clk) then combined <= combined + 1; end if; end process; counter <= combined(combined'high downto combined'high+1-counter'length); process (counter, d0, d1, d2, d3) begin case counter is when "00" => lo_en <= "1110"; q <= d0; when "01" => lo_en <= "1101"; q <= d1; when "10" => lo_en <= "1011"; q <= d2; when "11" => lo_en <= "0111"; q <= d3; when others => lo_en <= "----"; q <= "----"; end case; end process; end default;
Diskussion