基于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位。

整理后的接口
在这里插入图片描述
在这里插入图片描述
接口代码

/* 定时基准码 <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


测试文件

`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


  • 5
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
BT1120是一种FPGA调试技术,用于通过FPGA控制和分析外部视频接口信号。在进行BT1120FPGA调试时,需要以下步骤: 1. 确定调试目标:首先确定要调试的外部视频接口信号类型和问题。该接口通常用于传输高清视频信号,如720p或1080p。如果存在信号传输问题或其他异常,需要确定具体的调试目标。 2. 配置FPGA:将FPGA配置成基于BT1120的视频接口信号处理器。这可以通过编程FPGA来实现,编写适当的Verilog或VHDL代码,以实现接口信号的读取和处理。 3. 连接外部接口:将FPGA与外部视频接口连接起来。确保连接正确并稳定。 4. 信号分析和调试工具:使用适当的信号分析和调试工具,例如示波器,逻辑分析仪或者其他测试设备,来监测和分析BT1120接口的信号。这将帮助我们识别和解决可能存在的问题,例如信号损坏、时序问题等。 5. 调试过程中的观察:监测和记录外部接口信号的特征和变化。观察时序波形,检查信号的时钟、数据和同步等方面的正确性。根据观察到的问题,尝试利用FPGA的编程能力进行调整和优化。 6. 修改FPGA代码:根据观察结果和信号分析,适时修改FPGA代码,以修复可能存在的问题。这可能包括修改时序逻辑、优化信号处理算法或调整接口参数等。 7. 重复步骤:根据调试过程中的反馈和观测结果,多次重复上述过程,直到成功解决问题并满足调试目标。 总之,BT1120FPGA调试过程需要结合观察、信号分析和FPGA编程等技术,通过不断的优化和修改来解决问题,最终实现对外部视频接口信号的稳定和高质量传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值