求VHDL编写的LCD液晶显示程序
想要在HS12864液晶显示器上显示一字符A,自写的程序如下:(内部时钟为50MHZ)entity lcd_8 is
Port ( clk : inSTD_LOGIC;
reset : inSTD_LOGIC;
rs : outSTD_LOGIC;
rw : outSTD_LOGIC;
en : outSTD_LOGIC;
data : outSTD_LOGIC_VECTOR (7 downto 0));
end lcd_8;
architecture Behavioral of lcd_8 is
type istate is (
write_instr,
write_data8,
set_addr,
ret_home
);
signal state:istate;
signal q : std_logic_vector(24 downto 0);
signal clk1 :std_logic;
signal cnt :std_logic_vector(2 downto 0);
begin
en<=clk1;
rw<='0';
process(clk,reset)
begin
if(reset='1') then
q<=(others=>'0');
elsif(rising_edge(clk)) then
q <= q + 1;
end if;
clk1<=q(15);
end process;
process(clk1,reset)
begin
if(reset='1')then
state<=write_instr;
rs<='0';
cnt<="000";
elsif(rising_edge(clk1))then
if(cnt="111")then
cnt<="000";
else
cnt<=cnt+1;
end if;
case state is
when write_instr=>
rs<='0';
case cnt is
when "000"=>data<="00110000";
when "001" =>data<="00000110";
when "010" =>data<="00001100";
when "011" =>data<="00000001";
when others =>data<="00000000";
end case;
state<=write_data8;
when write_data8=>
rs<='1';
data<="01000001";
state<= set_addr;
when set_addr=>
rs<='0';
data<="10000000";
state<= ret_home;
when ret_home=>
rs<='0';
data<="00000010";
state<=write_data8;
when others=>
state<=write_instr;
end case;
end if;
end process;
end Behavioral;
程序已经仿真成功,但是无法配置引脚,下载进去之后,LCD只显示方格而不显示字符,恳请大家帮忙看看,或是给一可以显示的程序 ** 文件名称: LCD_Top.v
** 创建者:
** 创建日期: 2008
** 版本号: V3.0
** 功能描述: 按键检测
**
**--------------------------------------修改文件的相关信息--------------------------------------------------
** 修改人:
** 修改日期:
** 版本号:
** 修改内容:
**
*******************************************************************************/
// LCD_Top.v
//连接Clock_Gen模块和LCD_Driver模块
module LCD_Top(clk_48M,rst,LCD_EN,RS,RW,DB8);
input clk_48M,rst;
outputLCD_EN,RS,RW;
output DB8;
wire clk_LCD; //用于将Clock_Gen模块clk_LCD输出连接至LCD_Driver模块的clk_LCD输入
Clock_Gen U1(.clk_48M(clk_48M),
.rst(rst),
.clk_LCD(clk_LCD));
LCD_DriverU2(.clk_LCD(clk_LCD),
.rst(rst),
.LCD_EN(LCD_EN),
.RS(RS),
.RW(RW),
.DB8(DB8));
endmodule
// Clock_Gen.v
/****************为LCD_Drvier模块产生500Hz的时钟信号**************/
module Clock_Gen(clk_48M,rst,clk_LCD);
input clk_48M,rst; //rst为全局复位信号(高电平有效)
outputclk_LCD;
wire clk_counter;
reg cnt; //对时钟进行计数分频
wire clk_equ;
reg count;
reg clk_BUF;
parameter counter= 50; //多少分频
/********************************************************************************
** 模块名称:分频器
** 功能描述:通过计数器实现分频功能.
********************************************************************************/
always@(posedge clk_48M)
begin
if(!rst) //低电平复位
cnt <= 12'd0;
else
if(clk_equ)
cnt <= 12'd0;
else
cnt <= cnt+1'b1;
end
assign clk_equ = (cnt==counter);
assign clk_counter = clk_equ;
always @(posedge clk_counter or negedge rst)
begin //利用计数器分频产生500Hz时钟
if(!rst)
begin
clk_BUF <= 1'b0;
count <= 10'b0;
end
else
begin
if(count == 10'd1000)
begin
clk_BUF <= ~clk_BUF;
count <= 10'b0;
end
else
begin
clk_BUF <= clk_BUF; //clk_BUF为500Hz的时钟信号
count <= count + 1'b1;
end
end
end
assignclk_LCD = clk_BUF;
//clk_LCD为LCD_Drvier模块所需要的500Hz的时钟信号
endmodule
// LCD_Driver.v
//功能简述:在1602液晶模块上显示字符串,其中第一行显示“Welcom to hx"
// 在第二行显示“www.mcuhx.com"
//液晶模块为TC1602A,相关特性请参考其数据手册
module LCD_Driver(clk_LCD,rst,LCD_EN,RS,RW,DB8);
input clk_LCD,rst; //rst为全局复位信号(高电平有效)
outputLCD_EN,RS,RW;
//LCD_EN为LCD模块的使能信号(下降沿触发)
//RS=0时为写指令;RS=1时为写数据
//RW=0时对LCD模块执行写操作;RW=1时对LCD模块执行读操作
output DB8; //8位指令或数据总线
reg DB8;
reg Data_First_Buf,Data_Second_Buf; //液晶显示的数据缓存
reg RS,LCD_EN_Sel;
reg disp_count;
reg state;
parameter Clear_Lcd = 4'b0000, //清屏并光标复位
Set_Disp_Mode = 4'b0001, //设置显示模式:8位2行5x7点阵
Disp_On = 4'b0010, //显示器开、光标不显示、光标不允许闪烁
Shift_Down = 4'b0011, //文字不动,光标自动右移
Write_Addr = 4'b0100, //写入显示起始地址
Write_Data_First = 4'b0101, //写入第一行显示的数据
Write_Data_Second = 4'b0110, //写入第二行显示的数据
Idel = 4'b0111; //空闲状态
parameter Data_First = "welcome to hx", //液晶显示的第一行的数据
Data_Second = "www.mcuhx.com"; //液晶显示的第二行的数据
assignRW = 1'b0; //RW=0时对LCD模块执行写操作
assignLCD_EN = LCD_EN_Sel ? clk_LCD : 1'b0;
//通过LCD_EN_Sel信号来控制LCD_EN的开启与关闭
always @(posedge clk_LCD or negedge rst)
begin
if(!rst)
begin
state <= Clear_Lcd; //复位:清屏并光标复位
RS <= 1'b0; //复位:RS=0时为写指令;
DB8 <= 8'b0; //复位:使DB8总线输出全0
LCD_EN_Sel <= 1'b1; //复位:开启夜晶使能信号
//Data_First_Buf <= Data_First;
//Data_Second_Buf <= Data_Second;
disp_count <= 4'b0;
end
else
case(state) //初始化LCD模块
Clear_Lcd:
begin
state <= Set_Disp_Mode;
DB8 <= 8'b00000001; //清屏并光标复位
end
Set_Disp_Mode:
begin
state <= Disp_On;
DB8 <= 8'b00111000; //设置显示模式:8位2行5x8点阵
end
Disp_On:
begin
state <= Shift_Down;
DB8 <= 8'b00001100; //显示器开、光标不显示、光标不允许闪烁
end
Shift_Down:
begin
state <= Write_Addr;
DB8 <= 8'b00000110; //文字不动,光标自动右移
end
Write_Addr:
begin
state <= Write_Data_First;
DB8 <= 8'b10000001; //写入第一行显示起始地址:第一行第二个位置
Data_First_Buf <= Data_First; //将第一行显示的数据赋给Data_First_Buf?
end
Write_Data_First: //写第一行数据
begin
if(disp_count == 14) //disp_count等于14时表示第一行数据已写完
begin
DB8 <= 8'b11000001; //送入写第二行的指令
RS <= 1'b0;
disp_count <= 4'b0;
Data_Second_Buf <= Data_Second;
state <= Write_Data_Second; //写完第一行进入写第二行状态
end
else
begin
DB8 <= Data_First_Buf;
Data_First_Buf <= (Data_First_Buf << 8);
RS <= 1'b1; //RS=1表示写数据
disp_count <= disp_count + 1'b1;
state <= Write_Data_First;
end
end
Write_Data_Second: //写第二行数据
begin
if(disp_count == 14)
begin
LCD_EN_Sel <= 1'b0;
RS <= 1'b0;
disp_count <= 4'b0;
state <= Idel; //写完进入空闲状态
end
else
begin
DB8 <= Data_Second_Buf;
Data_Second_Buf <= (Data_Second_Buf << 8);
RS <= 1'b1;
disp_count <= disp_count + 1'b1;
state <= Write_Data_Second;
end
end
Idel:
begin
state <=Idel; //在Idel状态循环
end
default:state <= Clear_Lcd; //若state为其他值,则将state置为Clear_Lcd
endcase
end
endmodule
页:
[1]