代码改变世界

基于FPGA的视频时序生成

2019-04-20 18:37  江南夜色下的小桥屋檐  阅读(2362)  评论(0编辑  收藏  举报

之前用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写的。