基于FPGA的1080P 60Hz BT1120接口调试过程记录

这篇具有很好参考价值的文章主要介绍了基于FPGA的1080P 60Hz BT1120接口调试过程记录。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这个BT1120接口是在1080P 60Hz的视频中验证的,其它频率的视频使用时要修改对应的参数。另外由于接口代码里面例化了一个深度位512的FIFO(quartus),所以在做仿真测试时需要quartus和modelsim联合仿真。

bt1120接口最重要的部分是结束码和起始码(FF 00 00 XYZ)
前面3字节的FF 00 00 是固定不变的,最后一字节需要根据F V H来编码,当FVH确定时P3 P2 P1 P0也确定了。使用8bit的数据位宽时保留高8位,舍去低2位。
bt1120,fpga开发
整理后的接口
bt1120,fpga开发
bt1120,fpga开发
接口代码

/* 定时基准码 <0xff 0x00 0x00 xxx>
 * 其中xxx为如下的取值范围:
 * 1 0 1 0 1 0 1 1 0 0  0xab(帧消隐期间,SAV)
 * 1 0 1 1 0 1 1 0 0 0  0xb6(帧消隐期间,EAV)
 * 1 0 0 0 0 0 0 0 0 0  0x80(视频有效区时间,SAV)
 * 1 0 0 1 1 1 0 1 0 0  0x9d(视频有效区时间,EAV)
 */

`timescale 1ns / 1ps
module ycbcr422_to_bt1120(
    input           rst_n,
    input           clk ,
    input           data_de,
    input           hsync,
    input           vsync,
    input  [15:0]   ycbcr,     
    output          bt1120_pclk,
    output reg [15:0]   bt1120_ycbcr

);

  localparam  BLANKING  =  4'd0;    //消隐阶段   
  //SAV
  localparam  CODE_SAV1 =  4'd1;    //数据开始码阶段
  localparam  CODE_SAV2 =  4'd2;
  localparam  CODE_SAV3 =  4'd3;
  localparam  CODE_SAV4 =  4'd4;

  //EAV
  localparam  CODE_EAV1 =  4'd5;    //数据结束码阶段
  localparam  CODE_EAV2 =  4'd6;
  localparam  CODE_EAV3 =  4'd7;
  localparam  CODE_EAV4 =  4'd8;

  localparam  VAILD_VIDEO = 4'd9;    //数据有效阶段



  //在行场消隐区填充STUFF
  localparam  STUFF  = 16'h8010;

  localparam BSAV = 8'hab;
  localparam BEAV = 8'hb6;

  localparam VSAV = 8'h80;
  localparam VEAV = 8'h9d;



//1080p 60hz
localparam   WIDTH_TOTAL = 12'd2200 ;   //一行的宽度
localparam   HEIGHT_TOTAL= 12'd1125 ;   //一帧的高度
localparam   VIDEO_BEFORE_BLANK_NUM = 6'd41 ;   //一帧开始前的帧消隐行数
localparam   VIDEO_AFTER_BLANK_NUM  = 3'd4  ;   //一帧结束后的帧消隐行数
localparam   BLANK_NUM   = 12'd280  ;



wire        full    ;
reg         rd_en   ;
wire[15:0]  rd_data ;
wire        empty   ;

reg [3:0]   state_c ;
reg [3:0]   state_n ; 
wire        blank2sav ;
wire        video2eav ;

reg         data_de0  ;
reg         hsync0    ;
reg         vsync0    ;
reg [15:0]  ycbcr0    ;        
reg         data_de1  ;
reg         hsync1    ;
reg         vsync1    ;
reg [15:0]  ycbcr1    ;
wire        v_pos     ;

reg [11:0]  cnt_h     ;
reg [11:0]  cnt_v     ; 

wire[7:0]   Lumi    ;
wire[7:0]   cbcr ;


assign  bt1120_pclk =  clk ;

yc2bt_fifo yc2bt_fifo_inst0
(
	 .clock (clk     ),
     .data  (ycbcr1  ),
	 .wrreq (data_de1),
	 .full  (full    ),
	 .rdreq (rd_en   ),
	 .q     (rd_data ),
	 .empty (empty   ) 
);

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        state_c <= BLANKING;
    end
    else begin
        state_c <= state_n;
    end
end


always@(*)begin
    case(state_c)
        BLANKING:begin
            if(blank2sav)begin
                state_n = CODE_SAV1;
            end
            else begin
                state_n = state_c;
            end
        end
        CODE_SAV1:begin
                state_n = CODE_SAV2;
        end
        CODE_SAV2:begin
                state_n = CODE_SAV3;
        end
        CODE_SAV3:begin
                state_n = CODE_SAV4;
        end
        CODE_SAV4:begin
                state_n = VAILD_VIDEO;
        end
        VAILD_VIDEO:begin
            if(video2eav)begin
                state_n = CODE_EAV1;
            end
            else begin
                state_n = state_c;
            end
        end
        CODE_EAV1:begin
                state_n = CODE_EAV2;
        end
        CODE_EAV2:begin
                state_n = CODE_EAV3;
        end
        CODE_EAV3:begin
                state_n = CODE_EAV4;
        end
        CODE_EAV4:begin
                state_n = BLANKING;
        end        
        default:begin
            state_n = BLANKING;
        end
    endcase
end

assign blank2sav = state_c==BLANKING && cnt_h==12'd275; 
assign video2eav = state_c==VAILD_VIDEO && cnt_h==12'd2199;


//输入打拍
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        data_de0 <= 1'b0 ;
        hsync0   <= 1'b0 ;
        vsync0   <= 1'b0 ;
        ycbcr0   <= 16'b0 ;
    end
    else begin
        data_de0 <= data_de ;
        hsync0   <= hsync   ;
        vsync0   <= vsync   ;
        ycbcr0   <= ycbcr   ;

        data_de1 <= data_de0 ;
        hsync1   <= hsync0   ;
        vsync1   <= vsync0   ;
        ycbcr1   <= ycbcr0   ;
    end
end

//获取场信号上升沿
assign v_pos = !vsync1 && vsync0 ;

//一行计数器
always @(posedge clk )begin
    if(v_pos || cnt_h == WIDTH_TOTAL-1)
        cnt_h <= 12'b0;
    else 
        cnt_h <= cnt_h + 1;
end

//一帧计数器
always @(posedge clk )begin
    if(v_pos)
        cnt_v <= 12'b0;
    else if(cnt_h == WIDTH_TOTAL-1)begin
        if(cnt_v == HEIGHT_TOTAL-1)
            cnt_v <= 12'b0;
        else
            cnt_v <= cnt_v + 1;
    end                        
end 

//出数据
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        bt1120_ycbcr <= STUFF ;
    end
    else begin  
        case(state_c)
            BLANKING:begin 
                    bt1120_ycbcr<= STUFF ; 
            end
            CODE_SAV1:begin 
                    bt1120_ycbcr<= 16'hffff ; 
            end
            CODE_SAV2:begin 
                    bt1120_ycbcr<= 16'h0 ; 
            end            
            CODE_SAV3:begin 
                    bt1120_ycbcr<= 16'h0 ; 
            end             
            CODE_SAV4:begin
               if(cnt_v<12'd41 ||(cnt_v >= 12'd1121 && cnt_v < 12'd1125)) 
                    bt1120_ycbcr<= 16'habab ;
               else if(cnt_v>=12'd41 && cnt_v<12'd1121)
                    bt1120_ycbcr<= 16'h8080 ; 
            end
            VAILD_VIDEO:begin                
                    bt1120_ycbcr<= rd_data ; 
            end
            CODE_EAV1:begin
                    bt1120_ycbcr <= 16'hffff;
            end
            CODE_EAV2:begin
                    bt1120_ycbcr <= 16'h0;
            end
            CODE_EAV3:begin
                    bt1120_ycbcr <= 16'h0;
            end
            CODE_EAV4:begin
               if(cnt_v<12'd41 ||(cnt_v >= 12'd1121 && cnt_v < 12'd1125)) 
                    bt1120_ycbcr<= 16'hb6b6 ;
               else if(cnt_v>=12'd41 && cnt_v<12'd1121)
                    bt1120_ycbcr<= 16'h9d9d ;
            end            
        endcase    
    end
end

assign Lumi =  bt1120_ycbcr[15:8] ;
assign cbcr =  bt1120_ycbcr[7:0] ;
//read en 
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        rd_en <= 1'b0 ;
    end
    else if(cnt_v>=12'd41 && cnt_v < 12'd1121 )begin
        if(cnt_h>=12'd279 && cnt_h<12'd2200)
            rd_en <= 1'b1 ;
        else
            rd_en <= 1'b0 ;
    end
    else begin
        rd_en <= 1'b0 ;
    end
end


endmodule


测试文件文章来源地址https://www.toymoban.com/news/detail-602883.html

`timescale 1 ns/1ps

module tb_bt1120();

reg       clk  ;
reg       rst_n;
wire[15:0] ycrcb;
reg       de   ;
reg       vsync;
reg       hsync;
reg[11:0] cnt_h;
reg[11:0] cnt_v;
reg[7:0] lumi ;
reg[7:0] cbcr ;


//uut的输出信号
wire       bt1120_clk;
wire[15:0] bt1120_data;

//时钟周期,单位为ns,可在此修改时钟周期。
parameter CYCLE    = 7;

//复位时间,此时表示复位3个时钟周期的时间。
parameter RST_TIME = 20 ;


ycbcr422_to_bt1120 u_ycbcr422_to_bt1120(
    .rst_n   (rst_n ), //input         
    .clk     (clk   ), //input          
    .data_de (de    ), //input [15:0]   
    .hsync   (hsync ), //input          
    .vsync   (vsync ), //input          
    .ycbcr   (ycrcb ), //input          
  
   //bt.1120接口
    .bt1120_pclk (bt1120_clk ) , //output           
    .bt1120_ycbcr(bt1120_data)   //output reg[15:0] 

    );
//1080P 60Hz
parameter   h_total  = 12'd2200;
parameter   hsync_pw = 6'd44   ;  //行消隐脉冲宽度,以时钟为单位

parameter   v_total  = 12'd1125;
parameter   vsync_pw = 3'd5    ;  //行消隐脉冲宽度,以行为单位

parameter   data_f_enabel = 6'd42   ;  //有效数据的第一行,以行为单位
parameter   data_e_enabel = 12'd1120;  //有效数据的最后一行,以行为单位

parameter   data_de_start = 8'd192   ;  //数据有效开始,以时钟为单位
parameter   data_de_end   = 12'd2112;  //数据有效结束,以时钟为单位

//生成本地时钟50M
initial begin
    clk = 0;
    forever
    #(CYCLE/2)
    clk=~clk;
end

//产生复位信号
initial begin
    rst_n = 1;
    #2;
    rst_n = 0;
    #(CYCLE*RST_TIME);
    rst_n = 1;
end

//一行数据的计数器
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        cnt_h <= 12'b0 ;
    end
    else begin
        if(cnt_h == h_total-1)
            cnt_h <= 12'b0 ;
        else
            cnt_h <= cnt_h + 1 ;
    end
end

//一帧数据的计数器,1080P 60hz的一帧数据共有1125行
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        cnt_v <= 12'b0 ;
    end
    else if(cnt_h == h_total-1)begin
        if(cnt_v == v_total-1)
            cnt_v <= 12'b0 ;
        else
            cnt_v <= cnt_v + 1 ;
    end
end

//产生行信号
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        hsync <= 1'b0 ;
    end
    else if(cnt_h < hsync_pw  )begin
        hsync <= 1'b1 ;
    end
    else begin
        hsync <= 1'b0 ;
    end
end

//产生场信号
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        vsync <= 1'b0 ;
    end
    else if(cnt_v < vsync_pw  )begin
        vsync <= 1'b1 ;
    end
    else begin
        vsync <= 1'b0 ;
    end
end

//产生数据有效信号
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        de   <= 1'b0 ;
        lumi <= 8'b0;
        cbcr <= 8'b0;
    end
    else if(cnt_v >= data_f_enabel-1 && cnt_v <= data_e_enabel)begin
        if(cnt_h >= data_de_start-1 && cnt_h < data_de_end-1 )begin
            de   <= 1'b1    ;
            lumi <= lumi+1;
            cbcr <= cbcr+1;
        end
        else begin
            de   <= 1'b0 ;
            lumi <= 8'b0;
            cbcr <= 8'b0;
        end
    end
end

assign ycrcb = {lumi,cbcr} ;

endmodule


到了这里,关于基于FPGA的1080P 60Hz BT1120接口调试过程记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Macbook用HDMI(非HDMI2.0)外接4K显示器1080p只能30Hz的解决方法

    这个问题困扰我很久了,我用的是比较老的4K显示器,不支持HDMI2.0,接上Macbook的时候4K分辨率不支持60Hz,最高只能30Hz,用起来卡卡的,这个也是正常的。但我调到1080p还是只能选择30Hz,这就很郁闷,看了下显示器设置,还是显示出入的是4K分辨率,怪不得不支持60Hz。 这一度

    2024年02月16日
    浏览(222)
  • 利用PowerPoint把PPT导出成60帧1080P的视频

    想要把PPT导出成1080P60帧率的视频,可以尝试以下办法 软件用的是office power point 点击文件–选项–自定义功能区 这时候就有了开发工具 点击运行–运行宏 随便起个名字,点击创建 这样 ,然后叉掉 这时候就看到开始导出了 下面解释下每行代码的作用: 可以根据需要自己调

    2024年02月13日
    浏览(59)
  • 安卓手机做电脑摄像头(USB连接1080P 60FPS低延迟非常稳定)

            在网上找了非常久的方案,有Droidcam的还有一些别的软件,经过我测试基本不是分辨率不够就是比较延迟卡顿,无线网是没那么稳定,那些软件也比较久,经过我的搜索终于找到个方法能达到1080P60低延迟0卡顿。 第一步,下载IP摄像头专业版 ,界面如下图所示,别

    2024年02月03日
    浏览(56)
  • Lattice FPGA解码MIPI视频,IMX219摄像头4Line 1080P采集USB3.0输出,提供工程源码硬件原理图PCB和技术支持

    FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了,MIPI解码难度之高,令无数英雄竞折腰,以至于Xilinx官方不得不推出专用的IP核供开发者使用,不然太高端的操作直接吓退一大批FPGA开发者,就没人玩儿了。 本设计基于Lattice的LCMXO3LF-6900C-5BG256C开发板,采

    2024年02月02日
    浏览(54)
  • 优酷youku 1080P 视频下载方法

    PC端下载优酷视频方法,以下是优酷视频下载地址解析python脚本  1. 登录优酷 ,按F12获取你登录后的COOKIE,将自己的COOKIE替换掉源代码中的COOKIE   2. 运行这个python,将youku的播放URL地址复制进去 就可以获取到视频1080P的M3U8下载链接  3. 在52pojie找到 \\\"M3U8批量下载器\\\"  ,使用M3U8下载器

    2024年02月11日
    浏览(48)
  • 学校的地下网站(学校的地下网站1080P高清)

    这个问题本身就提得有问题,为什么这么说,这是因为YouTube本身就不是一个视频网站或者说YouTube不是一个传统的视频网站!!! YouTube能够一家独大,可不仅仅是因为有了Google 这个亲爹,还有一点,跟本身的技术和产品积累有很大关系,就好比Google这个搜索引擎,做大了就

    2023年04月10日
    浏览(46)
  • VGA驱动原理(以1080p显示器为例)

    1080p显示器的刷新率是60Hz(每秒刷新67500/1125=60帧图像),行频率是67.5KHz(每秒刷新148500000/2200=67 500行),像素频率是148.5MHz(每秒刷新148 500 000个像素点) 1080p显示器的驱动时序如下图所示, HSync,VSync信号为正极性 下图是基于1920 x 1080@60Hz这个分辨率的具体时序参数表 对照时序参数

    2024年03月20日
    浏览(63)
  • 4K、2K、1080p、720p、480p、240p常见视频清晰度

    记录自用 一、清晰度对应的格式 标号 视频类型 格式尺寸 类型 比例 1 4K 4096*2160 4K 16:9 2 2K 2560*1440 2K 16:9 3 全高清 1920*1080 1080p 16:9 4 高清 1280*720 720p 16:9 5 标清 720*480 480p 3:2 6 标清 640*480 480p 4:3 7 流畅 320*240 240p ​4:3 注: 字母P意为逐行扫描 多数情况下4k特指4096 * 2160分辨率。而根

    2024年02月11日
    浏览(100)
  • RK356X 解除UVC摄像头预览分辨率1080P限制

      RK3566 + Android 11     UVC: USB video class(又称为USB video device class or UVC)就是USB device class视频产品在不需要安装任何的驱动程序下即插即用,包括摄像头、数字摄影机、模拟视频转换器、电视卡及静态视频相机。 测试代码: 打印出来后显示支持的预览分辨率如下: 然而,把

    2023年04月22日
    浏览(55)
  • AX7A200教程(8): HDMI输入和输出显示1080p视频

    本章节主要将hdmi输入的1080p视频通过ddr3缓存,然后通过hdmi输出口输出到显示屏上显示 设置读写突发长度为64 1.突发写命令 当写fifo计数器rd_data_count计数大于62,执行一次写突发命令,拉高wr_len_en 2.突发读命令 当读fifo计数器wr_data_count小于等于64执行一次读突发命令,拉高rd_

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包