FPGA RGB565的LCD显示屏驱动(Verilog)
文章目录
- 1屏幕
- 2行场扫描时序
- 3分析
- 4代码
- 4-1产生9M驱动时钟
- 4-2驱动部分
- 4-3显示内容部分
- 4-3顶层
- 5结果
- 5-1
- 5-2
- 6Testbench
1屏幕
使用像素:480*272的一块RGB565屏幕。
像素时钟:9Mhz
接口:
lcd_bl:lcd背光lcd_rgb[15:0]:色彩值lcd_de:当计数器处于valid(有效)区域时应将其拉高,此时输出lcd_rgb[15:0]的值到屏幕的对应像素点上。lcd_hs:可一直将其拉高没有影响lcd_vs:可一直将其拉高没有影响lcd_pclk:9M时钟lcd_rst:lcd单独复位低电平有效
2行场扫描时序
3分析
1、利用ip核倍分频获得9M时钟。
2、使用子母两个计数器对驱动时钟进行计数。
3、子计数器的计数范围为0-524,所代表一个行扫描周期,满载时在下一个时钟周期清零,并使母计数器+1。
4、母计数器的计数范围为0-285,所代表一个场扫描周期,满载时在下一个时钟周期清零。
5、利用组合逻辑将子母俩个计数的计数值做范围限定,确定真正valid的范围。
6、当计数值处于真正valid的范围时,需要回传当前的坐标值,用户根据回传的坐标值设置RGB565的色彩值。
4代码
4-1产生9M驱动时钟
-其端口列表如下:
module pll_9m (areset,//注意:其为高电平复位inclk0,//输入时钟c0, //输出时钟locked //稳定锁:当c0输出稳定时locked会从低电平变为高电平);
4-2驱动部分
module lcd_driver(input lcd_clk, //lcd模块驱动时钟input sys_rst_n, //复位信号//下列信号与RGBLCD屏幕相连接 output lcd_hs, //LCD 行同步信号output lcd_vs, //LCD 场同步信号output lcd_de, //LCD 数据使能output [15:0] lcd_rgb, //LCD RGB565颜色数据output lcd_bl, //LCD 背光控制信号output lcd_rst, //LCD 复位信号output lcd_pclk, //LCD 采样时钟//接口信号,此模块推出valid坐标值,并接收用户发来的RGB565的像素点颜色值 input [15:0] pixel_data, //像素点数据output [10:0] pixel_xpos, //像素点横坐标output [10:0] pixel_ypos //像素点纵坐标); //参数列表parameter H_SYNC = 11'd41; //行同步parameter H_BACK = 11'd2; //行显示后沿parameter H_DISP = 11'd480; //行有效数据parameter H_FRONT = 11'd2; //行显示前沿parameter H_TOTAL = 11'd525; //行扫描周期parameter V_SYNC = 11'd10; //场同步parameter V_BACK = 11'd2; //场显示后沿parameter V_DISP = 11'd272; //场有效数据parameter V_FRONT = 11'd2; //场显示前沿parameter V_TOTAL = 11'd286; //场扫描周期//子母两个计数器 reg [10:0] cnt_h;reg [10:0] cnt_v;//...wire lcd_en;wire data_req; //对lcd屏幕的某些信号加以固定assign lcd_bl = 1'b1; assign lcd_rst = 1'b1; assign lcd_pclk = lcd_clk; assign lcd_hs = 1'b1; assign lcd_vs = 1'b1; //当子母计数器的值处于valid范围内时,将lcd_de拉高,此时输出lcd_rgb[15:0]的值到屏幕的对应像素点上。assign lcd_de = lcd_en; assign lcd_en = (((cnt_h > H_SYNC+H_BACK) && (cnt_h <= H_SYNC+H_BACK+H_DISP))&&((cnt_v > V_SYNC+V_BACK) && (cnt_v <= V_SYNC+V_BACK+V_DISP)))? 1'b1 : 1'b0;//lcd_rgb[15:0]的值由用户(input)给予即为:pixel_data assign lcd_rgb = lcd_en ? pixel_data : 16'd0;//...此处做一个简单的分析,lcd_de拉高,lcd_rgb[15:0]的值瞬间到达屏幕的对应像素点上。// 我们最开始的分析是:cnt值->产生坐标->根据坐标确认有效范围->再往范围里放颜色值// 所以说我们在上面写的那个就是有效范围,由于触发器的特性,所以要提前一个时钟周期将坐标值送出,才来的及在lcd_en为1时候准确的送出颜色值// 而一场是由很多行组成的,母计数器,要比子计数器慢。子计数器变很多次,母计数器才变一次。所以对子计数器需要提前一个时钟周期发送出坐标。// PS:如果没懂的话也没关系,因为我也比较晕。但只要时序对,屏幕就能出现颜色然后进行simulation或者实物调试assign data_req = (((cnt_h > H_SYNC+H_BACK-1'b1) && (cnt_h <= H_SYNC+H_BACK+H_DISP-1'b1)) //对子计数器需要提前一个时钟周期发送出坐标。&& ((cnt_v > V_SYNC+V_BACK) && (cnt_v <= V_SYNC+V_BACK+V_DISP))) //母计数器不变? 1'b1 : 1'b0;//当前像素点坐标 assign pixel_xpos = data_req ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 11'd0;assign pixel_ypos = data_req ? ((cnt_v - (V_SYNC + V_BACK - 1'b1)) - 1'b1) : 11'd0;//这块为什么有个-1 在最下面的测试图片中可以看到解释//行计数器对像素时钟计数(子)always @(posedge lcd_clk or negedge sys_rst_n) begin if (!sys_rst_n)cnt_h <= 11'd0; else beginif(cnt_h < H_TOTAL - 1'b1) cnt_h <= cnt_h + 1'b1; else cnt_h <= 11'd0; endend//场计数器对行计数(母)always @(posedge lcd_clk or negedge sys_rst_n) begin if (!sys_rst_n)cnt_v <= 11'd0; else if(cnt_h == H_TOTAL - 1'b1) beginif(cnt_v < V_TOTAL - 1'b1) cnt_v <= cnt_v + 1'b1; else cnt_v <= 11'd0; endendendmodule
4-3显示内容部分
module lcd_display(input lcd_clk, //lcd驱动时钟input sys_rst_n, //复位信号input [10:0] pixel_xpos, //像素点横坐标input [10:0] pixel_ypos, //像素点纵坐标 output reg [15:0] pixel_data //像素点数据); localparam WHITE = 16'b11111_111111_11111; //RGB565 白色
localparam BLACK = 16'b00000_000000_00000; //RGB565 黑色
localparam RED = 16'b11111_000000_00000; //RGB565 红色
localparam GREEN = 16'b00000_111111_00000; //RGB565 绿色
localparam BLUE = 16'b00000_000000_11111; //RGB565 蓝色
localparam BROWN = 16'h7800; //RGB565 棕色//测试边框always @(posedge lcd_clk or negedge sys_rst_n) begin if (!sys_rst_n)pixel_data <= 16'hffff;else beginif(pixel_xpos == 11'd1) pixel_data <= GREEN; else if(pixel_xpos == 11'd480)pixel_data <= GREEN;else if(pixel_xpos == 11'd240)pixel_data <= GREEN; else if(pixel_ypos == 11'd1)pixel_data <= GREEN; else if(pixel_ypos == 11'd272)pixel_data <= GREEN; else if(pixel_ypos == 11'd136)pixel_data <= GREEN; else pixel_data <= BROWN;endend//彩条// always @(posedge lcd_clk or negedge sys_rst_n) begin // if (!sys_rst_n)// pixel_data <= 16'hffff;// else begin// if((pixel_xpos >= 1) && (pixel_xpos < (11'd480/5)*1)) // pixel_data <= GREEN; // else if((pixel_xpos >= (11'd480/5)*1) && (pixel_xpos < (11'd480/5)*2))// pixel_data <= BLACK; // else if((pixel_xpos >= (11'd480/5)*2) && (pixel_xpos < (11'd480/5)*3))// pixel_data <= RED; // else if((pixel_xpos >= (11'd480/5)*3) && (pixel_xpos < (11'd480/5)*4))// pixel_data <= BLUE; // else // pixel_data <= BROWN;// end// endendmodule
4-3顶层
module lcd_rgb_colorbar(input sys_clk, input sys_rst_n, output lcd_hs, output lcd_vs, output lcd_de, output [15:0] lcd_rgb, output lcd_bl, output lcd_rst, output lcd_pclk );wire lcd_clk_w;
wire locked_w;
wire rst_n_w;
wire [15:0] pixel_data_w;
wire [ 9:0] pixel_xpos_w;
wire [ 9:0] pixel_ypos_w; //待PLL输出稳定之后,停止复位
assign rst_n_w = sys_rst_n & locked_w;pll_9m u_lcd_pll( //时钟分频模块.inclk0 (sys_clk), .areset (~sys_rst_n),.c0 (lcd_clk_w), //lcd驱动时钟.locked (locked_w)); lcd_driver u_lcd_driver( //lcd驱动模块.lcd_clk (lcd_clk_w), .sys_rst_n (rst_n_w), .lcd_hs (lcd_hs), .lcd_vs (lcd_vs), .lcd_de (lcd_de), .lcd_rgb (lcd_rgb),.lcd_bl (lcd_bl),.lcd_rst (lcd_rst),.lcd_pclk (lcd_pclk),.pixel_data (pixel_data_w), .pixel_xpos (pixel_xpos_w), .pixel_ypos (pixel_ypos_w)); lcd_display u_lcd_display( //lcd显示模块.lcd_clk (lcd_clk_w), .sys_rst_n (rst_n_w),.pixel_xpos (pixel_xpos_w),.pixel_ypos (pixel_ypos_w),.pixel_data (pixel_data_w)); endmodule
5结果
5-1
可以看到,测试中出现了列偏移(1-480)*(0~271),所以对代码进行修整
见上面代码中的这一句:
5-2
OK!(1-480)*(1~272)
6Testbench
给予时钟激励,观察信号关系即可。
FPGA RGB565的LCD显示屏驱动(Verilog)相关推荐
- 基于FPGA的LCD1602显示屏驱动
一.LCD1602显示原理 1.引脚功能 其内部功能框图如下图所示: 一般来说,LCD1602有16条引脚,各个厂家的LCD1602可能略有不同,但基本上一样,其16个引脚功能如下: LCD1602引 ...
- FPGA实现LCD显示屏显示彩条
目录 总体设计 读显示屏ID 读显示屏ID代码 时钟分频 时钟分频代码 LCD显示 lcd显示模块 LCD驱动模块 lcd驱动代码 顶层模块 顶层模块代码 总体设计 系统总体分为五个模块,分别是:rd ...
- 晶联讯JLX12864G-086-PC-3S LCD显示屏 C51驱动代码
晶联讯JLX12864G-086-PC-3S LCD显示屏 C51驱动代码 //7.1.2 例程:以下为串行方式显示汉字及 ASCII 字符的例程: //液晶屏型号:JLX12864G-086-PC- ...
- LCD显示--Ht1621b芯片显示屏驱动
Ht1621b芯片显示屏驱动 关于HT1621b芯片的详细信息可以参考数据手册上的内容:百度文库HT1621b中文资料 CS : 片选输入接一上拉电阻当/CS 为高电平读写HT1621的数据和命令无效 ...
- 基于FPGA的iic主从机驱动实现 Verilog实现iic slave和iic master
基于FPGA的iic主从机驱动实现 Verilog实现iic slave和iic master 顶层模块实现master对slave自定义的寄存器读取 带仿真模块 ID:153069768739840 ...
- FPGA接口_N25Q128型号的spi flash驱动verilog代码编写
# N25Q128型号的spi flash驱动verilog代码编写 提示:使用正点原子达芬奇pro做的小例子,由于教程中无flash的读写,因此撰写记录 文章目录 # N25Q128型号的spi f ...
- 关于STM32驱动LCD显示屏,程序下载后白屏、乱码需要上电复位才能恢复正常问题的解决办法
解决方法: 在显示屏初始化前加一定延时,比如100ms,因为单片机复位时间比LCD显示屏短,可能会造成显示屏未复位完就被单片机操作的问题,如果是CUBEMX配置的工程,需要找到生成代码关于显示屏初始化 ...
- linux的LCD的驱动编写
Framebuffer设备 Framebuffer 翻译过来就是帧缓冲,简称 fb,因 此大家在以后的 Linux 学习中见到"Framebuffer"或者"fb&q ...
- 全志 Tina Linux LCD显示屏调试指南 支持MIPI DSI RGB LVDS I8080 SPI等接口,开发板支持百问网T113 D1-H哪吒 DongshanPI-D1s V853
1 概述 编写目的 本文档将介绍sunxi 平台Display Engine 模块中LCD 的调试方法. LCD 调试方法,调试手段. LCD 驱动编写. lcd0 节点下各个属性的解释. 典型LCD ...
最新文章
- CentOS网络配置
- Android stadio 调试太掉了
- 怎么查交集_胃镜要不要查?
- 高通平台点亮LCD个人总结
- 从手机App到网点交互请求的日志记录
- 打勾显示输入的密码 --EditText与setTransformationMethod
- 编程挑战:字符串的完美度
- The Everyman's Guide to How Network Packets Are Routed Across the Web
- java正则匹配的坑_java正则表达式入坑指南
- 在开发环境中,自己搭建一个ssl环境(小例子)
- was连接oracle rac集群,Oracle 学习之RAC(九) 集群负载均衡及故障转移
- 移动网络新漏洞影响2G 以来的所有蜂窝网络
- Support Vector Machines
- 学习总结 java基础
- java case when多分支判断_Apache Spark之单分支CaseWhen优化为IF
- 文字图片灰度化matlab,采用matlab将图像灰度化的方法
- 免费客户旅程(Customer Journey Mapping) 示例总汇
- 英雄联盟服务器维护2019.4.5,lol维护公告最新时间 英雄联盟11.9版本4月29日更新内容...
- 数学Ⅰ基础复习(六)
- [TypeScript]中字符和ASCII码转换
热门文章
- 【bioinfo】酶切法片段化建库相比超声打断建库引入softclip使用FADE软件识别/去除
- 【转载】缓存策略-Cache aside旁路缓存
- NOI题库4.3 1526 宗教信仰
- PB中的像素与PBU之间的转换
- 点云降采样--ApproximateVoxelGrid点云降采样
- Stable Diffusion 用2D图片制作3D动态壁纸
- 如何提高(编程)学习效率的三个心得感受
- 一个好玩有趣的Python手绘图形库(雷达图、柱状图、折线图...)
- 计通智能监控管理平台V7.0通过华为官方技术认证
- VR全景诚邀您走进2019中国北京世界园艺博览会(可在线体验)