------------------------------------------------------------ -- Escrever dados na memória RAM e visualizar os dados da memória no LCD ------------------------------------------------------------ -- INTERFACE -- entrada: 1 bit - número de linha (0 linha de topo, 1 linha em baixo) -- entrada: 4 bits - endereço do caracter na linha (de 0 a 15) -- entrada: 8 bits - o código ASCII do caracter -- entrada: LCD_cs - chip select - 0 activo, 1 passivo ------------------------------------------------------------ library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; entity LCD_control is port ( clk48 : in std_logic; -- relógio de 48 MHz rst : in std_logic; -- reset(activo a '0') ----------------------------------for LCD begin ext_a : out std_logic_vector(2 downto 0); -- endereço do LCD ext_d : out std_logic_vector(7 downto 0); -- código ASCII do caracter a visualizar no LCD ext_rw : out std_logic; -- LCD read/write cs_lcd : out std_logic; -- chip select do LCD (activo a ?1?) csn_lcd : out std_logic; -- este sinal não é usado, deve estar sempre a '0' ----------------------------------for LCD end linha : in std_logic; --linha do display LCD ('0' - linha de cima, '1' - linha de baixo) address : in std_logic_vector(3 downto 0); --número do caracter dentro duma linha (de 0 a 15) ASCII : in std_logic_vector(7 downto 0); --código ASCII do caracter a guardar no endereço "address" na memória do LCD LCD_cs : in std_logic); --chip select da memória do LCD (activo a '0') end LCD_control; architecture Behavioral of LCD_control is type RAM is array (0 to 31) of std_logic_vector(7 downto 0); signal LCD_RAM : RAM; --memória de LCD que guarda os códigos ASCII de todos os caracteres a visualizar ----------------------------------for LCD begin signal clk_lcd : std_logic; -- sinal de relógio para o LCD signal div : unsigned (14 downto 0); -- sinal para divisão do clk48 signal reset : std_logic; signal cmd : std_logic_vector (7 downto 0); signal rs : std_logic; signal idx : integer range 0 to 3; signal cs : std_logic; signal cnt : integer range 0 to 63; ----------------------------------for LCD end begin RAM_write: process (LCD_cs, rst) begin if rst = '0' then null; elsif falling_edge(LCD_cs) then LCD_RAM(conv_integer(linha & address)) <= ASCII; end if; end process RAM_write; ---------------------------------- for LCD begin -- the following code provides visualization of data ------------------------------------------------------------------ local_clock: process(clk48, rst) --geração do relógio local begin if rst = '0' then div <= (others=> '0'); elsif rising_edge(clk48) then div <= div + 1; end if; end process local_clock; clk_lcd <= div(div'left); -- clk_lcd é o relógio local index_ger: process(clk_lcd, rst) --sequência de índices (idx) begin if rst = '0' then idx <= 0; elsif rising_edge(clk_lcd) then if idx = 3 then idx <= 0; else idx <= idx + 1; end if; --idx obtém valores: 0,1,2,3,0,1,2,3,0,1,2,3,0,etc. end if; end process index_ger; LCD_write_cycle: process (clk_lcd, rst) begin if rst = '0' then cs <= '0'; --desactivar o chip select ext_a <= (others=> '0'); ext_d <= (others=> '0'); elsif rising_edge(clk_lcd) then case idx is when 0 => ext_a <= "00" & rs; when 1 => cs <= '1'; ext_d <= cmd; --escrever dados, activar o chip select when 2 => cs <= '0'; --desactivar o chip select when 3 => null; end case; end if; end process LCD_write_cycle; ext_rw <= '0'; --sempre a escrever cs_lcd <= cs; csn_lcd <= '0'; LCD_init_write: process(clk_lcd, rst) --ler os dados da RAM e escrevê-los para o LCD begin if rst = '0' then --se o reset externo for activo cmd <= x"00"; --código de controlo é 00000000 (não há informação) rs <= '1'; reset <= '1'; --inicializar o LCD cnt <= 0; --inicializar o contador de comandos elsif rising_edge(clk_lcd) then --na transição ascendente do relógio local if idx = 2 then cnt <= cnt + 1; --incrementar o contador de comandos end if; if (reset = '0') then --se o sinal reset do LCD estiver inactivo case cnt is -- visualização de dados (16 caracteres) na linha 0 do LCD (na linha superior) when 0 => cmd <= x"80"; rs <= '0'; --instrução - inicializar o cursor when 1 to 16 => cmd <= LCD_RAM(cnt-1); rs <= '1'; --dados -- visualização de dados (16 caracteres) na linha 1 do LCD (na linha inferior) when 17 => cmd <= x"C0"; rs <= '0'; --instrução when 18 to 33 => cmd <= LCD_RAM(cnt-2); rs <= '1'; --dados when others => cmd <= x"80"; rs <= '0'; --instrução end case; else --se o sinal reset do LCD estiver activo case cnt is when 0 => cmd <= x"38"; rs <= '0'; -- Function Set (8-bit, Dual Line) when 48 => cmd <= x"0c"; rs <= '0'; -- Display On/Off (display on, cursor off, cursor blink of) when 52 => cmd <= x"06"; rs <= '0'; -- Entry Mode Set (increment on, display shift off) when 56 => cmd <= x"01"; rs <= '0'; -- Limpar o display when 60 => cmd <= x"02"; rs <= '0'; -- Inicializar o cursor when 63 => reset <= '0'; cnt <= 0; when others => null; end case; end if; end if; end process LCD_init_write; ---------------------------------- for LCD end end Behavioral;