EPM240驱动LCD1602
时间:10-02
整理:3721RD
点击:
初学verilog,手头正好有EPM240核心板和LCD1602,参考了一些资料尝试着用三段式状态机写得,但通电后LCD没有显示,请大神帮忙看看程序有什么问题,不胜感激。代码如下:
module lcd1602(
clk_50,
rst,
lcd_rs,
lcd_rw,
lcd_en,
lcd_data
);
input clk_50;
input rst;
output lcd_rs;
output lcd_rw;
output lcd_en;
output [7:0]lcd_data;
reg clk_lcd;
reg lcd_rs;
reg [7:0]lcd_data;
reg [7:0]current_state;
reg [7:0]next_state;
reg [15:0]count;
wire lcd_en;
wire lcd_rw;
/*************状态编码**************/
parameter idle =8'b0000_0000;
parameter displaymode =8'b0000_0010;
parameter displayoff =8'b0000_0100;
parameter displayclear =8'b0000_1000;
parameter displayshift =8'b0001_0000;
parameter displayon =8'b0010_0000;
parameter setddram =8'b0100_0000;
parameter writeram =8'b1000_0000;
/*************50M分频至500Hz**************/
always@(posedge clk_50)
begin
if(!rst)
begin
count<=0;
clk_lcd<=0;
end
else
if(count<49999)
begin
count<=count+1'b1;
end
else
begin
count<=0;
clk_lcd<=~clk_lcd;
end
end
/****************LCD初始化****************/
assign lcd_en=clk_lcd;
assign lcd_rw=1'b0;
always@(posedge clk_lcd or negedge rst)
begin
if(!rst)
current_state<=idle;
else
current_state<=next_state;
end
always@(*)
begin
case(current_state)
idle :next_state=displaymode;
displaymode :next_state=displayoff;
displayoff :next_state=displayclear;
displayclear :next_state=displayshift;
displayshift :next_state=displayon;
displayon :next_state=setddram;
setddram :next_state=writeram;
writeram :next_state=setddram;
default :next_state=idle;
endcase
end
always@(posedge clk_lcd or negedge rst)
begin
if(!rst)
begin
lcd_rs<=0;
lcd_data<=8'bzzzz_zzzz;
end
else
begin
case(next_state)
idle : lcd_rs<=0;
displaymode : lcd_rs<=0;
displayoff : lcd_rs<=0;
displayclear: lcd_rs<=0;
displayshift: lcd_rs<=0;
displayon : lcd_rs<=0;
setddram : lcd_rs<=0;
writeram : lcd_rs<=1;
default : lcd_rs<=0;
endcase
case(next_state)
idle : lcd_data<=8'bzzzz_zzzz;
displaymode : lcd_data<=8'b0011_1000;//38h,显示模式设置
displayoff : lcd_data<=8'b0000_1000;//08h,显示关闭
displayclear: lcd_data<=8'b0000_0001;//01h,显示清屏
displayshift: lcd_data<=8'b0000_0110;//06h,显示光标移动设置
displayon : lcd_data<=8'b0000_1100;//0ch,显示开及光标设置
setddram : lcd_data<=8'b1000_0000;//设置第一行第一个地址
writeram : lcd_data<="A";//显示字符"A"
endcase
end
end
endmodule
module lcd1602(
clk_50,
rst,
lcd_rs,
lcd_rw,
lcd_en,
lcd_data
);
input clk_50;
input rst;
output lcd_rs;
output lcd_rw;
output lcd_en;
output [7:0]lcd_data;
reg clk_lcd;
reg lcd_rs;
reg [7:0]lcd_data;
reg [7:0]current_state;
reg [7:0]next_state;
reg [15:0]count;
wire lcd_en;
wire lcd_rw;
/*************状态编码**************/
parameter idle =8'b0000_0000;
parameter displaymode =8'b0000_0010;
parameter displayoff =8'b0000_0100;
parameter displayclear =8'b0000_1000;
parameter displayshift =8'b0001_0000;
parameter displayon =8'b0010_0000;
parameter setddram =8'b0100_0000;
parameter writeram =8'b1000_0000;
/*************50M分频至500Hz**************/
always@(posedge clk_50)
begin
if(!rst)
begin
count<=0;
clk_lcd<=0;
end
else
if(count<49999)
begin
count<=count+1'b1;
end
else
begin
count<=0;
clk_lcd<=~clk_lcd;
end
end
/****************LCD初始化****************/
assign lcd_en=clk_lcd;
assign lcd_rw=1'b0;
always@(posedge clk_lcd or negedge rst)
begin
if(!rst)
current_state<=idle;
else
current_state<=next_state;
end
always@(*)
begin
case(current_state)
idle :next_state=displaymode;
displaymode :next_state=displayoff;
displayoff :next_state=displayclear;
displayclear :next_state=displayshift;
displayshift :next_state=displayon;
displayon :next_state=setddram;
setddram :next_state=writeram;
writeram :next_state=setddram;
default :next_state=idle;
endcase
end
always@(posedge clk_lcd or negedge rst)
begin
if(!rst)
begin
lcd_rs<=0;
lcd_data<=8'bzzzz_zzzz;
end
else
begin
case(next_state)
idle : lcd_rs<=0;
displaymode : lcd_rs<=0;
displayoff : lcd_rs<=0;
displayclear: lcd_rs<=0;
displayshift: lcd_rs<=0;
displayon : lcd_rs<=0;
setddram : lcd_rs<=0;
writeram : lcd_rs<=1;
default : lcd_rs<=0;
endcase
case(next_state)
idle : lcd_data<=8'bzzzz_zzzz;
displaymode : lcd_data<=8'b0011_1000;//38h,显示模式设置
displayoff : lcd_data<=8'b0000_1000;//08h,显示关闭
displayclear: lcd_data<=8'b0000_0001;//01h,显示清屏
displayshift: lcd_data<=8'b0000_0110;//06h,显示光标移动设置
displayon : lcd_data<=8'b0000_1100;//0ch,显示开及光标设置
setddram : lcd_data<=8'b1000_0000;//设置第一行第一个地址
writeram : lcd_data<="A";//显示字符"A"
endcase
end
end
endmodule