非常详细的verilog写的LCD1602驱动 下载本文

内容发布更新时间 : 2024/5/3 16:48:22星期一 下面是文章的全部内容请认真阅读。

最近在网上找了很多用verilog驱动LCD1602的程序,但基本没有一个是完美运行,很多论坛所谓大神的代码综合时候一样很多缺陷,要知道每一个warning都有可能是导致最终失败的原因。于是乎只能自己下功夫,找到一个稍微靠谱的开发板配套例程,但是分频器模块编的叫一塌糊涂,主时钟分频后继续分频而且组合时序乱用,通过分频模块重新编写后基本无warning完美运行,仿真功能实现并且下载显示成功,后面附上了我的testbench,本人用的软件为ISE12.2,不过个人感觉quartus应该一样跑,下面是代码 ,需要在1602显示什么字符自己改显示函数就行,希望对大家有帮助。

module lcd1602(clk,rst,LCD_E,LCD_RW,LCD_RS,LCD_D); input clk,rst; output LCD_E,LCD_RW,LCD_RS; output [7:0] LCD_D; reg LCD_E,LCD_RW,LCD_RS; reg [7:0] LCD_D; reg [9:0] state; reg [5:0] address; parameter IDLE =10'b0000000000; parameter CLEAR =10'b0000000001; //清屏 parameter RETURNCURSOR =10'b0000000010; //归home位 parameter SETMODE =10'b0000000111; //输入方式设置,读写数据后ram地址增/减1;画面动/不动 parameter SWITCHMODE =10'b0000001111; //显示状态设置,显示开/关;光标开/关;闪烁开/关 parameter SHIFT =10'b0000011100;

//光标画面滚动 画面/光标平移一位;左/右平移一位

parameter SETFUNCTION =10'b0000111100;

//工作方式设置 1:8/1:4位数据接口;两行/一行显示;5x10/5x7点阵

parameter SETCGRAM =10'b0001000000; //设置CGRAM parameter SETDDRAM1 =10'b0010000001; //设置DDRAM parameter SETDDRAM2 =10'b0010000010; //设置DDRAM parameter READFLAG =10'b0100000000; //读状态 parameter WRITERAM1 =10'b1000000001; //写RAM parameter WRITERAM2 =10'b1000000010; //写RAM parameter READRAM =10'b1100000000; //读RAM

parameter cur_inc =1; parameter cur_dec =0; parameter cur_shift =1; parameter cur_noshift =0; parameter open_display =1; parameter open_cur =0; parameter blank_cur =0; parameter shift_display =1; parameter shift_cur =0; parameter right_shift =1; parameter left_shift =0; parameter LCD_Dwidth8 =1; parameter LCD_Dwidth4 =0; parameter twoline =1; parameter oneline =0; parameter font5x10 =1; parameter font5x7 =0;

/******************************************************************/

function [7:0] ddram; //写入需要的字符数据 input [5:0] n; begin case(n) 0:ddram=8'h48;//H 1:ddram=8'h65;//e 2:ddram=8'h6c;//l 3:ddram=8'h6c;//l 4:ddram=8'h6f;//o 5:ddram=8'h21;//! 6:ddram=8'h21;//! 7:ddram=8'hA0;//space 8:ddram=8'h7E;//-> 9:ddram=8'hA0;//space 10:ddram=8'h5A;//Z 11:ddram=8'h52;//R 12:ddram=8'h74;//t 13:ddram=8'h65;//e 14:ddram=8'h63;//c 15:ddram=8'h68;//h 16:ddram=8'h77;//w 17:ddram=8'h77;//w 18:ddram=8'h77;//w 19:ddram=8'h2E;//.

20:ddram=8'h5A;//Z 21:ddram=8'h52;//R 22:ddram=8'hB0;//R 23:ddram=8'h74;//t 24:ddram=8'h65;//e 25:ddram=8'h63;//c 26:ddram=8'h68;//h 27:ddram=8'h2E;//. 28:ddram=8'h6E;//n 29:ddram=8'h65;//e 30:ddram=8'h74;//t 31:ddram=8'hA0;//space default: ddram=8'hxx; endcase end endfunction

/******************************************************************/ //分频模块 reg [16:0] clkcnt; reg clkdiv; always @ (posedge clk) if(!rst) clkcnt<=17'b0_0000_0000_0000_0000; else begin if(clkcnt<17'b0_1001_1100_0100_0000) //16'b1001_1100_0100_0000 begin clkcnt<=clkcnt+1; clkdiv<=0; end else if(clkcnt==17'b1_0011_1000_0111_1111) clkcnt<=17'b0_0000_0000_0000_0000; else begin clkcnt<=clkcnt+1; clkdiv<=1; end end