今天又试着做了VGA显示实验,虽然回过头来看也是相当简单的,但其中有几个细节还是应该注意的(对我来说。。。。)。
首先,就是行消隐和场消隐的数据宽度,我第一次在网上随便找了一组数据试着写了写,仿真出的结果和这组数据的本来预期是准确的,但是,下载到板子上在显示器上运行下,就出问题了,有信号但这个屏幕都是黑的。
没办法,我直接用了特权同学系列教程中提供的数据,这次就直接可以了。
另一方面,在消隐信号过程中rgb必须保持置0,否则也会出现整个屏幕全黑的状态。
至于VGA的扫描过**的比较简单,(假定为800*600)每一帧的扫描为一个整体,首先场同步信号拉低一定时间,然后拉高保持一段时间,这也是场消隐过程,之后正式开始行扫描,行同步信号拉低一定时间,然后保持一段时间,属于行消隐,之后800个时钟周期用于显示一行,后继续拉高行同步信号,也属于行消隐,在下一次行同步信号拉低前为一小部分,这样的小部分执行600次,场同步信号再次拉高一段时间,属于场消隐,在下一次场同步信号拉低前为一个整体结束。
虽然我写的代码在屏幕上正确显示了,但按照我写的刷新频率应该是72HZ,比标准的60HZ要高,测试的时候居然显示超出频率限制,真挫。。。。
最后附上代码。
/*-----------------------------------------------------------------------------------------
Module Name: test_vga.v
File Author: creation
Finish Time: 2013-07-27
Description: VGA实验
-------------------------------------------------------------------------------------------
Version Design Coding Simulate Review Rel data
V1.0
-------------------------------------------------------------------------------------------
Version Modified History
V1.0 draft
-----------------------------------------------------------------------------------------*/
`timescale 1ns / 10ps
module test_vga(
input wire asy_rst ,//复位
input wire clk ,//50MHZ
output wire [7:0] o_vga_rgb ,//开发板上8个I/O控制256色显示
output wire o_vsync ,//场同步信号
output wire o_hsync //行同步信号
);
/*---------------------------Internal registers and wires--------------------------------*/
/* Register Output Signals */
reg [7:0] vga_rgb; //8位rgb寄存器
reg hsync; //场同步寄存器
reg vsync; //行同步寄存器
/* internal logic use signals */
reg [10:0] cnt_x; //每行上的元素计数(相当于x坐标)
reg [8:0] cnt_y; //行计数(相当于y坐标)
reg [10:0] xpos; //可在屏幕上显示的x坐标
reg [9:0] ypos; //可在屏幕上显示的y坐标
reg valid;
reg dian;
/* ----------------------Logical Implementation------------------------------------------*/
/*-----------------------------------------------------------------------------------------
gen the cnt_x signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
cnt_x <= 1'b0;
else if ( cnt_x == 11'd1039 ) //行同步信号每隔1040个时钟周期拉低一次
cnt_x <= 1'b0;
else
cnt_x <= cnt_x + 1'b1;
end
/*-----------------------------------------------------------------------------------------
gen the cnt_y signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
cnt_y <= 1'b0;
else if ( cnt_y == 10'd665 ) //场同步信号每隔666个时钟周期拉低一次
cnt_y <= 1'b0;
else if ( cnt_x == 11'd1039 ) //每扫描一行,扫描位置下降一行,
cnt_y <= cnt_y + 1'b1;
else
cnt_y <= cnt_y;
end
/*-----------------------------------------------------------------------------------------
gen the xpos signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
xpos <= 1'b0;
else
xpos <= cnt_x - 8'd187; //每行的前187个时钟周期为行消隐信号
end
/*-----------------------------------------------------------------------------------------
gen the ypos signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
ypos <= 1'b0;
else
ypos <= cnt_y - 5'd31; //每帧的前31行为场消隐信号
end
/*-----------------------------------------------------------------------------------------
gen the valid signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
valid = 1'b0; //每帧中的186 else if ( (cnt_x>8'd186) && (cnt_x<10'd988) && (cnt_y>5'd30) && (cnt_y<10'd632) )
valid = 1'b1;
else
valid = 1'b0;
end
/*-----------------------------------------------------------------------------------------
gen the hsync signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
hsync <= 1'b1;
else if ( cnt_x == 1'b0 )
hsync <= 1'b0;
else if ( cnt_x == 7'd120 ) //行消隐信号中的前120个时钟周期用于拉低行同步信号,开始行扫描
hsync <= 1'b1;
else
hsync <= hsync;
end
assign o_hsync = hsync;
/*-----------------------------------------------------------------------------------------
gen the vsync signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
vsync <= 1'b1;
else if ( cnt_y == 1'b0 )
vsync <= 1'b0;
else if ( cnt_y == 3'd6 ) //场消隐信号中的前6行用于拉低场同步信号,开始新一帧的扫描
vsync <= 1'b1;
else
vsync <= vsync;
end
assign o_vsync = vsync;
/*-----------------------------------------------------------------------------------------
gen the dian signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
dian <= 1'b0;
else //此处dian内的坐标为想显示红色的坐标范围
dian <= (xpos>8'd200) && (xpos<10'd600) && (ypos>8'd200) && (ypos<9'd400);
end
/*-----------------------------------------------------------------------------------------
gen the vga_rgb signal
-----------------------------------------------------------------------------------------*/
always @ ( posedge clk or negedge asy_rst )
begin
if ( !asy_rst )
vga_rgb <= 8'd0;
else if ( valid )
begin
if ( dian ) //dian内的坐标位置显示红色
vga_rgb <= 8'd128;
else //不在dian内的坐标位置显示绿色
vga_rgb <= 8'd55;
end
else //消隐信号过程中rgb保持0,这一步必须
vga_rgb <= 8'd0;
end
assign o_vga_rgb = vga_rgb; //输出rgb
endmodule<988,30
文章评论(0条评论)
登录后参与讨论