软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
1概述
前文中,我们已经实现了HDMI输出实验,米联客的HDMI输出采用了FPGA实现了HDMI输出协议,直接驱动了HDMI接口的液晶屏。我们可以把HDMI输出IP看作一个黑盒子,黑盒子的接口是RGB输入接口,输出是HDMI接口输出。不管是HDMI接口,或者是VGA接口,亦或是RGB接口等等...关键的是让程序正确输出RGB时序。对于本文中使用的液晶屏,可以通过RGB接口直接驱动液晶屏,也可以通过LVDS驱动液晶屏,如果使用LVDS接口,也是首先要正确输出RGB的驱动时序。 米联客的液晶屏同时支持RGB接口和LVDS接口,RGB接口是3.3V IO,LVDS接口支持标准的LVDS和LVDS25。用户在使用液晶屏的时候一定要根据开发板支持的电平选择对应的驱动接口,以免损坏液晶屏或者开发板。 液晶屏参数: 型号 | VCLD-7TH | 液晶显示屏型号 | T HC63LVDM83D | 液晶分辨率 | 1024*600 | 液晶屏幕比例 | 4:3 | 液晶驱动接口 | RGB/VGA | 触摸芯片型号 | GP915 | 支持触点数量 | 5 | 支持最大分辨率 | 1024*600 | 2LCD液晶屏参数
以上参数中液晶屏支持分辨率为1024*600,使用的接口是LVDS接口。我们做的液晶屏产品增加的RGB转LVDS芯片所以也支持RGB接口驱动液晶屏,对于一些新手来说,RGB接口更加方便,而且RGB是3.3V的接口。 3LCD液晶屏驱动时序
本实验以8bit LVDS 方式工作,下图中给出了6bit和8bit的工作时序,FPGA程序设计需要满足以下时序。另外注意,时钟的占空比,高电平:低电平=4:3
4LCD液晶屏接口 RGB接口定义 | 引脚号 | 标识 | 描述 | 类型 | 1 | CTP_INT | 触摸中断 | 输出 | 2 | CTP_RST | 触摸复位 | 输入 | 3 | CTP_SDA | I2C数据脚 | 输入/输出 | 4 | CTP_SCL | I2C时钟脚 | 输出入 | 5 | GND | 电源地 | 电源 | 6 | PWM | PWM调光 | 输入 | 7 | DE | 数据有效 | 输入 | 8 | VSYNC | 场同步 | 输入 | 9 | HSYNC | 行同步 | 输入 | 10 | BL-EN | 背光使能 | 输入 | 11 | PCLK | 像素时钟 | 输入 | 12 | GND | 电源地 | 电源 | 13~20 | B0~B7 | 数据 | 输入 | 21~28 | G0~G7 | 数据 | 输入 | 29~36 | R0~R7 | 数据 | 输入 | 37 | VDD | 电源3.3V | 电源 | 38 | GND | 电源地 | 电源 | 39 | BL_VDD | 电源5V | 电源 | 40 | BL_VDD | 电源5V | 电源 |
LVDS接口定义
| 引脚号 | 标识 |
| 类型 | 1~3 | BL-5V | 电源5V | 电源 | 4 | NC | 悬空 |
| 5 | BL-EN | 背光使能 | 输入 | 6 | PWM | PWM调光 | 输入 | 7 | NC | 悬空 |
| 8~10 | BL-GND | 电源地 | 电源 | 11 | GND | 电源地 | 电源 | 12 | CTP_INT | 触摸中断 | 输出 | 13 | CTP_RST | 触摸复位 | 输入 | 14 | CTP_SCL | I2C时钟脚 | 输入 | 15 | CTP_SDA | I2C数据脚 | 输入/输出 | 16 | GND | 电源地 | 电源 | 17~18 | NC | 悬空 |
| 19 | GND | 电源地 | 电源 | 20/21 | RXIN3+/ RXIN3- | 差分数据 | 输入 | 22 | GND | 电源地 | 电源 | 23/24 | RXCLKIN+/ RXCLKIN - | 差分时钟 | 输入 | 25 | GND | 电源地 | 电源 | 26/27 | RXIN2+/ RXIN2- | 差分数据 | 输入 | 28 | GND | 电源地 | 电源 | 29/30 | RXIN1+/ RXIN1- | 差分数据 | 输入 | 31 | GND | 电源地 | 电源 | 32/33 | RXIN0+/ RXIN0- | 差分数据 | 输入 | 34~36 | GND | 电源地 | 电源 | 37~39 | VDD | 电源3.3V | 电源 | 40 | NC | 悬空 |
| 5硬件电路分析硬件接口和子卡模块请阅读“附录 1” 配套工程的 FPGA PIN 脚定义路径为 fpga_prj/uisrc/04_pin/ fpga_pin.xdc。 6系统框图
7 LVDS接口显示程序默认液晶屏是直接支持LVDS信号驱动,而不支持RGB驱动,所以如果从省硬件IO资源以及省成本角度,LVDS成本更低。但是LVDS对于FPGA支持有要求,XILINX 的FPGA支持LVDS25和标准LVDS。而一般的开发板IO电平为3.3V所以一般情况下,开发板默认不能支持LVDS输出。米联客的开发板如果支持3.3V默认输出的,需要修改核心板的ADJ电阻实现2.5V或者1.8V输出,修改后就可以使用LVDS驱动液晶屏。用户选购板卡使用液晶的时候需要清楚知道自己的IO电平。 LVDS接口驱动适合FEP扩展接口是1.8V的IO电平的开发板。支持LVDS电平,DIFF_SSTL18_I电平标准。本文中代码还调用了RGB转LVDS接口的代码,对于RGB转LVDS部分的代码本文不做分析。 - /*************LCD 视频输出测试*************
- --版本号1.1
- --使用VTC产生视频时序
- --使用TPG产生测试图像数据
- --使用RGB转LVDS IP 点亮LCD
- *********************************************************************/
- `timescale 1ns / 1ns //仿真时间刻度/精度
- module display(
- input I_sysclk_p,
- input I_sysclk_n, //系统时钟输入
- output O_lcd_clk_p, //LCD LVDS 时钟输出P
- output O_lcd_clk_n, //LCD LVDS 时钟输出N
- output [3:0] O_lcd_d_p, //LCD LVDS 数据输出P
- output [3:0] O_lcd_d_n, //LCD LVDS 数据输出N
- output O_lcd_pwm,
- output wire O_card_power_en //背光PWM
- );
- wire I_clk;
- IBUFGDS CLK_U(
- .I(I_sysclk_p),
- .IB(I_sysclk_n),
- .O(I_clk)
- );
- wire vid_rstn,vid_clk,vid_clkx7,vid_vs,vid_hs,vid_de;
- wire[7:0]lcd_r,lcd_g,lcd_b;
- assign O_card_power_en = 1'b1;
- assign O_lcd_pwm = 1'b1;//设置背光PWM,设置1背光全开
- //MMCM/PLL 时钟模块
- clk_wiz_0 u_clk(.clk_in1(I_clk),.clk_out1(vid_clk),.clk_out2(vid_clkx7),.locked(vid_rstn));
- //例化uivtc VTC 产生视频时序,液晶屏分辨率1024*600
- uivtc#
- (
- .H_ActiveSize(1024), //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素
- .H_FrameSize(1024+24+136+143), //视频时间参数,行视频信号,一行视频信号总计占用的时钟数
- .H_SyncStart(1024+24), //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号
- .H_SyncEnd(1024+24+136), //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行有效数据部分
- .V_ActiveSize(600), //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSize
- .V_FrameSize(600+1+1+26), //视频时间参数,场视频信号,一帧视频信号总计占用的行数量
- .V_SyncStart(600+1), //视频时间参数,场同步开始,即多少行数后开始产生场同步信号
- .V_SyncEnd (600+1+1) //视频时间参数,场同步结束,即多少行数后停止产生场同步信号,之后就是场有效数据部分
- )
- uivtc_inst
- (
- .I_vtc_clk(vid_clk),//系统时钟,像素时钟
- .I_vtc_rstn(vid_rstn),//系统复位
- .O_vtc_vs(vid_vs),//场同步输出
- .O_vtc_hs(vid_hs),//行同步输出
- .O_vtc_de_valid(vid_de), //视频数据有效
- .O_vtc_user(), //满足stream时序产生 user 信号,用于帧同步
- .O_vtc_last() //满足stream时序产生 later 信号,用于每行结束
- );
- //例化TPG 产生测试视频数据
- uitpg uitpg_inst
- (
- .I_tpg_clk(vid_clk),//系统时钟,像素时钟
- .I_tpg_rstn(vid_rstn),//系统复位
- .I_tpg_vs(vid_vs),//场同步输入
- .I_tpg_hs(vid_hs),//行同步输入
- .I_tpg_de(vid_de),//视频数据有效
- .O_tpg_vs(),
- .O_tpg_hs(),
- .O_tpg_de(),
- .O_tpg_data({lcd_r,lcd_g,lcd_b})//测试图像数据输出
- );
- //例化uilcd2lvds,实现内部RGB数据转为LVDS接口液晶屏数据
- uilcd2lvds uilcd2lvds_inst
- (
- .I_rst_n(vid_rstn), //系统复位
- .I_clk_350MHz (vid_clkx7), // 像素7倍时钟
- .I_clk_50MHz (vid_clk), // 像素1倍时钟
- .I_lcd_de (vid_de), // 视频数据有效
- .I_lcd_red (lcd_r), // RED
- .I_lcd_green (lcd_g), // GREEN
- .I_lcd_blue (lcd_b), // BLUE
- .O_lcd_clk_p (O_lcd_clk_p), // LCD差分时钟输出 P端
- .O_lcd_clk_n (O_lcd_clk_n), // LCD差分时钟输出 N端
- .O_lcd_d_p (O_lcd_d_p), // LCD差分输出输出 P端
- .O_lcd_d_n (O_lcd_d_n) // LCD差分输出输出 N端
- );
- endmodule
复制代码
8 RGB转LVDS驱动液晶屏代码uilcd2lvds.v - *********************************************************************/
- /*********uilcd2lvds 液晶屏RGB转LVDS输出***********
- --实现RGB转LVDS输出,时钟和数据速度比为1:7
- *********************************************************************/
- `timescale 1ns/1ps
- module uilcd2lvds
- (
- // 全局时钟和复位信号
- input I_rst_n, // 复位信号,低电平有效
- input I_clk_350MHz, // 350MHz
- input I_clk_50MHz, // 50MHz
-
- //LCD接口信号,RGB时序
- input I_lcd_de, // LCD数据使能信号,高电平有效
- input [7:0] I_lcd_red, // LCD R分量数据
- input [7:0] I_lcd_green, // LCD G分量数据
- input [7:0] I_lcd_blue, // LCD B分量数据
-
- //LVDS接口信号
- output O_lcd_clk_p, // 差分输出P LVDS接口时钟,50MHz
- output O_lcd_clk_n, // 差分输出N
-
- output [3:0] O_lcd_d_p, // 差分输出P
- output [3:0] O_lcd_d_n // 差分输出N
- );
- //----------------------------------------------------------------------
- // LVDS LCD信号输出
- wire lcd_clk; //LVDS LCD时钟
- wire [7:0] I_lcd_red; //RGB 红
- wire [7:0] I_lcd_green; //RGB 绿
- wire [7:0] I_lcd_blue; //RGB 蓝
- //信号转换下命名,主要为了简化写法
- wire [7:0] R = I_lcd_red;
- wire [7:0] G = I_lcd_green;
- wire [7:0] B = I_lcd_blue;
- //典型LVDS时序,先把RGB格式转为典型时序,转为LVDS依次输出
- wire [6:0] lvds_ind0 = {G[0] , R[5], R[4], R[3], R[2], R[1], R[0]};
- wire [6:0] lvds_ind1 = {B[1] , B[0], G[5], G[4], G[3], G[2], G[1]};
- wire [6:0] lvds_ind2 = {I_lcd_de , 1'b0, 1'b0, B[5], B[4], B[3], B[2]};
- wire [6:0] lvds_ind3 = {1'b0 , B[7], B[6], G[7], G[6], R[7], R[6]};
- //LVDS数据发送模块例化
- lvds_tx u_lvds_tx
- (
- .I_rst_n (I_rst_n ), //复位输入
- .I_clk_50MHz (I_clk_50MHz ), //50M时钟输入
- .I_clk_350MHz (I_clk_350MHz ), //7倍50M时钟输入
- .I_lvds_ind0 (lvds_ind0 ), //串行通道0数据
- .I_lvds_ind1 (lvds_ind1 ), //串行通道1数据
- .I_lvds_ind2 (lvds_ind2 ), //串行通道2数据
- .I_lvds_ind3 (lvds_ind3 ), //串行通道3数据
- .O_dout ({lcd_data3,lcd_data2,lcd_data1,lcd_data0} ), //串行通道数据输出,时钟速度是lvds_ind0~lvds_ind3的7倍
- .O_outclock (lcd_clk ) //50M时钟以4:3占空比输出
- );
- //----------------------------------------------------------------------
- // 通过原语实现单端信号转差分信号
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // I/O电平标准
- .SLEW("SLOW")
- )
- u_clk_OBUFDS (
- .O (O_lcd_clk_p ),
- .OB (O_lcd_clk_n ),
- .I (lcd_clk )
- );
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // I/O电平标准
- .SLEW("SLOW")
- )
- u_d0_OBUFDS (
- .O (O_lcd_d_p[0] ),
- .OB (O_lcd_d_n[0] ),
- .I (lcd_data0 )
- );
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // I/O电平标准
- .SLEW("SLOW")
- )
- u_d1_OBUFDS (
- .O (O_lcd_d_p[1] ),
- .OB (O_lcd_d_n[1] ),
- .I (lcd_data1 )
- );
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // I/O电平标准
- .SLEW("SLOW")
- )
- u_d2_OBUFDS (
- .O (O_lcd_d_p[2] ),
- .OB (O_lcd_d_n[2] ),
- .I (lcd_data2 )
- );
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // I/O电平标准
- .SLEW("SLOW")
- )
- u_d3_OBUFDS (
- .O (O_lcd_d_p[3] ),
- .OB (O_lcd_d_n[3] ),
- .I (lcd_data3 )
- );
- endmodule
复制代码
lvds_tx.v代码中给的50M和350M实际是7倍关系,不一定必须标准的50M,关键是满足7倍关系。这个和LVDS输出时序有关系。
9硬件连线(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。) 本实验注意采我们的cep跳线帽跳线1.8V,子卡采用1.8V BASE卡,接口使用的是我们液晶屏的LVDS口。下图是LVDS接线方式。请确保下载器和开发板已经正确连接,另外需要把核心板上的2P模式开关设置到JTAG模式,即ON ON,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)
7寸液晶屏的接口使用的是LVDS接口
10测试结果
|