library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity display is port (clk_400 : in std_ulogic; --400Hz Taktsignal sys_clk : in std_ulogic; --Systemtakt 50Mhz reset : in std_ulogic; --Reset-Signal data_input : in std_ulogic_vector (13 downto 0); --Token-Signal des Morsedecoders enable_char : in std_ulogic; --Pausen-Signal der Entity morsedecoder ob ein Token-Signal abgeschlossen ist vga_next : in std_ulogic; --Schalter zum Ändern der Zeile bei Videoausgabe vga_clear : in std_ulogic; --Taste zum vollständigen Löschen des gesamten Bildschirm Push-button[1]/KEY[1] del_switch : in std_ulogic; --Schalter zum Aktivieren der Löschfunktion mittels Morsetaste data_out : out std_ulogic_vector (7 downto 0); --Datensignale für das LCD (Zeichen) lcd_control : out std_ulogic_vector (3 DOWNTO 0); --Steuersignale für das LCD rx_done_tick: out std_ulogic; --Zeichenausgabe-Signal (VGA) vga_out : out std_ulogic_vector (7 downto 0)); --Datensignale für den Bildschirm (Hex) end display; architecture structure of display is signal LCD_DATA : std_ulogic_vector (7 downto 0); --Datensignal für das Display signal LCD_ON, LCD_RS, LCD_EN, LCD_RW : std_ulogic; --Steuersignale für das Display signal sig_old : std_ulogic; --Signale zum Prüfen eines Signalwechsels signal sig_rise : std_ulogic; --Signale für die VGA-Steuerung signal rx_done_tick_sig :std_ulogic; signal vga_out_sig : std_ulogic_vector (7 downto 0); signal lcd_en_fall : std_ulogic; signal lcd_en_old : std_ulogic; signal en_old : std_ulogic; signal en_fall : std_ulogic; signal valid : std_ulogic := '0'; signal state: natural range 0 to 25; signal state2: natural range 0 to 6; signal state3: natural range 0 to 3; signal cnt : natural; signal del : std_ulogic := '0'; begin vga_control: process (sys_clk, reset, LCD_DATA, LCD_EN, LCD_RS, vga_next, lcd_en_old, lcd_en_fall, valid, state, state2, state3, en_old, en_fall) begin if reset = '0' then rx_done_tick_sig <= '0'; vga_out_sig <= (others => '0'); lcd_en_fall <= '0'; en_old <= '0'; en_fall <= '0'; state <= 0; state2 <= 0; state3 <= 0; cnt <= 0; elsif sys_clk'event and sys_clk ='1' then lcd_en_old <= LCD_EN; en_old <= vga_next; cnt <= cnt + 1; if en_old ='1' and vga_next = '0' then en_fall <='1'; rx_done_tick_sig <= '0'; else en_fall <='0'; end if; if lcd_en_old ='1' and LCD_EN = '0' then -- Die eingegebenen Zeichen können nur übertragen werden, wenn LCD_EN = '0' lcd_en_fall <= '1'; else lcd_en_fall <= '0'; end if; if (en_fall ='1' or state > 0 ) and valid = '1' then case state is when 0=> vga_out_sig <= x"5A"; --ENTER rx_done_tick_sig <= '1'; state <= state +1; when 1=> rx_done_tick_sig <= '0'; state <= state +1; when 2=> vga_out_sig <= x"4D"; --"M" rx_done_tick_sig <= '1'; state <= state +1; when 3=> rx_done_tick_sig <= '0'; state <= state +1; when 4=> vga_out_sig <= x"4F"; --"O" rx_done_tick_sig <= '1'; state <= state +1; when 5=> rx_done_tick_sig <= '0'; state <= state +1; when 6=> vga_out_sig <= x"52"; --"R" rx_done_tick_sig <= '1'; state <= state +1; when 7=> rx_done_tick_sig <= '0'; state <= state +1; when 8=> vga_out_sig <= x"53"; --"S" rx_done_tick_sig <= '1'; state <= state +1; when 9=> rx_done_tick_sig <= '0'; state <= state +1; when 10=> vga_out_sig <= x"45"; --"E" rx_done_tick_sig <= '1'; state <= state +1; when 11=> rx_done_tick_sig <= '0'; state <= state +1; when 12=> vga_out_sig <= x"43"; --"C" rx_done_tick_sig <= '1'; state <= state +1; when 13=> rx_done_tick_sig <= '0'; state <= state +1; when 14=> vga_out_sig <= x"4F"; --"O" rx_done_tick_sig <= '1'; state <= state +1; when 15=> rx_done_tick_sig <= '0'; state <= state +1; when 16=> vga_out_sig <= x"44"; --"D" rx_done_tick_sig <= '1'; state <= state +1; when 17=> rx_done_tick_sig <= '0'; state <= state +1; when 18=> vga_out_sig <= x"45"; --"E" rx_done_tick_sig <= '1'; state <= state +1; when 19=> rx_done_tick_sig <= '0'; state <= state +1; when 20=> vga_out_sig <= x"20"; --"Leer" rx_done_tick_sig <= '1'; state <= state +1; when 21=> rx_done_tick_sig <= '0'; state <= state +1; when 22=> vga_out_sig <= x"1A"; --">" rx_done_tick_sig <= '1'; state <= state +1; when 23=> rx_done_tick_sig <= '0'; state <= state +1; when 24 => en_fall <='0'; state <= 25; when others => state <= 0; end case; elsif (cnt >= (10*10**6) and del_switch = '1') and (sig_rise = '1' or state2 > 0) then del <= not del; cnt <= 0; case state2 is when 0=> vga_out_sig <= x"6B"; --Cursor springt nach links rx_done_tick_sig <= '1'; state2 <= state2 +1; when 1=> rx_done_tick_sig <= '0'; state2 <= state2 +1; when 2=> vga_out_sig <= x"20"; --Leerzeichen "Löschen" rx_done_tick_sig <= '1'; state2 <= state2 +1; when 3=> rx_done_tick_sig <= '0'; state2 <= state2 +1; when 4=> vga_out_sig <= x"6B"; --Cursor springt nach links rx_done_tick_sig <= '1'; state2 <= state2 +1; when 5=> rx_done_tick_sig <= '0'; state2 <= state2 +1; when others => state2 <= 0; end case; elsif vga_clear = '0' then case state3 is when 0=> vga_out_sig <= x"66"; --Backspace "Clear All" rx_done_tick_sig <= '1'; state3 <= state3 +1; when 1=> rx_done_tick_sig <= '0'; state3 <= state3 +1; when others => state3 <= 0; end case; elsif valid = '0' then rx_done_tick_sig <='0'; elsif lcd_en_fall = '1' then vga_out_sig <= LCD_DATA; rx_done_tick_sig <='1'; lcd_en_fall <= '0'; else rx_done_tick_sig <='0'; end if; rx_done_tick <= rx_done_tick_sig; vga_out <= vga_out_sig; end if; end process; -------------------------------------------------------------- --Ansteuerung des Displays mit Initialisierung und Ausgabe der Zeichnen-- -------------------------------------------------------------- LCD_init: process (clk_400, reset, data_input, enable_char, valid) variable ini : natural range 0 to 11 := 0; variable next_command : natural range 0 to 11 := 0; variable char_cnt : natural range 0 to 34 := 0; variable char : integer range 0 tO 12 := 0; begin --LCD reinitialisieren if reset = '0' then LCD_ON <= '1'; --LCD Power ON/OFF LCD_EN <= '1'; --LCD Aktivierung LCD_RW <= '0'; --LCD Schreiben(0)/Lesen(1) LCD_RS <= '0'; --LCD Kommando(0)/Daten(1) LCD_DATA <= x"38"; --Display aus / Beide Zeilen leer (=reset) valid <= '0'; ini := 0; next_command := 0; char_cnt := 0; elsif clk_400'event and clk_400 = '1' then case ini is --LCD Initialisierung when 0 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --Display aus / Beide Zeilen leer (=reset) valid <= '0'; next_command := next_command+1; ini := 8; when 1 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --Display aus / Beide Zeilen leer (=reset) next_command := next_command+1; ini := 8; when 2 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --Display aus / Beide Zeilen leer (=reset) next_command := next_command+1; ini := 8; when 3 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"38"; --Display aus / Beide Zeilen leer (=reset) 4x notwendig zum Initialisieren next_command := next_command+1; ini := 8; when 4 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"0D"; --Display ein / Cursor blinkt an Position next_command := next_command+1; ini := 8; when 5 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"01"; --Display leeren next_command := next_command+1; ini := 8; when 6 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"0D"; --Display ein / Cursor blinkt an Position next_command := next_command+1; ini := 8; when 7 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"06"; --Addresse wird automatisch inkrementiert und der Cursor nach rechts verschoben valid <= '0'; next_command := 11; ini := 8; -- Initialisierung ist ab hier beendet when 8 => --Dieser Zyklus dient dazu das Enable-Signal in LCD_EN auch auf '0' zu setzen. --Ansonsten können die Daten nicht an den Bildschirm übertragen werden!!! LCD_ON <= '1'; LCD_EN <= '0'; ini := next_command; when 9 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '1'; LCD_DATA <= x"20"; --" " next_command:= 10; ini := 8; when 10 => LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"10"; --scrollt cursor nach links next_command := 11; ini := 8; when 11 => if char_cnt = 16 then LCD_RS <= '0'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_ON <= '1'; LCD_DATA <= x"C0"; --Setzt den Cursor an den Anfang der zweiten Zeile des Displays char_cnt := char_cnt + 1; ini := 8; elsif char_cnt = 34 then LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '0'; LCD_DATA <= x"01"; --Display leeren char_cnt := 0; ini := 8; else valid <= '1'; sig_rise <= '0'; --Das Signal "sig_rise" wird standardmäßig auf ein LOW gesetzt, da dass enable_char-Signal nicht immer eine steigende Flanke hat sig_old <= enable_char; --Das aktuelle enable_char-Signal wird "sig_old" zugewiesen if sig_old = '0' AND enable_char = '1' then --Überprüfung ob sich Signale unterscheiden, ist dies der Fall (positive Flanke) sig_rise <= '1'; --Die Zuweisung erfolgt erst im nächsten Taktzyklus, deshalb ist die vorherige Zuweisung zu prüfen end if; ---------------------------------------- --Ansteuerung des LCD im Decoder-Modus-- ---------------------------------------- If sig_rise = '1' then LCD_ON <= '1'; LCD_EN <= '1'; LCD_RW <= '0'; LCD_RS <= '1'; case data_input is when "00000000000000" => LCD_EN <= '0'; --Buchstaben when "00000000000111" => LCD_DATA <=x"41"; -- A when "00000011010101" => LCD_DATA <=x"42"; -- B when "00000011011101" => LCD_DATA <=x"43"; -- C when "00000000110101" => LCD_DATA <=x"44"; -- D when "00000000000001" => LCD_DATA <=x"45"; -- E when "00000001011101" => LCD_DATA <=x"46"; -- F when "00000000111101" => LCD_DATA <=x"47"; -- G when "00000001010101" => LCD_DATA <=x"48"; -- H when "00000000000101" => LCD_DATA <=x"49"; -- I when "00000001111111" => LCD_DATA <=x"4A"; -- J when "00000000110111" => LCD_DATA <=x"4B"; -- K when "00000001110101" => LCD_DATA <=x"4C"; -- L when "00000000001111" => LCD_DATA <=x"4D"; -- M when "00000000001101" => LCD_DATA <=x"4E"; -- N when "00000000111111" => LCD_DATA <=x"4F"; -- O when "00000001111101" => LCD_DATA <=x"50"; -- P when "00000011110111" => LCD_DATA <=x"51"; -- Q when "00000000011101" => LCD_DATA <=x"52"; -- R when "00000000010101" => LCD_DATA <=x"53"; -- S when "00000000000011" => LCD_DATA <=x"54"; -- T when "00000000010111" => LCD_DATA <=x"55"; -- U when "00000001010111" => LCD_DATA <=x"56"; -- V when "00000000011111" => LCD_DATA <=x"57"; -- W when "00000011010111" => LCD_DATA <=x"58"; -- X when "00000011011111" => LCD_DATA <=x"59"; -- Y when "00000011110101" => LCD_DATA <=x"5A"; -- Z --Zahlen when "00001111111111" => LCD_DATA <=x"30"; -- 0 when "00000111111111" => LCD_DATA <=x"31"; -- 1 when "00000101111111" => LCD_DATA <=x"32"; -- 2 when "00000101011111" => LCD_DATA <=x"33"; -- 3 when "00000101010111" => LCD_DATA <=x"34"; -- 4 when "00000101010101" => LCD_DATA <=x"35"; -- 5 when "00001101010101" => LCD_DATA <=x"36"; -- 6 when "00001111010101" => LCD_DATA <=x"37"; -- 7 when "00001111110101" => LCD_DATA <=x"38"; -- 8 when "00001111111101" => LCD_DATA <=x"39"; -- 9 when others => LCD_DATA <= x"3F"; end case; char_cnt := char_cnt + 1; ini := 8; if del_switch = '1' and char_cnt = 0 then next_command := 5; elsif del_switch = '1' and char_cnt > 0 then LCD_RS <= '0'; LCD_DATA <= x"10"; valid <= '0'; next_command := 9; char_cnt := char_cnt - 2; end if; end if; end if; end case; --Übertragung der Steuersignale und Datenbits an das LCD lcd_control(3) <= LCD_ON; lcd_control(0) <= LCD_EN; lcd_control(1) <= LCD_RW; lcd_control(2) <= LCD_RS; data_out <= LCD_DATA; end if; end process; end structure;