設計背景
VGA (Video Graphics Array) 即視頻圖形陣列,是IBM于1987年隨PS/2機(PersonalSystem 2)一起推出的使用模擬信號的一種視頻傳輸標準。這個標準對于現今的個人電腦市場已經十分過時。但在當時具有分辨率高、顯示速率快、顏色豐富等優點,在彩色顯示器領域取得了廣泛的應用,是眾多制造商所共同支持的一個低標準。
設計原理
VGA的實體圖與接口示意圖,如下圖所示,它有15個針孔:
在本次設計使用的開發板中,VGA的電路原理圖如下圖所示:
通過原理圖,我們不難發現,VGA需要我們控制的接口只有5個:
顯示器的掃描規律是什么?本設計采用逐行掃描,逐行掃描是掃描從屏幕左上角一點開始,從左向右逐點掃描,每掃描完一行,電子束回到屏幕的左邊下一行的起始位置,在這期間,CRT對電子束進行消隱,每行結束時,用行同步信號進行行同步;當掃描完所有的行,形成一幀,用場同步信號進行場同步,并使掃描回到屏幕左上方,同時進行場消隱,開始下一幀。通過這種掃描規律,很容易看出,在設計兩個有效范圍計數器時,場同步信號計數器是以行同步信號計數器為周期的。
VGA的顯示標準如下表所示:
對于普通的VGA顯示器都要嚴格遵循“VGA工業標準”,否則可能會損害VGA顯示器,因此我們在設計時VGA控制器時,都需要參考顯示器的顯示標準,下面是VGA的行掃描時序與場掃描時序:
行掃描時序:
場掃描時序:
根據上述顯示器的掃描參數以及掃描時序,例如800*600@60的顯示模式,60指得是顯示器圖像的刷新頻率,時鐘40MHz指得是一個像素輸出的頻率。800*600為VGA的分辨率,指有效顯示區域為時序中的c段只有800*600,也就是行計數在[216,1016],列計數在[27,627],在這個范圍內,給RGB色值才會有效。
在VGA 工業標準顯示模式要求:行同步、場同步都為負極性,即同步脈沖要求是負脈沖。行同步信號上電拉高,在行同步計數為0時拉低a個時鐘周期,即128,之后拉高,在行同步計數到1055時,行同步計數器清零,場同步計數器加1。在行掃描時序中,掃描計數時,周期就是一個像素點的時間。
場同步信號上電拉高,在場同步計數為0時拉低場同步a個時鐘周期,即4,之后拉高,在場同步計數到627時,場同步計數器清零。
在VGA控制器中,還需要控制三個接口,即三種基色(R、G、B),它們共專用8位,分別是Red為3位,Green為3位,Blue為3位,所以可以顯示256種顏色,RGB數據的格式如下表所示:
設計框架
本設計選擇的VGA顯示標準為800*600@60,實現點亮整個屏幕,并顯示為全紅。通過分析設計的功能,可以得到如下的頂層架構:
頂層模塊端口列表如下:
vga_pll模塊是為了滿足分辨率800*600@60的時鐘為40MHz,而ZX_1開發板的系統時鐘為50MHz,通過鎖相環,將50MHz轉化為40MHz。vga_control模塊是為了設定行場同步信號,并標定出有效顯示區域,并輸出控制顏色的po_rgb信號。為了便于移植,根據800*600@60分辨率下的參數,對其進行參數化定義。
設計代碼
頂層模塊vga_display_pure代碼:
module vga_display_pure (pi_clk, pi_rst_n, po_hs, po_vs, po_rgb); input pi_clk, pi_rst_n; //系統時鐘復位 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; //系統時鐘復位 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 (行數) parameter V_A = 4; parameter V_B = 23; parameter V_C = 600; parameter V_D = 1; parameter V_E = 628; //行掃描計數器, 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 //場掃描計數器 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視圖如下:
仿真測試
為了驗證本設計的邏輯正確性,我們先對其進行了仿真,在仿真時,為了減少仿真的時間,先將行、場掃描的對應參數,進行了縮放,這樣不僅節約了仿真時間,同時由于掃描數據量變少,更加便于分析觀察。其仿真代碼所示:
`timescale 1ns/1ps //仿真時間精度時間單位 module vga_display_pure_tb; reg pi_clk, pi_rst_n; //系統時鐘復位 wire po_vs; //VGA場同步信號 wire po_hs; //VGA行同步信號 wire [7:0] po_rgb; //VGA場紅綠藍三基色 //初始化數據,并附相應初值 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基色信號輸出,時序仿真細節圖如下所示:
通過觀察和分析時序圖,可以發現與設計吻合,接下來則可進行管腳分配,并下板驗證,驗證結果如下:
-
FPGA
+關注
關注
1630文章
21766瀏覽量
604598 -
VGA
+關注
關注
5文章
536瀏覽量
63051
原文標題:源碼系列:基于FPGA的VGA驅動設計(附源工程)
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論