VGA原理簡介 2.1.1 VGA定義 VGA即視頻圖像陣列的意思,時IBM公司在1987年隨ps/2一起推出的一種視頻傳輸標準,具有分辨率高、顯示速度快、顏色豐富等優點,在彩色顯示領域得到了廣泛的應用。VGA顯示器時陰極射線管顯示器,通過VGA顯示器接口和計算機內部的顯卡相連。 2.1.2 VGA規格參數 實驗用到的顯示器規格為640*480,具體參數如下: 行同步: 場同步: 2.1.3 彩色原理 人眼是根據所看見光的波長來識別顏色的,這些顏色是根據三種基色按照不同的比例相互混合得到的,三種基本光色為紅、綠、藍三原色光,當這三種光以不同的顏色比例混合,得到了不同的顏色(比如相同比例得到白色)。 在VGA顯示器上,R、G、B三種基色分別接到電子槍的陽極,通過陰極發射電子,然后在電場的作用下,電子轟擊熒光粉層,熒光粉層發出不同強度的三種顏色光,根據空間混色法將三個基色光同時照射同一表面相鄰很近的三個點上進行混色,可以產生不同的顏色,利用人眼在超過一定距離后分辨率下降的原理,可以得到較為清晰的顏色。 對于本實驗,只能顯示八種顏色,就是RGB分別用一位二進制數表示,從而顯示8中顏色。 2.1.4 消隱脈沖和同步脈沖 同步脈沖:場同步和行同步 消隱脈沖:場消隱和行消隱 計算機顯示器采用逐行掃描顯示,從屏幕的左上方開始,按照從左到右、從上到下的順序進行掃描。每掃描完一行,行同步信號進行行同步,會到下一行的起點進行掃描。掃描完所有行后,即顯示了整個屏幕,用場同步信號進行場同步,并且掃描回到屏幕左上方,進行下一幀的刷新。 當電子槍從某一行的末尾轉到下一行的開頭時,或者從屏幕最下面一行最后一個像素轉到左上角第一個像素位置時,都需要一定的時間,這期間不需要發射電子,否則會干擾畫面。所以行同步場和同步信號要在需要顯示區域驅動顯示器顯示,通過對行同步和場同步的設置,實現行消隱和場消隱。 2.1.5 VGA顯示原理 對于640*480*60hz的顯示器,工業標準的時鐘頻率為25.175hz,行周期為800個周期,場周期為525個周期,這些周期數也就對應著時間。 計算機顯示器采用逐行掃描顯示,從屏幕的左上方開始,按照從左到右、從上到下的順序進行掃描。每掃描完一行,行同步信號進行行同步,會到下一行的起點進行掃描。掃描完所有行后,即顯示了整個屏幕,用場同步信號進行場同步,并且掃描回到屏幕左上方,進行下一幀的刷新。 每行800個時鐘脈沖,前640個時鐘頻率對應前640個點,在不同的時間輸出不同的顏色,在640到800時鐘頻率RGB輸出低電平,行計數器為648時,場計數器加一或清零,行計數器為656到752時,行同步信號為低電平,其他時刻為高電平;場計數器為490到492時,場同步信號為低電平,其他時刻為高電平。因為整個過程是循環進行的,從而顯示正常。
3 信號發生器設計 3.1軟件環境介紹 本實驗使用的軟件是QuartusⅡ9.1。QuartusⅡ 是Altera公司為FPGA/CPLD芯片設計的集成化專用開發工具,在QuartusⅡ上可以設計輸入、HDL綜合、布線布局、仿真、下載和硬件測試等整個設計流程,功能強大,被廣泛使用。 在早期, Max+plusⅡ 是Altera公司的開發工具,現在已經被QuartusⅡ代替。并且Max+plusⅡ已經不再支持Altera公司的新器件,同時,QuartusⅡ也放棄了對老器件的支持。QuartusⅡ具有Max+plusⅡ界面,上手簡單,界面友好、使用便捷。 Altera Quartus Ⅱ提供了完整的設計環境,設計工具完全支持VHDL、Verilog和AHDL設計流程。QuartusⅡ也可以使用第三方的綜合工具,并且可以直接調用這些綜合工具;同時QuartusⅡ也支持第三方的仿真工具,如Modelism;QuartusⅡ與Matlab和DSP Builder結合,也可以進行DSP系統開發。 除此之外,Quartus還包含許多LPM模塊,在SOPC設計中被大量使用,也可以在普通設計文件一起使用。例如DSP模塊、PLL、各類片上存儲器等。 QuartusⅡ還支持第三方EDIF文件輸入,并且提供了很多EDA軟件接口,支持層次化設計,解決了原理圖和HDL混合輸入問題。
3.4 VGA貪吃蛇游戲顯示設計 3.4.1模塊功能 VGA顯示模塊:主要實現VGA的顯示,hcnt,vcnt,hs,vs的設置。 靜態圖片模塊:這里顯示在貪吃蛇撞身顯示the end靜態圖案。 游戲背景模塊:貪吃蛇邊界設計,設計了四堵墻,在顯示器顯示,在墻外有自己的名字英文縮寫DLH顯示。 游戲控制模塊:貪吃蛇蛇身移動及運動方向處理,蛇身撞身處理,蛇身吃到后自增處理和蛇身上限處理,隨機出現的食物方塊處理。這一模塊最為重要,將會重點進行說明。 連線模塊:將這些模塊連到一起,使最終下載到顯示器上的是可以顯示正確的圖案。 3.4.2貪吃蛇設計 VGA顯示模塊: (1)分頻模塊: 這里通過二分頻,clk為輸入50mhz的頻率,在clk上升沿對clk25取反,就得到二分頻的clk25,頻率為25mhz:
always@(posedgeclk or negedge rst) if(!rst) clk_25M=0; else clk_25M=~clk_25M; (2)顯示模塊: 設置了行計數器和場計數器hcnt、vcnt,行信號和場信號hs、vs。 按照先通過行同步頭/場同步頭,再通過后沿,再通過顯示區域,再到前沿完成一整個周期來計算: hs行信號hcnt>=639+16并且hcnt<639+16+96輸出為0,其他輸出1; vs場信號在vcnt>=479+10并且vcnt<479+10+2輸出為0,其他輸出1。 設置了坐標位置,xpos和ypos,分別為hcnt-96-48和vcnt-2-33用于后面位置的表示。 當hcnt和vcnt在顯示區域輸出rgb_sig, rgb_sig與后面的相對應。 always@(posedgeclk_25M or negedge rst) begin if(!rst) begin h_cnt<=0; v_cnt<=0; end else begin if(h_cnt==(H_CNT_MAX-1))begin h_cnt<=0; if(v_cnt==(V_CNT_MAX-1))v_cnt<=0; elsev_cnt<=v_cnt+10'd1; end else h_cnt<=h_cnt+10'd1; end end
靜態圖片和游戲背景模塊: 設置了the end和DLH靜態圖案,設置了四堵墻,這些設置方法基本相同,都是通過對hcnt和vcnt的范圍進行設置,這里可以直接使用xpos和ypos,在規定的范圍內填充RGB色彩即可。 例如對我的名字縮寫而言,d的設置包括兩橫兩豎,對xpos和ypos進行設置即可: 左右為10上下為20: assign d1 = ((vga_xpos > 40 ) &&(vga_xpos < 50 ) && (vga_ypos > 20 ) && (vga_ypos < 40) ); 左右為10上下為40: assignd2 = ((vga_xpos > 70 ) && (vga_xpos < 80 ) && (vga_ypos> 0 ) && (vga_ypos < 40 ) ); 左右為40上下為5: assignd3 = ((vga_xpos > 40 ) && (vga_xpos <80 ) && (vga_ypos> 20 ) && (vga_ypos < 25 ) ); 左右為40上下為5: assignd4 = ((vga_xpos > 40 ) && (vga_xpos < 80 ) && (vga_ypos> 35 ) && (vga_ypos < 40 ) ); 這樣就得到了小寫d,通過這樣一直將背景和四堵墻的顯示設置好。對于四堵墻,這里只設置了在顯示器中顯示,而對四堵墻的邊界格擋作用,在游戲控制模塊進行說明。 游戲控制模塊: (1)時鐘控制:在時鐘上升沿(25mhz頻率的時鐘),i自增,當i到達摸個數值的時候,i清零,同時temp取反,這樣在后面的貪吃蛇移動模塊,通過在temp上升沿移動,從而可以通過i的最大值來實現對速度的控制,這里設置i為4999999,如果想要更快,只需要慢速度即可。 (2)運動模塊: 首先設置了四種狀態,來標識運動方向,這四個狀態和ps/2鍵盤相連接,來完成對運動的控制。 if(P_left) state<= left; elseif(P_right) state<= right; elseif(P_down) state<= down; elseif(P_up) state<= up; 我這里設置每個小貪吃蛇由10*10的像素方塊組成。設置了兩個數組m和n,代表左上角坐標,m數組代表左邊坐標,n代表上邊坐標。 蛇頭運動:對于貪吃蛇蛇頭運動,通過rst信號對貪吃蛇初始位置進行設定。當貪吃蛇出邊界時(我們上面設置的四堵墻就是這里的邊界),四堵墻上下左右邊界值分別為:60,420,40,600。例如當出左邊界時即m[0]<40的時候m【0】=600,實現當出邊界時可以從對應邊界回來。當未出邊界時,與上面的上下左右四種運動標識對應,實現運動(加減10): if(!rst) beginm[0]<=200; n[0]<=200;end elseif(m[0] > 600) m[0]<= 40; elseif(m[0] < 40) m[0]<= 600; elseif( n[0] > 420) n[0]<= 60; elseif( n[0] < 60) n[0]<= 420; elseif(hit) beginm[0]<=0; n[0]<=0;the_end=1;end else begin case(state) left: m[0] <= m[0] - 12'd10; right: m[0] <= m[0] + 12'd10; down: n[0] <= n[0] + 12'd10; up:n[0] <= n[0] - 12'd10; default: m[0] <= m[0]+12'd10 ; end case; 蛇身運動:每當設運動一次,m[a+1]就會代替m[a]的位置: for(long_cnt=0; long_cnt<(2**N-1);long_cnt=long_cnt+1) begin m[long_cnt+1]<= m[long_cnt]; n[long_cnt+1]<= n[long_cnt]; end (3)撞身模塊:當蛇頭和蛇身相撞時,即為m[0]=m[a],n[0]=n[a]時,結束游戲顯示屏顯示the end 界面。 (4)食物隨機出現:設置一個初始的食物出現位置(300,300),通過吃到食物所用用的時鐘時間,來判斷下一個食物的位置。 設置了四個信號o,p,o_temp ,p_temp。在時鐘上升沿o_temp ,p_temp加10,當吃到才會將o_temp 和p_temp賦值給o,p,實現了根據吃到食物所用的時間變位置(其實是一個偽隨機),其中change是用來判斷是否吃到的信號,吃到為1,未吃到為0。 if(!rst)begin p <= 300;//lie o <= 300;//hang end else if(change) begin p <= p_temp; o <= o_temp; end else if(o_temp > 400) o_temp <= 100; else if(o_temp <100) o_temp <= 400; else if(p_temp > 400) p_temp <= 80; else if(p_temp < 80) p_temp <= 400; else begin o_temp <= o_temp+ 10; p_temp <= p_temp+ 10; (5)吃食物:當o和p和蛇頭坐標,m[0],n[0]對應時吃到食物。吃到食物后相應的蛇身也要增長:
(6)貪吃蛇顯示:貪吃蛇左上坐標為m[a],n[a],坐標在xpos和ypos的范圍內,例如蛇頭為m[0] <xpos < m[0] + 10并且n[0] < ypos < n[0] + 10這樣就可以在VGA上顯示。
連線模塊:這里就是將這些模塊,設置的信號,連在一起,例如將每個模塊設置的顏色和VGA顯示模塊顏色先對應、貪吃蛇坐標對應行計數器和場計數器等等。
此程序用Cyclone Ⅲ EP3C40Q240C8對應引腳分配圖:
51hei.png (72.66 KB, 下載次數: 70)
下載附件
2022-3-5 20:11 上傳
51hei.png (6.74 KB, 下載次數: 83)
下載附件
2022-3-5 20:11 上傳
上圖壓縮包代碼下載,僅供參考:
基于FPGA的貪吃蛇小游戲(1).7z
(6.38 MB, 下載次數: 33)
2022-3-5 20:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|