library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity lcdxianshi is
port(
CLK : in std_logic;
Reset : in std_logic;
enter: in std_logic;
key_encri: in std_logic_vector(3 downto 0);
key_decri: in std_logic_vector(3 downto 0);
LCD_RS : out std_logic;
outxianshi:out std_logic;
LCD_RW : out std_logic;
LCD_EN : out std_logic;
data : out std_logic_vector(3 downto 0));
end lcdxianshi;
architecture Behavioral of lcdxianshi is
type iState is (
Write_instr, --写命令字
Write_DataUP4_1, --写LCD一线高4位
Write_DataDown4_1, --写LCD一线低4位
Set_DDRamAddUp,
--设置DDRam地址高4位
Set_DDRamAddDown, --设置DDRam地址低4位
Write_DataUP4_2, --写LCD二线高4位
Write_DataDown4_2 --写LCD二线低4位
);
signal State:iState;
type ram is array(0 to 15) of std_logic_vector(7 downto 0);
constant
myram0_up:ram:=(x"50",x"4c",x"45",x"41",--PLEASE
x"53",x"45",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram0_down:ram:=(x"49",x"4e",x"50",x"55",x"54",x"20",x"50",x"41",--
INPUT PASSWORD!
x"53",x"53",x"57",x"4f",x"52",x"44",x"21",x"20");
constant
myram1_up:ram:=(x"57",x"45",x"4c", --WELCOME!
x"43",x"4f",x"4d",x"45",x"21",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram1_down:ram:=(x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20"
,x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram2_up:ram:=(x"45",x"52",x"52", --ERROR!
x"4F",x"52",x"21",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram2_down:ram:=(x"54",x"57",x"4f",x"20",x"54", --TWO TIMES!
x"49",x"4d",x"45",x"53",x"21",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram3_up:ram:=(x"57",x"4f",x"52",x"4e",x"49", --
WORNING!
x"4e",x"47",x"21",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram3_down:ram:=(x"4f",x"4e",x"4c",x"59",x"20",x"4f",x"4e",
--ONLY ONE TIME!
x"45",x"20",x"54",x"49",x"4d",x"45",x"21",x"20",x"20");
constant myram4_up:ram:=(x"46", --
FAILED!
x"41",x"49",x"4c",x"45",x"44",x"21",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20",x"20");
constant
myram4_down:ram:=(x"54",x"48",x"45",x"20",x"4b",x"45",x"59",
--THE KEY LOCKED!
x"20",x"4c",x"4f",x"43",x"4b",x"45",x"44",x"21",x"20");
signal LCD_Clk : std_logic :='0';
signal datacnt : integer range 0 to 23:=0;--作为地址指针计数
signal cnt : integer range 0 to
100:=0;--统计密码输入次数
-- signal addr_cnt: integer range 0 to 15:=0;--显示字符地址指?
begin
LCD_RW <= '0';
LCD_EN <= LCD_Clk;
process(CLK)
--20000分频,满足时序要求
variable n1:integer range 0 to 899999;
begin
if rising_edge(CLK) then
if n1<899999 then
n1:=n1+1;
else
n1:=0;
LCD_Clk<=not LCD_Clk;
end if;
end if;
end process;
process(reset, enter)--统计密码输入次数
begin
if Reset='0' then
cnt<=0;
-- outxianshi<='0';
elsif rising_edge(enter) then
cnt<=cnt+1;
end if;
end process;
process(LCD_Clk,state,reset,cnt,key_decri,key_encri,enter)
begin
if Reset='0' then
state<=Write_instr;
LCD_RS <= '0';
outxianshi<='0';
elsif rising_edge(LCD_Clk) then
case cnt is
when 0 =>--显示 please input password!
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
data<="0000";
--0011
datacnt<=datacnt+1;
elsif(datacnt=1)then
data<="0001";
--0011
datacnt<=datacnt+1;
elsif(datacnt=2)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=3)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=4)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=5)then
data<="0010";
--0010
datacnt<=datacnt+1;
elsif(datacnt=6)then
--0x28 : 0010 1000 =>功能设置 8位总线双行显示
data<="0010";
datacnt<=datacnt+1;
elsif(datacnt=7)then
data<="1000";
datacnt<=datacnt+1;
elsif(datacnt=8)then
--0x06 : 0000 0110 =>模式设定
光标右移,字符不动
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=9)then
data<="0110";
datacnt<=datacnt+1;
elsif(datacnt=10)then
--0x0c : 0000 1100 =>显示设定 整体显示开
无光标
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=11)then
data<="1100";
datacnt<=datacnt+1;
elsif(datacnt=12)then
--0x10 : 1000 0000 =>00H
设定列吹刂肺? data<="1000";
datacnt<=datacnt+1;
else
data<="0000";
datacnt<=0;
state<=Write_DataUP4_1;
end if;
when Write_DataUP4_1=>
LCD_RS<='1';
data <=
myram0_up(datacnt)(7 downto 4);
state <= Write_DataDown4_1;
when Write_DataDown4_1=>
if datacnt=23 then
data <=
myram0_up(datacnt)(3 downto 0);
datacnt<=0;
state
<=Set_DDRamAddUp;
else
data <=
myram0_up(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_1;
end if;
when Set_DDRamAddUp=> --0xc0 : 1100
0000=>40H 设定读写地址位
LCD_RS<='0';
data<="1100";
state<=Set_DDRamAddDown;
when Set_DDRamAddDown=>
data<="0000";
state<=Write_DataUP4_2;
when Write_DataUP4_2=>
LCD_RS<='1';
data <=
myram0_down(datacnt)(7 downto 4);
state <= Write_DataDown4_2;
when Write_DataDown4_2=>
if datacnt=23 then
data <=
myram0_down(datacnt)(3 downto 0);
datacnt<=0;
state
<=Write_DataUP4_1;
else
data <=
myram0_down(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_2;
end if;
when others=>
state<=Write_instr;
end case;-- state machine PLEASE INPUT
PASSWORD!
when 1 =>
if(enter='1') then
if(key_decri=key_encri) then --显示 WELCOME!
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
data<="0000";
--0011
datacnt<=datacnt+1;
elsif(datacnt=1)then
data<="0001";
--0011
datacnt<=datacnt+1;
elsif(datacnt=2)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=3)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=4)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=5)then
data<="0010";
--0010
datacnt<=datacnt+1;
elsif(datacnt=6)then
--0x28 : 0010 1000 =>功能设置 8位总线双行显示
data<="0010";
datacnt<=datacnt+1;
elsif(datacnt=7)then
data<="1000";
datacnt<=datacnt+1;
elsif(datacnt=8)then
--0x06 : 0000 0110 =>模式设定
光标右移,字符不动
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=9)then
data<="0110";
datacnt<=datacnt+1;
elsif(datacnt=10)then
--0x0c : 0000 1100 =>显示设定 整体显示开
无光标
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=11)then
data<="1100";
datacnt<=datacnt+1;
elsif(datacnt=12)then
--0x10 : 1000 0000 =>00H 设定读写地址位
data<="1000";
datacnt<=datacnt+1;
else
data<="0000";
datacnt<=0;
state<=Write_DataUP4_1;
end if;
when Write_DataUP4_1=>
LCD_RS<='1';
data <=
myram1_up(datacnt)(7 downto 4);
state <= Write_DataDown4_1;
when Write_DataDown4_1=>
if datacnt=23 then
data <=
myram1_up(datacnt)(3 downto 0);
datacnt<=0;
state
<=Set_DDRamAddUp;
else
data <=
myram1_up(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_1;
end if;
when Set_DDRamAddUp=> --0xc0 : 1100
0000=>40H 设定读写地址位
LCD_RS<='0';
data<="1100";
state<=Set_DDRamAddDown;
when Set_DDRamAddDown=>
data<="0000";
state<=Write_DataUP4_2;
when Write_DataUP4_2=>
LCD_RS<='1';
data <=
myram1_down(datacnt)(7 downto 4);
state <= Write_DataDown4_2;
when Write_DataDown4_2=>
if datacnt=23 then
data <=
myram1_down(datacnt)(3 downto 0);
datacnt<=0;
state
<=Write_DataUP4_1;
else
data <=
myram1_down(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_2;
end if;
when others=>
state<=Write_instr;
end case;-- end state machine2
else
--显示 ERROR! TWO TIMES!
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
data<="0000";
--0011
datacnt<=datacnt+1;
elsif(datacnt=1)then
data<="0001";
--0011
datacnt<=datacnt+1;
elsif(datacnt=2)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=3)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=4)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=5)then
data<="0010";
--0010
datacnt<=datacnt+1;
elsif(datacnt=6)then
--0x28 : 0010 1000 =>功能设置 8位总线双行显示
data<="0010";
datacnt<=datacnt+1;
elsif(datacnt=7)then
data<="1000";
datacnt<=datacnt+1;
elsif(datacnt=8)then
--0x06 : 0000 0110 =>模式设定
光标右移,字符不动
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=9)then
data<="0110";
datacnt<=datacnt+1;
elsif(datacnt=10)then
--0x0c : 0000 1100 =>显示设定 整体显示开
无光标
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=11)then
data<="1100";
datacnt<=datacnt+1;
elsif(datacnt=12)then
--0x10 : 1000 0000 =>00H 设定读写地址位
data<="1000";
datacnt<=datacnt+1;
else
data<="0000";
datacnt<=0;
state<=Write_DataUP4_1;
end if;
when Write_DataUP4_1=>
LCD_RS<='1';
data <=
myram2_up(datacnt)(7 downto 4);
state <= Write_DataDown4_1;
when Write_DataDown4_1=>
if datacnt=23 then
data <=
myram2_up(datacnt)(3 downto 0);
datacnt<=0;
state
<=Set_DDRamAddUp;
else
data <=
myram2_up(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_1;
end if;
when Set_DDRamAddUp=> --0xc0 : 1100
0000=>40H 设定读写地址位
LCD_RS<='0';
data<="1100";
state<=Set_DDRamAddDown;
when Set_DDRamAddDown=>
data<="0000";
state<=Write_DataUP4_2;
when Write_DataUP4_2=>
LCD_RS<='1';
data <=
myram2_down(datacnt)(7 downto 4);
state <= Write_DataDown4_2;
when Write_DataDown4_2=>
if datacnt=23 then
data <=
myram2_down(datacnt)(3 downto 0);
datacnt<=0;
state
<=Write_DataUP4_1;
else
data <=
myram2_down(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_2;
end if;
when others=>
state<=Write_instr;
end case; --end state machine3
end if;
else--显示 please input password !
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
data<="0000";
--0011
datacnt<=datacnt+1;
elsif(datacnt=1)then
data<="0001";
--0011
datacnt<=datacnt+1;
elsif(datacnt=2)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=3)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=4)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=5)then
data<="0010";
--0010
datacnt<=datacnt+1;
elsif(datacnt=6)then
--0x28 : 0010 1000 =>功能设置 8位总线双行显示
data<="0010";
datacnt<=datacnt+1;
elsif(datacnt=7)then
data<="1000";
datacnt<=datacnt+1;
elsif(datacnt=8)then
--0x06 : 0000 0110 =>模式设定
光标右移,字符不动
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=9)then
data<="0110";
datacnt<=datacnt+1;
elsif(datacnt=10)then
--0x0c : 0000 1100 =>显示设定 整体显示开
无光标
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=11)then
data<="1100";
datacnt<=datacnt+1;
elsif(datacnt=12)then
--0x10 : 1000 0000 =>00H 设定读写地址位
data<="1000";
datacnt<=datacnt+1;
else
data<="0000";
datacnt<=0;
state<=Write_DataUP4_1;
end if;
when Write_DataUP4_1=>
LCD_RS<='1';
data <=
myram0_up(datacnt)(7 downto 4);
state <= Write_DataDown4_1;
when Write_DataDown4_1=>
if datacnt=23 then
data <=
myram0_up(datacnt)(3 downto 0);
datacnt<=0;
state
<=Set_DDRamAddUp;
else
data <=
myram0_up(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_1;
end if;
when Set_DDRamAddUp=> --0xc0 : 1100
0000=>40H 设定读写地址位
LCD_RS<='0';
data<="1100";
state<=Set_DDRamAddDown;
when Set_DDRamAddDown=>
data<="0000";
state<=Write_DataUP4_2;
when Write_DataUP4_2=>
LCD_RS<='1';
data <=
myram0_down(datacnt)(7 downto 4);
state <= Write_DataDown4_2;
when Write_DataDown4_2=>
if datacnt=23 then
data <=
myram0_down(datacnt)(3 downto 0);
datacnt<=0;
state
<=Write_DataUP4_1;
else
data <=
myram0_down(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_2;
end if;
when others=>
state<=Write_instr;
end case;
end if;
when 2 => --第二次输入密钥
if(enter='1') then
if(key_decri=key_encri) then
--显示 welocme!
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
data<="0000";
--0011
datacnt<=datacnt+1;
elsif(datacnt=1)then
data<="0001";
--0011
datacnt<=datacnt+1;
elsif(datacnt=2)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=3)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=4)then
data<="0011";
--0011
datacnt<=datacnt+1;
elsif(datacnt=5)then
data<="0010";
--0010
datacnt<=datacnt+1;
elsif(datacnt=6)then
--0x28 : 0010 1000 =>功能设置 8位总线双行显示
data<="0010";
datacnt<=datacnt+1;
elsif(datacnt=7)then
data<="1000";
datacnt<=datacnt+1;
elsif(datacnt=8)then
--0x06 : 0000 0110 =>模式设定
光标右移,字符不动
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=9)then
data<="0110";
datacnt<=datacnt+1;
elsif(datacnt=10)then
--0x0c : 0000 1100 =>显示设定 整体显示开
无光标
data<="0000";
datacnt<=datacnt+1;
elsif(datacnt=11)then
data<="1100";
datacnt<=datacnt+1;
elsif(datacnt=12)then
--0x10 : 1000 0000 =>00H 设定读写地址位
data<="1000";
datacnt<=datacnt+1;
else
data<="0000";
datacnt<=0;
state<=Write_DataUP4_1;
end if;
when Write_DataUP4_1=>
LCD_RS<='1';
data <=
myram1_up(datacnt)(7 downto 4);
state <= Write_DataDown4_1;
when Write_DataDown4_1=>
if datacnt=23 then
data <=
myram1_up(datacnt)(3 downto 0);
datacnt<=0;
state
<=Set_DDRamAddUp;
else
data <=
myram1_up(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_1;
end if;
when Set_DDRamAddUp=> --0xc0 : 1100
0000=>40H 设定读写地址位
LCD_RS<='0';
data<="1100";
state<=Set_DDRamAddDown;
when Set_DDRamAddDown=>
data<="0000";
state<=Write_DataUP4_2;
when Write_DataUP4_2=>
LCD_RS<='1';
data <=
myram1_down(datacnt)(7 downto 4);
state <= Write_DataDown4_2;
when Write_DataDown4_2=>
if datacnt=23 then
data <=
myram1_down(datacnt)(3 downto 0);
datacnt<=0;
state
<=Write_DataUP4_1;
else
data <=
myram1_down(datacnt)(3 downto 0);
datacnt<=datacnt+1;
state
<=Write_DataUP4_2;
end if;
when others=>
state<=Write_instr;
end case;
else
--显示 warning
one time!
case state is
when
Write_instr=>
--写命令字到LCD控制器
LCD_RS<='0';
if(datacnt=0)then
&