当前位置: 首页>編程日記>正文

FPGA实现BT.1120编码

FPGA实现BT.1120编码

研究了两天的BT1120规范,以及CEA-861-D视频时序,找到了一些对应关系(见我另外一篇文章《视频时序与BT1120的关系》)。于是写了如下的verilog代码,可对接sii9134芯片的行场内嵌方式,其中sii9134配置C代码如下:

void sii9134_init(void)
{
      u8 u8Data = 0;
      I2C_WriteByte(0x05, 0x08, 0x72); //value reg_addr device_addr
      
      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代码如下(行场同步信号hsync和vsync为高电平有效):

另外,如果发现像素数据为0xff或0x00则需要替换为0xfe和0x01,防止对端误判。(本文没有做这一步)

 

/**
 * author : mkelehk@gmail.com
 * time : 2017/8/28
 * function : ycbcr4:2:2 embed_hs_vs encoder module, compatible bt.1120
 *
 * 定时基准码 <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 / 100ps
module 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, 
  //----------------------------------------------------------
  
  //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 - 3'd6) //SAV 提前4个时钟,因为SAV和EAV要包含4个时钟周期,并且补偿state_cs和第三段带来的2拍延时
        state_ns  = SYNC1_SAV;
      else if(hs_cnt ==  hs_rising_to_de_g + width_g - 3'd2) //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
  end
 
endmodule

 

    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), 
  //----------------------------------------------------------
  
  //bt.1120接口
  .         embed_hs_vs_pclk_o(bt1120_clk),
  .         embed_hs_vs_yc422_o(bt1120_yc)
    );


https://www.fengoutiyan.com/post/14149.html

相关文章:

  • 若用一位定长编码
  • 怎么用数字进行编码
  • n1120种子链接
  • 实现快速现场编码
  • FPGA UART
  • BT1120转Wifi
  • bt1120与sdi关系
  • 编码实现
  • 鏡像模式如何設置在哪,圖片鏡像操作
  • 什么軟件可以把圖片鏡像翻轉,C#圖片處理 解決左右鏡像相反(旋轉圖片)
  • 手機照片鏡像翻轉,C#圖像鏡像
  • 視頻鏡像翻轉軟件,python圖片鏡像翻轉_python中鏡像實現方法
  • 什么軟件可以把圖片鏡像翻轉,利用PS實現圖片的鏡像處理
  • 照片鏡像翻轉app,java實現圖片鏡像翻轉
  • 什么軟件可以把圖片鏡像翻轉,python圖片鏡像翻轉_python圖像處理之鏡像實現方法
  • matlab下載,matlab如何鏡像處理圖片,matlab實現圖像鏡像
  • 圖片鏡像翻轉,MATLAB:鏡像圖片
  • 鏡像翻轉圖片的軟件,圖像處理:實現圖片鏡像(基于python)
  • canvas可畫,JavaScript - canvas - 鏡像圖片
  • 圖片鏡像翻轉,UGUI優化:使用鏡像圖片
  • Codeforces,CodeForces 1253C
  • MySQL下載安裝,Mysql ERROR: 1253 解決方法
  • 勝利大逃亡英雄逃亡方案,HDU - 1253 勝利大逃亡 BFS
  • 大一c語言期末考試試題及答案匯總,電大計算機C語言1253,1253《C語言程序設計》電大期末精彩試題及其問題詳解
  • lu求解線性方程組,P1253 [yLOI2018] 扶蘇的問題 (線段樹)
  • c語言程序設計基礎題庫,1253號C語言程序設計試題,2016年1月試卷號1253C語言程序設計A.pdf
  • 信奧賽一本通官網,【信奧賽一本通】1253:抓住那頭牛(詳細代碼)
  • c語言程序設計1253,1253c語言程序設計a(2010年1月)
  • 勝利大逃亡英雄逃亡方案,BFS——1253 勝利大逃亡
  • 直流電壓測量模塊,IM1253B交直流電能計量模塊(艾銳達光電)
  • c語言程序設計第三版課后答案,【渝粵題庫】國家開放大學2021春1253C語言程序設計答案
  • 18轉換為二進制,1253. 將數字轉換為16進制
  • light-emitting diode,LightOJ-1253 Misere Nim
  • masterroyale魔改版,1253 Dungeon Master
  • codeformer官網中文版,codeforces.1253 B
  • c語言程序設計考研真題及答案,2020C語言程序設計1253,1253計算機科學與技術專業C語言程序設計A科目2020年09月國家開 放大學(中央廣播電視大學)
  • c語言程序設計基礎題庫,1253本科2016c語言程序設計試題,1253電大《C語言程序設計A》試題和答案200901
  • 肇事逃逸車輛無法聯系到車主怎么辦,1253尋找肇事司機