话不多说先上图

前言

在做这个实验的时候在网上找了许多资料,都是关于使用单片机驱动LCD显示,确实用单片机驱动是要简单不少,记得在FPGA学习交流群里问问题的时候,被前辈指教,说给我最好的指教便是别在玩这个了,多看看关于FPGA方面的书籍,比做这个单片机做的东西价值强多了。现在想来确实,自从学习FPGA以来,看过的书没有多少,只是想做个什么了,就在网上找找例程,照抄下来,把算法推理一遍,下个板子实现了,便以为自己会了懂了,要是自己在写一个便问题百出。那么菜鸟始终是菜鸟。自己根本没有掌握FPGA的设计思想和优势,用着FPGA做着单片机的东西,这种东西练练手就足够了,所以,做完这个实验LCD就到此为止了,我也要好好想想该如何进行下面的学习了。在这个上面我还是花费了不少时间,所以写一篇博文总结记录想,回头看的时候,以警醒自己。

摘要

做完这个实验我最大的感触是一定要会读数据手册。拿到元件(LCD12864),上面有16个的引脚,先要搞清楚每个引脚的功能,这时候就一定要会读数据手册。我个qc12864b的中文手册琢磨了很久才看懂了一些简单的操作指令,包括在手册上要提取出来,元件的驱动时序,扫描时钟,引脚定义,操作指令,功能描述等。

LCD显示原理

扫描时钟

      

  从手册上可以读出,qc12864b(这是我所使用LCD12864的型号)的扫描时钟介于470—590khz之间,最适为530khz,为了方便分频,所以取500khz。

 

引脚说明

  VSS        电源地,0v ­——接开发板GND就行

  VDD      电源正极(5v,3.3v)

  VO        液晶显示偏压,调整对比度

  RS         RS=1时,当mpu进行读模块操作,指向地址寄存器

          当mpu进行写模块操作,指向指令寄存器

  RS=0时,无论进行读/写操作,都指向数据寄存器

  R/W             高电平读操作,低电平写操作

  E           使能信号,高电平读取信息,下降沿执行命令

  DB0      数据总线第0位

  DB1      数据总线第1位

  DB2      数据总线第2位

  DB3      数据总线第3位

  DB4      数据总线第4位

  DB5      数据总线第5位

  DB6      数据总线第6位

  DB7      数据总线第7位

  PSB      串并控制端口,H为并行,L为串行,直接接5v

  RST       液晶复位端口,低电平有效

  A           背光正极输入,调整电压大小可以调整亮度

  K           背光负极输入,一般直接接地

指令说明

       具体指令说明,这里就不一一列出,可查阅qc12864b中文数据手册,我在阅读这一部分的时候耗费了很长时间,这些指令是驱动LCD显示文字与图片的核心,所以必须要掌握。

并口显示时序

Verilog实现方案

  从时序图可以看出在使能信号的一个周期内可以完成写入数据操作,扫描时钟与使能信号周期相同即可。

状态转移图

  状态机初始化位置          IDLE                            lcd_data = 8’hzz

  功能设计                          SETFUNCTION            lcd_data = 8’h36//扩充指令绘图显示

  显示设置                          SWITCHMODE           lcd_data = 8’h0c//显示状态

  清屏                                  CLEAR                       lcd_data = 8’h01//清零指令

  设置Y坐标                      SETDDRAM_Y

  设置X坐标                      SETDDRAM_X

  写入数据                          WRITERAM

  结束                                  STOP

 

绘图指令下的坐标图

代码如下

  1 module lcd_qc12864b(
  2             input mclk,
  3             input rst_n,
  4             output reg lcd_rs,//H读写数据,L指令
  5             output lcd_rw, //高电平读操作,低电平写操作
  6             output lcd_e,//使能信号高电平有效
  7             output reg [7:0]lcd_data,//八位数据总线
  8         output psb,//串并控制端口,H为并行,L为串行,直接接5v
  9         output lcd_rst//液晶的复位端口,低电平有效
 10     );
 11
 12     reg lcd_clk;//需要500khz频率的时钟
 13     reg [7:0] state;//状态机寄存器
 14     reg [23:0] cnt;//分频驱动12864计数器
 15     reg flag = 1'b1;//显示完成标志
 16     reg [9:0] char_cnt;//
 17     wire [7:0] data_disp;//一个字节是八位,一个英文字符是一个字节,中文是俩个字节
 18     reg [5:0] cnt1;//行计数
 19
 20     parameter T500KHZ=24'd49999;
 21
 22         //分频500khz时钟
 23         always @(posedge mclk or negedge rst_n)
 24         begin
 25             if(!rst_n)begin
 26                 lcd_clk <= 1'b0;
 27                 cnt <= 24'd0;
 28             end
 29             else if(cnt == T500KHZ)begin
 30                 cnt <= 24'd0;
 31                 lcd_clk <= ~lcd_clk;
 32             end
 33             else
 34                 cnt <= cnt + 1'd1;
 35         end
 36
 37         //状态机8个状态设置
 38     parameter IDLE = 8'b00_000_000,//初始状态
 39                         SETFUNCTION = 8'b00_000_001,//功能设置
 40                           SWITCHMODE = 8'b00_000_010,//设置显示开和光标闪烁关闭
 41                           CLEAR = 8'b00_000_100,//清屏操作
 42                           SETDDRAM_Y = 8'b00_010_000,//设置y轴坐标
 43                             SETDDRAM_X = 8'b00_100_000,//设置x轴坐标
 44                           WRITERAM = 8'b01_000_000,//写设置写入寄存器
 45                           STOP = 8'b10_000_000;//LCD操作停止,释放其控制
 46
 47       //三段式书写状态机
 48       always @(posedge lcd_clk or negedge rst_n)
 49       begin
 50           if(!rst_n)
 51               lcd_rs <= 1'b0;
 52           else begin
 53               if(state == WRITERAM)
 54                   lcd_rs <= 1'b1;//写数据模式
 55               else
 56                   lcd_rs <= 1'b0;//写命令模式
 57           end
 58       end
 59
 60       //lcd_rst始终为高电平,psb始终为低电平即可
 61     assign lcd_rst = 1'b1;
 62     assign psb = 1'b1;
 63     assign lcd_rw = 1'b0;//只是写操作,不需要读操作
 64     assign lcd_e = (flag==1)?lcd_clk:1'b0;//使能信号与液晶时钟同步
 65
 66       always @(posedge lcd_clk or negedge rst_n)
 67       begin
 68           if(!rst_n)begin
 69               cnt1<= 1'b0;
 70               state <= IDLE;
 71               lcd_data <= 8'hzz;
 72               char_cnt <= 6'd0;
 73           end
 74           else begin
 75               case(state)
 76                   IDLE:begin
 77                       state <=  SETFUNCTION;//功能设置,8-bit+基本指令集0x30
 78                       lcd_data <= 8'h36;
 79                   end
 80
 81                   SETFUNCTION:begin
 82                       state <= SWITCHMODE;//设置显示开和光标闪烁关闭
 83                       lcd_data <= 8'h36;
 84                   end
 85
 86                   SWITCHMODE:begin
 87                       state <= CLEAR;
 88                       lcd_data <= 8'h3e;//显示设置,全显示开,光标和闪烁关
 89                   end
 90                   CLEAR:begin//清屏操作
 91                       state <= SETDDRAM_Y;//点设置
 92             lcd_data <= 8'h01;//清屏
 93           end
 94             SETDDRAM_Y:begin
 95              if(cnt1< 32)
 96                  lcd_data <= 8'h80 + cnt1;//80H~9fH
 97              else
 98                  lcd_data <= 8'h80 + (cnt1- 32); //80H~9fH
 99
100              state <= SETDDRAM_X;
101           end
102                     SETDDRAM_X:begin
103                       if(cnt1< 32)
104                           lcd_data <=  8'h80;            //80H
105                       else
106                           lcd_data <=  8'h88;            //88H
107                       state <= WRITERAM;
108                     end
109                     WRITERAM:begin
110                         lcd_data <= data_disp;
111                  char_cnt <= char_cnt + 1'b1;
112                  if(char_cnt[3:0] == 4'hf)begin      //计算行
113                      cnt1<= cnt1+ 1'b1;
114                 if(cnt1== 63)
115                     state <= STOP;
116                      else
117                   state <= SETDDRAM_Y;
118                        end
119                        else
120                  state <= WRITERAM;
121             end
122           STOP:begin
123               flag <= 1'b0;
124               state <= STOP;//LCD操作停止,释放其控制
125             end
126           default: state <= IDLE;//回到初始状态
127         endcase
128       end
129      end
130
131          // ROM
132         rom U1_rom (
133     .clka(mclk),
134     .addra(char_cnt),
135     .douta(data_disp)
136     );
137
138 endmodule

lcd_qc12864b

配置ROM

  有分布式ROM/ROM和块ROM/RAM,这里配置的是块ROM/RAM。这两种方式具体我也不是了解很深,以后再深入学习。

该实验最让我头疼的是调用ROM,第一次接触IP核有许多地方都完全不懂。用LCD(带中文字库)显示文字的时候,可以直接输入文字的十六进制数值,设置显示地址坐标即可,12864显示原理点阵控制点的亮灭来实现,但是如果要显示图片的话一个个输入难免太过麻烦,这个时候调用ROM就方便许多。找一张或做一张像素为128x64的单色图片,使用取模软件,按c51的方式取模。取模出来的数据为十六进制,行8个,64个。

配置块RAM/ROM时,要加载的是.coe文件,所以需要将取模的十六进制数据保存到.coe文件中。最开始我一直在找如何能直接将图片取模出来的数据转化成.coe文件,试了很多方法都失败了,最后发现完全可以自己按文件格式编辑一个即可,最终文件保存格式如下。

  将图片取模出来的每个数据前的ox去掉,这只是C语言中16进制的表示形式,文件第一行的MEMORY_INITIALIZATION_RADIX=16;表示数据全都为16进制数,这里的16可以换成8、2、10都行。

打开ISE建立工程后,新建文件,选择IP(CORE Generator & Architecture Wizard),填写文件名,next

  找到Memories & Storage Elements单击,选择RAMs & ROMs单击,选择Block Memory Generator 7.3,next,finish。

  上面直接next,下面这里选Single Port ROM,next

  这里要填写数据位宽和深度,位宽是你所需要输出的数据位宽,LCD有8个数据位,故这里定义位宽为8,深度即有多少个这样的数据,从取模出来的数据看,易得共有1024个数据位。我使用的basys2开发板使用的是Xilinx Spantan3E—100TQ144 FPGA包含73728位的块RAM/ROM。因此,使用的块RAM的最大容量为9216字节或4608个16位字。从这里来看,是完全够用的。

  Next,加载.coe数据文件,勾选Load Init File 加载.coe文件,我这里是在桌面上保存着,直接找到选择就好。

  然后一直点击next直至最后一个界面,最后点击Generate,生成rom.xco。生成的IP核在工程目录下的ipcore_dir文件中。

  将rom.v文件打开端口定义如下,直接在顶层文件对其实例化,如代码所示

  最后可直接仿真,新建tb文件查看仿真传输数据是否正确。由波形图可得在功能设定指令传输完毕后,进入读数据状态,所读入的数据与文件中数据相符,一行数据传输完毕进入下一行,继续读入数据,仿真图结果正确。下板子也正确。

  最开始学习FPGA,最容易出现的就是两个问题,一个是把verilog当C语言来写,另一个就是把FPGA当单片机来用。前者我已经有了改善,后者我还需要继续努力。

转载请注明出处:NingHeChuan(宁河川)

个人微信订阅号:NingHeChuan

如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号

知乎ID:NingHeChuan

微博ID:NingHeChuan

原文地址:http://www.cnblogs.com/ninghechuan/p/6340691.html

转载于:https://www.cnblogs.com/ninghechuan/p/6340691.html

基于basys2驱动LCDQC12864B的verilog设计图片显示相关推荐

  1. 基于FPGA开发板使用Verilog设计PWM呼吸灯实验

    基于FPGA开发板使用Verilog设计PWM呼吸灯实验 1,实验原理 2,实验模块设计 2.1 RTL设计,呼吸灯模块设计 2.2,测试数据,下载到FPGA开发板板级的数据 2.3,两个模块综合的n ...

  2. 基于Basys2的八位CPU的设计与FPGA实现

    目录 一.设计指标(鲲鲲提的要求,直接贴过来) 二.设计思路: 1.完整的8位CPU的设计: 2.本次设计思路: 三.Verilog实现 1.RAM: 2.指令寄存器IR 3.ALU 4.CPU 5. ...

  3. FPGA基于VGA的彩条、字符及图片显示

    文章目录 1.vga简介 2.vga彩条显示 2.1.原理分析 2.2.代码实现 2.3.测试结果 3.实现字符串的显示 3.1.生成点阵字模 3.2.代码编写(文尾会附上整体代码) 3.3.测试结果 ...

  4. 基于Basys2的Booth乘法器的设计

    目录 一.设计指标(老样子,鲲鲲定的,我直接贴上来) 二.Booth乘法原理 三.Verilog代码 1.Booth乘法器: 2.显示转换模块: 3.数值位译码器: 4.符号位译码器: 5.时钟分频模 ...

  5. 基于FPGA多通道数据采集系统verilog设计

    本设计实现多通道数据采集系统,该系统包括多通道数据采集和数据传输,使用verilog语言设计. 本设计实现功能:采集8路16位的AD数据,并发送到串口助手. 该设计架构图如下: 顶层模块代码如下: m ...

  6. 基于Basys2的分秒计时器的设计

    目录 一.设计指标(同样的都是鲲鲲指定的,我直接贴过来) 二.计时器原理: 三.Verilog实现 1.十进制计数器: 2.六进制计数器: 3.六十进制计数器: 4.计时器: 5.时钟分频:50MHz ...

  7. 基于FPGA的分形编码器verilog设计

    目录 一.理论基础 二.核心程序 三.仿真测试结果 一.理论基础 分形图像编码是目前较有发展前途的图像编码方法之一, 也是目前研究较为广泛的编码方法之一.对其研究已有近十年的历史,其间,人们发现了它所 ...

  8. m基于FPGA的数字下变频verilog设计

    目录 1.算法描述 2.仿真效果预览 3.verilog核心程序 4.完整FPGA 1.算法描述 整个数字下变频的基本结构如下所示 NCO使用CORDIC算法,CIC采用h结构的CIC滤波器,HBF采 ...

  9. 数字电子计算机处理信号shi,余洪伟 基于单片机数字电子时钟设计(led显示).doc...

    余洪伟 基于单片机数字电子时钟设计(led显示) 沈阳航空航天大学 课 程 设 计 (论文) 题目 基于单片机的数字电子时钟设计 (LED显示) 班 级 学 号 2013040701060 学 生 姓 ...

最新文章

  1. 在Outlook中用VBA导出HTML格式邮件
  2. 卓越领袖的的32条经营管理思想
  3. 两个月不到,我是如何从Python新手成长为谷歌认证TensorFlow开发者的?
  4. (提示)ubuntu16.04通过sealos安装k8s,需要重新部署apply一下calico组件
  5. MapReduce排序-实现比较器和序列化代码
  6. PyTorch 1.0 中文官方教程:基于注意力机制的 seq2seq 神经网络翻译
  7. oracle chinese_china.al32utf8,Oracle11g字符集更改为AL32UTF8
  8. Niushop开源微信商城+小程序商城源码
  9. vjc机器人灰度怎么编程_求用vc++编程实现显示灰度直方图的详细步骤,越详细越好...
  10. HTML之我的个人主页
  11. macOS pages 插入公式快捷键
  12. 选择正规的资质好的期货公司开户
  13. 2007年大连软件出口全国第三 荣获中国软件出口(外包)政府推进奖
  14. 最新京东短信登录,免费送JDCK获取短信登录
  15. 测试脂肪的软件叫,智能健康监测app
  16. mybatis show sql 打印 SQL 语句到控制台
  17. osgEarth配置地图资源
  18. vue八角云台控制组件萤石云less
  19. Ubuntu16.04 安装 wechat
  20. 破解NET的四大神器(转)

热门文章

  1. Warm Audio现场:Trope - Lambs - WA47电子管话筒
  2. Sci-Hub最新网址
  3. CRCC铁路产品认证
  4. 2022 Robocom 本科组省赛 RC-u3 跑团机器人
  5. 一套次世代建模的流程是怎样的?资深游戏建模师分享月薪3W技术
  6. 电脑硬件工程师怎么考证
  7. java catch throwable_如何处理异常? catch Exception OR catch Throwable
  8. R语言分析分析大数据的一些问题
  9. 为何场效应管要用UGD与UGS(off)来比较判断夹断情况?
  10. 作业调度和进程调度的辨析