1.VGA的显示不是直接让图像在屏幕上显示出来,而是通过扫描的方式,将构成图像的像素点,在行场同步时序信号的控制下,按照从上到下,从左到右的顺序显示在屏幕上,其具体的流程可表示为如下的步骤”
框图:(这一部分参考的野火教程,侵权就删)只用于自我学习的笔记加总结。
注:这里的行场时序一样,所以用一个图来表示
功能:驱动七寸800*480的lcd屏幕并显示彩条
module vga_ctrl(
input wire pexil_clk ,
input wire sys_rst ,
input wire [15:0] pexil_data ,
output wire Hsync ,
output wire Vsync ,
output wire [9:0] pexil_x ,
output wire [9:0] pexil_y ,
output wire [15:0] rgb_data
);
reg [9:0] Cnt_H ;
reg [9:0] Cnt_V ;
wire rgb_valid ;
wire pexil_data_req;
/****************************************************************************
#参数定义:@行信号参数定义
@场信号参数定义
@数据信号的定义
*****************************************************************************/
parameter H_SYNC = 10'd96,
H_BACK = 10'd40,
H_LEFT = 10'd8,
H_VALID = 10'd640,
H_RIGHT = 10'd8,
H_FRONT = 10'd8,
H_TOTAL = H_SYNC + H_BACK + H_LEFT + H_VALID + H_RIGHT + H_FRONT;
parameter V_SYNC = 10'd2,
V_BACK = 10'd25,
V_UP = 10'd8,
V_VALID = 10'd480,
V_DOWN = 10'd8,
V_FRONT = 10'd2,
V_TOTAL = V_SYNC + V_BACK + V_UP + V_VALID + V_DOWN + V_FRONT;
parameter WHITE = 16'hffff ,
BLACK = 16'h0000 ,
RED = 16'hf800 ,
GREEN = 16'h07E0 ,
BLUE = 16'h001f ;
/************************************************
#模块说明:行信号计数器,用于表示行信号的周期循环
在时钟的上升沿加一,用于计数行信号。
单位:像素
************************************************/
always @(posedge pexil_clk or negedge sys_rst) begin
if(!sys_rst)
Cnt_H <= 10'b0;
else if(Cnt_H == H_TOTAL - 10'd1 )
Cnt_H <= 10'b0;
else
Cnt_H <= Cnt_H + 10'd1;
end
/************************************************
#模块说明:场信号计数器,用于表示场信号的周期循环
在时钟的上升沿加一,用于计数场信号。
单位:行
************************************************/
always @(posedge pexil_clk or negedge sys_rst) begin
if(!sys_rst)
Cnt_V <= 10'b0;
else if((Cnt_V == V_TOTAL - 10'd1)&&(Cnt_H == H_TOTAL - 10'd1))
Cnt_V <= 10'b0;
else if(Cnt_H == H_TOTAL - 10'd1)
Cnt_V <= Cnt_V + 10'd1;
else
Cnt_V <= Cnt_V;
end
// 数据显示有效标志位:当Cnt_H范围在[同步信号+后沿+左边框,同步信号+后沿+左边框+显示的有效区域)
// Cnt_V范围在[同步信号+后沿+上边框,同步信号+后沿+左边框+显示的有效区域)时,该信号拉高
assign rgb_valid = ((Cnt_H >= H_SYNC + H_BACK + H_LEFT)
&&(Cnt_H < H_SYNC + H_BACK + H_LEFT + H_VALID )
&&(Cnt_V >= V_SYNC +V_BACK +V_UP)
&&(Cnt_V < V_SYNC +V_BACK +V_UP + V_VALID))
? 1'b1 :1'b0 ;
// 数据显示请求有效标志位:当Cnt_H范围在[同步信号+后沿+左边框-1,同步信号+后沿+左边框+显示的有效区域-1)
// Cnt_V范围在[同步信号+后沿+上边框,同步信号+后沿+左边框+显示的有效区域)时,该信号拉高,
// 以达到提前一个时钟周期的效果
assign pexil_data_req = ((Cnt_H >= H_SYNC + H_BACK + H_LEFT - 1'b1)
&&(Cnt_H < H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1 )
&&(Cnt_V >= V_SYNC +V_BACK +V_UP)
&&(Cnt_V < V_SYNC +V_BACK +V_UP + V_VALID))
? 1'b1 :1'b0 ;
// 有效显示区域坐标
assign pexil_x = (pexil_data_req==1'b1) ? (Cnt_H - (H_SYNC + H_BACK + H_LEFT - 1'b1 )):10'd0;
assign pexil_y = (pexil_data_req==1'b1) ? (Cnt_V - (V_SYNC + V_BACK + V_UP) ):10'd0;
//同步信号拉高
assign Hsync = (Cnt_H <= H_SYNC - 10'd1) ? 1'b1:1'b0;
assign Vsync = (Cnt_V <= V_SYNC - 10'd1) ? 1'b1:1'b0;
assign rgb_data = (rgb_valid == 1'b1) ? pexil_data:16'h0000;
/************************************************
//下面是数据生成模块
always @(posedge pexil_clk or negedge sys_rst) begin
if(!sys_rst)
pexil_data <=BLACK;
else if((pexil_x >= 10'd0) && (pexil_x < (H_VALID /5)))
pexil_data <= WHITE;
else if((pexil_x >= (H_VALID /5)) && (pexil_x < (H_VALID /5)*2))
pexil_data <= BLACK;
else if((pexil_x >= (H_VALID /5)*2) && (pexil_x < (H_VALID /5)*3))
pexil_data <= RED;
else if((pexil_x >= (H_VALID /5)*3) && (pexil_x < (H_VALID /5)*4))
pexil_data <= GREEN;
else if((pexil_x >= (H_VALID /5)*4) && (pexil_x < H_VALID))
pexil_data <= BLUE;
else
pexil_data <= BLACK;
end
***/
endmodule
注:最后的数据生成模块意思是,可以在此模块中直接生成,而不需要外部的数据输入,当然代码也要进行相关的修改。