由于人的肉眼有感知红、绿、蓝三种不同颜色的锥体细胞,因此色彩空间通常可以由三种基本色来表达。三种基色是相互独立的,任何一种基色都不能有其它两种颜色合成。红绿蓝是三基色,这三种颜色合成的颜色范围最为广泛。我们的RGB信号就是三基色的运用,对这三个信号赋予不同的数值,混合起来便是不同的色彩。
VGA一共有15个针脚,其中红,蓝,绿三路输入为模拟量输入,行,场为数字输入,而FPGA的输出全部为数字信号,所以需要将数字量转为模拟量。具体有以下几种方案。
VGA显示图像使用扫描的方式,从第一行的第一个像素开始,逐渐填充,第一行第一个、第一行第二个、、、、第二行第一个、第二行第二个、、、、第n行最后一个。
通过这种方式构成一帧完整的图像,当扫描速度足够快,加之人眼的视觉暂留特性,我们会看到一幅完整的图片,而不是一个个闪烁的像素点。这就是VGA 显示的原理。
那么这两个信号时如何配合的呢?
这就和我们希望VGA显示的模式有关了,VGA可以显示不同分辨率的图像,不同分辨率及帧率对应参数如下:
先搞明白各参数意义以640x480@60为例:
行同步进入同步阶段96个时钟周期、后沿40、 左边框8 ;
行同步走到第145个时钟周期时,RGB输出数据,屏幕的第1行第1个像素将被点亮;
行同步走到第146个时钟周期时,RGB输出数据,屏幕的第1行第2个像素将被点亮;
。。。
行同步走到第785个时钟周期时,RGB输出数据,屏幕的第1行第640个像素将被点亮;
至此第一行全部图像显示完毕 。
行同步继续走16个时钟周期(右边沿8个+前沿8个),直到一共走完800个时钟周期。
行同步进入同步阶段96个时钟周期、后沿40 、左边框8 ;
行同步走到第145个时钟周期时,RGB输出数据,屏幕的第2行第1个像素将被点亮;
行同步走到第146个时钟周期时,RGB输出数据,屏幕的第2行第2个像素将被点亮;
。。。
行同步走到第785个时钟周期时,RGB输出数据,屏幕的第2行第640个像素将被点亮;
至此第二行全部图像显示完毕;
行同步继续走16个时钟周期(右边沿8个+前沿8个),直到一共走完800个时钟周期
。。。
FPGA的编程是时序逻辑,会产生延迟一拍的效果,所以会多添加一些信号辅助设计。
代码来自野火,大家可以参照波形进行学习,希望对大家有所帮助!
`timescale 1ns/1ns
module vga_ctrl (
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [15:0] pix_data , //输入像素点色彩信息
output wire [9:0] pix_x , //输出VGA有效显示区域像素点X轴坐标 output wire [9:0] pix_y , //输出VGA有效显示区域像素点Y轴坐标 output wire hsync , //输出行同步信号 output wire vsync , //输出场同步信号 output wire [15:0] rgb //输出像素点色彩信息
);
//parameter define
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 = 10'd800 ; //行扫描周期
parameter V_SYNC = 10'd2 , //场同步
V_BACK = 10'd25 , //场时序后沿
V_TOP = 10'd8 , //场时序上边框
V_VALID = 10'd480 , //场有效数据
V_BOTTOM = 10'd8 , //场时序下边框
V_FRONT = 10'd2 , //场时序前沿
V_TOTAL = 10'd525 ; //场扫描周期
//wire define
wire rgb_valid ; //VGA有效显示区域
wire pix_data_req ; //像素点色彩信息请求信号
//reg define
reg [9:0] cnt_h ; //行同步信号计数器
reg [9:0] cnt_v ; //场同步信号计数器
//***** Main Code ****//
//cnt_h:行同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_h <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_h <= 10'd0 ;
else
cnt_h <= cnt_h + 1'd1 ;
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//cnt_v:场同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_v <= 10'd0 ;
else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
cnt_v <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_v <= cnt_v + 1'd1 ;
else
cnt_v <= cnt_v ;
//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//rgb_valid:VGA有效显示区域
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_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_data_req:像素点色彩信息请求信号,超前rgb_valid信号一个时钟周期
assign pix_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_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_x,pix_y:VGA有效显示区域像素点坐标
assign pix_x = (pix_data_req == 1'b1)
? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 10'h3ff;
assign pix_y = (pix_data_req == 1'b1)
? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 10'h3ff;
//rgb:输出像素点色彩信息
assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;
endmodule
`timescale 1ns/1ns
module vga_pic (
input wire vga_clk , //输入工作时钟,频率25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [9:0] pix_x , //输入VGA有效显示区域像素点X轴坐标
input wire [9:0] pix_y , //输入VGA有效显示区域像素点Y轴坐标
output reg [15:0] pix_data //输出像素点色彩信息
);
//** Parameter and Internal Signal ***//
parameter H_VALID = 10'd640 , //行有效数据
V_VALID = 10'd480 ; //场有效数据
parameter RED = 16'hF800, //红色
ORANGE = 16'hFC00, //橙色
YELLOW = 16'hFFE0, //黄色
GREEN = 16'h07E0, //绿色
CYAN = 16'h07FF, //青色
BLUE = 16'h001F, //蓝色
PURPPLE = 16'hF81F, //紫色
BLACK = 16'h0000, //黑色
WHITE = 16'hFFFF, //白色
GRAY = 16'hD69A; //灰色
//**********// //***** Main Code ****// //************//
//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pix_data <= 16'd0;
else if((pix_x >= 0) && (pix_x < (H_VALID/10)1))
pix_data <= RED;
else if((pix_x >= (H_VALID/10)1) && (pix_x < (H_VALID/10)2))
pix_data <= ORANGE;
else if((pix_x >= (H_VALID/10)2) && (pix_x < (H_VALID/10)3))
pix_data <= YELLOW;
else if((pix_x >= (H_VALID/10)3) && (pix_x < (H_VALID/10)4))
pix_data <= GREEN;
else if((pix_x >= (H_VALID/10)4) && (pix_x < (H_VALID/10)5))
pix_data <= CYAN;
else if((pix_x >= (H_VALID/10)5) && (pix_x < (H_VALID/10)6))
pix_data <= BLUE;
else if((pix_x >= (H_VALID/10)6) && (pix_x < (H_VALID/10)7))
pix_data <= PURPPLE;
else if((pix_x >= (H_VALID/10)7) && (pix_x < (H_VALID/10)8))
pix_data <= BLACK;
else if((pix_x >= (H_VALID/10)8) && (pix_x < (H_VALID/10)9))
pix_data <= WHITE;
else if((pix_x >= (H_VALID/10)9) && (pix_x < H_VALID))
pix_data <= GRAY;
else
pix_data <= BLACK;
endmodule
`timescale 1ns/1ns module
vga_colorbar (
input wire sys_clk , //输入工作时钟,频率50MHz
input wire sys_rst_n , //输入复位信号,低电平有效
output wire hsync , //输出行同步信号
output wire vsync , //输出场同步信号
output wire [15:0] rgb //输出像素信息
);
//**********// //** Parameter and Internal Signal ***// //**********// //wire define
wire vga_clk ; //VGA工作时钟,频率25MHz
wire locked ; //PLL locked信号
wire rst_n ; //VGA模块复位信号
wire [9:0] pix_x ; //VGA有效显示区域X轴坐标
wire [9:0] pix_y ; //VGA有效显示区域Y轴坐标
wire [15:0] pix_data; //VGA像素点色彩信息
//rst_n:VGA模块复位信号
assign rst_n = (sys_rst_n & locked);
//**********// //**** Instantiation ***// //************//
//------------- clk_gen_inst -------------
clk_gen clk_gen_inst
(
.areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
.inclk0 (sys_clk ), //输入50MHz晶振时钟,1bit
.c0 (vga_clk ), //输出VGA工作时钟,频率25Mhz,1bit
.locked (locked ) //输出pll locked信号,1bit
);
//------------- vga_ctrl_inst -------------
vga_ctrl vga_ctrl_inst
(
.vga_clk (vga_clk ), //输入工作时钟,频率25MHz,1bit
.sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
.pix_data (pix_data ), //输入像素点色彩信息,16bit
.pix_x (pix_x ), //输出VGA有效显示区域像素点X轴坐标,10bit
.pix_y (pix_y ), //输出VGA有效显示区域像素点Y轴坐标,10bit
.hsync (hsync ), //输出行同步信号,1bit
.vsync (vsync ), //输出场同步信号,1bit
.rgb (rgb ) //输出像素点色彩信息,16bit
);
//------------- vga_pic_inst -------------
vga_pic vga_pic_inst
( .vga_clk (vga_clk ), //输入工作时钟,频率25MHz,1bit
.sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
.pix_x (pix_x ), //输入VGA有效显示区域像素点X轴坐标,10bit
.pix_y (pix_y ), //输入VGA有效显示区域像素点Y轴坐标,10bit
.pix_data (pix_data ) //输出像素点色彩信息,16bit
);
endmodule
原网址: 访问
创建于: 2023-08-16 18:30:37
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论