LCD1602写自定义字符的Verilog源码
开发工具:Quartus II 9.1;
仿真软件:Questa Sim 10.0c;
硬件平台:Terasic DE2-115(EP2C35F672C6);
外设:hd44780控制器lcd1602;
3个工程文件:"lcd1602_cgram_controller.v" + "lcd1602_cgram_driver.v" + "lcd1602_cgram_driver_tsb.v";
设计思路:
底层直接操作lcd1602的模块为"*_controller.v"文件,三段式状态机,完成初始化液晶工作模式(无光标、5X8、2行...)、在CGRAM写入自定义的8个字符(源文件里条形图,可用于音频FFT波形图显示),完成CGRAM写数据之后进入通用的显示状态,每次显示完一个字符产生的ack信号;
"_driver.v"完成循环调用显示8个自定义字符;
"_driver_tsb.v"完成仿真时的驱动(原本是和"_driver.v"在同一个文件,为了方便后续综合,分开了);
注意事项:
系统工作频率为50MHz,lcd操作的指令、数据周期为2ms(1ms下也能用);
CYCLONEII的芯片上电未复位之前的寄存器是0,因此程序下载到板子上的时候液晶是不显示的,没有复位引脚的需要自行设计软件复位;
lcd_on,lcd_blon为DE2-115板子特有设计;
源码1...
`timescale ns / ps
//`define SIM
`define SYS_CLK 50_000_000
//achieve lcd1602 cgram display
//author wuyuehang1990
//version 0.1
module lcd1602_cgram_controller(
sys_clk,
sys_rst_n,
sys_dat_i,
sys_addr_i,
lcd_ack_o,
lcd_en,
lcd_rw,
lcd_rs,
lcd_bus,
lcd_on,
lcd_blon
); input sys_clk;
input sys_rst_n;
input [:] sys_dat_i;//CGRAM ONLY DISP 8 DIFFERENT FONTS//00~07
input [:] sys_addr_i;//DDRAM ADDR
output reg lcd_ack_o;
//lcd interface
output lcd_en;
output lcd_rw;
output reg lcd_rs;
output reg [:] lcd_bus;
//spec io
output lcd_on;
output lcd_blon; `ifdef SIM
parameter ST_WIDTH = ;
parameter CLR = "CLR.....";
parameter FUNC = "FUNC....";
parameter ONOFF = "ON/OFF..";
parameter ENTRY = "ENTRY...";
parameter SETCGRAM = "SETCGRAM";
parameter WRCGRAM = "WR_CGRAM";
parameter SETDDRAM = "SETDDRAM";
parameter WRDDRAM = "WR_DDRAM";
parameter ACK = "ACK.....";
`else
`define FSM
parameter ST_WIDTH = `FSM;
parameter CLR = `FSM'b0_0000_0001;//01
parameter FUNC = `FSM'b0_0000_0010;//38(8BUS-2LINE) 37(8BUS-1LINE)
parameter ONOFF = `FSM'b0_0000_0100;//0C(ON-SHINE)
parameter ENTRY = `FSM'b0_0000_1000;//06(DISP_FIXED-CURSOR_SHIFT)
parameter SETCGRAM = `FSM'b0_0001_0000;
parameter WRCGRAM = `FSM'b0_0010_0000;
parameter SETDDRAM = `FSM'b0_0100_0000;
parameter WRDDRAM = `FSM'b0_1000_0000;
parameter ACK = `FSM'b1_0000_0000; `endif //generate 1KHz(1ms)
reg [:] cnt_1KHz=;
reg clk_1KHz=;
reg pulse1ms=; always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) begin
cnt_1KHz <= ;
end
else if(cnt_1KHz > 'd99999) begin
cnt_1KHz <= ;
end
else begin
cnt_1KHz <= cnt_1KHz + 'd1;
end
end always @ (posedge sys_clk) begin
if(cnt_1KHz < 'd49999) begin
clk_1KHz <= 'd1;
end
else begin
clk_1KHz <= 'd0;
end
end always @ (posedge sys_clk) begin
if(cnt_1KHz == 'd99999) pulse1ms <= 1'd1;
else pulse1ms <= 'd0;
end //generate lcd_en,lcd_rw;
assign lcd_en = clk_1KHz;
assign lcd_rw = 'b0;
//generate spec io
assign lcd_on = 'b1;
assign lcd_blon = 'b1; //FSM
reg [:] cnt64=;//count 64 hex char
reg [ST_WIDTH-:] c_st = FUNC;
reg [ST_WIDTH-:] n_st = FUNC;
//fsm-1
always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) c_st <= FUNC;
else c_st <= n_st;
end //fsm-2
always @ (*) begin
n_st = FUNC;
case(c_st)
FUNC:begin
n_st = (pulse1ms == 'b1)?ONOFF:FUNC;
end
ONOFF:begin
n_st = (pulse1ms == 'b1)?ENTRY:ONOFF;
end
ENTRY:begin
n_st = (pulse1ms == 'b1)?CLR:ENTRY;
end
CLR:begin
n_st = (pulse1ms == 'b1)?SETCGRAM:CLR;
end
SETCGRAM:begin
n_st = (pulse1ms == 'b1)?WRCGRAM:SETCGRAM;
end
WRCGRAM:begin
if((pulse1ms == 'b1) && (cnt64 == 6'd63))
n_st = SETDDRAM;
else if(pulse1ms == 'b1)
n_st = SETCGRAM;
else
n_st = WRCGRAM;
end
SETDDRAM:begin
n_st = (pulse1ms == 'b1)?WRDDRAM:SETDDRAM;
end
WRDDRAM:begin
n_st = (pulse1ms == 'b1)?ACK:WRDDRAM;
end
ACK:begin
n_st = SETDDRAM;
end
default:begin
n_st = FUNC;
end
endcase
end //FSM-3
//generate lcd_bus lcd_rs and lcd_ack always @ (posedge sys_clk) begin
if('b0 == sys_rst_n) begin
lcd_ack_o <= ;
lcd_rs <= ;
lcd_bus <= 'h38;
cnt64 <= ;
end
else begin
case(n_st)
FUNC:begin
lcd_rs <= ;
lcd_ack_o <= ;
lcd_bus <= 'h38;//3c(2-line-5*10)//38(2-line-5*8)
cnt64 <= 'd63;
end
ONOFF:begin
lcd_rs <= ;
lcd_ack_o <= ;
lcd_bus <= 'h0d;//no cursor
cnt64 <= 'd63;
end
ENTRY:begin
lcd_rs <= ;
lcd_ack_o <= ;
lcd_bus <= 'h06;
cnt64 <= 'd63;
end
CLR:begin
lcd_rs <= ;
lcd_ack_o <= ;
lcd_bus <= 'h01;
cnt64 <= 'd63;
end
SETCGRAM:begin
lcd_ack_o <= ;
lcd_rs <= ;
cnt64 <= (pulse1ms == 'b1)?cnt64 + 1'd1:cnt64;
lcd_bus <= {'b01,cnt64};
end
WRCGRAM:begin
lcd_ack_o <= ;
lcd_rs <= ;
cnt64 <= cnt64;
/*
case(cnt64)
6'd0,6'd1,6'd2,6'd3,6'd4,6'd5,6'd6,6'd7:lcd_bus <= 8'h00;//empty
6'd8,6'd9,6'd10,6'd11,6'd12,6'd13:lcd_bus <= 8'h00;
6'd14:lcd_bus <= 8'h1f;
6'd15:lcd_bus <= 8'h00;//1step
6'd16,6'd17,6'd18,6'd19,6'd20:lcd_bus <= 8'h00;
6'd21,6'd22:lcd_bus <= 8'h1f;
6'd23:lcd_bus <= 8'h00;//2step
6'd24,6'd25,6'd26,6'd27:lcd_bus <= 8'h00;
6'd28,6'd29,6'd30:lcd_bus <= 8'h1f;
6'd31:lcd_bus <= 8'h00;//3step
6'd32,6'd33,6'd34:lcd_bus <= 8'h00;
6'd35,6'd36,6'd37,6'd38:lcd_bus <= 8'h1f;
6'd39:lcd_bus <= 8'h00;//4step
6'd40,6'd41:lcd_bus <= 8'h00;
6'd42,6'd43,6'd44,6'd45,6'd46:lcd_bus <= 8'h1f;
6'd47:lcd_bus <= 8'h00;//5step
6'd48:lcd_bus <= 8'h00;
6'd49,6'd50,6'd51,6'd52,6'd53,6'd54:lcd_bus <= 8'h1f;
6'd55:lcd_bus <= 8'h00;//6step
6'd56,6'd57,6'd58,6'd59,6'd60,6'd61,6'd62:lcd_bus <= 8'h1f;
6'd63:lcd_bus <= 8'h00;//7step
endcase
*/
case(cnt64)
'd0,6'd1,'d2,6'd3,'d4,6'd5,'d6:lcd_bus <= 8'h00;
'd7:lcd_bus <= 8'h1f;//s1
'd8,6'd9,'d10,6'd11,'d12,6'd13:lcd_bus <= 'h00;
'd14:lcd_bus <= 8'h1f;
'd15:lcd_bus <= 8'h1f;//s2
'd16,6'd17,'d18,6'd19,'d20:lcd_bus <= 8'h00;
'd21,6'd22:lcd_bus <= 'h1f;
'd23:lcd_bus <= 8'h1f;//s3
'd24,6'd25,'d26,6'd27:lcd_bus <= 'h00;
'd28,6'd29,'d30:lcd_bus <= 8'h1f;
'd31:lcd_bus <= 8'h1f;//4step
'd32,6'd33,'d34:lcd_bus <= 8'h00;
'd35,6'd36,'d37,6'd38:lcd_bus <= 'h1f;
'd39:lcd_bus <= 8'h1f;//5step
'd40,6'd41:lcd_bus <= 'h00;
'd42,6'd43,'d44,6'd45,'d46:lcd_bus <= 8'h1f;
'd47:lcd_bus <= 8'h1f;//6step
'd48:lcd_bus <= 8'h00;
'd49,6'd50,'d51,6'd52,'d53,6'd54:lcd_bus <= 'h1f;
'd55:lcd_bus <= 8'h1f;//7step
'd56,6'd57,'d58,6'd59,'d60,6'd61,'d62:lcd_bus <= 8'h1f;
'd63:lcd_bus <= 8'h1f;//8step
endcase
end
SETDDRAM:begin
lcd_ack_o <= ;
lcd_rs <= ;
lcd_bus <= sys_addr_i;
cnt64 <= cnt64;
end
WRDDRAM:begin
lcd_ack_o <= ;
lcd_rs <= ;
cnt64 <= cnt64;
lcd_bus <= sys_dat_i;
end
ACK:begin
lcd_ack_o <= ;
lcd_rs <= ;
lcd_bus <= lcd_bus;
cnt64 <= cnt64;
end
default:begin
lcd_ack_o <= ;
lcd_rs <= ;
lcd_bus <= 'h38;
cnt64 <= cnt64;
end
endcase
end
end endmodule
源码2...
`timescale ns / ps
module lcd1602_cgram_driver(
sys_clk,
sys_rst_n,
lcd_en,
lcd_rw,
lcd_rs,
lcd_bus,
lcd_on,
lcd_blon
);
input sys_clk;
input sys_rst_n;
output lcd_rs;
output lcd_rw;
output lcd_en;
output lcd_on;
output lcd_blon;
output [:] lcd_bus; reg [:] sys_dat_i=;
reg [:] sys_addr_i=;
wire lcd_ack_o; always @ (posedge sys_clk) begin
if(sys_rst_n == 'b0) begin
sys_dat_i <= ;
sys_addr_i <= 'h80;
end
else if(lcd_ack_o == 'b1) begin
if(sys_dat_i == 'd7) begin
sys_dat_i <= ;
sys_addr_i <= 'h80;
end
else begin
sys_dat_i <= sys_dat_i + 'd1;
sys_addr_i <= sys_addr_i + 'd1;
end
end
else begin
sys_dat_i <= sys_dat_i;
sys_addr_i <= sys_addr_i;
end
end lcd1602_cgram_controller hal(
.sys_clk( sys_clk ),
.sys_rst_n( sys_rst_n ),
.sys_dat_i( sys_dat_i ),
.sys_addr_i( sys_addr_i ),
.lcd_ack_o( lcd_ack_o ),
.lcd_en( lcd_en ),
.lcd_rw( lcd_rw ),
.lcd_rs( lcd_rs ),
.lcd_bus( lcd_bus ),
.lcd_on( lcd_on ),
.lcd_blon( lcd_blon )
); endmodule
源码3...
`timescale ns / ps
module lcd1602_cgram_driver_tsb();
reg sys_clk;
reg sys_rst_n; initial begin
sys_clk=;
sys_rst_n=;
# sys_rst_n=;
end always begin
# sys_clk=~sys_clk;
end wire lcd_rw;
wire lcd_rs;
wire lcd_en;
wire [:] lcd_bus;
wire lcd_on;
wire lcd_blon; lcd1602_cgram_driver api(
.sys_clk( sys_clk ),
.sys_rst_n( sys_rst_n ),
.lcd_en( lcd_en ),
.lcd_rw( lcd_rw ),
.lcd_rs( lcd_rs ),
.lcd_bus( lcd_bus ),
.lcd_on( lcd_on ),
.lcd_blon( lcd_blon )
); endmodule
LCD1602写自定义字符的Verilog源码的更多相关文章
- Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析
这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...
- Jquery+Ajax+asp.net+sqlserver-编写的通用邮件管理(源码)
开始 邮件管理通常用在各个内部系统中,为了方便快捷的使用现有的代码开发一个邮件管理系统而诞生的. 准备条件 这是我的设计表结构,大家一看就懂了 --邮件接收表CREATE TABLE [dbo]. ...
- spring security 之自定义表单登录源码跟踪
上一节我们跟踪了security的默认登录页的源码,可以参考这里:https://www.cnblogs.com/process-h/p/15522267.html 这节我们来看看如何自定义单表认 ...
- 实现简单的手写涂鸦板(demo源码)
在一些软件系统中,需要用到手写涂鸦的功能,然后可以将涂鸦的结果保存为图片,并可以将"真迹"通过网络发送给对方.这种手写涂鸦功能是如何实现的了?最直接的,我们可以使用Windows提 ...
- 自定义TableViewCell 的方式实现自定义TableView(带源码)
转载于:http://www.cnblogs.com/macroxu-1982/archive/2012/08/30/2664121.html 实现的效果 实现过程 Step One 创建 自定义Ta ...
- [原创]分享本人自己PY写的BOOST编译程序(源码)
本程序WINDOWS专用,只做抛砖引玉,希望诸位按照各自需求自行修改,主要目的是为了让诸位编译时可以省一些组合指令的时间,只需要修改几个参数即可自动编译. 支持64位编译模式. 改进版本:http:/ ...
- 一个基于jQuery写的弹窗效果(附源码)
最近项目中频繁遇到需要弹出窗口的功能,一直使用浏览器默认的Alert和Confirm弹窗,感觉视觉效果不是那么好,而从网上下载的话又找不到合适的,找到的话有些也是十分臃肿,有时候感觉学习配置的功夫自己 ...
- client-go客户端自定义开发Kubernetes及源码分析
介绍 client-go 是一种能够与 Kubernetes 集群通信的客户端,通过它可以对 Kubernetes 集群中各资源类型进行 CRUD 操作,它有三大 client 类,分别为:Clien ...
- 十四.自定义yum仓库、源码编译安装
pc7:192.168.4.7 1.自定义yum仓库1.1 源码仓库下:/root/tools/other]# createrepo .]# ls ntfs-3g-2014.2.15-6.el6.x8 ...
随机推荐
- CSS样式选择器优先级
CSS样式选择器分为4个等级,a.b.c.d,可以以这四种等级为依据确定CSS选择器的优先级. 1.如果样式是行内样式(通过Style=””定义),那么a=12.b为ID选择器的总数3.c为Class ...
- MySQL主机127.0.0.1与localhost区别总结
1. mysql -h 127.0.0.1 的时候,使用TCP/IP连接, mysql server 认为该连接来自于127.0.0.1或者是"localhost.localdomain&q ...
- Python学习路程day10
Twsited异步网络框架 Twisted是一个事件驱动的网络框架,其中包含了诸多功能,例如:网络协议.线程.数据库管理.网络操作.电子邮件等. 事件驱动 简而言之,事件驱动分为二个部分:第一,注册事 ...
- 初学web开发——怎么解决无法找到路径的问题
刚刚接触web开发一个月,在接手项目时,总会出项无法找到改路径的问题, 那么,这个是什么原因造成的呢?因为我现在使用的是MVC架构,大部分的原因是在View里创建了视图,但是并未在controller ...
- REDIS key notification
Commands Clients Documentation Community Download Support License Join us in London October 19th for ...
- M6: 使用摄像头(CameraCaptureUI)
本小节介绍UWP中摄像头的使用,使用CameraCaptureUI来拍照,不仅能够获得图像,还能够对图像进行剪裁 (目前Mobile设备还上不支持). 在本例中, 单击Camera按钮调用摄像头来拍摄 ...
- 不同vlan之间的相互访问
拓扑图: 用到的命令: 给端口的vlan <sw1>用户模式 切换到系统模式 system-view 交换机名称 sysname swj1 创建vlan 3 端口模式选择int g0/0/ ...
- img标签中alt和title属性的正确使用
在的img标签有两个属性分别为alt和title,对于很多初学者而言对这两个属性的正确使用都还抱有迷惑,当然这其中一部分原因也是ie浏览器所导致的.正确的使用这两个属性除了可以提高图片的搜索能力外,在 ...
- dede织梦后台如何修改?如何增加删除菜单?(
织梦后台的模板存放在dede/templets下面, 登陆首页模板login.htm, 进入首页模板index_body.htm, 左侧菜单模板index_menu2.htm. 修改左侧菜单dede/ ...
- mysql workbench is well-designed
我用过mysql纯cli(command line),即纯命令行的执行环境,也用过navicat for mysql pro 破解版,甚至还用过比较高端的sqlyog,最后我还是选择了官方的workb ...