📄 lcd.vhd
字号:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity lcd is
generic ( asciiwidth : positive := 8);
port ( clk : in std_logic;
reset : in std_logic; -- active low
data_valid : in std_logic; -- enables lcd to start new write cycle when high
------interface to LCM----------------------------------------------
lcd_data : out std_logic_vector(asciiwidth-1 downto 0);
lcd_select : out std_logic; -- selects data(0) or instruction(1)
lcd_rw,tt : out std_logic; -- read (1) or write (0) data
lcd_enable : out std_logic; -- must be pulsed at clock frequency
---------------------------------------------------------------------
done : out std_logic); -- set low during write cycle, high if ready for new data
end lcd;
architecture behavioural of lcd is
constant countwidth : positive := 3;
type state_type is (warmup, setfunc, dispoff, clear, setmode, home, idle, write);
signal state : state_type;
signal rw_int, enable_int : std_logic;
signal count : std_logic_vector(countwidth downto 0);
signal write_mode : std_logic; -- stores whether to enter write cycle after clearing display
signal last_data_valid : std_logic; -- used to track rising edge on valid
begin
tt<='0';
lcd_rw <= rw_int;
lcd_enable <= enable_int;
enable_int <= not clk; -- this is very important! if enable is not pulsed, lcd will not write
state_set: process (clk, reset)
begin
if reset = '0' then
count <= (others => '0');
write_mode <= '1';
state <= warmup;
elsif (clk'event and clk = '1') then
case state is
when warmup =>
lcd_select <= '0';
rw_int <= '0';
done <= '0';
lcd_data <= "00000000"; -- do nothing
if count = "0111" then
count <= (others => '0');
state <= setfunc;
else
count <= count + '1';
state <= warmup;
end if;
when setfunc =>
lcd_data <= "00110000";
if count = "1111" then
state <= dispoff;
else
count <= count + '1';
state <= setfunc;
end if;
when dispoff =>
lcd_data <= "00001000";
count <= (others => '0');
state <= clear;
when clear =>
lcd_data <= "00000001"; -- clear display
if count = "0101" then
state <= setmode;
else
count <= count + '1';
state <= clear;
end if;
when setmode =>
lcd_data <= "00000110";
count <= (others => '0');
state <= home;
when home =>
lcd_data <= "00001100";
if count = "0100" then
if write_mode = '0' then
done <= '1';
state <= idle;
else
done <= '0';
count <= (others => '0');
state <= write;
end if;
else
count <= count + '1';
state <= home;
end if;
when idle =>
if data_valid = '1' and last_data_valid = '0' then
last_data_valid <= '1';
count <= (others => '0');
done <= '0';
write_mode <= '1';
state <= clear;
else
if data_valid = '0' then
last_data_valid <= '0';
end if;
lcd_data <= (others => '0');
done <= '1';
state <= idle;
end if;
when write =>
CASE count IS
WHEN "0000" =>
lcd_data <= "00100000"; -- ' '
WHEN "0001" =>
lcd_data <= "00100000"; -- ' '
WHEN "0010" =>
lcd_data <= "01110100"; -- 't'
WHEN "0011" =>
lcd_data <= "01100101"; -- 'e'
WHEN "0100" =>
lcd_data <= "01110011"; -- 's'
WHEN "0101" =>
lcd_data <= "01110100"; -- 't'
WHEN "0110" =>
lcd_data <= "01101001"; -- 'i'
WHEN "0111" =>
lcd_data <= "01101110"; -- 'n '
WHEN "1000" =>
lcd_data <= "01100111"; -- 'g'
WHEN "1001" =>
lcd_data <= "00100000"; -- ' '
WHEN "1010" =>
lcd_data <= "01101110"; -- 'n'
WHEN "1011" =>
lcd_data <= "01101111"; -- 'o'
WHEN "1100" =>
lcd_data <= "01110111"; -- 'w'
WHEN "1101" =>
lcd_data <= "00100001"; -- '!'
WHEN "1110" =>
lcd_data <= "00100000"; -- ' '
WHEN "1111" =>
lcd_data <= "00100000"; -- ' '
WHEN OTHERS =>
lcd_data <= "00100000"; -- ' '
END CASE;
lcd_select <= '1';
count <= count + '1';
state <= write;
end case;
end if;
end process;
end behavioural;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -