From 12bbdb42cdcf5e6e39832d75fbbd31e3781d550a Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 11 Apr 2014 19:29:53 +0200 Subject: Import fichiers projet Quartus --- FPGA/vhdl/lcd_controller.vhd | 363 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 FPGA/vhdl/lcd_controller.vhd (limited to 'FPGA/vhdl/lcd_controller.vhd') diff --git a/FPGA/vhdl/lcd_controller.vhd b/FPGA/vhdl/lcd_controller.vhd new file mode 100644 index 0000000..0818db2 --- /dev/null +++ b/FPGA/vhdl/lcd_controller.vhd @@ -0,0 +1,363 @@ +---------------------------------------------------------- +-- LCD 2 lines controller +-- +-- 8 bits interface -- +---------------------------------------------------------- +-- ESIEE +-- Creation : A. Exertier, mars 2008 +---------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +---------------------------------------------------------- +-- INPUTS +---------------------------------------------------------- +-- clk : system clock +-- resetn : aynchronous active low reset +-- en_250kHz : enable at 250 kHz (lasts 1 clock cycle) +-- char : input ASCII character +-- write_char : write character command +-- ready : set to 1 when device is ready for a writing +---------------------------------------------------------- +-- OUTPUTS +---------------------------------------------------------- +-- LCD_DATA : ASCII data to LCD +-- LCD_RS : RS to LCD +-- LCD_RW : Read/write to LCD +-- LCD_EN : Enable to LCD +------------------------------------------------------------ + +Entity LCD_controller is + + port( + clk : in std_logic; + resetn : in std_logic; + en_250kHz : in std_logic; + + mode : in std_logic_vector(1 downto 0); + char : in std_logic_vector (7 downto 0); + address : in std_logic_vector(6 downto 0); + write_char : in std_logic; + write_address : in std_logic; + ready : out std_logic; + D : in std_logic; + C : in std_logic; + B : in std_logic; + + -- LCD signals + + LCD_data : inout std_logic_vector(7 downto 0); + LCD_RS : out std_logic; + LCD_RW : out std_logic; + LCD_EN : out std_logic + ); + +end LCD_Controller; + + + +Architecture RTL of LCD_Controller is + + type State_type is (Boot, FunctionSet, DisplayControl, EntryModeSet, Clear, + Address_set, Waiting, Verify, Putchar, Homecursor, + WriteAddress, WriteData); + signal present : State_type; + + signal future : State_type; + + +-- Timing Constants : + + constant T_30ms : integer := 30_000/4; -- 7500; -- 30 ms + + constant T_2ms : integer := 2_000/4; --500; -- 2 ms + + constant T_40us : integer := 12; -- > 39 us after E down + + constant En_delay : integer := 1; -- 8 us + + constant LastPosition : integer := 16; + + +-- CLEAR DisplayControl + constant CLR : std_logic_vector(7 downto 0) := "00000001"; +-- RETURN HOME + constant RET_HOME : std_logic_vector(7 downto 0) := "00000010"; -- 0000001x + -- DDRAM address to 0 (beginning of first line) + +-- ENTRY MODE SET + constant ENTRY_MODE : std_logic_vector(7 downto 0) := "00000110"; -- 0000 01 I/D S + -- I/D : 1 => Increment, 0 => Decrement + -- S : 1 => DisplayControl shift + +-- FUNCTION SET + constant FUNC_SET : std_logic_vector(7 downto 0) := "00111100"; -- 001 DL N F xx + -- DL : 1 => 8 bits, 0 => 4 bits + -- N : 1 => 2 lines, 0 => 1 line + -- F : 1 => 5x10 dots, 0 => 5x8 dots + +-- DisplayControl ON/OFF CONTROL + constant DON : std_logic_vector(7 downto 0) := "00001110"; -- 0000 1 D C B + -- D : 1 => Display on + -- C : 1 => Cursor on + -- B : 1 => Cursor blink on + + constant RET_LINE2 : std_logic_vector(7 downto 0) := "11000000"; + -- set DDRAM address to 32 (beginning of second line) + constant RET_LINE1 : std_logic_vector(7 downto 0) := "10000000"; + -- set DDRAM address to 0 (beginning of first line) + + + + signal Position : natural range 0 to 2*LastPosition; + + signal Count : natural range 0 to T_30ms; + signal inc_C : std_logic; + + signal cmd_P : std_logic_vector(1 downto 0); + --signal reset_P : std_logic; + + signal test_EN : std_logic; + signal test_T_40us : std_logic; + + + + begin + + + LCD_RW <= '0'; + + +process (Clk, resetn) + + begin + + if resetn = '0' then + + present <= Boot; + position <= 0; + count <= 0; + + elsif rising_edge(clk) then + + if en_250kHz = '1' then + + present <= future; + + if inc_C = '1' then count <= count+1; + + else count <= 0; + + end if; + case cmd_P is + when "00" => position <= 0; + when "01" => if position >= 31 then position <= 0; + else position <= position+1; + end if; + when "10" => if address(6 downto 4) = "000" then position <= to_integer(unsigned(address(3 downto 0))); + elsif address(6 downto 4) = "100" then position <= to_integer(unsigned(address(3 downto 0)))+16; + else position <= 0; + end if; + when others => null; + end case; + + end if; + + end if; + end process; + + +test_EN <= '1' when Count = En_delay else '0'; +test_T_40us <= '1' when count >= T_40us else '0'; + + process(present, Write_char, mode, write_address, count, Position,char, + address,test_EN, test_T_40us , D, C, b) is + + begin + + future <= present; + + inc_C <= '1'; + + cmd_P <= "11"; + + ready <= '0'; + + LCD_RS <= '0'; + + LCD_EN <= '0'; + + LCD_data <= X"00"; + + + + case present is + + + when Boot => -- Wait for 30 ms + + if Count = T_30ms then + future <= FunctionSet; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + + + when FunctionSet => -- Function Set + LCD_data <= FUNC_SET; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= EntryModeSet; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + + + + when EntryModeSet => -- Entry Mode Set + + LCD_data <= ENTRY_MODE; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= DisplayControl; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when DisplayControl => + -- Display ON/OFF control + + LCD_data <= DON(7 downto 3)&D&C&B; + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= Clear; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when Clear => + -- Clear Display + LCD_data <= CLR; + LCD_EN <= test_EN; + if Count >= T_2ms then + inc_C <= '0'; + future <= Address_set; + end if; + cmd_P <= "00"; + + when Address_set => + -- DDRAM address set + LCD_data <= RET_LINE1; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + + future <= Waiting; + + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when Waiting => + -- Waits for input + if mode (1) = '1' then + + if write_address = '1' then future <= WriteAddress; + elsif write_char = '1' then future <= WriteData; + end if; + elsif write_char = '1' then + + if char = x"0C" then future <= Clear; + else future <= Putchar; + end if; + end if; + + ready <= '1'; + + inc_C <= '0'; + + + when WriteAddress => + -- Set CGRAM/DDRAM Address + if mode(0) = '0' then LCD_data <= '1'&address; + else LCD_data <= "01"&address(5 downto 0); + end if; + LCD_EN <= test_EN; + if test_T_40us = '1' then + future <= Waiting; + inc_C <= '0'; + end if; + cmd_P <= "10"; + + when WriteData => + -- Write data to CGRAM or DDRAM + LCD_RS <= '1'; + LCD_EN <= test_EN; + LCD_DATA <= char; + if test_T_40us = '1' then + future <= Waiting; + inc_C <= '0'; + cmd_P <= "01"; + end if; + + + when Verify => + + if char = x"0C" then -- FormFeed => Clear Screen + + future <= Clear; + else future <= Putchar; + + end if; + inc_C <= '0'; + LCD_data <= char; + + + + when Putchar => + -- Display character on the LCD + LCD_RS <= '1'; + LCD_EN <= test_EN; + if test_T_40us = '1' then + if Position = 15 or Position = 31 then + future <= HomeCursor; + else future <= Waiting; + cmd_P <= "01"; + end if; + inc_C <= '0'; + end if; + LCD_data <= char; + + + + when HomeCursor => + LCD_EN <= test_EN; + if Position = 31 then LCD_data <= RET_LINE1; --RET_HOME; + else LCD_data <= RET_LINE2; + end if; + if test_T_40us = '1' then + --if Count >= T_2ms then + if Position = 31 then cmd_P <= "00"; + else cmd_P <= "01"; + end if; + future <= Waiting; + inc_C <= '0'; + + end if; + + end case; + + end process; + + +end RTL; -- cgit v1.2.3