一. VGA时序图
下面引用黑金教程里面的一个图片。所以VGA显示的时序图都是如此的。从图中可以看到两个信号线,分别是行同步和列同步,它们都是在同步时间内拉高,其余时间都为低电平。
从图中可以得知,在每一行的开始,行同步拉高,在每一列的开始,列同步拉高,它们各自拉高的时间可以参考手册。
二. 查看手册
这里以AN430显示模块的手册为例。通过手册可以清楚的看出,显示的时钟频率以及各个状态所对应的持续时间。
Horizontal_cycle : 一行的周期是525个VGA时钟周期
Horzontal_display_period:行显示有效的时钟周期为480,也就是是显示的宽度为480。
同理显示的高度为272
其他的一些时间数据可以结和上下两幅图片来看。
三. VGA显示数据输出
通过第一幅图可以知道,显示数据在Hor_Active_start和Hor_Active_end,以及Ver_Active_start和Ver_Active_end之间有效
结和下图可以知道,图像数据上在时钟的下降沿变动,上升沿要保存稳定,这一点需要注意一下。
四 . VGA驱动
通过两组计数器,然后结合上面的图片,就可以来编写我们的驱动程序了
1. 参数定义
将上面的图片参数搬运下来即可
//480 * 272 clk 9MHz localparam H_CYCLE = 525; localparam H_Display = 480; localparam H_Pulse_W = 41; localparam H_Back_p = 2; localparam H_Front_p = 2; localparam H_Value_S = 43; //水平有效开始 localparam H_Value_E = 523; //水平有效结束 localparam V_CYCLE = 286; localparam V_Display = 272; localparam V_Pulse_W = 10; localparam V_Back_p = 2; localparam V_Front_p = 2; localparam V_Value_S = 12; //水平有效开始 localparam V_Value_E = 284; //水平有效结束
2. 行列计数
每一个时钟周期水平计数加一,满之后归零
水平计数每满一次,垂直计数加一,满之后归零
//水平计数 always@(posedge vga_clk or negedge rst) begin if(rst == 1'b0) H_cnt <= 'd0; else if(H_cnt == H_CYCLE) H_cnt <= 'd0; else H_cnt <= H_cnt + 1'b1; end //垂直计数 always@(posedge vga_clk or negedge rst) begin if(rst == 1'b0) V_cnt <= 'd0; else if(V_cnt == V_CYCLE - 1'b1 && H_cnt == H_CYCLE) V_cnt <= 'd0; else if(H_cnt == H_CYCLE) V_cnt <= V_cnt + 1'b1; else V_cnt <= V_cnt; end
3. 水平垂直同步信号
在小于同步时间也就是Pulse-width内拉高即可。
assign H_SYNC = (H_cnt < H_Pulse_W) ? 1'b1 : 1'b0; assign V_SYNC = (V_cnt < V_Pulse_W) ? 1'b1 : 1'b0;
4. 当前显示的行列坐标
通过简单地计算即可算出。
assign x_addr = (H_cnt > H_Value_S && H_cnt < H_Value_E) ? H_cnt - H_Value_S :'d0; assign y_addr = (V_cnt > V_Value_S && V_cnt < V_Value_E) ? V_cnt - V_Value_S :'d0;
5. 显示数据输出,以及模块端口
模块通过向外输出读取的x,y值,来获取显示的具体数值。
always@(posedge vga_clk or negedge rst) begin if(rst == 1'b0) VGA_Data <= 'd0; else VGA_Data <= idata; end module VGA_Driver( input clk, input vga_clk, input rst, //坐标输出 output[8:0] x_addr, //水平坐标 output[8:0] y_addr, //竖直坐标 //显示数据输入 input[23:0] idata, //VGA output VGA_CLK, output VGA_EN, output H_SYNC, //行同步时序 output V_SYNC, //列同步时序 output reg[23:0] VGA_Data //VGA数据 );
公众号:FPGA之旅