开发工具: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...

  1. `timescale ns / ps
  2. //`define SIM
  3. `define SYS_CLK 50_000_000
  4. //achieve lcd1602 cgram display
  5. //author wuyuehang1990
  6. //version 0.1
  7. module lcd1602_cgram_controller(
  8. sys_clk,
  9. sys_rst_n,
  10. sys_dat_i,
  11. sys_addr_i,
  12. lcd_ack_o,
  13. lcd_en,
  14. lcd_rw,
  15. lcd_rs,
  16. lcd_bus,
  17. lcd_on,
  18. lcd_blon
  19. );
  20.  
  21. input sys_clk;
  22. input sys_rst_n;
  23. input [:] sys_dat_i;//CGRAM ONLY DISP 8 DIFFERENT FONTS//00~07
  24. input [:] sys_addr_i;//DDRAM ADDR
  25. output reg lcd_ack_o;
  26. //lcd interface
  27. output lcd_en;
  28. output lcd_rw;
  29. output reg lcd_rs;
  30. output reg [:] lcd_bus;
  31. //spec io
  32. output lcd_on;
  33. output lcd_blon;
  34.  
  35. `ifdef SIM
  36. parameter ST_WIDTH = ;
  37. parameter CLR = "CLR.....";
  38. parameter FUNC = "FUNC....";
  39. parameter ONOFF = "ON/OFF..";
  40. parameter ENTRY = "ENTRY...";
  41. parameter SETCGRAM = "SETCGRAM";
  42. parameter WRCGRAM = "WR_CGRAM";
  43. parameter SETDDRAM = "SETDDRAM";
  44. parameter WRDDRAM = "WR_DDRAM";
  45. parameter ACK = "ACK.....";
  46. `else
  47. `define FSM
  48. parameter ST_WIDTH = `FSM;
  49. parameter CLR = `FSM'b0_0000_0001;//01
  50. parameter FUNC = `FSM'b0_0000_0010;//38(8BUS-2LINE) 37(8BUS-1LINE)
  51. parameter ONOFF = `FSM'b0_0000_0100;//0C(ON-SHINE)
  52. parameter ENTRY = `FSM'b0_0000_1000;//06(DISP_FIXED-CURSOR_SHIFT)
  53. parameter SETCGRAM = `FSM'b0_0001_0000;
  54. parameter WRCGRAM = `FSM'b0_0010_0000;
  55. parameter SETDDRAM = `FSM'b0_0100_0000;
  56. parameter WRDDRAM = `FSM'b0_1000_0000;
  57. parameter ACK = `FSM'b1_0000_0000;
  58.  
  59. `endif
  60.  
  61. //generate 1KHz(1ms)
  62. reg [:] cnt_1KHz=;
  63. reg clk_1KHz=;
  64. reg pulse1ms=;
  65.  
  66. always @ (posedge sys_clk) begin
  67. if(sys_rst_n == 'b0) begin
  68. cnt_1KHz <= ;
  69. end
  70. else if(cnt_1KHz > 'd99999) begin
  71. cnt_1KHz <= ;
  72. end
  73. else begin
  74. cnt_1KHz <= cnt_1KHz + 'd1;
  75. end
  76. end
  77.  
  78. always @ (posedge sys_clk) begin
  79. if(cnt_1KHz < 'd49999) begin
  80. clk_1KHz <= 'd1;
  81. end
  82. else begin
  83. clk_1KHz <= 'd0;
  84. end
  85. end
  86.  
  87. always @ (posedge sys_clk) begin
  88. if(cnt_1KHz == 'd99999) pulse1ms <= 1'd1;
  89. else pulse1ms <= 'd0;
  90. end
  91.  
  92. //generate lcd_en,lcd_rw;
  93. assign lcd_en = clk_1KHz;
  94. assign lcd_rw = 'b0;
  95. //generate spec io
  96. assign lcd_on = 'b1;
  97. assign lcd_blon = 'b1;
  98.  
  99. //FSM
  100. reg [:] cnt64=;//count 64 hex char
  101. reg [ST_WIDTH-:] c_st = FUNC;
  102. reg [ST_WIDTH-:] n_st = FUNC;
  103. //fsm-1
  104. always @ (posedge sys_clk) begin
  105. if('b0 == sys_rst_n) c_st <= FUNC;
  106. else c_st <= n_st;
  107. end
  108.  
  109. //fsm-2
  110. always @ (*) begin
  111. n_st = FUNC;
  112. case(c_st)
  113. FUNC:begin
  114. n_st = (pulse1ms == 'b1)?ONOFF:FUNC;
  115. end
  116. ONOFF:begin
  117. n_st = (pulse1ms == 'b1)?ENTRY:ONOFF;
  118. end
  119. ENTRY:begin
  120. n_st = (pulse1ms == 'b1)?CLR:ENTRY;
  121. end
  122. CLR:begin
  123. n_st = (pulse1ms == 'b1)?SETCGRAM:CLR;
  124. end
  125. SETCGRAM:begin
  126. n_st = (pulse1ms == 'b1)?WRCGRAM:SETCGRAM;
  127. end
  128. WRCGRAM:begin
  129. if((pulse1ms == 'b1) && (cnt64 == 6'd63))
  130. n_st = SETDDRAM;
  131. else if(pulse1ms == 'b1)
  132. n_st = SETCGRAM;
  133. else
  134. n_st = WRCGRAM;
  135. end
  136. SETDDRAM:begin
  137. n_st = (pulse1ms == 'b1)?WRDDRAM:SETDDRAM;
  138. end
  139. WRDDRAM:begin
  140. n_st = (pulse1ms == 'b1)?ACK:WRDDRAM;
  141. end
  142. ACK:begin
  143. n_st = SETDDRAM;
  144. end
  145. default:begin
  146. n_st = FUNC;
  147. end
  148. endcase
  149. end
  150.  
  151. //FSM-3
  152. //generate lcd_bus lcd_rs and lcd_ack
  153.  
  154. always @ (posedge sys_clk) begin
  155. if('b0 == sys_rst_n) begin
  156. lcd_ack_o <= ;
  157. lcd_rs <= ;
  158. lcd_bus <= 'h38;
  159. cnt64 <= ;
  160. end
  161. else begin
  162. case(n_st)
  163. FUNC:begin
  164. lcd_rs <= ;
  165. lcd_ack_o <= ;
  166. lcd_bus <= 'h38;//3c(2-line-5*10)//38(2-line-5*8)
  167. cnt64 <= 'd63;
  168. end
  169. ONOFF:begin
  170. lcd_rs <= ;
  171. lcd_ack_o <= ;
  172. lcd_bus <= 'h0d;//no cursor
  173. cnt64 <= 'd63;
  174. end
  175. ENTRY:begin
  176. lcd_rs <= ;
  177. lcd_ack_o <= ;
  178. lcd_bus <= 'h06;
  179. cnt64 <= 'd63;
  180. end
  181. CLR:begin
  182. lcd_rs <= ;
  183. lcd_ack_o <= ;
  184. lcd_bus <= 'h01;
  185. cnt64 <= 'd63;
  186. end
  187. SETCGRAM:begin
  188. lcd_ack_o <= ;
  189. lcd_rs <= ;
  190. cnt64 <= (pulse1ms == 'b1)?cnt64 + 1'd1:cnt64;
  191. lcd_bus <= {'b01,cnt64};
  192. end
  193. WRCGRAM:begin
  194. lcd_ack_o <= ;
  195. lcd_rs <= ;
  196. cnt64 <= cnt64;
  197. /*
  198. case(cnt64)
  199. 6'd0,6'd1,6'd2,6'd3,6'd4,6'd5,6'd6,6'd7:lcd_bus <= 8'h00;//empty
  200. 6'd8,6'd9,6'd10,6'd11,6'd12,6'd13:lcd_bus <= 8'h00;
  201. 6'd14:lcd_bus <= 8'h1f;
  202. 6'd15:lcd_bus <= 8'h00;//1step
  203. 6'd16,6'd17,6'd18,6'd19,6'd20:lcd_bus <= 8'h00;
  204. 6'd21,6'd22:lcd_bus <= 8'h1f;
  205. 6'd23:lcd_bus <= 8'h00;//2step
  206. 6'd24,6'd25,6'd26,6'd27:lcd_bus <= 8'h00;
  207. 6'd28,6'd29,6'd30:lcd_bus <= 8'h1f;
  208. 6'd31:lcd_bus <= 8'h00;//3step
  209. 6'd32,6'd33,6'd34:lcd_bus <= 8'h00;
  210. 6'd35,6'd36,6'd37,6'd38:lcd_bus <= 8'h1f;
  211. 6'd39:lcd_bus <= 8'h00;//4step
  212. 6'd40,6'd41:lcd_bus <= 8'h00;
  213. 6'd42,6'd43,6'd44,6'd45,6'd46:lcd_bus <= 8'h1f;
  214. 6'd47:lcd_bus <= 8'h00;//5step
  215. 6'd48:lcd_bus <= 8'h00;
  216. 6'd49,6'd50,6'd51,6'd52,6'd53,6'd54:lcd_bus <= 8'h1f;
  217. 6'd55:lcd_bus <= 8'h00;//6step
  218. 6'd56,6'd57,6'd58,6'd59,6'd60,6'd61,6'd62:lcd_bus <= 8'h1f;
  219. 6'd63:lcd_bus <= 8'h00;//7step
  220. endcase
  221. */
  222. case(cnt64)
  223. 'd0,6'd1,'d2,6'd3,'d4,6'd5,'d6:lcd_bus <= 8'h00;
  224. 'd7:lcd_bus <= 8'h1f;//s1
  225. 'd8,6'd9,'d10,6'd11,'d12,6'd13:lcd_bus <= 'h00;
  226. 'd14:lcd_bus <= 8'h1f;
  227. 'd15:lcd_bus <= 8'h1f;//s2
  228. 'd16,6'd17,'d18,6'd19,'d20:lcd_bus <= 8'h00;
  229. 'd21,6'd22:lcd_bus <= 'h1f;
  230. 'd23:lcd_bus <= 8'h1f;//s3
  231. 'd24,6'd25,'d26,6'd27:lcd_bus <= 'h00;
  232. 'd28,6'd29,'d30:lcd_bus <= 8'h1f;
  233. 'd31:lcd_bus <= 8'h1f;//4step
  234. 'd32,6'd33,'d34:lcd_bus <= 8'h00;
  235. 'd35,6'd36,'d37,6'd38:lcd_bus <= 'h1f;
  236. 'd39:lcd_bus <= 8'h1f;//5step
  237. 'd40,6'd41:lcd_bus <= 'h00;
  238. 'd42,6'd43,'d44,6'd45,'d46:lcd_bus <= 8'h1f;
  239. 'd47:lcd_bus <= 8'h1f;//6step
  240. 'd48:lcd_bus <= 8'h00;
  241. 'd49,6'd50,'d51,6'd52,'d53,6'd54:lcd_bus <= 'h1f;
  242. 'd55:lcd_bus <= 8'h1f;//7step
  243. 'd56,6'd57,'d58,6'd59,'d60,6'd61,'d62:lcd_bus <= 8'h1f;
  244. 'd63:lcd_bus <= 8'h1f;//8step
  245. endcase
  246. end
  247. SETDDRAM:begin
  248. lcd_ack_o <= ;
  249. lcd_rs <= ;
  250. lcd_bus <= sys_addr_i;
  251. cnt64 <= cnt64;
  252. end
  253. WRDDRAM:begin
  254. lcd_ack_o <= ;
  255. lcd_rs <= ;
  256. cnt64 <= cnt64;
  257. lcd_bus <= sys_dat_i;
  258. end
  259. ACK:begin
  260. lcd_ack_o <= ;
  261. lcd_rs <= ;
  262. lcd_bus <= lcd_bus;
  263. cnt64 <= cnt64;
  264. end
  265. default:begin
  266. lcd_ack_o <= ;
  267. lcd_rs <= ;
  268. lcd_bus <= 'h38;
  269. cnt64 <= cnt64;
  270. end
  271. endcase
  272. end
  273. end
  274.  
  275. endmodule

源码2...

  1. `timescale ns / ps
  2. module lcd1602_cgram_driver(
  3. sys_clk,
  4. sys_rst_n,
  5. lcd_en,
  6. lcd_rw,
  7. lcd_rs,
  8. lcd_bus,
  9. lcd_on,
  10. lcd_blon
  11. );
  12. input sys_clk;
  13. input sys_rst_n;
  14. output lcd_rs;
  15. output lcd_rw;
  16. output lcd_en;
  17. output lcd_on;
  18. output lcd_blon;
  19. output [:] lcd_bus;
  20.  
  21. reg [:] sys_dat_i=;
  22. reg [:] sys_addr_i=;
  23. wire lcd_ack_o;
  24.  
  25. always @ (posedge sys_clk) begin
  26. if(sys_rst_n == 'b0) begin
  27. sys_dat_i <= ;
  28. sys_addr_i <= 'h80;
  29. end
  30. else if(lcd_ack_o == 'b1) begin
  31. if(sys_dat_i == 'd7) begin
  32. sys_dat_i <= ;
  33. sys_addr_i <= 'h80;
  34. end
  35. else begin
  36. sys_dat_i <= sys_dat_i + 'd1;
  37. sys_addr_i <= sys_addr_i + 'd1;
  38. end
  39. end
  40. else begin
  41. sys_dat_i <= sys_dat_i;
  42. sys_addr_i <= sys_addr_i;
  43. end
  44. end
  45.  
  46. lcd1602_cgram_controller hal(
  47. .sys_clk( sys_clk ),
  48. .sys_rst_n( sys_rst_n ),
  49. .sys_dat_i( sys_dat_i ),
  50. .sys_addr_i( sys_addr_i ),
  51. .lcd_ack_o( lcd_ack_o ),
  52. .lcd_en( lcd_en ),
  53. .lcd_rw( lcd_rw ),
  54. .lcd_rs( lcd_rs ),
  55. .lcd_bus( lcd_bus ),
  56. .lcd_on( lcd_on ),
  57. .lcd_blon( lcd_blon )
  58. );
  59.  
  60. endmodule

源码3...

  1. `timescale ns / ps
  2. module lcd1602_cgram_driver_tsb();
  3. reg sys_clk;
  4. reg sys_rst_n;
  5.  
  6. initial begin
  7. sys_clk=;
  8. sys_rst_n=;
  9. # sys_rst_n=;
  10. end
  11.  
  12. always begin
  13. # sys_clk=~sys_clk;
  14. end
  15.  
  16. wire lcd_rw;
  17. wire lcd_rs;
  18. wire lcd_en;
  19. wire [:] lcd_bus;
  20. wire lcd_on;
  21. wire lcd_blon;
  22.  
  23. lcd1602_cgram_driver api(
  24. .sys_clk( sys_clk ),
  25. .sys_rst_n( sys_rst_n ),
  26. .lcd_en( lcd_en ),
  27. .lcd_rw( lcd_rw ),
  28. .lcd_rs( lcd_rs ),
  29. .lcd_bus( lcd_bus ),
  30. .lcd_on( lcd_on ),
  31. .lcd_blon( lcd_blon )
  32. );
  33.  
  34. endmodule

LCD1602写自定义字符的Verilog源码的更多相关文章

  1. Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析

    这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...

  2. Jquery+Ajax+asp.net+sqlserver-编写的通用邮件管理(源码)

    开始 邮件管理通常用在各个内部系统中,为了方便快捷的使用现有的代码开发一个邮件管理系统而诞生的. 准备条件 这是我的设计表结构,大家一看就懂了   --邮件接收表CREATE TABLE [dbo]. ...

  3. spring security 之自定义表单登录源码跟踪

    ​ 上一节我们跟踪了security的默认登录页的源码,可以参考这里:https://www.cnblogs.com/process-h/p/15522267.html 这节我们来看看如何自定义单表认 ...

  4. 实现简单的手写涂鸦板(demo源码)

    在一些软件系统中,需要用到手写涂鸦的功能,然后可以将涂鸦的结果保存为图片,并可以将"真迹"通过网络发送给对方.这种手写涂鸦功能是如何实现的了?最直接的,我们可以使用Windows提 ...

  5. 自定义TableViewCell 的方式实现自定义TableView(带源码)

    转载于:http://www.cnblogs.com/macroxu-1982/archive/2012/08/30/2664121.html 实现的效果 实现过程 Step One 创建 自定义Ta ...

  6. [原创]分享本人自己PY写的BOOST编译程序(源码)

    本程序WINDOWS专用,只做抛砖引玉,希望诸位按照各自需求自行修改,主要目的是为了让诸位编译时可以省一些组合指令的时间,只需要修改几个参数即可自动编译. 支持64位编译模式. 改进版本:http:/ ...

  7. 一个基于jQuery写的弹窗效果(附源码)

    最近项目中频繁遇到需要弹出窗口的功能,一直使用浏览器默认的Alert和Confirm弹窗,感觉视觉效果不是那么好,而从网上下载的话又找不到合适的,找到的话有些也是十分臃肿,有时候感觉学习配置的功夫自己 ...

  8. client-go客户端自定义开发Kubernetes及源码分析

    介绍 client-go 是一种能够与 Kubernetes 集群通信的客户端,通过它可以对 Kubernetes 集群中各资源类型进行 CRUD 操作,它有三大 client 类,分别为:Clien ...

  9. 十四.自定义yum仓库、源码编译安装

    pc7:192.168.4.7 1.自定义yum仓库1.1 源码仓库下:/root/tools/other]# createrepo .]# ls ntfs-3g-2014.2.15-6.el6.x8 ...

随机推荐

  1. [Weekly] 2014.03.01-2014.03.08

    这周写过好多东西,虽然还没有完全弄明白线段树,但是progress还是有的! 不过有时候真的很想哭,因为自己的梦想连别人看看韩剧.无所事事还要分量轻,实在不明白政治课的Teamwork意义何在,花两分 ...

  2. Tri-Training: Exploiting Unlabeled Data Using Three Classifiers

    Abstract – In many practical data mining applications such as web page classification, unlabeled tra ...

  3. cassandra 环境搭建

    1 下载安装包 http://www.planetcassandra.org/cassandra/?dlink=http://downloads.datastax.com/community/dsc- ...

  4. 永不消逝的电波(二)HackRF入门:家用无线门铃信号重放

    0×00 前言 在第一篇文章:永不消逝的电波(一):无线电入门篇 我们了解了一下无线电的发展史以及无线电的一些物理知识,在第二篇里我们将用HackRF录制家用门铃的无线信号,然后重放门铃信号. 门铃从 ...

  5. Asp.net中Json的序列化和反序列化(一)

    JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介绍 ...

  6. 黑马程序员——【Java基础】——正则表达式

    ---------- android培训.java培训.期待与您交流! ---------- 一.概述 1. 概念:符合一定规则的表达式. 2. 作用:用于专门操作字符串. 3. 特点:用一些特定的符 ...

  7. HDU 3555 Bomb

    RT. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> ...

  8. HDU5898、 HDU 2089(数位DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5898 题意:很明确,找出区间[l , r]中符合连续奇数为偶数,连续偶数为奇数的个数. 思路:dp[i ...

  9. 12-8下午 php语法

    <?php //var_dump(empty($a)); //判断变量是否为空//var_dump(isset($a)); //判断变量是否定义//$a = 10;//unset($a); // ...

  10. IOS ASIFormDataRequest使用简介(2/25)

    ASIHTTPRequest类库中的ASIFormDataRequest是实现HTTP协议中的处理POST表单的很好的类库.使用起来非常简单.下面特酷吧简要总结其用法. 在说明之前先需要了解HTTP请 ...