2015-12-30 146 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