FPGA实现BT.1120编码

来源:互联网 发布:李洪成排盘软件下载 编辑:程序博客网 时间:2024/06/10 07:58

仅作参考,modulesim仿真通过,未做时序优化

研究了两天的BT1120规范,以及CEA-861-D视频时序,找到了一些对应关系。于是写了如下的verilog代码,可对接sii9134芯片的行场内嵌方式,sii9134配置C代码如下:

void sii9134_init(void){      u8 u8Data = 0;      I2C_WriteByte(0x05, 0x08, 0x72);            I2C_ReadByte(&u8Data, sizeof(u8), 0x33, 0x72);      I2C_WriteByte(u8Data & 0x8f, 0x33, 0x72);            I2C_WriteByte(0x6e, 0x40, 0x72);      I2C_WriteByte(0x28, 0x44, 0x72);      I2C_WriteByte(0x00, 0x45, 0x72);      I2C_WriteByte(0x05, 0x46, 0x72);      I2C_WriteByte(0x05, 0x47, 0x72);      I2C_WriteByte(0x30, 0x48, 0x72);       I2C_WriteByte(0x3d, 0x4a, 0x72);}


FPGA实验板使用黑金的AV6045开发板。

FPGA端的bt1120 verilog代码如下:

//////////////////////////////////////////////////////////////////////////////////// Company: // Engineer: // /***author : lt*time : 2017/8/28*function : ycbcr4:2:2 embed_hs_vs encoder module, compatible bt.1120 & bt.656**//**  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 / 100psmodule embed_hs_vs_enc(  input       rst,    input       yc422_pclk_i,  input [15:0]  yc422_data_i,  input       yc422_de_i,  input       yc422_vs_i,  input       yc422_hs_i,    //--------------------------------------------------------  //视频时序参数,由CPU 通过i2c配置得到  input [11:0]       width_i,   // l  input [11:0]       height_i,   //  input [11:0]       hs_rising_to_de_i,  input [11:0]       hor_total_g_i,  input [11:0]       vs_rising_to_de_i, //L2  input [11:0]       ver_total_g_i,           //L6    //----------------------------------------------------------  input      video_pararm_enable_i, //a clock pulse  //----------------------------------------------------------    //bt.1120接口  output         embed_hs_vs_pclk_o,  output reg[15:0] embed_hs_vs_yc422_o    );  //状态机状态  localparam  INVAILD_BLANKING  =  4'd0;  localparam  VAILD_VIDEO = 4'd1;  localparam  SYNC1_SAV =  4'd2;  localparam  SYNC2_SAV =  4'd3;  localparam  SYNC3_SAV =  4'd4;  localparam  SYNC1_EAV =  4'd5;  localparam  SYNC2_EAV =  4'd6;  localparam  SYNC3_EAV =  4'd7;  localparam  SAV_BKANKING = 4'd8;  localparam  EAV_BKANKING = 4'd9;  localparam  SAV_VIDEO = 4'd10;  localparam  EAV_VIDEO = 4'd11;    //在行场消隐区填充STUFF  localparam  STUFF  = 16'h8010;    wire hs_rising; //rising or falling  wire vs_rising;    reg [11:0] vs_cnt;//场计数器  reg [11:0] hs_cnt;//行计数器    //复位信号要处理好,否则以下寄存器值未初始化  reg [11:0] width_g;  reg [11:0] height_g;  reg [11:0] hs_rising_to_de_g;  reg [11:0] hor_total_g;  reg [11:0] vs_rising_to_de_g;  reg [11:0] ver_total_g;    reg [3:0]state_cs;//当前状态 需注意寄存器变量的位宽,防止溢出  reg [3:0]state_ns;//下一个状态    //对信号进行延时操作,打1拍  //reg[15:0] yc422_data_d1;  reg yc422_de_d1;  reg yc422_vs_d1;  reg yc422_hs_d1;    always @(posedge yc422_pclk_i)  begin    if(rst) begin      //yc422_data_d1  <=  16'h00;      yc422_de_d1    <=  1'b0;      yc422_vs_d1    <=  1'b0;      yc422_hs_d1    <=  1'b0;    end else begin      //yc422_data_d1  <=  yc422_data_i;      yc422_de_d1    <=  yc422_de_i;      yc422_vs_d1    <=  yc422_vs_i;      yc422_hs_d1    <=  yc422_hs_i;    end   end     assign embed_hs_vs_pclk_o = yc422_pclk_i;  assign hs_rising = ~yc422_hs_d1 & yc422_hs_i;   assign vs_rising = ~yc422_vs_d1 & yc422_vs_i;     always @(posedge yc422_pclk_i)  begin    if(rst) begin      width_g <=              12'd1920;      height_g <=             12'd1080;      hs_rising_to_de_g <=    12'd192;      hor_total_g <=          12'd2200;      vs_rising_to_de_g <=    12'd41;      ver_total_g <=          12'd1125;    end else if(video_pararm_enable_i)begin      width_g <= width_i;      height_g <= height_i;      hs_rising_to_de_g <= hs_rising_to_de_i;      hor_total_g <= hor_total_g_i;      vs_rising_to_de_g <= vs_rising_to_de_i;      ver_total_g <= ver_total_g_i;    end  end    //行计数  always @(posedge yc422_pclk_i)  begin  if(rst)       hs_cnt <= 0;  else if(hs_rising || video_pararm_enable_i)    hs_cnt <= 0;  else if(hs_cnt == hor_total_g - 1'b1)    hs_cnt <= 0;  else    hs_cnt <= hs_cnt + 1'b1;  end    //帧计数  always @(posedge yc422_pclk_i)  begin     if(rst)       vs_cnt <= 0;    else if(vs_rising || video_pararm_enable_i)       vs_cnt <= 0;    else if(hs_cnt == hor_total_g - 1'b1)      if(vs_cnt == ver_total_g - 1'b1)        vs_cnt <= 0;      else        vs_cnt <= vs_cnt + 1'b1;    else       vs_cnt <= vs_cnt;  end  always @(posedge yc422_pclk_i)  begin    if(rst)      state_cs  <=  INVAILD_BLANKING;    else      state_cs  <=  state_ns;  end    always @(*)  begin    case(state_cs)    INVAILD_BLANKING :     begin      if(hs_cnt == hs_rising_to_de_g - 1'b1 - 3'd5) //SAV 提前4个时钟,因为SAV和EAV要包含4个时钟周期,并且补偿state_cs和第三段带来的2拍延时        state_ns  = SYNC1_SAV;      else if(hs_cnt ==  hs_rising_to_de_g + width_g - 1'b1 - 1'b1) //EAV 不需要提前4个时钟,但需要补偿state_cs和第三段带来的2拍延时        state_ns  = SYNC1_EAV;      else        state_ns  = INVAILD_BLANKING;    end        //SAV部分    SYNC1_SAV :  state_ns = SYNC2_SAV;    SYNC2_SAV :  state_ns = SYNC3_SAV;    SYNC3_SAV :     if((vs_cnt >= vs_rising_to_de_g - 1'b1) && (vs_cnt <=  height_g + vs_rising_to_de_g - 1'b1))//VILD_VIDEO      state_ns = SAV_VIDEO;    else      state_ns = SAV_BKANKING;        //EAV部分    SYNC1_EAV : state_ns = SYNC2_EAV;    SYNC2_EAV : state_ns = SYNC3_EAV;    SYNC3_EAV :    if((vs_cnt >= vs_rising_to_de_g - 1'b1) && (vs_cnt <=  height_g + vs_rising_to_de_g - 1'b1))//VILD_VIDEO      state_ns = EAV_VIDEO;    else      state_ns = EAV_BKANKING;        SAV_BKANKING : state_ns = INVAILD_BLANKING;    EAV_BKANKING : state_ns = INVAILD_BLANKING;    SAV_VIDEO :     state_ns = VAILD_VIDEO;    EAV_VIDEO :     state_ns = INVAILD_BLANKING;        VAILD_VIDEO :      if(hs_cnt == hs_rising_to_de_g + width_g - 1'b1 - 1'b1)          state_ns = SYNC1_EAV;//去EAV部分      else        state_ns = VAILD_VIDEO;    default :      state_ns  = INVAILD_BLANKING;    endcase  end    always @(posedge yc422_pclk_i)  begin    if(rst)      embed_hs_vs_yc422_o  <=  STUFF;    else begin      if(state_cs == INVAILD_BLANKING)        embed_hs_vs_yc422_o <= STUFF;      else if(state_cs == VAILD_VIDEO)        embed_hs_vs_yc422_o <= yc422_data_i; //yc422_data_d1      else if((state_cs == SYNC1_SAV) || (state_cs == SYNC1_EAV))        embed_hs_vs_yc422_o <= 16'hffff;      else if((state_cs == SYNC2_SAV) || (state_cs == SYNC2_EAV))        embed_hs_vs_yc422_o <= 16'h0000;      else if((state_cs == SYNC3_SAV) || (state_cs == SYNC3_EAV))        embed_hs_vs_yc422_o <= 16'h0000;      else if(state_cs == SAV_BKANKING)        embed_hs_vs_yc422_o <= 16'habab;      else if(state_cs == EAV_BKANKING)        embed_hs_vs_yc422_o <= 16'hb6b6;      else if(state_cs == SAV_VIDEO)        embed_hs_vs_yc422_o <= 16'h8080;      else if(state_cs == EAV_VIDEO)        embed_hs_vs_yc422_o <= 16'h9d9d;      else        embed_hs_vs_yc422_o <= STUFF;    end  endendmodule


例化后就能使用了

embed_hs_vs_enc U_embed_hs_vs_enc_0(  .       rst(rst),    .       yc422_pclk_i(video_clk_148m5),  .       yc422_data_i({yc_c,yc_y}),  .       yc422_de_i(yc_de),  .       yc422_vs_i(yc_vs),  .       yc422_hs_i(yc_hs),    //--------------------------------------------------------  //视频时序参数,由CPU 通过i2c配置得到  .         width_i(12'd1920),   // l  .         height_i(12'd1080),   //  .         hs_rising_to_de_i(12'd192),  .         hor_total_g_i(12'd2200),  .         vs_rising_to_de_i(12'd41), //L2  .         ver_total_g_i(12'd1125),           //L6    //----------------------------------------------------------  .      video_pararm_enable_i(video_pararm_enable), //a clock pulse  //----------------------------------------------------------    //bt.1120接口  .         embed_hs_vs_pclk_o(bt1120_clk),  .         embed_hs_vs_yc422_o(bt1120_yc));


原创粉丝点击