FPGA_WebLab/public/doc/06/doc.md

650 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 基础-6-HDMI显示
## 6.1 章节导读
随着多媒体技术的快速发展高清显示已成为嵌入式系统与FPGA应用中不可或缺的一部分。HDMIHigh-Definition Multimedia Interface作为目前最主流的视频数字传输标准广泛应用于电视、显示器、笔记本、摄像头等各类终端设备中。相比传统的模拟VGA接口HDMI具有传输带宽高、支持音视频同步、无压缩信号传输等优点能更好地满足现代图像处理和显示系统的需求。
在FPGA开发中掌握HDMI显示技术不仅是实现图像/视频输出的基础能力更是后续图像识别、视频监控、图形用户界面GUI等复杂系统设计的前提。因此本实验以HDMI显示为核心内容带领大家从零开始构建一个完整的视频输出链路。通过配置显示参数、生成时序控制信号、输出RGB图像数据等关键步骤最终实现在HDMI接口上稳定输出画面。
在本次实验中我们将学习利用实验板的HDMI接口和MS7210芯片进行HDMI显示实验的设计。
## 6.2 理论学习
### 6.2.1 VGA时序
VGA显示是在行同步和帧同步场同步的信号同步下按照从上到下从左到右的顺序扫描到显示屏上。VGA扫描方式见下图所示
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/1.png"
alt="无法显示图片时显示的文字"
style="zoom:50%"/>
<br> <!--换行-->
图1.VGA扫描顺序 <!--标题-->
</center>
</div>
如上图所示每一帧图像都是从左上角开始逐行扫描形成所以规定最左上角的像素点为第一个像素点坐标是00以这个像素为起点向右x坐标逐渐增大向下y坐标逐渐增大重复若干次后扫描到右下角完成一帧图像的扫描扫描完成后进行图像消隐随后指针跳回左上角重新进行新一帧的扫描。
在扫描的过程中会对每一个像素点进行单独赋值使每个像素点显示对应色彩信息当扫描速度足够快加之人眼的视觉暂留特性我们会看到一幅完整的图片这就是VGA 显示的原理。
VGA显示除了要有像素点的信息还需要有行同步HSync和场同步VSync两个信号辅助显示。行同步信号规定了一行像素的开始与结束场同步信号规定了一帧图像的开始与结束。在VESA DMT 1.12版本的标准文档中给出的VGA时序图如下图所示
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/2.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图2.VGA标准时序 <!--标题-->
</center>
</div>
行同步时序如下图所示:
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/3.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图3.行同步时序 <!--标题-->
</center>
</div>
行同步的一个扫周期要经过6个部分分别是Sync同步、 Back Porch后沿、 Left Border左边框、 “Addressable” Video有效图像、 Right Border右边框、 Front Porch前沿这些过程的长度都是以像素为单位的也就是以像素时钟为单位例如Sync的值为96也就意味着Sync阶段要经历96个像素时钟。HSync信号会在Sync同步阶段拉高不同的芯片可能有不同标准以确定新一行的开始与上一行的结束。而完整的一行像素很多但有效的真正能显示在屏幕上的像素只有 “Addressable” Video有效图像部分的像素其他阶段的像素均无效无法显示在屏幕中。
场同步时序如下图所示:
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/4.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图4.场同步时序 <!--标题-->
</center>
</div>
场同步时序与行同步时序相同也是分为6个部分在Sync同步阶段拉高标志着一帧的结束和新一帧的开始其中像素只有在“Addressable” Video有效图像阶段才有效其他阶段均无效。而场同步信号的基本单位是行比如Sync的值为2也就意味着Sync同步阶段要经历两行。
那么我们将行同步和场同步信号结合起来,遍可以得到一帧图像的样貌,如下图所示:
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/5.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图5.一帧图像组成示意图 <!--标题-->
</center>
</div>
可以看到在行场同步信号构成了一个二维坐标系,原点在左上方,中间遍形成了一帧图像,而真正能显示在屏幕中的图像只有 “Addressable” Video有效图像部分。
现在我们知道了行同步和场同步都要经历6个部分那么这些部分的长度都是如何规定的呢VGA 行时序对行同步时间、 消隐时间、 行视频有效时间和行前肩时间有特定的规范, 场时序也是如此。 常用VGA 分辨率时序参数如下表所示:
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/6.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图6.常用VGA分辨率时序参数 <!--标题-->
</center>
</div>
### 6.2.2 MS7210芯片
MS7210是一款HD发送芯片支持4K@30Hz的视频3D传输格式。可以支持的最高分辨率高达4K@30Hz最高采样率达到300MHz。MS7210支持YUV和RGB 之间的色彩空间转换数字接口支持YUV以及RGB格式输入。MS7210的IIS接口以及S/PDIF 接口支持高清音频的传输其中S/PDIF接口既可以兼容IEC61937标准下的压缩音频传输同时还支持高比特音频HBR的传输在高比特音频HBR模式下音频采样率最高为768KHz。MS7210的IIC 地址可以根据SA引脚进行选择。当 SA引脚上拉到电源电压或者悬空时地址为 OxB2。当 SA 引脚连接到 GND 时地址为0x56。
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/7.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图7.MS7210芯片 <!--标题-->
</center>
</div>
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/8.png"
alt="无法显示图片时显示的文字"
style="zoom:50%"/>
<br> <!--换行-->
图8.MS7210功能框图 <!--标题-->
</center>
</div>
MS7210芯片可以通过IIC协议对内部寄存器进行配置有关芯片寄存器配置需要向芯片厂家进行申请。
## 6.3 实战演练
### 6.3.1实验目标
### 6.3.2硬件资源
实验板共有一个HDMI-OUT接口由MS7210驱动一个HDMI-IN接口由MS7200驱动。
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/9.png"
alt="无法显示图片时显示的文字"
style="zoom:30%"/>
<br> <!--换行-->
图9.板载HDMI芯片 <!--标题-->
</center>
</div>
实验箱配备一个小型HDMI显示器该显示器HDMI接口与HDMI-OUT接口连接图像可以显示在显示屏中通过摄像头可以在网站观察现象
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/xxx.png"
alt="实验箱显示器"
style="zoom:40%"/>
<br> <!--换行-->
图10.实验箱显示器 <!--标题-->
</center>
</div>
### 6.3.3程序设计
在设计程序时我们先对本实验工程有一个整体认知首先来看一下HDMI彩条显示实验的整体框图。
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/xxxx.png"
alt="实验箱显示器"
style="zoom:40%"/>
<br> <!--换行-->
图11.HDMI彩条显示整体框图 <!--标题-->
</center>
</div>
可见整个实验一共由好多个模块组成,下面是各个模块简介
| 模块名称 |功能描述| 备注 |
|:----:|:----:|:----:|
| hdmi_top | 顶层模块 ||
| ms7210_ctrl_iic_top | ms7210芯片配置和iic顶层模块 |参考小眼睛例程|
| ms7210_ctl | ms7210芯片配置和时序控制模块 |使用小眼睛例程|
| iic_dri | iic驱动模块 |使用小眼睛例程|
| vga_ctrl | vga时序信号生成模块 |参考野火例程|
| vga_pic | vga像素数据生成模块 |参考野火例程|
本次实验主要完成vga_ctrl和vga_pic模块的设计。
对于vga_ctrl模块我们主要完成hsyncvsync信号xy坐标数据有效rgb_valid信号的设计。经过我们前面的学习已经对vga时序有了一定的了解我们可以想象到这几个信号也只是一种计数器而已。
本实验要实现640x480的彩条显示相关参数如下所示
```Verilog
//parameter define
parameter H_SYNC = 10'd96 , //行同步
H_BACK = 10'd40 , //行时序后沿
H_LEFT = 10'd8 , //行时序左边框
H_VALID = 10'd640 , //行有效数据
H_RIGHT = 10'd8 , //行时序右边框
H_FRONT = 10'd8 , //行时序前沿
H_TOTAL = 10'd800 ; //行扫描周期
parameter V_SYNC = 10'd2 , //场同步
V_BACK = 10'd25 , //场时序后沿
V_TOP = 10'd8 , //场时序上边框
V_VALID = 10'd480 , //场有效数据
V_BOTTOM = 10'd8 , //场时序下边框
V_FRONT = 10'd2 , //场时序前沿
V_TOTAL = 10'd525 ; //场扫描周期
```
首先设计两个计数器`cnt_h`和`cnt_v`分别对像素和行进行计数,一个像素时钟过后`cnt_h`加一,一行过后`cnt_v`加一,扫描完一帧之后,计数器归零。
而其他的状态信号则可以根据计数器的计数进行设计。hsync信号只要`cnt_h < H_SYNC`就拉高vsync信号类似当计数到有效数据部分数据有效信号rgb_valid就可以拉高注意由于时序逻辑有一个时钟周期的反应时间所以xy的坐标变化比rgb_valid提前一个时钟周期参考代码如下所示
```verilog
`timescale 1ns/1ns
////////////////////////////////////////////////////////////////////////
// Author : EmbedFire
// 实验平台: 野火FPGA系列开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
////////////////////////////////////////////////////////////////////////
module vga_ctrl
(
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [15:0] pix_data , //输入像素点色彩信息
output wire [11:0] pix_x , //输出VGA有效显示区域像素点X轴坐标
output wire [11:0] pix_y , //输出VGA有效显示区域像素点Y轴坐标
output wire hsync , //输出行同步信号
output wire vsync , //输出场同步信号
output wire rgb_valid ,
output wire [15:0] rgb //输出像素点色彩信息
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter H_SYNC = 10'd96 , //行同步
H_BACK = 10'd40 , //行时序后沿
H_LEFT = 10'd8 , //行时序左边框
H_VALID = 10'd640 , //行有效数据
H_RIGHT = 10'd8 , //行时序右边框
H_FRONT = 10'd8 , //行时序前沿
H_TOTAL = 10'd800 ; //行扫描周期
parameter V_SYNC = 10'd2 , //场同步
V_BACK = 10'd25 , //场时序后沿
V_TOP = 10'd8 , //场时序上边框
V_VALID = 10'd480 , //场有效数据
V_BOTTOM = 10'd8 , //场时序下边框
V_FRONT = 10'd2 , //场时序前沿
V_TOTAL = 10'd525 ; //场扫描周期
//wire define
wire pix_data_req ; //像素点色彩信息请求信号
//reg define
reg [11:0] cnt_h ; //行同步信号计数器
reg [11:0] cnt_v ; //场同步信号计数器
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_h:行同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_h <= 12'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_h <= 12'd0 ;
else
cnt_h <= cnt_h + 1'd1 ;
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//cnt_v:场同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_v <= 12'd0 ;
else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
cnt_v <= 12'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_v <= cnt_v + 1'd1 ;
else
cnt_v <= cnt_v ;
//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//rgb_valid:VGA有效显示区域
assign rgb_valid = (((cnt_h >= H_SYNC + H_BACK + H_LEFT)
&& (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID))
&&((cnt_v >= V_SYNC + V_BACK + V_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_data_req:像素点色彩信息请求信号,超前rgb_valid信号一个时钟周期
assign pix_data_req = (((cnt_h >= H_SYNC + H_BACK + H_LEFT - 1'b1)
&& (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1))
&&((cnt_v >= V_SYNC + V_BACK + V_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_x,pix_y:VGA有效显示区域像素点坐标
assign pix_x = (pix_data_req == 1'b1)
? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 12'hfff;
assign pix_y = (pix_data_req == 1'b1)
? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 12'hfff;
//rgb:输出像素点色彩信息
assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;
endmodule
```
对于vga_pic模块我们可以根据x坐标范围0~639分成十份每一份输出不同的颜色参考代码如下所示
```verilog
`timescale 1ns/1ns
////////////////////////////////////////////////////////////////////////
// Author : EmbedFire
// 实验平台: 野火FPGA系列开发板
// 公司 : http://www.embedfire.com
// 论坛 : http://www.firebbs.cn
// 淘宝 : https://fire-stm32.taobao.com
////////////////////////////////////////////////////////////////////////
module vga_pic
(
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [11:0] pix_x , //输入VGA有效显示区域像素点X轴坐标
input wire [11:0] pix_y , //输入VGA有效显示区域像素点Y轴坐标
output reg [15:0] pix_data //输出像素点色彩信息
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter H_VALID = 12'd640 , //行有效数据
V_VALID = 12'd480 ; //场有效数据
parameter RED = 16'hF800, //红色
ORANGE = 16'hFC00, //橙色
YELLOW = 16'hFFE0, //黄色
GREEN = 16'h07E0, //绿色
CYAN = 16'h07FF, //青色
BLUE = 16'h001F, //蓝色
PURPPLE = 16'hF81F, //紫色
BLACK = 16'h0000, //黑色
WHITE = 16'hFFFF, //白色
GRAY = 16'hD69A; //灰色
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pix_data <= 16'd0;
else if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
pix_data <= RED;
else if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
pix_data <= ORANGE;
else if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
pix_data <= YELLOW;
else if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
pix_data <= GREEN;
else if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
pix_data <= CYAN;
else if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
pix_data <= BLUE;
else if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
pix_data <= PURPPLE;
else if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
pix_data <= BLACK;
else if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
pix_data <= WHITE;
else if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
pix_data <= GRAY;
else
pix_data <= BLACK;
endmodule
```
在顶层模块我们首先要利用PLL ip核生成iic的驱动时钟进行初始化由于ms7210芯片的需要我们通过计数设置一个延迟复位信号由于我们的彩条颜色是按照RGB565格式生成的所以需要向RGB888进行转换只需要填0补位即可同时由于板载时钟是27M与25.175M相差不大所以直接使用板载时钟作为像素时钟输出然后我们将输出的行场同步信号像素时钟像素数据像素数据有效信号等与模块相连接即可完成设计顶层模块参考代码如下
```Verilog
`timescale 1ns / 1ns
module hdmi_top(
input wire sys_clk ,// input system clock 50MHz
input rstn_in ,
output rstn_out ,
output hd_scl ,
inout hd_sda ,
output led_int ,
//hdmi_out
output pixclk_out ,//pixclk
output wire vs_out ,
output wire hs_out ,
output wire de_out ,
output wire [7:0] r_out ,
output wire [7:0] g_out ,
output wire [7:0] b_out
);
wire cfg_clk ;
wire locked ;
wire rstn ;
wire init_over ;
reg [15:0] rstn_1ms ;
//**********************************************//
//*****************MS7210初始化******************//
//**********************************************//
//**************仿真时不编译此部分***************//
`ifndef SIM
//初始化成功标志
assign led_int = init_over;
//生成10M IIC时钟
PLL u_pll (
.clkout0(cfg_clk), // output
.lock(locked), // output
.clkin1(sys_clk) // input
);
//ms7210初始化模块
ms7210_ctrl_iic_top ms7210_ctrl_iic_top_inst(
.clk ( cfg_clk ), //input clk,
.rst_n ( rstn_out ), //input rstn,
.init_over ( init_over ), //output init_over,
.iic_scl ( hd_scl ), //output iic_scl,
.iic_sda ( hd_sda ) //inout iic_sda
);
//延迟复位
always @(posedge cfg_clk)
begin
if(!locked)
rstn_1ms <= 16'd0;
else
begin
if(rstn_1ms == 16'h2710)
rstn_1ms <= rstn_1ms;
else
rstn_1ms <= rstn_1ms + 1'b1;
end
end
assign rstn_out = (rstn_1ms == 16'h2710) && rstn_in;
//**********************************************//
`else
assign led_int = 1;
assign rstn_out = rstn_in;
`endif
//**********************************************//
//**********************************************//
//**********************************************//
//**********************************************//
wire [15:0] rgb565;
wire [15:0] pix_data ;
wire [11:0] pix_x;
wire [11:0] pix_y;
//vga行场同步控制模块
vga_ctrl vga_ctrl_inst (
.vga_clk (sys_clk ),
.sys_rst_n (rstn_out ),
.pix_data (pix_data ),
.pix_x (pix_x ),
.pix_y (pix_y ),
.hsync (hs_out ),
.vsync (vs_out ),
.rgb_valid (de_out ),
.rgb (rgb565 )
);
//彩条数据生成模块
vga_pic vga_pic_inst (
.vga_clk (sys_clk ),
.sys_rst_n (rstn_out ),
.pix_x (pix_x ),
.pix_y (pix_y ),
.pix_data_out (pix_data )
);
//RGB565转RGB888
assign pixclk_out = sys_clk ;//直接使用27M时钟与25.175相差不大
assign r_out = {rgb565[15:11],3'b0};
assign g_out = {rgb565[10: 5],2'b0};
assign b_out = {rgb565[ 4: 0],3'b0};
endmodule
```
### 6.3.4仿真验证
由于仿真不需要对MS7210芯片进行初始化所以我们在top文件中加入条件编译指令并且在仿真文件中定义SIM宏那么就可以在仿真中不编译ms7210初始化相关代码只对vga时序进行仿真我们只需要提供时钟和复位即可对模块进行仿真仿真文件如下所示
```verilog
`timescale 1ns / 1ns
`define SIM
module hdmi_top_tb;
// Parameters
//Ports
reg sys_clk;
reg rstn_in;
wire rstn_out;
wire hd_scl;
wire hd_sda;
wire led_int;
wire pixclk_out;
wire vs_out;
wire hs_out;
wire de_out;
wire [7:0] r_out;
wire [7:0] g_out;
wire [7:0] b_out;
initial begin
sys_clk = 0;
rstn_in = 0;
#100
rstn_in = 1;
end
always #(500/27) sys_clk = ~sys_clk;
hdmi_top hdmi_top_inst (
.sys_clk(sys_clk),
.rstn_in(rstn_in),
.rstn_out(rstn_out),
.hd_scl(hd_scl),
.hd_sda(hd_sda),
.led_int(led_int),
.pixclk_out(pixclk_out),
.vs_out(vs_out),
.hs_out(hs_out),
.de_out(de_out),
.r_out(r_out),
.g_out(g_out),
.b_out(b_out)
);
endmodule
```
直接点击sim文件夹下hebav文件夹中的do.bat文件即可利用ModuleSim对模块进行仿真仿真波形如下
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/10.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图10.仿真波形(一) <!--标题-->
</center>
</div>
从上图我们可以发现vsync信号拉高了两个行同步信号的长度与设计相符
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/11.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图11.仿真波形(二) <!--标题-->
</center>
</div>
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/12.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图12.仿真波形(三) <!--标题-->
</center>
</div>
从图11和12中我们可以看到当cnt_h信号计数结束后会恢复0cnt_v会加一hsync信号会拉高96个像素时钟0~95cnt_h和hsync与设计相符。
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/13.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图13.仿真波形(四) <!--标题-->
</center>
</div>
如图13所示当cnt_h计数到H_SYNC + H_BACK + H_LEFT也就是144时rgb_valid拉高xy轴坐标比rgb_valid提前一个时钟周期以便pix_data准备好数据符合设计。
<div> <!--块级封装-->
<center> <!--将图片和文字居中-->
<img src="./images/14.png"
alt="无法显示图片时显示的文字"
style="zoom:100%"/>
<br> <!--换行-->
图14.仿真波形(五) <!--标题-->
</center>
</div>
从每一行看每一行被分成了10个部分每部分像素数据分别对应不同颜色符合设计要求。可以进行下一步上板验证。
### 6.3.5上板验证
仿真已经通过,可以进行上板验证,上板前要先进行管脚约束。端口与对应管脚如下表所示:
| 端口名称 |信号类型| 对应管脚|功能|
|:----:|:----:|:----:|:----:|
| sysclk | Input | D18 | 27M时钟 |
| rstn_in | Input | C22 | 外部输入复位 |
| rstn_out | Output | G25 | 输出ms7210复位 |
| hd_scl | Output | K22 | iic SCL信号 |
| hd_sda | Output | K23 | iic SDA信号 |
| led_int | Output | A20 | 配置完成信号 |
| pixclk_out | Output | G25 | 像素时钟输出 |
| vs_out | Output | R21 | Vsync输出 |
| hs_out | Output | R20 | Hsync输出 |
| de_out | Output | N19 | RGB_valid输出 |
| r_out[0] | Output | N21 | RGB888输出 |
| r_out[1] | Output | L23 | RGB888输出 |
| r_out[2] | Output | L22 | RGB888输出 |
| r_out[3] | Output | L25 | RGB888输出 |
| r_out[4] | Output | L24 | RGB888输出 |
| r_out[5] | Output | K26 | RGB888输出 |
| r_out[6] | Output | K25 | RGB888输出 |
| r_out[7] | Output | P16 | RGB888输出 |
| g_out[0] | Output | T25 | RGB888输出 |
| g_out[1] | Output | P25 | RGB888输出 |
| g_out[2] | Output | R25 | RGB888输出 |
| g_out[3] | Output | P24 | RGB888输出 |
| g_out[4] | Output | P23 | RGB888输出 |
| g_out[5] | Output | N24 | RGB888输出 |
| g_out[6] | Output | N23 | RGB888输出 |
| g_out[7] | Output | N22 | RGB888输出 |
| b_out[0] | Output | P19 | RGB888输出 |
| b_out[1] | Output | P21 | RGB888输出 |
| b_out[2] | Output | P20 | RGB888输出 |
| b_out[3] | Output | M22 | RGB888输出 |
| b_out[4] | Output | M21 | RGB888输出 |
| b_out[5] | Output | N18 | RGB888输出 |
| b_out[6] | Output | R22 | RGB888输出 |
| b_out[7] | Output | T22 | RGB888输出 |
管脚分配可以直接编写.fdc文件也可以使用PDS内置的工具进行分配。完成管脚分配之后就可以生成sbit文件将文件提交到网站后点击烧录即可将sbit下载到实验板中在摄像头页面即可观察到显示屏中显示出彩条。
## 6.4 章末总结
本次实验主要学习VGA时序的相关知识并使用HD硬核进行HDMI显示感兴趣的同学可以尝试使用HDMI显示其他图像。