顶层代码:
module lcd1602(
input CLOCK_50,
input RST_N,
inout[7:0] LCD_DATA,
output LCD_EN,
output LCD_RS,
output LCD_RW,
output LCD_ON,
output LCD_BLON
);
//initial//
wire[7:0] LCD_D_1;
wire LCD_RS_1;
wire LCD_RW_1;
wire LCD_EN_1;
wire DLY_RST;
assign LCD_DATA=LCD_D_1;
assign LCD_RS=LCD_RS_1;
assign LCD_RW=LCD_RW_1;
assign LCD_EN=LCD_EN_1;
assign LCD_ON=1'b1;
assign LCD_BLON=1'b0;
Reset_Delay r0(.iCLK(CLOCK_50), .oRESET(DLY_RST));
LCD1602_TEST u1( //Host Side
.iCLK(CLOCK_50),
.iRST_N(DLY_RST),
//LCD Side
.LCD_DATA(LCD_D_1),
.LCD_RW(LCD_RW_1),
.LCD_EN(LCD_EN_1),
.LCD_RS(LCD_RS_1)
);
endmodule
RST_N初始延迟代码:
module Reset_Delay(iCLK,oRESET);
input iCLK;
output reg oRESET;
reg[19:0] Cont;
always@(posedge iCLK)
begin
if(Cont!=20'hfffff)
begin
Cont<=Cont+1'b1;
oRESET<=1'b0;
end
else
oRESET<=1'b1;
end
endmodule
底层代码LCD1602_TEST:
module LCD1602_TEST(
input iCLK,iRST_N, //Host Side
output[7:0] LCD_DATA, //LCD1602 Side
output LCD_RS,LCD_RW,LCD_EN
);
//Internal Wires/Registers
reg[5:0] LUT_INDEX;
reg[8:0] LUT_DATA;
reg[5:0] mLCD_ST;
reg[17:0] mDLY;
reg[7:0] mLCD_DATA;
reg mLCD_Start;
reg mLCD_RS;
wire mLCD_Done;
parameter LCD_INITIAL = 0;
parameter LCD_LINE1 = 5; //Just have 5 control command
parameter LCD_CH_LINE = LCD_LINE1+16; //Change Line
parameter LCD_LINE2 = LCD_LINE1+16+1;
parameter LUT_SIZE = LCD_LINE1+32+1;
always@(posedge iCLK or negedge iRST_N)
begin
if(!iRST_N)
begin
LUT_INDEX <= 0;
mLCD_ST <= 0;
mDLY <= 0;
mLCD_Start <= 0;
mLCD_DATA <= 0;
mLCD_RS <= 0;
end
else
begin
if(LUT_INDEX<LUT_SIZE)
begin
case(mLCD_ST)
0: begin
mLCD_DATA <= LUT_DATA[7:0];
mLCD_RS <= LUT_DATA[8];
mLCD_Start <= 1;
mLCD_ST <= 1;
end
1: begin
if(mLCD_Done)
begin
mLCD_Start <= 0;
mLCD_ST <= 2;
end
end
2: begin
if(mDLY<18'h3ffff)
mDLY <= mDLY+18'b1;
else
begin
mDLY <= 0;
mLCD_ST <= 3;
end
end
3: begin
LUT_INDEX <= LUT_INDEX+6'b1;
mLCD_ST <= 0;
end
endcase
end
end
end
always
begin
case(LUT_INDEX)
// Inital
LCD_INITIAL+0: LUT_DATA <= 9'h038; //设置16x2显示,5x7点阵,8位数据接口
LCD_INITIAL+1: LUT_DATA <= 9'h00C; //设置开显示,不显示光标
LCD_INITIAL+2: LUT_DATA <= 9'h001; //显示清零,数据指针清零
LCD_INITIAL+3: LUT_DATA <= 9'h006; //写一个字符后地址指针加一
LCD_INITIAL+4: LUT_DATA <= 9'h080; //Line1 First Address
// Line1
LCD_LINE1+0: LUT_DATA <= 9'h120; // Welcome to
LCD_LINE1+1: LUT_DATA <= 9'h120; //
LCD_LINE1+2: LUT_DATA <= 9'h120; //
LCD_LINE1+3: LUT_DATA <= 9'h157; //w
LCD_LINE1+4: LUT_DATA <= 9'h165; //e
LCD_LINE1+5: LUT_DATA <= 9'h16C; //l
LCD_LINE1+6: LUT_DATA <= 9'h163; //c
LCD_LINE1+7: LUT_DATA <= 9'h16F; //o
LCD_LINE1+8: LUT_DATA <= 9'h16D; //m
LCD_LINE1+9: LUT_DATA <= 9'h165; //e
LCD_LINE1+10: LUT_DATA <= 9'h120; //
LCD_LINE1+11: LUT_DATA <= 9'h174; //t
LCD_LINE1+12: LUT_DATA <= 9'h16F; //o
LCD_LINE1+13: LUT_DATA <= 9'h120; //
LCD_LINE1+14: LUT_DATA <= 9'h120; //
LCD_LINE1+15: LUT_DATA <= 9'h120; //
// Change Line
LCD_CH_LINE: LUT_DATA <= 9'h0C0;
// Line 2
LCD_LINE2+0: LUT_DATA <= 9'h120; // www.njodin.com
LCD_LINE2+1: LUT_DATA <= 9'h157; //w
LCD_LINE2+2: LUT_DATA <= 9'h157; //w
LCD_LINE2+3: LUT_DATA <= 9'h157; //w
LCD_LINE2+4: LUT_DATA <= 9'h12E; //.
LCD_LINE2+5: LUT_DATA <= 9'h16E; //n
LCD_LINE2+6: LUT_DATA <= 9'h16A; //j
LCD_LINE2+7: LUT_DATA <= 9'h16F; //o
LCD_LINE2+8: LUT_DATA <= 9'h164; //d
LCD_LINE2+9: LUT_DATA <= 9'h169; //i
LCD_LINE2+10: LUT_DATA <= 9'h16E; //n
LCD_LINE2+11: LUT_DATA <= 9'h12E; //.
LCD_LINE2+12: LUT_DATA <= 9'h163; //c
LCD_LINE2+13: LUT_DATA <= 9'h16F; //o
LCD_LINE2+14: LUT_DATA <= 9'h16D; //m
LCD_LINE2+15: LUT_DATA <= 9'h120; //
default: LUT_DATA <= 9'h120;
endcase
end
LCD1602_Controller u0 ( //Host Side
.iDATA(mLCD_DATA),
.iRS(mLCD_RS),
.iStart(mLCD_Start),
.oDone(mLCD_Done),
.iCLK(iCLK),
.iRST_N(iRST_N),
//LCD1602 Interface
.LCD_DATA(LCD_DATA),
.LCD_RW(LCD_RW),
.LCD_EN(LCD_EN),
.LCD_RS(LCD_RS)
);
endmodule
底层代码LCD1602_Controller:
module LCD1602_Controller(
//Host Side
input iCLK,iRST_N,
input iRS,iStart,
input[7:0] iDATA,
output reg oDone,
//LCD1602 Interface
output[7:0] LCD_DATA,
output LCD_RS,
output LCD_RW,
output reg LCD_EN
);
//Internal Register
reg[4:0] Cont;
reg[1:0] ST;
reg preStart,mStart;
//Only write to LCD,bypass iRS to LCD_RS
assign LCD_DATA = iDATA;
assign LCD_RS = iRS;
assign LCD_RW = 1'b0;
parameter CLK_Divide = 16;
always@(posedge iCLK or negedge iRST_N)
begin
if(!iRST_N)
begin
oDone <= 1'b0;
LCD_EN <= 1'b0;
preStart<= 1'b0;
mStart <= 1'b0;
Cont <= 0;
ST <= 0;
end
else
begin
//Input Start Detect
preStart <= iStart;
if({preStart,iStart}==2'b01)
begin
mStart <= 1'b1;
oDone <= 1'b0;
end
if(mStart)
begin
case(ST)
0: ST <= 1; //Wait Setup
1: begin
LCD_EN <= 1'b1;
ST <= 2;
end
2: begin
if(Cont<CLK_Divide)
Cont <= Cont+5'b1;
else
ST <= 3;
end
3: begin
LCD_EN <= 1'b0;
mStart <= 1'b0;
oDone <= 1'b1;
Cont <= 0;
ST <= 0;
end
endcase
end
end
end
endmodule
效果图: