通常情况下,使用IP的顺序就是:创建和设置IP、连接输入输出、对IP进行配置(可选)。
创建和设置IP
我们先看一下默认设置以及对应的IP接口。
每时钟像素数量
这个很好理解 ,例如常规解码芯片(如HDMI转RGB)、解串芯片(SDI转BT1120)输出的并行数据一般是每时钟一个像素,带打包功能的传输协议(例如MIPI)解码之后通常会每时钟超过一个像素。
此选项会影响视频输入的数据位宽,即原来的位宽的1/2/4/8倍。
视频格式
此选项包含了常见的视频格式选项。
最显著的影响就是数据位宽,即使输入数据与此处所选的视频格式不对应,IP依然能够完成打包发送的任务,只需要后级知道实际的视频格式就能正确解码。 例如YUV422格式每个像素就是16位。
视频输入元素宽度
需要注意的是,这里指的不是像素宽度,而是组成像素元素的宽度。例如,RGB由RGB三个分量组成,YUV由Y和UV组成。
此选项依然会影响视频输入的数据宽度。
AXI4S视频输出元素宽度
在第一章中我们了解到了IP的数据位宽变化功能,即输入数据与输出数据位宽可以不相等。
此选项影响输出数据位宽,需要注意的是下变换(输入位宽大于输出位宽)通常会造成信息的丢失(例如颜色深度,试想一下RGB888和RGB565的颜色表现)。同时要注意的是,输出位宽总是8的整数倍。
FIFO深度
FIFO最小深度32,有可选深度,但不支持2的指数倍的定制深度,这可能会造成一定程度的资源浪费。
时钟模式
时钟模式分为普通模式(同步模式)和独立模式(异步模式)。普通模式不需要使用内部FIFO进行跨时钟域的同步,可以减少资源的使用。异步时钟需要同步逻辑,且要关注两个时钟间的快慢关系,这会影响所需的FIFO深度。
通常,如果是外部输入的带时钟的并行数据,需要独立模式进行跨时钟域同步。外部串行输入,FPGA内部模块进行解串,可以使用普通模式。
普通模式示例一
这里我们使用默认配置进行仿真和上板测试,以下为Testbench,使用到了一个视频时序生成模块和视频像素生成模块。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/07/12 15:15:29
// Design Name:
// Module Name: vtg_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module vtg_tb(
);
`include "video_timing_define.vh"
reg clk;
reg rstn;
wire vtg_vs;
wire vtg_hs;
wire vtg_de;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
rstn = 0;
#1000 rstn = 1;
end
video_timing_generator # (
.VTG_V_PULSE_LEVEL ( HSYNC_PULSE_LEVEL ),
.VTG_H_PULSE_LEVEL ( VSYNC_PULSE_LEVEL ),
.VTG_V_ACTIVE ( VIDEO_V_ACTIVE ),
.VTG_V_FRONT_PORCH ( VIDEO_V_FRONT_PORCH ),
.VTG_V_PULSE ( VIDEO_V_PULSE_WIDTH ),
.VTG_V_BACK_PORCH ( VIDEO_V_BACK_PORCH ),
.VTG_H_ACTIVE ( VIDEO_H_ACTIVE ),
.VTG_H_FRONT_PORCH ( VIDEO_H_FRONT_PORCH ),
.VTG_H_PULSE ( VIDEO_H_PULSE_WIDTH ),
.VTG_H_BACK_PORCH ( VIDEO_H_BACK_PORCH )
) video_timing_generator_u0 (
.i_clk(clk),
.i_rstn(rstn),
.o_vs(vtg_vs),
.o_hs(vtg_hs),
.o_de(vtg_de)
);
wire [7:0] vg_red;
wire [7:0] vg_green;
wire [7:0] vg_blue;
wire vg_de;
wire vg_hs;
wire vg_vs;
video_pixel_gen # (
.VPG_H_PULSE_LEVEL ( HSYNC_PULSE_LEVEL ),
.VPG_V_PULSE_LEVEL ( VSYNC_PULSE_LEVEL ),
.VPG_H_ACTIVE ( VIDEO_H_ACTIVE ),
.VPG_V_ACTIVE ( VIDEO_V_ACTIVE )
) video_pixel_gen_u0 (
.i_clk( clk ),
.i_de( vtg_de ),
.i_hs( vtg_hs ),
.i_vs( vtg_vs ),
.i_mode( 5 ),
.o_red( vg_red ),
.o_green( vg_green ),
.o_blue( vg_blue ),
.o_de( vg_de ),
.o_hs( vg_hs ),
.o_vs( vg_vs )
);
wire fid;
wire overflow;
wire underflow;
wire [23:0] axis_tdata;
wire axis_tlast;
wire axis_tuser;
wire axis_tvalid;
wire vto_active_video;
wire vto_active_field;
wire vto_hblank;
wire vto_hsync;
wire vto_vblank;
wire vto_vsync;
video_test video_test_u0(
.aclk_0( clk ),
.aclken_0( 1'b1 ),
.aresetn_0( rstn ),
.axis_enable_0( 1'b1 ),
.fid_0( fid ),
.overflow_0( overflow ),
.underflow_0( underflow ),
.vid_io_in_0_active_video( vg_de ),
.vid_io_in_0_data( {vg_red, vg_green, vg_blue} ),
.vid_io_in_0_field( 0 ),
.vid_io_in_0_hblank( 0 ),
.vid_io_in_0_hsync( vg_hs ),
.vid_io_in_0_vblank( 0 ),
.vid_io_in_0_vsync( vg_vs ),
.vid_io_in_ce_0( 1'b1 ),
.video_out_0_tdata( axis_tdata ),
.video_out_0_tlast( axis_tlast ),
.video_out_0_tready( 1'b1 ),
.video_out_0_tuser( axis_tuser ),
.video_out_0_tvalid( axis_tvalid ),
.vtiming_out_0_active_video( vto_active_video ),
.vtiming_out_0_field( vto_active_field ),
.vtiming_out_0_hblank( vto_hblank ),
.vtiming_out_0_hsync( vto_hsync ),
.vtiming_out_0_vblank( vto_vblank ),
.vtiming_out_0_vsync( vto_vsync )
);
endmodule
仿真输出如下:
放大看一下TUSER和TVALID(帧起始信号)
再看一下TLAST(行结束)信号
再看一下带宽的使用率(TVALID信号占空比),这就是使用独立时钟时所允许的时钟下降空间。
上板调试,结果与仿真基本一致
标签:wire,vtg,Stream,vg,IP,PULSE,video,vto,Video From: https://blog.csdn.net/slyywd/article/details/140370810