FPGA纯verilog解码SDI视频 纯逻辑资源实现 提供2套工程源码和技术支持
目录
- 1、前言
- 2、硬件电路解析
- SDI摄像头
- Gv8601a单端转差
- GTX解串
- SDI解码
- VGA时序恢复
- YUV转RGB
- 图像输出
- FDMA图像缓存
- HDMI输出
- 3、工程1详解:无缓存输出
- 4、工程2详解:缓存3帧输出
- 5、上板调试验证并演示
- 6、福利:工程代码的获取
1、前言
FPGA实现SDI视频编解码目前有两种方案:
一是使用专用编解码芯片,比如典型的接收器GS2971,发送器GS2972,优点是简单,比如GS2971直接将SDI解码为并行的YCRCB,缺点是成本较高,可以百度一下GS2971的价格;
另一种方案是使用FPGA实现编解码,利用FPGA的GTP/GTX资源实现解串,优点是合理利用了FPGA资源,GTP/GTX资源不用白不用,缺点是操作难度大一些,对FPGA水平要求较高。
本文详细描述了FPGA纯verilog解码SDI视频的实现设计方案,工程代码编译通过后上板调试验证,文章末尾有演示视频,可直接项目移植,适用于在校学生做毕业设计、研究生项目开发,也适用于在职工程师做项目开发,可应用于医疗、军工等行业的数字成像和图像传输领域;
提供完整的、跑通的工程源码和技术支持;
工程源码和技术支持的获取方式放在了文章末尾,请耐心看到最后;
本设计提供两套vivado工程;
一是SDI 1080P@30Hz帧视频输入解码后,无缓存直接HDMI 1080P@30Hz帧输出;
二是SDI 1080P@30Hz帧视频输入解码后,缓存3帧后HDMI 1080P@60Hz帧输出;
关于SDI的理论知识部分,可自行搜索一下,很多大佬讲得很详细,也可以参考我之前写的文章:点击查看:SDI解码详解
2、硬件电路解析
硬件电路连接如下:
SDI摄像头
我用到的SDI摄像头输出视频分辨率1080P@30Hz;根据不同相机有所区别;
Gv8601a单端转差
Gv8601a起到均衡 EQ 功能,这里选用Gv8601a是因为抄袭了Xilinx官方的板子,当然也可以用其他型号器件。
GTX解串
GTX负责解串,将原始SDI视频解为20位的并行数据,我的板子是K7,所以用GTX,如果是A7的板子则用GTP,这里使用GTX并没有调用IP,而是直接调用GTXE2_CHANNEL和GTXE2_COMMON源语,这一点可谓将Xilinx的GTX资源用到了极致水平,值得好好品读,其实调用IP无非也就是把调用源语变得界面化而已,直接调用源语或许理解更为深刻,这一点,在市面上的所谓FPGA教程里都学不到。
SDI解码
调用SMPTE-SDI IP核实现,GTX只是将高速串行数据解为了并行,但并没有解析SDI协议,SMPTE-SDI IP核则完成了SDI协议的解码,去掉了SDI协议中的数据包信息和控制信息,解析出有效的视频数据,详细的SMPTE-SDI IP核接口定义请参考官方的使用手册;
VGA时序恢复
此模块的作用就是解码恢复出hs、vs以及de信号,即恢复正常的VGA视频时序;
要恢复正常的VGA视频时序,首先得看懂下面这张图:
根据这张表即可恢复出图像时序,具体看代码,这里一两句话实在讲不清楚,如果要完全讲明白,写5本书都搓搓有余;
YUV转RGB
这里就简单了,YUV4:4:4转RGB8:8:8,几条公式和几行代码的事儿,属于低端操作;
至此,SDI解码过程就完成了,接下来就是图像输出过程;
图像输出
图像输出有两种通路
一种是无缓存直接输出,这种方式的优点是没有延迟,适用于做图传的项目,缺点是不能对图像进行其他处理了;
另一种是缓存输出,这种方式的优点是可以平衡和同步后端的接收,比如后端接收不过来时就可以缓存几帧再输出;另外,如果还需要对图像进行其他处理时也需要缓存,适用于做图像处理的项目,缺点是输出有延迟,根据设置可以延迟多帧,本设计是延迟3帧;
既然需求是多样的,所以我们直接做两个工程。
FDMA图像缓存
我常用的FDMA数据缓存架构,详情请参考我之前的文章:点击查看:FDMA图像缓存
HDMI输出
纯verilog代码实现HDMI发送,输出时序1920x1080P,输出帧率由输入HDMI时钟决定;
HDMI输出顶层接口如下:
module helai_hdmi_out(input clk_hdmi ,input clk_hdmix5 ,input reset_n ,input i_vga_hs ,input i_vga_vs ,input i_vga_de , input [23:0] i_vga_rgb , output o_hdmi_clk_p ,output o_hdmi_clk_n ,output [2: 0] o_hdmi_data_p,output [2: 0] o_hdmi_data_n
);
3、工程1详解:无缓存输出
开发板:Xilinx Kintex7开发板;
开发环境:Vivado2019.1;
输入:SDI摄像头,分辨率1080p@30帧;
输出:HDMI,分辨率1080p@30帧;
工程代码架构如下:
顶层源码如下:
module helai_sdi_decode_2023(input I_SDI_2_N ,input I_SDI_2_P , input SDI_GTX_CLK_148_5_N , // MGT REFCLKs 148.5 MHz clockinput SDI_GTX_CLK_148_5_P , input SDI_GTX_CLK_148_35_P, // MGT REFCLKs 148.35 MHz clockinput SDI_GTX_CLK_148_35_N,output HDMI_CLK_P ,output HDMI_CLK_N ,output [2:0] HDMI_DATA_P ,output [2:0] HDMI_DATA_N );wire o_vout_clk ;
wire o_vout_hs ;
wire o_vout_vs ;
wire o_vout_de ;
wire [23:0] o_vout_rgb ; wire clk_hdmi ;
wire clk_hdmix5;
wire hdmi_rstn ;helai_sdi_driver u_helai_sdi_driver(.I_SDI_2_N (I_SDI_2_N ),.I_SDI_2_P (I_SDI_2_P ), .O_SDI_2_N (),.O_SDI_2_P (), .SDI_GTX_CLK_148_5_N (SDI_GTX_CLK_148_5_N ), // MGT REFCLKs 148.5 MHz clock.SDI_GTX_CLK_148_5_P (SDI_GTX_CLK_148_5_P ), .SDI_GTX_CLK_148_35_P(SDI_GTX_CLK_148_35_P), // MGT REFCLKs 148.35 MHz clock.SDI_GTX_CLK_148_35_N(SDI_GTX_CLK_148_35_N),.o_vout_clk (o_vout_clk ),.o_vout_hs (o_vout_hs ),.o_vout_vs (o_vout_vs ),.o_vout_de (o_vout_de ),.o_vout_rgb (o_vout_rgb )
);clk_wiz_1 clk_hdmi (.clk_hdmi(clk_hdmi), // output clk_hdmi.clk_hdmi_clkx5(clk_hdmix5), // output clk_hdmi_clkx5.locked(hdmi_rstn), // output locked.clk_in1(o_vout_clk) // input clk_in1
); helai_hdmi_out(.clk_hdmi (clk_hdmi ),.clk_hdmix5 (clk_hdmix5 ),.reset_n (hdmi_rstn ),.i_vga_hs (o_vout_hs ),.i_vga_vs (o_vout_vs ),.i_vga_de (o_vout_de ), .i_vga_rgb (o_vout_rgb ), .o_hdmi_clk_p (HDMI_CLK_P ),.o_hdmi_clk_n (HDMI_CLK_N ),.o_hdmi_data_p(HDMI_DATA_P),.o_hdmi_data_n(HDMI_DATA_N)
);
endmodule
资源消耗和功耗预估如下:
4、工程2详解:缓存3帧输出
开发板:Xilinx Kintex7开发板;
开发环境:Vivado2019.1;
输入:SDI摄像头,分辨率1080p@30帧;
输出:HDMI,分辨率1080p@60帧;
工程BD如下:
工程代码架构如下:
顶层源码如下:
module helai_sdi_decode_2023(input clk_27m ,input I_SDI_2_N ,input I_SDI_2_P , input SDI_GTX_CLK_148_5_N , // MGT REFCLKs 148.5 MHz clockinput SDI_GTX_CLK_148_5_P , input SDI_GTX_CLK_148_35_P, // MGT REFCLKs 148.35 MHz clockinput SDI_GTX_CLK_148_35_N,input i_uart_rx , output o_uart_tx ,
// DDR3 output [12: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 [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 ,output ddr3_ok ,
// HDMI_OUT output HDMI_CLK_P ,output HDMI_CLK_N ,output [2:0] HDMI_DATA_P ,output [2:0] HDMI_DATA_N );wire ui_clk_200m;
wire rst_n ;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 o_vout_clk ;
wire o_vout_hs ;
wire o_vout_vs ;
wire o_vout_de ;
wire [23:0] o_vout_rgb ; wire o_vga_hs ;
wire o_vga_vs ;
wire o_vga_de ;
wire [23:0] o_vga_rgb;
wire [23:0] i_vga_rgb; wire clk_hdmi ;
wire clk_hdmix5;
wire hdmi_rstn ;assign ud_r_0_ud_rclk =clk_hdmi ;
assign ud_r_0_ud_rde = o_vga_de ;
assign ud_r_0_ud_rvs = o_vga_vs ;
assign i_vga_rgb =ud_r_0_ud_rdata[23:0];assign ud_w_0_ud_wclk =o_vout_clk;
assign ud_w_0_ud_wdata =o_vout_rgb;
assign ud_w_0_ud_wde =o_vout_de ;
assign ud_w_0_ud_wvs =o_vout_vs ; design_1 u_design_1 (.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_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 ),.ddr3_ok (ddr3_ok ), .clk_in1_0 (clk_27m ),.ui_clk_0 (ui_clk_200m ),.rst_n (rst_n ),.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_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_wvs (ud_w_0_ud_wvs )
); helai_sdi_driver u_helai_sdi_driver(.I_SDI_2_N (I_SDI_2_N ),.I_SDI_2_P (I_SDI_2_P ), .O_SDI_2_N (),.O_SDI_2_P (), .SDI_GTX_CLK_148_5_N (SDI_GTX_CLK_148_5_N ), // MGT REFCLKs 148.5 MHz clock.SDI_GTX_CLK_148_5_P (SDI_GTX_CLK_148_5_P ), .SDI_GTX_CLK_148_35_P(SDI_GTX_CLK_148_35_P), // MGT REFCLKs 148.35 MHz clock.SDI_GTX_CLK_148_35_N(SDI_GTX_CLK_148_35_N),.o_vout_clk (o_vout_clk ),.o_vout_hs (o_vout_hs ),.o_vout_vs (o_vout_vs ),.o_vout_de (o_vout_de ),.o_vout_rgb (o_vout_rgb )
);clk_wiz_1 clk_hdmi (.clk_hdmi(clk_hdmi), // output clk_hdmi.clk_hdmi_clkx5(clk_hdmix5), // output clk_hdmi_clkx5.locked(hdmi_rstn), // output locked.clk_in1(o_vout_clk) // input clk_in1
); video_timing_control vga(.i_clk (clk_hdmi ), .i_rst_n(hdmi_rstn), .i_rgb (i_vga_rgb),.o_hs (o_vga_hs ),.o_vs (o_vga_vs ),.o_de (o_vga_de ),.o_rgb (o_vga_rgb)
);helai_hdmi_out(.clk_hdmi (clk_hdmi ),.clk_hdmix5 (clk_hdmix5 ),.reset_n (hdmi_rstn ),.i_vga_hs (o_vga_hs ),.i_vga_vs (o_vga_vs ),.i_vga_de (o_vga_de ), .i_vga_rgb (o_vga_rgb ), .o_hdmi_clk_p (HDMI_CLK_P ),.o_hdmi_clk_n (HDMI_CLK_N ),.o_hdmi_data_p(HDMI_DATA_P),.o_hdmi_data_n(HDMI_DATA_N)
);
endmodule
FPGA逻辑资源消耗和功耗如下:
5、上板调试验证并演示
输出演示视频如下:
FPGA纯verilog解码SDI视频
6、福利:工程代码的获取
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下:
相关文章:

FPGA纯verilog解码SDI视频 纯逻辑资源实现 提供2套工程源码和技术支持
目录1、前言2、硬件电路解析SDI摄像头Gv8601a单端转差GTX解串SDI解码VGA时序恢复YUV转RGB图像输出FDMA图像缓存HDMI输出3、工程1详解:无缓存输出4、工程2详解:缓存3帧输出5、上板调试验证并演示6、福利:工程代码的获取1、前言 FPGA实现SDI视…...

JVM篇之垃圾回收
一.如何判断对象可以回收 1.引用计数法 只要一个对象被其他变量所引用,就让它的计数加1,被引用了两次就让它的计数变成2,当这个变量的计数变成0时,就可以被垃圾回收; 弊端:当出现如下图的情况࿰…...

尝试用程序计算Π(3.141592653......)
文章目录1. π\piπ2. 用微积分来计算π\piπ2.1 原理2.2 代码2.3 结果2.4 分析1. π\piπ π\piπ的重要性或者地位不用多说,有时候还是很好奇,精确地π\piπ值是怎么计算出来的。研究π\piπ的精确计算应该是很多数学家计算机科学家努力的方向…...

【异常检测三件套】系列3--时序异常检测综述
写在前面: 异常检测共包含3个内容,从多个方面剖析异常检测方法,本文为第三篇。过往内容请查看以下链接: 【异常检测三件套】系列1--14种异常检测算法https://blog.csdn.net/allein_STR/article/details/128114175?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%…...

关于SAP 错误日志解析
有时候启动或操作sap会出现故障,只是察看sap用户当前目录下的日志文件可能不得要领,此时有必要察看work目录下的一些trace. 以Linux系统为例,其他的也差不多。 instance说明 如下 DVEBMGS?? ABAP Central Instance D?? …...

java:自定义变量加载到系统变量后替换shell模版并执行shell
这里的需求前提是,在项目中进行某些操作前,需要在命令后对shell配置文件的进行修改(如ip、port),这个对于用户是不友好的,需要改为用户页面输入ip、port,后台自动去操作修改配置;那么…...

Redis高级删除策略与数据淘汰
第二章:Redis高级 学习目标 目标1:能够说出redis中的数据删除策与略淘汰策略 目标2:能够说出主从复制的概念,工作流程以及场景问题及解决方案 目标3:能够说出哨兵的作用以及工作原理,以及如何启用哨兵 …...

社畜大学生的Python之pandas学习笔记,保姆入门级教学
接上期,上篇介绍了 NumPy,本篇介绍 pandas。 目录 pandas 入门pandas 的数据结构介绍基本功能汇总和计算描述统计处理缺失数据层次化索引 pandas 入门 Pandas 是基于 Numpy 构建的,让以 NumPy 为中心的应用变的更加简单。 Pandas是基于Numpy…...

20_FreeRTOS低功耗模式
目录 低功耗模式简介 STM32低功耗模式 Tickless模式详解 Tickless模式相关配置 实验源码 低功耗模式简介 很多应用场合对于功耗的要求很严格,比如可穿戴低功耗产品、物联网低功耗产品等。 一般MCU都有相应的低功耗模式,裸机开发时可以使用MCU的低功耗模式。 FreeRTOS也…...

Hive的使用方式
操作Hive可以在Shell命令行下操作,或者是使用JDBC代码的方式操作 针对命令行这种方式,其实还有两种使用 第一个是使用bin目录下的hive命令,这个是从hive一开始就支持的使用方式 后来又出现一个beeline命令,它是通过HiveServer2服…...

Flume三大核心组件
Flume的三大核心组件: Source:数据源 Channel:临时存储数据的管道 Sink:目的地 Source:数据源:通过source组件可以指定让Flume读取哪里的数据,然后将数据传递给后面的 channel Flume内置支持读…...

数据结构(六)二叉树
一、树形结构概念树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:1、有一个…...

Docker buildx 的跨平台编译
docker buildx 默认的 docker build 命令无法完成跨平台构建任务,我们需要为 docker 命令行安装 buildx 插件扩展其功能。buildx 能够使用由 Moby BuildKit 提供的构建镜像额外特性,它能够创建多个 builder 实例,在多个节点并行地执行构建任…...

【java基础】方法重载和方法重写
文章目录方法重载方法重写方法重载 方法重载就是可以在一个类里面定义多个相同名称的方法,只需要参数列表的个数或者类型不同就行。 public class Overload {public int add(int a, int b) {return a b;}public double add(double a, double b) {return a b;}}对…...

Gradle7.4安装与基本使用
文章目录一.前言二.下载Gradle三.Gradle镜像源-全局级配置四.配置Gradle wrapper-项目级配置五.Gradle对测试的支持五.生命周期5.1 settings文件六.Gradle任务入门6.1 任务行为6.2 任务依赖方式七. Dependencies依赖引入7.1 依赖冲突及解决方案八.Gradle整合多模块SpringBoot九…...

[系统安全] 虚拟化安全之虚拟化概述
本文为笔者从零基础学习系统安全相关内容的笔记,如果您对系统安全、逆向分析等内容感兴趣或者想要了解一些内容,欢迎关注。本系列文章将会随着笔者在未来三年的读研过程中持续更新,由于笔者现阶段还处于初学阶段,不可避免参照复现各类书籍内容,如书籍作者认为侵权请告知,…...

如何从零开始系统的学习项目管理?
经常会有人问,项目管理到底应该学习一些什么?学习考证之后能得到什么价值? 以下我就总结一下内容 一,学习项目管理有用吗? 有效的项目管理带来的益处大致包括以下几个方面:更有效达成业务目标、满足相关…...

面试题-----
面试题---- 一.HTML 1.常用哪些浏览器进行测试,对应有哪些内核? ①IE------------------->Trident ②Chrome---------->以前是Webkit现在是Blink ③Firefox------------>Gecko ④Safari-------------->Webkit ⑤Opera--------------&…...

线材-电子线载流能力
今天来讲的是关于电子线的一个小知识,可能只做板子的工程师遇到此方面的问题会比较少,做整机的工程师则必然会遇到此方面问题,那就是线材问题。 下面主要说下电子线的过电流能力。(文末有工具下载)电子线(h…...

单变量回归问题
单变量回归问题 对于某房价问题,x为房屋大小,h即为预估房价,模型公式为: hθ(x)θ0θ1xh_{\theta}(x)\theta_{0}\theta_{1}x hθ(x)θ0θ1x 要利用训练集拟合该公式(主要是计算θ0、θ1\theta_{0}、\theta_{1}θ…...

ubuntu/linux系统知识(36)linux网卡命名规则
文章目录背景命名规范系统默认命名规则优势背景 很久以前Linux 操作系统的网卡设备的传统命名方式是 eth0、eth1、eth2等,属于biosdevname 命名规范。 服务器通常有多块网卡,有板载集成的,同时也有插在PCIe插槽的。Linux系统的命名原来是et…...

java的一些冷知识
接口并没有继承Object类首先接口是一种特殊的类,理由就是将其编译后是一个class文件大家都知道java类都继承自Object,但是接口其实是并没有继承Object类的 可以自己写代码测试: 获取接口类的class对象后遍历它的methods,可以发现是不存在Obje…...

java代理模式
代理模式 为什么要学习代理模式?因为这是SpringAOP的底层! 【SpringAOP和SpingMVC}】 代理模式的分类: 静态代理 动态代理 代理就像这里的中介,帮助你去做向房东租房,你不能直接解出房东,而房东和中介…...

JUC包:CountDownLatch源码+实例讲解
1 缘起 有一次听到同事谈及AQS时,我有很多点懵, 只知道入队和出队,CLH(Craig,Landin and Hagersten)锁,并不了解AQS的应用, 同时结合之前遇到的多线程等待应用场景,发现…...

Log4j2基本使用
文章目录1. Log4j2入门2. Log4j2配置3. Log4j2异步日志4. Log4j2的性能Apache Log4j 2是对Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带 来了一些重大的提升,主要有: 异常处理,…...

A2L在CAN FD总线的使用
文章目录 前言CAN时间参数BTL CyclesTime Quantum时间份额SWJ同步跳转宽度波特率计算采样点计算CAN FD的第二采样点SSP推荐配置A2L配置总结前言 A2L作为XCP标定协议的载体,包括了总线信息的定义。本文介绍如何将基于CAN总线的A2L扩展为支持CAN-FD的A2L CAN时间参数 在介绍配…...

Android JetPack之启动优化StartUp初始化组件的详解和使用
一、背景 先看一下Android系统架构图 在Android设备中,设备先通电(PowerManager),然后加载内核层,内核走完,开始检查硬件,以及为硬件提供的公开接口,然后进入到库的加载。库挂载后开…...

[11]云计算|简答题|案例分析|云交付|云部署|负载均衡器|时间戳
升级学校云系统我们学校要根据目前学生互联网在线学习、教师教学资源电子化、教学评价过程化精细化的需求,计划升级为云教学系统。请同学们根据学校发展实际考虑云交付模型包含哪些?云部署采用什么模型最合适?请具体说明。9月3日买电脑还是租…...

C++11/C++14:lambda表达式
概念 lambda表达式:是一种表达式,是源代码的组成部分闭包:是lambda表达式创建的运行期对象,根据不同的捕获模式,闭包会持有数据的副本或引用闭包类:用于实例化闭包的类,每个lambda表达式都会触…...

算法课堂-分治算法
分治算法 把一任务分成几部分(通常是两部分)来完成(或只完成一部分),从而实现整个任务的完成 或者你可以把递归理解为分治算法的一部分 因为递归就是把问题分解来解决问题 例子 称假币 最笨的方法:两两称…...