NTSC和PAL制同步信号模拟输出
原由:由于我想输出一个NTSC制和PAL制的同步黑场,只需要输出同步信号,之后输出rgb信号给ADV(7123)后输出到显示屏。下面是我的心路历程和知识总结
一、了解NTSC和PAL
- PAL:电视标准,每秒25帧,电视扫描线为625线,奇场在前,偶场在后,标准的数字化PAL电视标准分辨率为720*576, 24比特的色彩位深,画面的宽高比为4:3, PAL制电视的供电频率为50Hz,场频为每秒50场,帧频为每秒25帧,扫描线为625行。
- NTSC:电视的供电频率为60Hz,场频为每秒60场,帧频为每秒30帧,扫描线为525行,图像信号带宽为6.2MHz。采用NTSC制的国家美国、日本等国家
当然若没有任何知识储备,这两段话很难理解,不过这里不做过多的解释,网络上的详解有很多,大家可以自行查看,也可以查看下面是我推荐的比较详细易懂的文章。
PAL与NTSC制式的详解
二、NTSC和PAL时序参数
大致了解NTSC和PAL概念内容之后,我们需要找到具体 的时序参数,为之后写代码打下基础,大部分的时序参数我上传到文档里,大家可以自行查看,这个有规定的标准,只需找到文档即可
- NTSC制→720*480i60HZ
- PAL制→720*576i50HZ
由图片可知NTSC和PAL制的时序参数如下 - NTSC:
H_TOTAL=1716
V_TOTAL=525
H_ACT=1440
V_ACT=480
H_FRONT = 38
HS_WIDTH = 124
H_BACK_POCH = 114 - PAL
H_TOTAL=1728
V_TOTAL=625
H_ACT=1440
V_ACT=576
H_FRONT = 24
HS_WIDTH = 126
H_BACK_POCH = 138
三、垂直同步波形详细信息
在整个同步模拟信号输出中最重要的一步,我们需要将垂直同步波形和水平同步波形叠加到一起,直接输出一个同步信号模拟波形,首先我们先看垂直同步波形的详细信息
如果大家有《数字电视基础-视频和音频系统的设计与安装》这本书也可以查看这本书的P11-P24,了解复合视频信号的组成。
下面的基准时钟都为27M
- NTSC制垂直同步波形的详细信息
由图像可以得出:一个长度为9行的块被划分为长度为3行的3个段。第一段包含6个预均衡脉冲,第二段包含具有6个锯齿的垂直同步脉冲,第三段包含6个后均衡脉冲。由NTSC制的时序参数我们可以将各个脉冲宽度计算出来。
图中的H=1716,0.5H=858
1s=1000000us
27mhz=27000000hz
经过单位换算可知
1us的宽度为27
4.7us宽度为27×4.7=127
2.3us宽度为27×2.3=62
- PAL制垂直同步波形的详细信息
图中的H=1728,0.5H=864
1s=1000000us
27mhz=27000000hz
经过单位换算可知
1us的宽度为27
4.7us宽度为27×4.7=127
27.1us宽度为27×27.1=731
2.3us宽度为27×2.3=62
四、水平同步波形详细信息
大家在上面垂直的图中应该都看到了,由于是复合视频信号,所以水平和垂直都复合到一块了,水平就是在每个hs的位置有一个类似于垂直锯齿的东东。
这里这个宽度可以参考时序参数,当然通过波形计算也可以。
- NTSC:
H_FRONT = 38
HS_WIDTH = 124
H_BACK_POCH = 114 - PAL
H_FRONT = 24
HS_WIDTH = 126
H_BACK_POCH = 138
五、代码
- NTSC制
module test_tpg(
input clk_148m5,
input rst_n,
output wire [9 :0] dac_r,
output wire [9 :0] dac_g,
output wire [9 :0] dac_b
);
parameter H_ACT = 1440;//1200;//
parameter H_TOTAL = 1716;//2020;//
parameter V_ACT = 480;//1920;//
parameter V_TOTAL = 525;//1136;//
parameter H_BACK_POCH = 114;//16;//
parameter HS_WIDTH = 124;//8;//8;
parameter VS_WIDTH = 3;//2;//8;//
parameter H_FRONT = 38;
parameter V_FRONT = 19;
parameter V_BACK_POCH = 26;//20;
(* keep = "true" *)reg [11:0] h_cntr;
(* keep = "true" *)reg [11:0] v_cntr;
(* keep = "true" *)reg vs;
(* keep = "true" *)reg de;
(* keep = "true" *)reg [9 :0] test_r;
(* keep = "true" *)reg [9 :0] test_g;
(* keep = "true" *)reg [9 :0] test_b;
always @ ( posedge clk_148m5 or negedge rst_n)begin
if(!rst_n)begin
h_cntr <= 12'h0;
v_cntr <= 12'h0;
end
else
begin
if( h_cntr == H_TOTAL - 12'h1 )
h_cntr <= 12'h0;
else
h_cntr <= h_cntr + 12'h1;
if((v_cntr == V_TOTAL) && (h_cntr == H_TOTAL -12'h1))
v_cntr <= 12'h1;
else if(h_cntr == H_TOTAL -12'h1)
v_cntr <= v_cntr + 12'h1;
else
v_cntr <= v_cntr;
end
end
always @ ( posedge clk_148m5 or negedge rst_n)begin
if(!rst_n)
de <= 1'd0;
else
if(h_cntr >= H_FRONT+HS_WIDTH+H_BACK_POCH && h_cntr < H_TOTAL && v_cntr >= V_FRONT+VS_WIDTH+V_BACK_POCH && v_cntr < V_TOTAL)
de <= 1'd1;
else
de <= 1'd0;
end
always @ ( posedge clk_148m5 or negedge rst_n)begin
if(!rst_n)
vs <= 1'd0;
else
begin
if((v_cntr>=12'h1 && v_cntr <= 12'd9)||(v_cntr >= 12'd264 && v_cntr <= 12'd271)||(h_cntr >= 12'd857 && h_cntr <=12'd1715 && v_cntr==12'd263)||(h_cntr >= 12'd0 && h_cntr <=12'd857 && v_cntr==12'd272))
vs <= 1'd1;
else
vs <= 1'd0;
end
end
always @(posedge clk_148m5 or negedge rst_n)begin
if(!rst_n)begin
test_r <= 10'd0;
test_g <= 10'd0;
test_b <= 10'd0;
end
else
// if(vs)begin
if((v_cntr >= 12'd1 && v_cntr <= 12'd3)||(v_cntr >= 12'd7 && v_cntr <= 12'd9)||(v_cntr >=12'd264 && v_cntr <= 12'd265)||(h_cntr >=12'd857 && h_cntr <= 12'd1715 &&v_cntr == 12'd263)||(h_cntr >=12'd0 && h_cntr <= 12'd857 &&v_cntr == 12'd266)||(v_cntr >=12'd270 && v_cntr <= 12'd271)||(h_cntr >=12'd857 && h_cntr <= 12'd1715 &&v_cntr == 12'd269)||(h_cntr >=12'd0 && h_cntr <= 12'd857 &&v_cntr == 12'd272))begin
if((h_cntr >= 12'd0 && h_cntr <= 12'd61)||(h_cntr >= 12'd857 && h_cntr <= 12'd919))begin
test_r <= 10'd0;
test_g <= 10'd0;
test_b <= 10'd0;
end
else begin
test_r <= 10'd93;
test_g <= 10'd93;
test_b <= 10'd93;
end
end
else if((v_cntr >= 12'd4 && v_cntr <= 12'd6)||(v_cntr >=12'd267 && v_cntr <= 12'd268)||(h_cntr >=12'd857 && h_cntr<=12'd1715&&v_cntr == 12'd266)||(h_cntr >=12'd0 && h_cntr <= 12'd857 &&v_cntr == 12'd269))begin
if((h_cntr >= 12'd730 && h_cntr <=12'd857)||(h_cntr >= 12'd1588 && h_cntr <= 12'd1715))begin
test_r <= 10'd93;
test_g <= 10'd93;
test_b <= 10'd93;
end
else begin
test_r <= 10'd0;
test_g <= 10'd0;
test_b <= 10'd0;
end
end
//end
else begin
if(h_cntr >= 12'h0 && h_cntr <= {12'd61,1'd0})begin
test_r <= 10'd0;
test_g <= 10'd0;
test_b <= 10'd0;
end
else begin
test_r <= 10'd100;
test_g <= 10'd100;
test_b <= 10'd100;
end
end
end
assign dac_r = test_r;
assign dac_g = test_g;
assign dac_b = test_b;
endmodule