FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持

您所在的位置:网站首页 bmpcc如何将lut录入视频 FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持

FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持

2024-07-12 20:57:06| 来源: 网络整理| 查看: 265

目录 1、前言2、视频显示的VESA协议3、VESA协议的bug4、FPGA实现任意分辨率视频输出显示5、FDMA实现数据缓存6、vivado工程详解7、上板调试验证并演示8、福利:工程代码的获取

1、前言

本设计使用纯Verilog代码实现,重点在于基于AXI协议的DDR控制器的运用,理论上讲,只要有AXI协议的FPGA均可使用,比如Xilinx、国产紫光同创等; 本设计主要解决非VESA协议分辨率视频的显示问题,高度贴近真实项目,适用于医疗、竣工等图像相关项目。

2、视频显示的VESA协议

视频显示行业有一个国际标准,那就是VESA协议; 视频电子标准协会(Video Electronics Standards Association, VESA)是由代表来自世界各地的、享有投票权利的140多家成员公司的董事会领导的非盈利国际组织,总部设立于加利福尼亚州的Milpitas,自1989年创立以来,一直致力于制订并推广显示相关标准。 VESA标准详细规定了每一种输出分辨率的时钟和数据组成,FPGA设计输出视频时序时就是参考了VESA标准,比如1080P、720P等; 典型的VESA时序如下: 行显示时序: 在这里插入图片描述 HSYNC:行同步信号,当此信号有效的时候就表示开始显示新的一行数据; 册可以知道此信号是低电平有效还是高电平有效,图 为低电平有效。 HSPW:行同步信号宽度,也就是 HSYNC 信号持续时间。HSYNC 信号不是一个脉冲,而是需要持续一段时间才是有效的,单位为 CLK。 HBP:行显示后沿(或后肩),单位是 CLK。 HOZVAL:行有效显示区域,即显示一行数据所需的时间,假如屏幕分辨率为 1024*600,那么 HOZVAL 就是 1024,单位为 CLK。 HFP:行显示前沿(或前肩),单位是 CLK。 当 HSYNC 信号发出以后,需要等待 HSPW+HBP 个 CLK 时间才会接收到真正有效的像素数据。当显示完一行数据以后需要等待 HFP 个 CLK 时间才能发出下一个 HSYNC 信号,所以显示一行所需要的时间就是:HSPW + HBP + HOZVAL + HFP。

一帧图像就是由很多个行组成的,帧显示时序如图: 在这里插入图片描述 VSYNC:帧(场)同步信号,当此信号有效的时候就表示开始显示新的一帧数据; VSPW:帧同步信号宽度,也就是 VSYNC 信号持续时间,单位为 1 行的时间。 VBP:帧显示后沿(或后肩),单位为 1 行的时间。 LINE:帧有效显示区域,即显示一帧数据所需的时间,假如屏幕分辨率为 1024*600,那么 LINE 就是600 行的时间。 VFP:帧显示前沿(或前肩),单位为 1 行的时间。 显示一帧所需要的时间就是:VSPW+VBP+LINE+VFP 个行时间,最终的计算公式: T = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP) FPGA做图像输出显示必须遵守此协议;

3、VESA协议的bug

VESA协议定义了很多种分辨率,具体请查看手册; 但有个bug,加入我的视频分辨率是500x500这样的呢?在VESA协议找不到这样的分辨率,那我们怎么写输出分辨率的代码呢? 当然,这种问题怎么可能难道FPGA工程师呢,请往下面看。。。

4、FPGA实现任意分辨率视频输出显示

设计方案如下: 在这里插入图片描述 这里加入要输出的分辨率为500x500,VESA协议里没有; 我们设计输出分辨率为标准的1920x1080的VESA协议分辨率; 将分辨率为500x500的视频写入DDR3中做三帧缓存; 写数据是一行写1920个像素,但只有前500个是有效的数据; 一帧图像共写1080行这样的数据,但只有前500行是有效的; 读数据是直接读取1920x1080的图像; 但规定有效区域只有500x500,其他区域为黑色或者其他; 这样就达到了上图的输出效果; 即在1920x1080的黑色背景下输出500x500的视频; 由于ov5640摄像头500x500输出的效果不好,这是ov5640自身决定的,所以我们的工程采用ov5640摄像头缩放至800x800作为例子;

5、FDMA实现数据缓存

关于FDMA三帧缓存,请参考我之前写的文章点击查看:FDMA三帧缓存方案 这里,我们将FDMA做了修改,使得输入分辨率由原来的参数类型变为输入类型,这样的好处时方便配置;

6、vivado工程详解

开发板:Xilinx Artix7开发板; 开发环境:vivado2019.1; 输入:ov5640摄像头,分辨率800x800; 输出:HDMI,分辨率1920x1080; 工程BD如下: 在这里插入图片描述 这里,我们将FDMA做了修改,使得输入分辨率由原来的参数类型变为输入类型,这样的好处时方便配置; 工程代码架构如下: 在这里插入图片描述 顶层代码如下:

`timescale 1ns / 1ps module top( //ddr3 output [14:0]DDR3_0_addr, output [2:0]DDR3_0_ba , output DDR3_0_cas_n , output [0:0]DDR3_0_ck_n , output [0:0]DDR3_0_ck_p , output [0:0]DDR3_0_cke , output [0:0]DDR3_0_cs_n , output [3:0]DDR3_0_dm , inout [31:0]DDR3_0_dq , inout [3:0]DDR3_0_dqs_n , inout [3:0]DDR3_0_dqs_p , output [0:0]DDR3_0_odt , output DDR3_0_ras_n , output DDR3_0_reset_n , output DDR3_0_we_n , input CLK_IN1_D_0_clk_n, input CLK_IN1_D_0_clk_p, output ddr3_ok , inout cmos_scl, //cmos i2c clock inout cmos_sda, //cmos i2c data input cmos_vsync, //cmos vsync input cmos_href, //cmos hsync refrence,data valid input cmos_pclk, //cmos pxiel clock output cmos_xclk, //cmos externl clock input [7:0]cmos_db, //cmos data output cmos_rst_n, //cmos reset output cmos_pwdn, //cmos power down inout hdmi_scl , //HDMI I2C clock inout hdmi_sda , //HDMI I2C data //hdmi_out output vout_hs , //horizontal synchronization for 9134 output vout_vs , //vertical synchronization for 9134 output vout_de , //data valid for 9134 output vout_clk , //clock for 9134 output[23:0] vout_data , //data for 9134 output hdmi_nreset ); wire clk_25m ; wire clk_200m ; wire clk_hdmi ; wire pll_resetn; wire [0:0] resetn; wire ud_r_0_ud_rclk; wire [31:0] ud_r_0_ud_rdata; wire ud_r_0_ud_rde; wire ud_r_0_ud_rvs; wire ud_w_0_ud_wclk; wire [31:0] ud_w_0_ud_wdata; wire ud_w_0_ud_wde; wire ud_w_0_ud_wvs; wire ui_clk_100m; wire [9:0] lut_index; wire [31:0] lut_data; wire [9:0] lut_index_hdmi; wire [31:0] lut_data_hdmi ; wire [23:0] ov5640_rgb; wire ov5640_de ; wire ov5640_vs ; wire o_data_req; wire [23:0] i_rgb; wire o_hs ; wire o_vs ; wire o_de ; wire [23:0] o_rgb; wire hdmi_clk_rstn; assign hdmi_nreset =pll_resetn; //assign hdmi_in_nreset=pll_resetn; assign ud_w_0_ud_wclk =cmos_pclk ; assign ud_w_0_ud_wvs =ov5640_vs ; assign ud_w_0_ud_wde =ov5640_de ; assign ud_w_0_ud_wdata={ov5640_rgb[7:0],ov5640_rgb[15:8],ov5640_rgb[23:16]}; assign ud_r_0_ud_rclk=clk_hdmi; assign ud_r_0_ud_rvs=o_vs; assign ud_r_0_ud_rde=o_data_req; assign i_rgb=ud_r_0_ud_rdata[23:0]; assign vout_clk=clk_hdmi; assign vout_hs=o_hs; assign vout_vs=o_vs; assign vout_de=o_de; assign vout_data=o_rgb; assign cmos_rst_n = 1'b1; assign cmos_pwdn = 1'b0; i2c_config i2c_config_ov5640( .rst (~pll_resetn ), .clk (clk_200m ), .clk_div_cnt (16'd500 ), .i2c_addr_2byte (1'b1 ), .lut_index (lut_index ), .lut_dev_addr (lut_data[31:24]), .lut_reg_addr (lut_data[23:8] ), .lut_reg_data (lut_data[7:0] ), .error ( ), .done ( ), .i2c_scl (cmos_scl ), .i2c_sda (cmos_sda ) ); ov5640_reg_cfg #( .DISPAY_H(800), .DISPAY_V(800 ) ) u_ov5640_reg_cfg( .lut_index(lut_index), //Look-up table address .lut_data (lut_data ) //Device address (8bit I2C address), register address, register data ); i2c_config i2c_config_hdmi( .rst (~pll_resetn ), .clk (clk_200m ), .clk_div_cnt (16'd500 ), .i2c_addr_2byte (1'b0 ), .lut_index (lut_index_hdmi ), .lut_dev_addr (lut_data_hdmi[31:24]), .lut_reg_addr (lut_data_hdmi[23:8] ), .lut_reg_data (lut_data_hdmi[7:0] ), .error ( ), .done ( ), .i2c_scl (hdmi_scl ), .i2c_sda (hdmi_sda ) ); lut_hdmi u_lut_hdmi( .lut_index(lut_index_hdmi), //Look-up table address .lut_data (lut_data_hdmi) //Device address (8bit I2C address), register address, register data ); uiSensorRGB565 u_uiSensorRGB565( .cmos_clk_i (clk_25m),//cmos senseor clock. .rst_n_i (resetn ),//system reset.active low. .cmos_pclk_i (cmos_pclk),//input pixel clock. .cmos_href_i (cmos_href),//input pixel hs signal. .cmos_vsync_i(cmos_vsync),//input pixel vs signal. .cmos_data_i (cmos_db),//data. .cmos_xclk_o (cmos_xclk),//output clock to cmos sensor. .rgb_o (ov5640_rgb), .de_o (ov5640_de ), .vs_o (ov5640_vs ), .hs_o () ); design_1_wrapper u_design_1_wrapper ( .CLK_IN1_D_0_clk_n(CLK_IN1_D_0_clk_n), .CLK_IN1_D_0_clk_p(CLK_IN1_D_0_clk_p), .DDR3_0_addr (DDR3_0_addr ), .DDR3_0_ba (DDR3_0_ba ), .DDR3_0_cas_n (DDR3_0_cas_n ), .DDR3_0_ck_n (DDR3_0_ck_n ), .DDR3_0_ck_p (DDR3_0_ck_p ), .DDR3_0_cke (DDR3_0_cke ), .DDR3_0_cs_n (DDR3_0_cs_n ), .DDR3_0_dm (DDR3_0_dm ), .DDR3_0_dq (DDR3_0_dq ), .DDR3_0_dqs_n (DDR3_0_dqs_n ), .DDR3_0_dqs_p (DDR3_0_dqs_p ), .DDR3_0_odt (DDR3_0_odt ), .DDR3_0_ras_n (DDR3_0_ras_n ), .DDR3_0_reset_n (DDR3_0_reset_n ), .DDR3_0_we_n (DDR3_0_we_n ), .clk_200m (clk_200m ), .clk_hdmi (clk_hdmi ), .ddr3_ok (ddr3_ok ), .pll_resetn (pll_resetn ), .resetn (resetn ), .ud_r_0_ud_rclk (ud_r_0_ud_rclk ), .ud_r_0_ud_rdata (ud_r_0_ud_rdata ), .ud_r_0_ud_rde (ud_r_0_ud_rde ), .ud_r_0_ud_rempty (ud_r_0_ud_rempty ), .ud_r_0_ud_rvs (ud_r_0_ud_rvs ), .ud_w_0_ud_wclk (ud_w_0_ud_wclk ), .ud_w_0_ud_wdata (ud_w_0_ud_wdata ), .ud_w_0_ud_wde (ud_w_0_ud_wde ), .ud_w_0_ud_wfull (ud_w_0_ud_wfull ), .ud_w_0_ud_wvs (ud_w_0_ud_wvs ), .ui_clk_100m (ui_clk_100m ), .clk_25m (clk_25m ), .FDMA_XSIZE_0 (800 ), .FDMA_YSIZE_0 (800 ) ); video_timing_control vga( .i_clk (clk_hdmi ), .i_rst_n (pll_resetn ), .i_start_x (0), .i_start_y (0), .i_disp_h (800), .i_disp_v (800), .i_rgb (i_rgb ), .o_hs (o_hs ), .o_vs (o_vs ), .o_de (o_de ), .o_rgb (o_rgb ), .o_data_req(o_data_req ) ); endmodule 7、上板调试验证并演示

输出静态展示和动态展示如下: 在这里插入图片描述

FPGA纯verilog实现任意分辨率视频输出显示,提供工程

8、福利:工程代码的获取

福利:工程代码的获取 代码太大,无法邮箱发送,以某度网盘链接方式发送, 资料获取方式:私,或者文章末尾的V名片。 网盘资料如下: 在这里插入图片描述 在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭