2015-12-30 140 views
2

我是FPGA新手和無法理解如何控制VGA信號 和VGA互動,以及如何正確生成更復雜的規格VGA控制 信號(使用Verilog):VGA控制信號如何在Verilog/HDL中工作?

  1. 貌似低水平和垂直同步信號中的部分分別對應於從一行到下一行的過渡,以及分別從右下角到左上角的過渡 。但是 是那些低信號「控制」的VGA?那些低信號 「告訴」VGA切換到下一行或跳回到起點?

  2. 那裏的後門廊和前廊是否滿足設置時間和 保持時間?正在門廊的持續時間在VGA時序表中只給出 所需的最小值(即我可以設置門廊比在時序表中的 給定的值更長的時間?)

  3. 這是最我混淆了:從兩個連續的水平和垂直同步信號 ,如何在地球上知道 (或我知道)究竟是哪個指向它正在顯示的屏幕上?如果時機 是唯一的因素,這是否意味着我必須非常注意 匹配RPG控制信號和h-sync和v-sync信號是否完美?如果 答案是肯定的,那麼我有更多的問題,我可以用我的任務僅僅作爲示例來 描述:

在這個作業中,我們使用一個內置的FPGA的50MHz的時鐘(斯巴達首發板),並且VGA的像素被指定爲800x600。幀率被指定爲72Hz。

的VGA定時表給出了以下同步信號結構:

H-同步: | 0 ---後廊(104)--- 103 | 104 ---顯示(800)--- 903 | 904 ---前廊(16)--- 919 | 920__脈衝寬度(120)__ 1039 |

v-sync: | 0 ---後廊(23)--- 22 | 23 ---顯示(600)--- 622 | 623 ---前廊(37)--- 659 | 660_脈衝寬度(6)__ 665 |

這似乎意味着對於屏幕上一行中的每個像素,我花費了1個時鐘週期(20ns)。然而,對於許多複雜的情況,我想 想要控制一個像素的顏色,取決於它在屏幕上的位置 以及許多其他條件,例如當前位置與其他位置的關係,某些狀態等等。現在,如果像素的位置取決於水平和垂直像素計數器,並且顏色還取決於位置,我如何能夠及時匹配它們?另外,如果我的邏輯必須花費超過20ns來決定像素的顏色呢?這會完全崩潰在VGA屏幕上的圖像?

其實我莫名其妙地完成了我的任務,但我發現我的代碼凌亂 和我完全不知道爲什麼它的工作:

例如,分配的部分需要我們展現出一顆星表示 每0.5秒改變一次顏色。我的實現是這樣的:

//----------------pixel counters---------------- 
[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) h_count <= 11'd 0; 
    else if (h_count >= 11'd 1039) h_count <= 11'd 0; 
    else h_count <= h_count + 11'd 1; 
end 

[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) v_count <= 10'd 0; 
    else if (v_count >= 10'd 665) v_count <= 10'd 0; 
    else if (h_count == 11'd 1039) v_count <= v_count + 10'd 1; 
    else v_count <= v_count; 
end 

//----------------h- and v- sync---------------- 
[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) VGA_HSYNC <= 1'b 0; 
    else VGA_HSYNC <= (h_count >= 11'd 0) & (h_count <= 11'd 919); 
end 

[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) VGA_VSYNC <= 1'b 0; 
    else VGA_VSYNC <= (v_count >= 10'd 0) & (v_count <= 10'd 659); 
end 

//----------------a frame counter and a flag---------------- 
[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) frame_count <= 6'd 0; 
    else if (frame_count >= 6'd 49) frame_count <= 6'd 0; 
    else if(v_count == 10'd 665) frame_count <= frame_count + 6'd 1; 
    else frame_count <= frame_count; 
end 

[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) color_flag <= 1'd 0; 
    else if (frame_count == 6'd 49) color_flag <= ~(color_flag); 
    else color_flag <= color_flag; 
end 

//----------------RGB control---------------- 
[email protected](posedge CLK or posedge RESET) begin 
    if(RESET) VGA_RGB <= 3'b 000; 
    else if(display) begin //display is high when counters in valid range 
     casez({tree, star, snow}) //these are outputs from submodules that decides the "shapes" of objects on screen 
      3'b ??1: VGA_RGB <= 3'b 111; //white snow 
      3'b ?10: VGA_RGB <= (color_flag) ? (3'b 110) : (3'b 111); 
       //switching between yellow and white 
      3'b 100: VGA_RGB <= 3'b 010; //green tree 
      default: VGA_RGB <= 3'b 001; //blue background 
    endcase 
    end 
    else VGA_RGB <= 3'b 000; //for transitions 
end 

在我看來,我的H_COUNT和v_count直接決定了我的VGA_HSYNC和VGA_VSYNC。但是我的VGA_RGB至少取決於color_flag,這還取決於frame_count,它取決於h_count和v_count。不應該導致幾個時鐘週期的延遲?代碼是可綜合的,並且產生了我想要顯示的內容。但是,我的VGA_RGB怎麼和VGA_HSYNC和VGA_VSYNC同步呢?我是否在解決這個問題?或者我只是幸運?我錯過了什麼?

+0

要部分地回答你的問題,通常你想有一些內存塊(打開或關閉芯片)來存儲您的像素數據。這樣,您就可以獨立於VGA控制器對其進行操作(進行更改,更新等),並且只要您想要/需要進行任何更改即可使用。 – wilcroft

回答

3

大部分的問題都可以通過VGA是一個模擬標準來解釋的,VGA最初是設計用於在模擬設備上運行的。水平同步和垂直同步脈衝簡單地觸發它們各自的偏轉線圈回到它們的起始位置,而前後門廊說明了光束開始和結束在屏幕的可見部分之外的事實。

關於準確性,它比以前更好:在數年內發送嚴重定時的VGA信號到模擬監視器實際上可能會損壞它。這一切都改變了現在的LCD等,它們的驅動電路能夠以任意刷新率檢測和顯示各種分辨率。根據我的經驗,儘管您擁有的餘量比您想象的要小,並且非常依賴顯示設備的品牌和型號,但他們中的許多人甚至在其用戶手冊中列出了稍微不同的時間安排!如果你想確保你的電路在你的測試儀運行的設備上工作,那麼你應該儘可能精確地遵守其中一個「官方」的分辨率。

就像素定時變化而言,一個800x600x72Hz的信號需要50MHz的時鐘,因此您有20nS的像素數據(這表示我不能100%確定您的同步和門廊時序是正確的,它們與我以前成功使用過的VGA Timings不同)。如果20nS不夠,那麼你需要使用多個電路,例如一個用於奇數像素,另一個用於平鋪。或者,你可以實現流水線階段,例如對於在週期X輸出的像素,您可以在週期X-1從ROM中讀取其值,並計算在週期X-2讀取的地址。我過去使用的另一個技巧是用兩行RAM對顯示進行雙緩衝,即在直接從一個緩衝區直接繪製的任何給定行上進行,同時寫入下一個;這給了你更多的時間來渲染每一行,但通常在渲染和顯示之間增加了獨立時鐘域的額外複雜性。

+0

非常感謝您花時間回答我的問題! – Naketo