项目简介
本项目基于Altera
公司的Cyclone IV
型芯片,利用NIOS II
软核,2-port RAM
与时序控制模块,实现64*48
分辨率的显存(再大的显存板载资源m9k
不够用)
实现效果如下:
VGA时序控制模块
VGA时序简介
网络上针对VGA
时序的讲解已经非常多了,简单的理解,VGA
主要有H_sync
和V_sync
这两个坐标同步信号,与RGB
这三个色彩信号。当H_sync
与V_sync
达到特定的值的时候,对应一个特别的坐标(x,y)
上的颜色为RGB
。VGA
上的RGB
信号是模拟信号,FPGA
通常通过接入一个DA
模块来实现数字信号到模拟信号的转换。我所用的板子上便是16位
的RGB数模转换的解决方案。
HSYNC的时序如下
VSYNC的时序如下
针对图中的不同段的长度,可以参考以下常用的参数配置表:
在我的IP核中,通过参数定义以增加核心的通用性:
//1024*758 60HZ
parameter H_SyncPulse=136; //HSYNC_A
parameter H_BackPorch=160; //HSYNC_B
parameter H_ActivePix=1024; //HSYNC_C
parameter H_FrontPorch=24; //HSYNC_D
parameter LinePeriod =1344; //HSYNC_E
parameter Hde_start=H_SyncPulse+H_BackPorch;
//HSYNC_A+HSYNC_B
parameter Hde_end=Hde_start+H_ActivePix;
//HSYNC_A+HSYNC_B+HSYNC_C
//1024*758 60HZ
parameter V_SyncPulse=6; //VSYNC_O
parameter V_BackPorch=29; //VSYNC_P
parameter V_ActivePix=768; //VSYNC_Q
parameter V_FrontPorch=3; //VSYNC_R
parameter FramePeriod =806; //VSYNC_S
parameter Vde_start=V_BackPorch+V_SyncPulse;
parameter Vde_end=Vde_start+V_ActivePix+V_FrontPorch;
由于板载时钟信号是一个50MHZ
,利用PLL
超频至65MHZ
,接入板子时钟:
pllvga mypll(.inclk0(clk),.c0(vga_clk),.areset(~rstn),.locked());
根据上面所述VGA
的基本时序,可以书写VGA
的时序模块:
always @ (posedge vga_clk)
if(~rstn)
x_cnt <= 1;
else if(x_cnt == LinePeriod)
x_cnt <= 1;
else
x_cnt <= x_cnt+ 1;
always @ (posedge vga_clk)
begin
if(~rstn)
hsync_r <= 1'b1;
else if(x_cnt == 1)
hsync_r <= 1'b0;
else if(x_cnt == H_SyncPulse)
hsync_r <= 1'b1;
if(~rstn)
hsync_de <= 1'b0;
else if(x_cnt == Hde_start)
hsync_de <= 1'b1;
else if(x_cnt == Hde_end)
hsync_de <= 1'b0;
end
always @ (posedge vga_clk)
if(~rstn)
y_cnt <= 1;
else if(y_cnt == FramePeriod)
y_cnt <= 1;
else if(x_cnt == LinePeriod)
y_cnt <= y_cnt+1;
always @ (posedge vga_clk)
begin
if(~rstn)
vsync_r <= 1'b1;
else if(y_cnt == 1)
vsync_r <= 1'b0;
else if(y_cnt == V_SyncPulse)
vsync_r <= 1'b1;
if(~rstn)
vsync_de <= 1'b0;
else if(y_cnt == Vde_start)
vsync_de <= 1'b1;
else if(y_cnt == Vde_end)
vsync_de <= 1'b0;
end
并且可以从x_cnt
与y_cnt
中得知当前对应的x
与y
的坐标的值:
assign display_x = x_cnt>Hde_start?x_cnt-Hde_start:12'd0;
assign display_y = y_cnt>Vde_start?y_cnt-Vde_start:12'd0;
利用iVerilog
对VGA
基本时序进行仿真,并利用GTKwave
查看仿真结果: