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的值:

每一行的像素排列,一定要注意顺序SAV(FF,00,00,XY),接下来的是Active video,然后是EAV(FF,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
时间: 2024-10-13 02:48:49

BT.656 NTSC制式彩条生成模块(verilog)的相关文章

标准BT.656并行数据结构

转自网络,感谢原作者和转载者. 还有参考:百科http://baike.baidu.com/link?url=bqBT3S7pz_mRJoQE7zkE0K-R1RgQ6FmHNOZ0EjhlSAN_oy-2-hj6G9oMPfTwPZvUoMTc5pCiAuQtUXj0SY--C_ 更重要的参考:http://www.spacewire.co.uk/video_standard.html 原文: BT.656并行接口除了传输4:2:2的YCbCr视频数据流外,还有行.列同步所用的控制信号.如图3

ITU-R BT.656 协议

ITU-R BT.601和ITU-R BT.656国际电信联盟(International Telecommunication Union)无线通信部门(ITU-R)制定的标准.严格来说,ITU-R BT.656应该是隶属ITU-R BT.601的一个子协议.ITU-R BT.601是演播室数字电视编码参数标准,而ITU-R BT.656 则是ITU-R BT.601附件A中的数字接口标准,用于主要数字视频设备(包括芯片)之间采用27Mhzs并口或243Mbs串行接口的数字传输接口标准. ITU

传感器仿真平台——数据生成模块(三)

数据生成模块有下面这样一种情况: 对于不同的传感器仿真实验,所使用的数据类型,数据数量不一样. 如实验一是进行最大覆盖率实验,则他需要的数据格式可能是如下所示: 1 Class Sensor 2 { 3 public int x; 4 public int y; 5 public double direction; //方向 6 public double sweep;//扇形大小 7 } 实验二进行的是信号强度实验,则他可能还需要一个用来作为覆盖物的目标,如下: 1 Class Target

apache 单独生成模块

apache 单独生成模块 一般这种模块都是后期自己去生成的,比如一般在安装apache时都会--enable-so  ,允许动态加载模块. 这个模块你可以这样去生成. 1.下载一个与当前使用的apache一样版本的安装包. 2.解压安装包,然后进入其目录#cd /tmp/httpd-2.2.11/modules/mappers/#ls   ,此目录有个mod_speling.c文件 3.生成模块/usr/local/apache/bin/apxs -c -i -a mod_speling.c

thinkphp3.2自动生成模块BIND_MODULE

thinphp3.2中提供了自定义生成模块与控制器的常量,分别是BIND_MODULE,BUILD_CONTROLLER_LIST 在 index.php 文件中定义 BIND_MODULE,BUILD_CONTROLLER_LIST 常量 1 2 3 4 5 6 7 8 9 10 11 // 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false define('APP_DEBUG',True); // 定义应用目录 define('APP_PATH','./App/'); // 自动

日期区间正则表达式生成模块

功能:给定开始日期和结束日期,返回匹配该段日期区间的正则表达式.生成的正则表达式假定了每个月都有39天,即01-39,所以不要使用该模块来判断日期的合法性.该模块生成的正则表达式的使用场景是从一组合法日期中提取给定区间内的日期.源码如下,使用scala实现. def genRegexp(start:String,end:String): String = { //s:开始e:结束y:年m:月d:日o:个位t:十位 //sy:开始年em:结束月,其他变量命名规则相同 val sy = start.

模块总结-二维码生成模块

qrcode 模块可以便捷地生成二维码,只是生成的二维码图像大小无法编辑. 1 import qrcode 2 qr = qrcode.QRCode( 3 version=1, 4 error_correction=qrcode.constants.ERROR_CORRECT_L, 5 box_size=100, 6 border=4, 7 ) 8 qr.add_data('hello, qrcode') ##二维码增添的数据 9 qr.make(fit=True) 10 img = qr.ma

python随机生成模块的应用

random() random()方法不能直接访问,需要导入random模块,然后通过random静态对象调用该方法 import random #用import导入random模块 random.randint(a,b)函数指定范围内随机数生成,其中参数a是最低限,参数b是上限 1 import random #导入随机数生成模块 2 print(random.randint(0,20)) # 打印指定范围内的随机数值 ,其中下限参数a不得大于上限参数b 终端执行结果13 random.ran

随机生成模块

import random print(random.randint(1,4))#从1到4随机生成一个数字 print(random.randrange(1,4))#从1到3随机生成一个数字,不包含3 print(random.randrange(1,10,2))#1到9随机生成一个基数 print(random.randrange(0,10,2))#1到9随机生成一个偶数 print(random.random())#随机生成一个浮点数,范围是0-1之间 print(random.unifor