作者:李西銳??校對:陸輝
大俠好,歡迎來到FPGA技術(shù)江湖。本系列將帶來FPGA的系統(tǒng)性學(xué)習(xí),從最基本的數(shù)字電路基礎(chǔ)開始,最詳細(xì)操作步驟,最直白的言語描述,手把手的“傻瓜式”講解,讓電子、信息、通信類專業(yè)學(xué)生、初入職場小白及打算進(jìn)階提升的職業(yè)開發(fā)者都可以有系統(tǒng)性學(xué)習(xí)的機(jī)會。
系統(tǒng)性的掌握技術(shù)開發(fā)以及相關(guān)要求,對個人就業(yè)以及職業(yè)發(fā)展都有著潛在的幫助,希望對大家有所幫助。本次帶來Vivado系列,VGA驅(qū)動設(shè)計(jì)。話不多說,上貨。
VGA驅(qū)動設(shè)計(jì)
VGA(Video Graphics Array)視頻圖形陣列是IBM于1987年提出的一個使用模擬信號的電腦顯示標(biāo)準(zhǔn)。VGA接口即電腦采用VGA標(biāo)準(zhǔn)輸出數(shù)據(jù)的專用接口。VGA接口共有15針,分成3排,每排5個孔,顯卡上應(yīng)用最為廣泛的接口類型,絕大多數(shù)顯卡都帶有此種接口。它傳輸紅、綠、藍(lán)模擬信號以及同步信號(水平和垂直信號)。
VGA作為視頻接口,具有分辨率高、顯示速度快、顏色豐富等優(yōu)點(diǎn)。隨著電子產(chǎn)品以及視頻圖像處理技術(shù)的發(fā)展,VGA接口應(yīng)用越來越廣泛。
首先我們先來看一下VGA接口,在我們的接口中,有很多針腳,我們在驅(qū)動之前,首先要了解每一個針腳的作用。接口原理圖如下:
如圖,我們可以看出在這15個針腳中,只有5個針腳需要我們?nèi)ヲ?qū)動,其他的針腳要么是電源或者地,要么就沒有接。所以,在我們驅(qū)動時(shí),只需要驅(qū)動這5個針腳即可。
首先我們在驅(qū)動之前,需要了解一下視頻顯示的掃描方式。平時(shí)大家看到的圖片是由一個一個的像素點(diǎn)構(gòu)成的,顯示器顯示時(shí)也是如此,一個點(diǎn)一個點(diǎn)的顯示。在掃描顯示時(shí),有兩種掃描方式:隔行掃描和逐行掃描。第一種掃描方式控制復(fù)雜,而且圖像閃爍,人眼易疲勞,所以現(xiàn)在很少使用,基本上主流的掃描方式都是逐行掃描。逐行掃描是從左上角第一個點(diǎn)開始一行一行的進(jìn)行掃描,直至最后一個點(diǎn)。在掃描時(shí)就需要我們確定掃描位置然后進(jìn)行時(shí)序約束。vga_hs和vga_vs這兩個信號為行列同步信號,用來同步掃描的。在時(shí)序上,要求在a段必須為低電平。
行時(shí)序每拉低一次即為一行的開始,場時(shí)序每拉低一次即為一幀圖片的開始。
另外,在了解完掃描的問題之后,還有一個問題需要解決,那就是我們在掃描到顯示區(qū)域時(shí),要給出顏色數(shù)據(jù),使得屏幕顯示出我們想看到的顏色。VGA 顯示器上每一個像素點(diǎn)可以很多種顏色,由R、G、B 三種顏色構(gòu)成。如果每個像素點(diǎn)采用3 位二進(jìn)制數(shù)表示,即R 用1bit 表示,G 用1bit 表示,B 用1bit 表示,則此像素點(diǎn)一共可以顯示8種顏色;如果每個像素點(diǎn)采用8 位二進(jìn)制數(shù)表示,即R 用3bit 表示,G 用3bit 表示,B 用2bit 表示,則此像素點(diǎn)一共可以顯示256 種顏色。此次實(shí)驗(yàn),采用RGB332 的進(jìn)行表示。
在進(jìn)行掃描時(shí),不同的分辨率對應(yīng)不同的掃描時(shí)鐘,下圖為各個常用分辨率的時(shí)序參數(shù)。
此次實(shí)驗(yàn),我們選擇分辨率為640*480,那么我們需要提供一個25Mhz的時(shí)鐘,這個時(shí)鐘我們可以通過鎖相環(huán)輸出,代碼如下:
1 module vga_ctrl (
2
3 input wire clk,
4 input wire rst_n,
5
6 output reg vga_hs,
7 output reg vga_vs,
8 output reg [7:0] vga_rgb
9 );
10
11 parameter HS_A = 96;
12 parameter HS_B = 48;
13 parameter HS_C = 640;
14 parameter HS_D = 16;
15 parameter HS_E = 800;
16
17 parameter VS_A = 2;
18 parameter VS_B = 33;
19 parameter VS_C = 480;
20 parameter VS_D = 10;
21 parameter VS_E = 525;
22
23 reg [9:0] cnt_hs;
24 reg [9:0] cnt_vs;
25 wire hs_en;
26 wire vs_en;
27
28 always @ (posedge clk, negedge rst_n) begin
29 if (rst_n == 1'b0)
30 cnt_hs <= 10'd0;
31 else
32 if (cnt_hs < HS_E - 1'b1)
33 cnt_hs <= cnt_hs + 1'b1;
34 else
35 cnt_hs <= 10'd0;
36 end
37
38 always @ (posedge clk, negedge rst_n) begin
39 if (rst_n == 1'b0)
40 vga_hs <= 1'b1;
41 else
42 if (cnt_hs < HS_A)
43 vga_hs <= 1'b0;
44 else
45 vga_hs <= 1'b1;
46 end
47
48 always @ (posedge clk, negedge rst_n) begin
49 if (rst_n == 1'b0)
50 cnt_vs <= 10'd0;
51 else
52 if (cnt_hs == HS_E - 1'b1)
53 if (cnt_vs < VS_E - 1'b1)
54 cnt_vs <= cnt_vs + 1'b1;
55 else
56 cnt_vs <= 10'd0;
57 else
58 cnt_vs <= cnt_vs;
59 end
60
61 always @ (posedge clk, negedge rst_n) begin
62 if (rst_n == 1'b0)
63 vga_vs <= 1'b1;
64 else
65 if (cnt_vs < VS_A)
66 vga_vs <= 1'b0;
67 else
68 vga_vs <= 1'b1;
69 end
70
71 assign hs_en = (cnt_hs > HS_A + HS_B - 1'b1) && (cnt_hs < HS_A + HS_B + HS_C);
72 assign vs_en = (cnt_vs > VS_A + VS_B - 1'b1) && (cnt_vs < VS_A + VS_B + VS_C);
73
74 always @ (posedge clk, negedge rst_n) begin
75 if (rst_n == 1'b0)
76 vga_rgb <= 8'd0;
77 else
78 if (hs_en == 1'b1 && vs_en == 1'b1)
79 vga_rgb <= 8'b111_000_00;
80 else
81 vga_rgb <= 8'd0;
82 end
83
84 endmodule
以上代碼為顯示純紅色的驅(qū)動,如果我們想顯示不同的純色,可以修改代碼79行的值。
在代碼71行和72行分別規(guī)定了顯示C區(qū),也就是我們能夠看到的最大顯示區(qū)域。如果大家想畫出不同形狀或者位置的,可以在這兩行約束出想要的區(qū)域。