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 ...
随机推荐
- Java - 简单的对象排序 - Comparator
注:对象排序,就是对对象中的某一字段进行比较,以正序或倒序进行排序. 例: 需要排序的对象: public class Person { public int age; public String n ...
- autotools工具使用记录
参考 http://blog.chinaunix.net/uid-25100840-id-271131.html http://blog.sina.com.cn/s/blog_4c2bf01a0101 ...
- WCF服务开发与调用的完整示例
WCF服务开发与调用的完整示例 开发工具:VS2008 开发语言:C# 开发内容:简单的权限管理系统 第一步.建立WCF服务库 点击确定,将建立一个WCF 服务库示例程序,自动生成一个包括IServi ...
- java中的包以及内部类的介绍
1:形式参数和返回值的问题(理解) (1)形式参数: 类名:需要该类的对象 抽象类名:需要该类的子类对象 接口名:需要该接口的实现类对象 (2)返 ...
- VC中预处理指令与宏定义详解
刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...
- Ubuntu远程连接windows
一般情况下都是使用windows系统,通过mstsc远程连接linux系统,但对于一些linuxer来说,有时候需要远程连接一下windows,最后采用的是rdesktop,一个非常好用的工具 sud ...
- 前端开发环境搭建 Grunt Bower、Requirejs 、 Angular
现在web开发的趋势是前后端分离.前端采用某些js框架,后端采用某些语言提供restful API,两者以json格式进行数据交互. 如果后端采用node.js,则前后端可以使用同一种语言,共享某些可 ...
- 【转载】知乎答案----孙志岗----Google 发布了程序员养成指南,国内互联网巨头是否也有类似的指南和课程推荐
国内公司在复制国外商业模式的同时,也应复制人家的社会担当.所以,来答题了!就参考 Google 的框架,列一下中文的课程.大体上在线学完一个计算机专业,是基本不成问题的.但是,这不意味着你可以不上大学 ...
- 地址(Address)——统一资源表示(URI)——WCF学习笔记(2)
统一资源标识(URI) URI:Uniform Resource Identifier(统一资源标识),唯一地标识一个网络资源的同时也表示资源所处的位置的方式(资源访问所用的网络协议). URI结构: ...
- C++ Primer : 第十三章 : 动态内存管理类
/* StrVec.h */ #ifndef _STRVEC_H_ #define _STRVEC_H_ #include <memory> #include <string> ...