之前用FPGA做过视频时序方面的设计,现将视频时序的设计方法分享给大家,希望对大家有所帮助。
时序部分可以参考CEA-861D,VESA时序标准。
1080P一帧视频中,一行有2200个像素,其中280个像素为消影区像素,1920个像素为有效像素。 一场有1125行,其中45行为消影区,1080个有效行。
1080P@60的时钟计算方法: 2200x1125x60=148500000, 即148.5MHz。
1080P的时序图请参考如下图所示:
通过以上两幅图,我们可以很好地理解视频时序,在每一行的开始前和结束后,都是Blank。
我们可以通过设计计数器的方法来实现 代码如下:
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: Ricky // // Create Date: 16:38:46 04/17/2019 // Design Name: Video timming generator // Module Name: Video_timming // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module Video_timming( input wire clk, input wire reset_n, output reg hsync_out, output reg hblank_out, output reg vsync_out, output reg vblank_out, output reg DE_out ); ////////////////////hsblnk means the biggest active pixels from 0~1919, and it's the begining of hblank. ////////////////////hssync means the active pixels + Front Proch, and it's the begining of hsync signal. ////////////////////hesync means the active pixels + Front Proch + hsync, it's the end of hsync signal. ////////////////////heblnk means the biggest line pixels from 0~2199,it's the end of a line. ////////////////////vsblnk means the biggest active lines from 0~1079, and it's the begining of vblank. ////////////////////vssync means the active lines + V Front Proch, and it's the begining of vsync signal. ////////////////////vesync means the active lines + V Front Proch + vsync, it's the end of vsync signal. ////////////////////veblnk means the biggest lines from 0~1124, it's the end of a frame. parameter [11:0] tc_hsblnk = 12'b0111_0111_1111; //hsblnk_1080P = 1920-1 = 1919 parameter [11:0] tc_hssync = 12'b0111_1101_0111; //hssync_1080P = 1919 + 88 = 2007 parameter [11:0] tc_hesync = 12'b1000_0000_0011; //hesync_1080P = 1919 + 88 + 44 = 2051 parameter [11:0] tc_heblnk = 12'b1000_1001_0111; //heblnk_1080P = 1919 + 88 + 44 + 148 = 2199 parameter [11:0] tc_vsblnk = 12'b0100_0011_0111; //vsblnk_1080P = 1080 -1 =1079 parameter [11:0] tc_vssync = 12'b0100_0011_1011; //vssync_1080P = 1079 + 4 = 1083 parameter [11:0] tc_vesync = 12'b0100_0100_0000; //vesync_1080P = 1079 + 4 + 5 = 1088 parameter [11:0] tc_veblnk = 12'b0100_0110_0100; //veblnk_1080P = 1079 + 4 + 5 + 36 = 1124 reg reg0; reg reg1; wire rst_n; reg hsync,vsync,hblank,vblank; reg [11:0] pixel_cnt,h_cnt,h_cntb; always @ (posedge clk or negedge reset_n) //这里使用同步复位异步释放的方法设计复位 begin if ( reset_n == 1'b0)begin reg0 <= 0; reg1 <= 0; end else begin reg0 <= 1; reg1 <= reg0; end end assign rst_n = reg1; always @ (posedge clk or negedge rst_n) begin // Pixel clock count if(!rst_n) pixel_cnt <= 12'd0; else if(pixel_cnt >= tc_heblnk) //2199 pixel_cnt <= 12'd0; else pixel_cnt <= pixel_cnt + 1; end always @ (posedge clk or negedge rst_n) begin// generate hsync if(!rst_n) hsync <= 1'b0; else if((pixel_cnt >= tc_hssync) && (pixel_cnt < tc_hesync))//2007 //2051 hsync <= 1'b1; else hsync <= 1'b0; end always @ (posedge clk or negedge rst_n) begin // generate hblank if(!rst_n) hblank <= 1'b1; else if((pixel_cnt >= tc_hsblnk) && (pixel_cnt < tc_heblnk)) //1919 //2199 hblank <= 1'b1; else hblank <= 1'b0; end always @ (posedge clk or negedge rst_n) begin //Line count if(!rst_n) h_cnt <= 12'd0; else if(h_cnt > tc_veblnk) //1124 h_cnt <= 12'd0; else if(pixel_cnt == tc_hssync-1) //2007 h_cnt <= h_cnt + 1; else h_cnt <= h_cnt; end always @ (posedge clk or negedge rst_n) begin // Generate vsync if(!rst_n) vsync <= 1'b0; else if ((h_cnt > tc_vssync) && (h_cnt <= tc_vesync)) //1083 //1088 vsync <= 1'b1; else vsync <= 1'b0; end always @ (posedge clk or negedge rst_n) begin //Line Countb if(!rst_n) h_cntb <= 12'd0; else if(h_cntb > tc_veblnk) //1124 h_cntb <= 12'd0; else if(pixel_cnt == tc_hsblnk - 1) //1919 h_cntb <= h_cntb + 1; else h_cntb <= h_cntb; end always @ (posedge clk or negedge rst_n) begin // Generate vblank if(!rst_n) vblank <= 1'b1; else if((h_cntb > tc_vsblnk) && (h_cntb <= tc_veblnk)) //1079 //1124 vblank <= 1'b1; else vblank <= 1'b0; end always @ (posedge clk or negedge rst_n) begin // Generate output singles if(!rst_n) begin hsync_out <= 1'b0; vsync_out <= 1'b0; hblank_out <= 1'b0; vblank_out <= 1'b0; DE_out <= 1'b0; end else begin hsync_out <= hsync; vsync_out <= vsync; hblank_out <= hblank; vblank_out <= vblank; DE_out <= (~ hblank) & (~ vblank); end end endmodule
TB如下:
`timescale 1ns/1ns module TB_Timing_gen; reg clk, reset_n; wire hsync,vsync,de,hblank,vblank; initial begin clk = 0; reset_n = 0; #100 reset_n = 1; end always #10 clk = ~clk; Video_timming timing_inst( .clk (clk), .reset_n (reset_n), .hsync_out (hsync), .hblank_out (hblank), .vsync_out (vsync), .vblank_out (vblank), .DE_out (de) ); endmodule
波形如下:
每行有1920个像素。
hsync, DE,hblank的关系。
Vblan, Vsync和DE的关系,和hsync的关系。
原创代码,转载请注明出处,该部分已经申请发明专利,只是这里是用verilog写的,之前专利是用VHDL写的。