• 正文
    • 設(shè)計背景
    • 設(shè)計原理
    • 設(shè)計框架
    • 設(shè)計代碼
    • 仿真測試
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

源碼系列:基于FPGA的VGA驅(qū)動設(shè)計(附源工程)

01/14 11:30
1992
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

大俠好,歡迎來到FPGA技術(shù)江湖,江湖偌大,相見即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。

今天給大俠帶來基于FPGA的VGA驅(qū)動設(shè)計。

設(shè)計背景

VGA (Video Graphics Array) 即視頻圖形陣列,是IBM于1987年隨PS/2機(PersonalSystem 2)一起推出的使用模擬信號的一種視頻傳輸標準。這個標準對于現(xiàn)今的個人電腦市場已經(jīng)十分過時。但在當時具有分辨率高、顯示速率快、顏色豐富等優(yōu)點,在彩色顯示器領(lǐng)域取得了廣泛的應(yīng)用,是眾多制造商所共同支持的一個低標準。

設(shè)計原理

VGA的實體圖與接口示意圖,如下圖所示,它有15個針孔:

在本次設(shè)計使用的開發(fā)板中,VGA的電路原理圖如下圖所示:

通過原理圖,我們不難發(fā)現(xiàn),VGA需要我們控制的接口只有5個:

顯示器的掃描規(guī)律是什么?本設(shè)計采用逐行掃描,逐行掃描是掃描從屏幕左上角一點開始,從左向右逐點掃描,每掃描完一行,電子束回到屏幕的左邊下一行的起始位置,在這期間,CRT對電子束進行消隱,每行結(jié)束時,用行同步信號進行行同步;當掃描完所有的行,形成一幀,用場同步信號進行場同步,并使掃描回到屏幕左上方,同時進行場消隱,開始下一幀。通過這種掃描規(guī)律,很容易看出,在設(shè)計兩個有效范圍計數(shù)器時,場同步信號計數(shù)器是以行同步信號計數(shù)器為周期的。

VGA的顯示標準如下表所示:

對于普通的VGA顯示器都要嚴格遵循“VGA工業(yè)標準”,否則可能會損害VGA顯示器,因此我們在設(shè)計時VGA控制器時,都需要參考顯示器的顯示標準,下面是VGA的行掃描時序與場掃描時序:

行掃描時序:

場掃描時序:

根據(jù)上述顯示器的掃描參數(shù)以及掃描時序,例如800*600@60的顯示模式,60指得是顯示器圖像的刷新頻率,時鐘40MHz指得是一個像素輸出的頻率。800*600為VGA的分辨率,指有效顯示區(qū)域為時序中的c段只有800*600,也就是行計數(shù)在[216,1016],列計數(shù)在[27,627],在這個范圍內(nèi),給RGB色值才會有效。

在VGA 工業(yè)標準顯示模式要求:行同步、場同步都為負極性,即同步脈沖要求是負脈沖。行同步信號上電拉高,在行同步計數(shù)為0時拉低a個時鐘周期,即128,之后拉高,在行同步計數(shù)到1055時,行同步計數(shù)器清零,場同步計數(shù)器加1。在行掃描時序中,掃描計數(shù)時,周期就是一個像素點的時間。

場同步信號上電拉高,在場同步計數(shù)為0時拉低場同步a個時鐘周期,即4,之后拉高,在場同步計數(shù)到627時,場同步計數(shù)器清零。

在VGA控制器中,還需要控制三個接口,即三種基色(R、G、B),它們共專用8位,分別是Red為3位,Green為3位,Blue為3位,所以可以顯示256種顏色,RGB數(shù)據(jù)的格式如下表所示:

設(shè)計框架

本設(shè)計選擇的VGA顯示標準為800*600@60,實現(xiàn)點亮整個屏幕,并顯示為全紅。通過分析設(shè)計的功能,可以得到如下的頂層架構(gòu):

頂層模塊端口列表如下:

vga_pll模塊是為了滿足分辨率800*600@60的時鐘為40MHz,而ZX_1開發(fā)板的系統(tǒng)時鐘為50MHz,通過鎖相環(huán),將50MHz轉(zhuǎn)化為40MHz。vga_control模塊是為了設(shè)定行場同步信號,并標定出有效顯示區(qū)域,并輸出控制顏色的po_rgb信號。為了便于移植,根據(jù)800*600@60分辨率下的參數(shù),對其進行參數(shù)化定義。

設(shè)計代碼

頂層模塊vga_display_pure代碼:

module vga_display_pure (pi_clk, pi_rst_n, po_hs, po_vs, po_rgb);    input pi_clk, pi_rst_n; //系統(tǒng)時鐘復(fù)位  output po_vs;  //VGA場同步信號  output po_hs;  //VGA行同步信號  output [7:0] po_rgb;  //VGA場紅綠藍三基色    //----------------VGA時序-----------------------------------  //    顯示模式      時鐘       //    800*600@60  40MHz    //行/場  同步(a)  消隱后沿(b)  有效顯示(c)  消隱前沿(d)  掃描時間(e)  //hs    128    88        800      40        1056  //vs    4      23        600      1        628      wire vga_clk;    vga_pll vga_pll_dut(    .areset(~pi_rst_n),    .inclk0(pi_clk),    .c0(vga_clk)  );    vga_control vga_control_dut(    .pi_clk(vga_clk),     .pi_rst_n(pi_rst_n),     .po_hs(po_hs),    .po_vs(po_vs),    .po_rgb(po_rgb)  );  endmodule

VGA控制器vga_control 模塊代碼:

module vga_control (pi_clk, pi_rst_n, po_hs, po_vs, po_rgb);    input pi_clk, pi_rst_n; //系統(tǒng)時鐘復(fù)位  output reg po_vs;  //VGA場同步信號  output reg po_hs;  //VGA行同步信號  output [7:0] po_rgb;  //VGA場紅綠藍三基色    //----------------VGA時序-----------------------------------  //    顯示模式      時鐘       //    800*600@60  40MHz    //行/場  同步(a)  消隱后沿(b)  有效顯示(c)  消隱前沿(d)  掃描時間(e)  //hs    128    88        800      40        1056  //vs    4      23        600      1        628      //  行(Horizontal)掃描  Parameter (像素)  parameter  H_A  =  128;  parameter  H_B  =  80;  parameter  H_C  =  800;  parameter  H_D  =  40;  parameter  H_E   =  1056;      //  場(Vertical)掃描  Parameter (行數(shù))  parameter  V_A  =  4;  parameter  V_B  =  23;  parameter  V_C  =  600;  parameter  V_D  =  1;  parameter  V_E  =  628;    //行掃描計數(shù)器,   reg [10:0] hcnt;    always @ (posedge pi_clk or negedge pi_rst_n)  begin    if (!pi_rst_n)      hcnt <= 11'd0;    else      begin        if (hcnt == (H_E - 1'b1)) //掃描完一行像素          hcnt <= 11'd0;        else          hcnt <= hcnt + 1'b1;      end   end     //場掃描計數(shù)器  reg [10:0] vcnt;      always @ (posedge pi_clk or negedge pi_rst_n)  begin    if (!pi_rst_n)      vcnt <= 11'd0;    else if (vcnt == (V_E - 1'b1))       vcnt <= 11'd0;    else if (hcnt == (H_E - 1'b1))      vcnt <= vcnt + 1;  end   
  //行同步輸出  always @ (posedge pi_clk or negedge pi_rst_n)  begin    if (!pi_rst_n)      po_hs <= 1'b1;    else if (hcnt < H_A)      po_hs <= 1'b0;    else      po_hs <= 1'b1;  end     //assign po_hs = (hcnt <= H_A - 1'b1) ? 1'b0 : 1'b1;    //場同步輸出  always @ (posedge pi_clk or negedge pi_rst_n)  begin    if (!pi_rst_n)      po_vs <= 1'b1;    else if (vcnt < V_A)      po_vs <= 1'b0;    else      po_vs <= 1'b1;  end     //assign po_vs = (vcnt <= V_A - 1'b1) ? 1'b0 : 1'b1;    wire rgb_en;    assign rgb_en = (hcnt >= H_A + H_B  && hcnt < H_A + H_B + H_C) &&             (vcnt >= V_A + V_B  && vcnt < V_A + V_B + V_C) ? 1'b1 : 1'b0;    assign po_rgb = rgb_en ? 8'b111_000_00 : 8'b0000_0000;  endmodule 

通過編譯后生成的RTL視圖如下:

仿真測試

為了驗證本設(shè)計的邏輯正確性,我們先對其進行了仿真,在仿真時,為了減少仿真的時間,先將行、場掃描的對應(yīng)參數(shù),進行了縮放,這樣不僅節(jié)約了仿真時間,同時由于掃描數(shù)據(jù)量變少,更加便于分析觀察。其仿真代碼所示:

`timescale 1ns/1ps  //仿真時間精度時間單位
module vga_display_pure_tb;    reg pi_clk, pi_rst_n; //系統(tǒng)時鐘復(fù)位  wire  po_vs;  //VGA場同步信號  wire  po_hs;  //VGA行同步信號  wire  [7:0] po_rgb;  //VGA場紅綠藍三基色    //初始化數(shù)據(jù),并附相應(yīng)初值  initial begin    pi_clk = 0;    pi_rst_n = 0;      #200.1 pi_rst_n = 1;    end 
  vga_display_pure vga_display_pure_inst (    .pi_clk(pi_clk),     .pi_rst_n(pi_rst_n),     .po_hs(po_hs),     .po_vs(po_vs),    .po_rgb(po_rgb)  );    always #10 pi_clk = ~pi_clk;  //50MHz時鐘描述
endmodule

仿真圖:

rgb_en信號,只有當po_vs和po_hs同時為高電平時,才有效,并且有po_rgb Red基色信號輸出,時序仿真細節(jié)圖如下所示:

通過觀察和分析時序圖,可以發(fā)現(xiàn)與設(shè)計吻合,接下來則可進行管腳分配,并下板驗證,驗證結(jié)果如下:

獲取源碼,請在“FPGA技術(shù)江湖”公眾號內(nèi)回復(fù)“VGA驅(qū)動設(shè)計源碼”,可獲取源碼文件。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

任何技術(shù)的學(xué)習就好比一個江湖,對于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。