BT.656 NTSC制式彩條生成模塊(verilog)


BT.656 NTSC制式彩條生成模塊(verilog)

1.知識儲備

隔行掃描是將一副圖像分成兩場掃描,第一場掃描第1,2,5,7...等奇數行,第二場掃描2,4,6,8...等偶數行,並把掃奇數行的場稱為奇數場,掃偶數行的場稱為偶數場,一幅圖像經過兩次掃描即可。由左到右的掃描稱為行掃描,由上到下的掃描稱為場掃描。

對於標准的8bit BT656(YUV4:2:2)標清制式來說,一幀圖像的格式定義如下:

 

一行是由4個部分組成:行 = 結束碼(EAV) + 水平消隱(Horizontal Vertical Blanking) + 起始碼(SAV) + 有效數據(Active Video)

 

注意:實際的工程中彩條每一行像素點的排列並不是這樣的,而是(SAV Code ->Active video->EAV Code->Blanking video)

2.代碼分析

TPG端口說明:

reset_in:由SDI播出工程內部信號提供。

pclk_in:與播出時鍾tx_usrclk對接。

data_out:輸出圖像數據。

tx_sd_ce:門控時鍾(SD-SDI,5/6/5/6)

並且初識化像素位置pixels=1,行位置lines=1,即圖像掃描的初始位置。

    彩條中各種色彩值設定(忽略十進制的數字,部分有誤),同時定義了用來存儲當前顏色的寄存器cur_color

 定義常數,總共有多少行,多少列(1716 525

 

 

彩條顏色分配函數,通過像素點的位置來分配當前位置的顏色。

 

有效像素點的排列如下圖所示:

 

pixels初始值為1,則

01:Cb

10:Y

11:Cr

00:Y

01:Cb

通過pixels[0],pixels[1:0]來分割cur_color,得到colorValue.

以下always塊里面是行掃描和場掃描控制,當一行掃描完成后,pixels回到初始位置,line加1.

 

根據行來控制F,V的值:

 

每一行的像素排列,一定要注意順序SAVFF,00,00,XY,接下來的是Active video,然后是EAVFF,00,00,XY),最后是Blanking video,80,10填充。

 

視頻數據的輸出:

顏色數據是8位的,SDI工程接收的是10bit的數據,如果要對接,就需要進行低位填充,當數據是ff時,低2位填充11,當數據不是ff時,低2位填充00.

 

module tpg(
  reset_in,
  pclk_in,
  pclk_out,
  data_out,
  pixels_out,
  tx_sd_ce
 );

input  reset_in;
input  pclk_in;
input  tx_sd_ce;
output pclk_out;
output [9:0]data_out;
output [10:0]pixels_out;

reg [10:0] pixels = 1;
reg [9:0] lines = 1;
reg [7:0] data;
reg F, V;

wire [10:0] pixels_w;


`define V_TOTAL_SIZE 525
`define V_ACTIVE_SIZE 239 //* 240 line
`define V_BLANK_SIZE 22 //* 22 line

`define H_TOTAL_SIZE 1716
`define H_ACTIVE_SIZE 1444 //* 1444 pixel (4(SAV) + 720*2(Y+Cr/Cb))
`define H_BLANK_SIZE 272 //* 272 pixel (4(EAV) + 268)

`define H_COUNT_ADD_ONE 11'b1
`define V_COUNT_ADD_ONE 10'b1

//* Y, Cb, Cr values for test pattern colours
//* 75% amplitude, 100% saturated
//* Values from "Video De-mystified" book, chapter 3
reg [23:0] white =   {8'heb, 8'h80, 8'h80};//{8'd235, 8'd128, 8'd128};
reg [23:0] black =   {8'h10, 8'h80, 8'h80};//{8'd16,  8'd128, 8'd128};
reg [23:0] blue =    {8'h29, 8'hf0, 8'h6e};//{8'd35,  8'd212, 8'd114};
reg [23:0] green =   {8'h91, 8'h36, 8'h22};//{8'd112, 8'd72,  8'd58};
reg [23:0] red =     {8'h51, 8'h5a, 8'hf0};//{8'd65,  8'd100, 8'd212};
reg [23:0] cyan =    {8'haa, 8'ha6, 8'h10};//{8'd131, 8'd156, 8'd44};
reg [23:0] yellow =  {8'hd2, 8'h10, 8'h92};//{8'd162, 8'd44,  8'd142};
reg [23:0] magenta = {8'h6a, 8'hca, 8'hde};//{8'd84,  8'd184, 8'd198};
reg [23:0] cur_color;

//產生圖像數據,數據8個8個出
function [7:0] colorValue;
input [10:0] pixels;
begin
   if(452 > pixels)
      cur_color = white;
   else if(632 > pixels)
      cur_color = black;
   else if(812 > pixels)
      cur_color = blue;
   else if(992 > pixels)
      cur_color = green;
   else if(1172 > pixels)
      cur_color = red;
   else if(1352 > pixels)
      cur_color = cyan;
   else if(1532 > pixels)
      cur_color = yellow;
   else
      cur_color = magenta;
   
   //* Y
   if(pixels[0] == 1'h0)
      colorValue = cur_color[23:16];
   //* Cr and Cb
   else if(pixels[1:0] == 2'h1)
      colorValue = cur_color[15:8]; //* Cb
   else
      colorValue = cur_color[7:0]; //* Cr
end
endfunction


//復位,pixels和lines都歸1,像素值逐漸增加,當一行的像素填充完后
//繼續掃描下一行,即lines加1
always @ (posedge pclk_in)
    if(reset_in)
        begin
            pixels <= 1;
              lines <= 1;
        end
    else if(tx_sd_ce)
        begin
            if(pixels < `H_TOTAL_SIZE)
                pixels <= pixels + `H_COUNT_ADD_ONE;
            else 
                begin
                    pixels <= 1;
                    if(lines < `V_TOTAL_SIZE)
                        lines <= lines + `V_COUNT_ADD_ONE;
                    else
                        lines <= 1;    
                end
        end


//通過bt656標准,行結構的分布來確定F,V
always @ (posedge pclk_in)
    if(reset_in)
        data <= 10'h00;
  else if(tx_sd_ce)
        begin
            //* even field is 1
            if(lines<4 || lines>265)
                F <= 1;
            else
                F <= 0;

        //* vertical blank is 1
        if(lines<20 || (lines>263 && lines<283))
          V <= 1;
        else
          V <= 0;

/*
        if(pixels <=1440)
          begin
              if( V== 1)
                data <= (pixels[0] == 1) ? 8'h80 : 8'h10;
              else
                data <= colorValue(pixels);
          end
        else if(pixels == 1441)  
          data <= 8'hFF;
        else if(pixels == 1442)
          data <= 8'h00;
        else if(pixels == 1443)
          data <= 8'h00;
        else if(pixels == 1444)
          begin
            //* EAV is 1   
            //H <= 1;
            //data <= { 1'b1, F, V, H, (V ^ H), (F ^ H), (F ^V ), (F ^ V ^ H) };
            data <= { 1'b1, F, V, 1'b1, (V ^ 1'b1), (F ^ 1'b1), (F ^ V ), (F ^ V ^ 1'b1) };
          end
        else if(pixels <= 1712)
            data <= (pixels[0] == 1) ? 8'h80 : 8'h10;
        else if(pixels == 1713)
          data <= 8'hFF;
        else if(pixels == 1714)
          data <= 8'h00;
        else if(pixels == 1715)
          data <= 8'h00;
        else if(pixels == 1716)
              begin
                //* SAV is 0    
                //H <= 0;
                //data <= { 1'b1, F, V, H, (V ^ H), (F ^ H), (F ^V ), (F ^ V ^ H) };
                data <= { 1'b1, F, V, 1'b0, (V ^ 1'b1), (F ^ 1'b1), (F ^ V ), (F ^ V ^ 1'b1) };
              end
        end
*/
        if(pixels == 1)
          data <= 8'hFF;
        else if(pixels == 2)
          data <= 8'h00;
        else if(pixels == 3)
          data <= 8'h00;
        else if(pixels == 4)
              begin
                //* EAV is 1    //換成sav
                //H <= 1;
                //data <= { 1'b1, F, V, H, (V ^ H), (F ^ H), (F ^V ), (F ^ V ^ H) };
                data <= { 1'b1, F, V, 1'b0, (V ^ 1'b1), (F ^ 1'b1), (F ^ V ), (F ^ V ^ 1'b1) };
              end
        else if(pixels <= 1444) //* horizontal blanking pixel
                begin
                    if( V== 1)
                      data <= (pixels[0] == 1) ? 8'h80 : 8'h10;
                    else
                      data <= colorValue(pixels);
                end              
        else if(pixels == 1445)
                data <= 8'hFF;
        else if(pixels == 1446)
                data <= 8'h00;
        else if(pixels == 1447)
                data <= 8'h00;
        else if(pixels == 1448)
              begin
                //* SAV is 0 //換成eav
                //H <= 0;
                //data <= { 1'b1, F, V, H, (V ^ H), (F ^ H), (F ^V ), (F ^ V ^ H) };
                data <= { 1'b1, F, V, 1'b1, (V ^ 1'b0), (F ^ 1'b0), (F ^ V ), (F ^ V ^ 1'b0) };
              end
        else //* horizontal active pixel
            //* if vertical blank, fill with 0x80, 0x10
              data <= (pixels[0] == 1) ? 8'h80 : 8'h10;
        end

assign pclk_out = pclk_in;
assign data_out = (data == 8'hff) ? {data, 2'b11} : {data, 2'b00};
assign pixels_out = pixels;

assign pixels_w = pixels;
endmodule

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM