不同分辨率的视频输出对应不同的时序和时钟,一般情况下是不存在同时或分时输出的,但现实项目中如果遇到这样的情况怎么办呢?
很好办,找我就行了。。。
不同分辨率的视频肯定有大有小,但输出分辨率却只有一个,很显然,要选择大的分辨率时序作为输出时序,大视频原样输出,小视频在大分辨率下降采样输出;
以本设计为例,输入分辨率有720P和1080P,那么输出时序当然就是1080P,720P视频在1080P时序下降采样输出;
设计架构如下:
输入1:ov5640摄像头1280x720@60Hz;
输入2:hdmi输入1920x1080@60Hz;
输出:hdmi输出1920x1080@60Hz;
具体哪一路作为输出视频,由串口协议帧控制;
具体协议如下:
串口协议帧有效数据0x00 0x00 0xaa 0xbb 输入2作为输出;
串口协议帧有效数据0x00 0x00 0xcc 0xdd 输入1作为输出;
ov5640摄像头输入:
ov5640摄像头输出rgb565格式视频,需要iic配置和数据采集,详细配置和采集源码请将文章看到最后;
HDMI输入和输出:
HDMI输入采用silicon9011解码,HDMI输出采用silicon9134编码,关于这一块的配置和使用,请参考我之前写的文章点击查看:silicon9011和silicon9134编解码
串口协议帧解析:
主要控制不同分辨率参数写入FDMA控制器,进而控制DDR读写,这个串口协议帧解析方案高度贴近真实项目,也是我常用的套路,关于串口协议帧解析这一块,请参考我之前写的文章点击查看:串口协议帧解析方案
FDMA数据缓存方案:
经典的图像缓存DDR3的方案,关于FDMA数据缓存方案点击查看:FDMA数据缓存方案这一块,请参考我之前写的文章
vivado版本:2019.1;
如果是高版本打开,升级IP即可;
如果是低版本打开,打开工程后需另存为,然后即可使用;
工程BD如下:
工程代码架构如下:
顶层源码如下:
`timescale 1ns / 1psmodule 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 clockinout cmos_sda, //cmos i2c datainput cmos_vsync, //cmos vsyncinput cmos_href, //cmos hsync refrence,data validinput cmos_pclk, //cmos pxiel clockoutput cmos_xclk, //cmos externl clockinput [7:0]cmos_db, //cmos dataoutput cmos_rst_n, //cmos resetoutput cmos_pwdn, //cmos power downoutput hdmi_in_nreset , //9011/9013 resetinput vin_clk , //clock for 9111/9013input vin_hs , //horizontal synchronization for 9011/9013input vin_vs , //vertical synchronization for 9011/9013input vin_de , //data valid for 9011/9013input[23:0] vin_data , //data for 9011/9013 inout hdmi_scl , //HDMI I2C clockinout hdmi_sda , //HDMI I2C data//hdmi_out output vout_hs , //horizontal synchronization for 9134output vout_vs , //vertical synchronization for 9134output vout_de , //data valid for 9134output vout_clk , //clock for 9134output[23:0] vout_data , //data for 9134output hdmi_nreset ,input i_uart_rx ,output o_uart_tx );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;reg ud_w_0_ud_wclk ;
reg [23:0] ud_w_0_ud_wdata;
reg ud_w_0_ud_wde ;
reg ud_w_0_ud_wvs ;
reg [10:0] dis_h;
reg [10:0] dis_v;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;wire o_rx_done;
wire [31:0]o_rx_data;
reg [31:0] _rx_data;assign hdmi_nreset =pll_resetn;
assign hdmi_in_nreset=pll_resetn;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(1280),.DISPAY_V(720 )
)
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 ());uart_rx_analysis_top #(.CLK_FREQ(200_000_000), //系统时钟频率.UART_BPS(115200 ) //串口波特率
)
uart_rx_analysis(.clk (clk_200m),.rst_n (resetn ),.i_uart_rx (i_uart_rx),.o_uart_tx (o_uart_tx),.o_rx_done (o_rx_done),.o_rx_data (o_rx_data)
);ila_0 u_ila_0 (.clk(clk_200m), // input wire clk.probe0(o_rx_done), // input wire [0:0] probe0 .probe1(o_rx_data) // input wire [31:0] probe1
);always @(posedge clk_200m) beginif(~resetn) _rx_data<=32'h00000000;else if(o_rx_done) _rx_data<=o_rx_data;
endalways @(*) beginif(_rx_data==32'h0000aabb) beginud_w_0_ud_wclk =vin_clk ;ud_w_0_ud_wdata=vin_data;ud_w_0_ud_wde =vin_de ;ud_w_0_ud_wvs =vin_vs ;dis_h =11'd1920;dis_v =11'd1080; endelse if(_rx_data==32'h0000ccdd) beginud_w_0_ud_wclk =cmos_pclk ;ud_w_0_ud_wdata={ov5640_rgb[7:0],ov5640_rgb[15:8],ov5640_rgb[23:16]};ud_w_0_ud_wde =ov5640_de ;ud_w_0_ud_wvs =ov5640_vs ; dis_h =11'd1280;dis_v =11'd720 ; endelse beginud_w_0_ud_wclk =vin_clk ;ud_w_0_ud_wdata=vin_data;ud_w_0_ud_wde =vin_de ;ud_w_0_ud_wvs =vin_vs ; dis_h =11'd1920;dis_v =11'd1080; end
enddesign_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 ),.R_XSIZE_0 (dis_h ), .R_YSIZE_0 (dis_v ), .W_XSIZE_0 (dis_h ), .W_YSIZE_0 (dis_v ) ); video_timing_control vga(.i_clk (clk_hdmi ), .i_rst_n (pll_resetn ), .i_start_x (0),.i_start_y (0),.i_disp_h (dis_h),.i_disp_v (dis_v), .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
资源消耗和功耗如下:使用的是Xilinx Artix7-35T;
开发板:Xilinx Artix7-35T开发板; 开发环境:vivado2019.1;
输入1:ov5640摄像头1280x720@60Hz;
输入2:hdmi输入1920x1080@60Hz;
输出:hdmi输出1920x1080@60Hz;
输出演示视频如下:
FPGA实现不同分辨率视频切换输出,串口协议帧控制,提供工程
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下: