-- Dateiname: LCD_Controller -- Design Software : Quartus II 13.0sp1 (64-bit) -- -- Erstellt: -- von Kai-Frederik Nessitt -- Am 2018 -- -- Verändert: -- Von Bouchnak Wassim -- Am 07.08.2021 -- -- Es findet die Initialisierung und den Datenfluss zu 8-Bit-Schnittstellen-LCD-Modulen HD44780 statt -- Zudem wird sowohl der Token im Decoder-Modus als auch die Tastaturdaten -- im Encoder-Modus ausgewertet und auf dem LCD-Display dargestellt. --------------------------------------------------------------------------------LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.numeric_std.ALL;ENTITY LCD IS GENERIC( display_lines : STD_LOGIC ; --number of display lines (0 = 1-line mode, 1 = 2-line mode) character_font : STD_LOGIC ; --font (0 = 5x8 dots, 1 = 5x10 dots) display_on_off : STD_LOGIC ; --display on/off (0 = off, 1 = on) cursor : STD_LOGIC ; --cursor on/off (0 = off, 1 = on) blink : STD_LOGIC ; --blink on/off (0 = off, 1 = on inc_dec : STD_LOGIC ; --increment/decrement (0 = decrement, 1 = increment) shift : STD_LOGIC --shift on/off (0 = off, 1 = on) ); PORT( clk : IN STD_LOGIC; --clock 800 HZ reset_n : IN STD_LOGIC; --active low reinitializes lcd data_input : IN STD_LOGIC_VECTOR (13 DOWNTO 0); --Token-Signal des Decoders / Morse data_keyboard : IN STD_LOGIC_VECTOR (7 DOWNTO 0); --Keyboard-Daten nach Betätigung einer Taste enable_Modus : IN STD_LOGIC; --Switch Signal zum Umschalten zwischen dem Decoder 0 und Encoder 1 enable_Pause : IN STD_LOGIC; --Pausen-Signal der Morse-Entity zur Überprüfung ob ein Token-Signal "fertig" ist done_pressing : IN STD_LOGIC; --gibt an ob die Tastaturtaste losgelassen wurde und die Datenübertragung beendet wurde rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data signals for lcd lcd_on : OUT STD_LOGIC; -- LCD Power On/Off lcd_blon : OUT STD_LOGIC; -- LCD Back Light On/Off busy : OUT STD_LOGIC --lcd feedback ); END LCD;ARCHITECTURE RTL OF LCD IS TYPE CONTROL IS(power_up, reset1, reset2, reset3, function_set, display_control, display_clear, mode_set, drop_lcd_en, ready, send, Line2, Return_Home); SIGNAL state, next_command : CONTROL; SIGNAL enable_Pause_p1 : STD_LOGIC; -- altes Signal enable_Pause ALTsig_Pause SIGNAL valid_Pause : STD_LOGIC; -- Bestätigung einer neuen Pause im decoder Modus SIGNAL enable_Modus_p1: STD_LOGIC; -- altes Signal enable_Modus ALTsig_Modus SIGNAL Modus_Wechsel: STD_LOGIC; SIGNAL done_pressing_p1: STD_LOGIC; -- altes Signal done_pressing ALTsig_pressing SIGNAL valid_done_pressing : STD_LOGIC; -- signal char_count : unsigned( 5 downto 0) := "000000"; -- auf dem lcd angezeigt Charakter Zähler BEGIN PROCESS(clk, reset_n) VARIABLE clk_count : INTEGER := 0; --event counter for timing BEGIN IF reset_n = '0' THEN state <= power_up; next_command <= reset1; -- reset1 lcd_on <= '1'; e <= '0'; rs <= '0'; rw <= '0'; busy <= '0'; char_count <= (others => '0'); --char_count := 0; clk_count := 0; ELSIF(clk'EVENT and clk = '1') THEN -- defaults : somit konnen inpuls signale erzeugt werden wenn die Bedingungen erfüllt sind valid_Pause <= '0'; Modus_Wechsel <= '0'; valid_done_pressing <= '0'; -- Shift value in : im nächsten Taktzyklus erfolgt die Zuweisung und somit kann jegliche änderung eines Signals fesgestellt werden enable_Pause_p1 <= enable_Pause; enable_Modus_p1 <= enable_Modus; done_pressing_p1 <= done_pressing; --Es wird geprüft ob sich das alte Signal zum neuen Signal unterscheidet. Ist dies der Fall, gab es eine positive Flanke IF enable_Pause_p1 = '0' AND enable_Pause = '1' AND enable_Modus = '0' THEN valid_Pause <= '1'; -- pause bestätigt und token bereit und vollständig END IF; IF (enable_Modus_p1 = '0' AND enable_Modus = '1') or ( enable_Modus_p1 = '1' AND enable_Modus = '0') THEN Modus_Wechsel <= '1'; -- switch decoder zum encoder END IF; IF done_pressing_p1 = '0' AND done_pressing = '1' AND enable_Modus = '1' THEN valid_done_pressing <= '1'; -- done_pressing bestätigt und data_keyboard bereit und vollständig END IF; --Beginn des fsm logic CASE state IS WHEN power_up => --wait 50 ms to ensure Vdd has risen and required LCD wait is met busy <= '1'; IF(clk_count < 20) THEN --wait 50 ms state <= power_up; clk_count := clk_count + 1;ELSE --power-up complete clk_count := 0; state <= next_command; next_command <= drop_lcd_en; END IF; WHEN reset1 => e <= '1'; lcd_data <= x"38"; IF(clk_count < 2) THEN --wait 5 ms state <= reset1; clk_count := clk_count + 1;ELSE clk_count := 0; state <= next_command; next_command <= reset2; END IF; WHEN reset2 => -- Externer RESET e <= '1'; lcd_data <= x"38"; state <= drop_lcd_en; next_command <= reset3; WHEN reset3 => -- Externer RESET e <= '1'; lcd_data <= x"38"; state <= drop_lcd_en; next_command <= function_set; WHEN function_set => --function set e <= '1'; lcd_data <= "0011" & display_lines & character_font & "00"; state <= drop_lcd_en; next_command <= display_control; WHEN display_control => --display on/off control e <= '1'; lcd_data <= "00001" & display_on_off & cursor & blink; state <= drop_lcd_en; next_command <= display_clear; WHEN display_clear => --display clear e <= '1'; lcd_data <= "00000001"; state <= drop_lcd_en; next_command <= mode_set; WHEN mode_set => --entry mode set e <= '1'; lcd_data <= "00001" & display_on_off & cursor & blink; state <= drop_lcd_en; next_command <= ready; --initialization complete WHEN drop_lcd_en => busy <= '1'; e <= '0'; state <= next_command; WHEN Line2 => --Setze Cursor an den Anfang der zweiten Zeile des Displays busy <= '1'; rs <= '0'; rw <= '0'; e <= '1'; lcd_data <= "11000000"; char_count <= char_count + 1; state <= drop_lcd_en; next_command <= ready; WHEN Return_Home => busy <= '1'; rs <= '0'; rw <= '0'; e <= '1'; lcd_data <= "00000001"; --clear Display --char_count := 0; char_count <= (others => '0'); state <= drop_lcd_en; next_command <= ready; WHEN ready => busy <= '0'; --IF ( char_count = 16 ) THEN IF ( char_count = "010000" ) THEN state <= Line2; --ELSIF ( char_count = 33 ) THEN ELSIF ( char_count = "100001" ) THEN state <= Return_Home; ELSE state <= send; END IF; WHEN send => busy <= '1'; IF ( Modus_Wechsel = '1') THEN state <= Return_Home; ELSIF( valid_Pause = '1') THEN rs <= '1'; rw <= '0'; e <= '1'; CASE data_input IS --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 -1 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 -2 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 --Sonderzeichen -- WHEN "00000111110111" => lcd_data <=x"8F"; -- Å WHEN "00000001110111" => lcd_data <=x"E1"; -- Ä -- WHEN "00000111010111" => lcd_data <=x"8A"; -- È -- WHEN "00000101110101" => lcd_data <=x"90"; -- É WHEN "00000011111101" => lcd_data <=x"EF"; -- Ö WHEN "00000001011111" => lcd_data <=x"F5"; -- Ü WHEN "01010111110101" => lcd_data <=x"E2"; -- ß WHEN "00110111011101" => lcd_data <=x"3B"; -- ; WHEN "00010111110101" => lcd_data <=x"3F"; -- ? WHEN "00110101010111" => lcd_data <=x"2D"; -- - WHEN "00010111110111" => lcd_data <=x"5F"; -- _ -- WHEN "00001111011111" => lcd_data <=x"A5"; -- Ñ WHEN "00011101110111" => lcd_data <=x"2E"; -- . WHEN "00111101011111" => lcd_data <=x"2C"; -- , WHEN "00111111010101" => lcd_data <=x"3A"; -- : WHEN "00001101111101" => lcd_data <=x"28"; -- ( WHEN "00110111110111" => lcd_data <=x"29"; -- ) WHEN "00011111111101" => lcd_data <=x"27"; -- ' WHEN "00001101010111" => lcd_data <=x"3D"; -- = WHEN "00000111011101" => lcd_data <=x"2B"; -- + WHEN "00001101011101" => lcd_data <=x"2F"; -- / WHEN "00011111011101" => lcd_data <=x"40"; -- @ WHEN OTHERS => lcd_data <= x"00"; END CASE;char_count <= char_count + 1; state <= drop_lcd_en; elsif (valid_done_pressing = '1') THEN rs <= '1'; rw <= '0'; e <= '1'; CASE data_keyboard IS --Buchstaben WHEN x"1C" => lcd_data <=x"41"; -- A WHEN x"32" => lcd_data <=x"42"; -- B WHEN x"21" => lcd_data <=x"43"; -- C WHEN x"23" => lcd_data <=x"44"; -- D WHEN x"24" => lcd_data <=x"45"; -- E WHEN x"2B" => lcd_data <=x"46"; -- F WHEN x"34" => lcd_data <=x"47"; -- G WHEN x"33" => lcd_data <=x"48"; -- H WHEN x"43" => lcd_data <=x"49"; -- I WHEN x"3B" => lcd_data <=x"4A"; -- J WHEN x"42" => lcd_data <=x"4B"; -- K WHEN x"4B" => lcd_data <=x"4C"; -- L WHEN x"3A" => lcd_data <=x"4D"; -- M WHEN x"31" => lcd_data <=x"4E"; -- N WHEN x"44" => lcd_data <=x"4F"; -- O WHEN x"4D" => lcd_data <=x"50"; -- P WHEN x"15" => lcd_data <=x"51"; -- Q WHEN x"2D" => lcd_data <=x"52"; -- R WHEN x"1B" => lcd_data <=x"53"; -- S WHEN x"2C" => lcd_data <=x"54"; -- T WHEN x"3C" => lcd_data <=x"55"; -- U WHEN x"2A" => lcd_data <=x"56"; -- V WHEN x"1D" => lcd_data <=x"57"; -- W WHEN x"22" => lcd_data <=x"58"; -- X WHEN x"1A" => lcd_data <=x"59"; -- Y WHEN x"35" => lcd_data <=x"5A"; -- Z --Zahlen WHEN x"45" => lcd_data <=x"30"; -- 0 WHEN x"16" => lcd_data <=x"31"; -- 1 WHEN x"1E" => lcd_data <=x"32"; -- 2 WHEN x"26" => lcd_data <=x"33"; -- 3 WHEN x"25" => lcd_data <=x"34"; -- 4 WHEN x"2E" => lcd_data <=x"35"; -- 5 WHEN x"36" => lcd_data <=x"36"; -- 6 WHEN x"3D" => lcd_data <=x"37"; -- 7 WHEN x"3E" => lcd_data <=x"38"; -- 8 WHEN x"46" => lcd_data <=x"39"; -- 9 --Sonderzeichen -- WHEN x"" => lcd_data <=x"8F"; -- Å WHEN x"52" => lcd_data <=x"E1"; -- Ä -- WHEN x"" => lcd_data <=x"8A"; -- È -- WHEN x"" => lcd_data <=x"90"; -- É WHEN x"4C" => lcd_data <=x"EF"; -- Ö WHEN x"54" => lcd_data <=x"F5"; -- Ü WHEN x"4E" => lcd_data <=x"E2"; -- ß -- WHEN x"" => lcd_data <=x"3B"; -- ; -- WHEN x"" => lcd_data <=x"3F"; -- ? WHEN x"4A" => lcd_data <=x"2D"; -- - -- WHEN x"" => lcd_data <=x"5F"; -- _ -- WHEN x"" => lcd_data <=x"A5"; -- Ñ WHEN x"49" => lcd_data <=x"2E"; -- . WHEN x"41" => lcd_data <=x"2C"; -- , -- WHEN x"" => lcd_data <=x"3A"; -- : -- WHEN x"" => lcd_data <=x"28"; -- ( -- WHEN x"" => lcd_data <=x"29"; -- ) -- WHEN x"" => lcd_data <=x"27"; -- ' -- WHEN x"" => lcd_data <=x"3D"; -- = WHEN x"5B" => lcd_data <=x"2B"; -- + -- WHEN x"" => lcd_data <=x"2F"; -- / -- WHEN x"" => lcd_data <=x"40"; -- @ WHEN x"29" => lcd_data <=x"20"; -- " " WHEN OTHERS => lcd_data <= x"00"; END CASE;char_count <= char_count + 1; state <= drop_lcd_en;END IF; END CASE; END IF;END PROCESS; END RTL;