VGA显示
目标:实现屏幕红、橙、黄、绿、青、蓝、紫、黑、白、灰条形显示
1. 模块框图与波形图
vga_colorbar是实现目标功能的总体模块框图,为了实现对应的输出,我们使用三个具体功能模块实现功能。
(1) clk_gen——使用pll锁相环实现时钟分频
(2)vga_ctrl——图像控制与输出模块
(3)vga_pic——图像数据生成模块
将三个模块布局布线,最终组成vga_colorbar模块,如下图:
首先讨论clk_gen模块。由图,sys_clk与sys_rst_n是系统时钟与复位按钮;
clk_gen是我们自定义的输出频率为15MHZ时钟的pll锁相环;
areset为复位按键,由于其为高电平有效,故对sys_rst_n取反输入。
clk_out是15MHZ时钟;
locked为标志信号,正常输出高电平,当复位信号有效时,输出低电平;
在讨论接下来的两个模块之前,我们先明确显示屏是如何显示我们需要的图像,这对后面的模块设计至关重要
首先明确VGA显示屏是如何扫描得到有效图像:
如上图所示,直观来看vga显示屏从左到右,从上到下逐个像素点进行扫描;
那么控制行扫描的信号成为行同步信号——hync;
控制列扫描信号成为场同步信号——vsync;
接着,我们进一步来看行同步信号hysnc与场同步信号vsync的详细数据:
行/场同步信号从波形的角度看可分为六部分,分别为同步、后沿、左边框、有效图像、右边框、前沿部分;表中的时钟部分代表着clk_gen的输出时钟频率,也是vga_ctrl、vga_pic的输入时钟频率,本文中我们使用25MHZ时钟频率。
至此,我们可以开始绘制各个模块的波形图进而编写代码。
2. 子模块波形图与代码实现
(1).vga_ctrl模块波形图
绿色为输入数据,红色为输出数据,黄色为中间变量;
cnt_h与cnt_v分别为行同步计数与场同步计数,即图像的坐标,由上表可知,当cnt_h技术到144-83范围且cnt_v在计数到35-514范围时,vga在有效图像的显示范围内。
pix_x与pix_y分别为有效图像显示的坐标变量;
rgb_valid为有效图像标志信号;
(2).vga_ctrl模块代码实现
RTL代码:
module vga_ctrl
(
input wire vga_clk ,
input wire sys_rst_n ,
input wire[15:0] pix_data ,
output wire hsync ,
output wire vsync ,
output wire [9:0] pix_y ,
output wire [9:0] pix_x ,
output wire [15:0] vga_rgb
);
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_TOTAL = 10'd525 ,
V_SYNC = 10'd2 ,
V_BACK = 10'd25 ,
V_TOP = 10'd8 ,
V_VALID = 10'd480 ,
V_RIGHT = 10'd8 ,
V_FRONT = 10'd2 ;
reg [9:0] cnt_h ;
reg [9:0] cnt_v ;
wire rgb_valid ;
wire pix_data_req ;
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 - 10'd1)
cnt_h <= 10'd0 ;
else
cnt_h <= 10'd1 + cnt_h ;
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 - 10'd1 && cnt_h == H_TOTAL - 10'd1)
cnt_v <= 10'd0 ;
else if(cnt_h == H_TOTAL -1'b1)
cnt_v <= 10'd1 + cnt_v ;
else
cnt_v <= 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_TOP)
&& (cnt_v < V_SYNC + V_BACK+ V_TOP + V_VALID))
? 1'b1 : 1'b0 ;
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 ;
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 ;
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 vga_rgb = (rgb_valid == 1'b1) ? pix_data : 16'h0000 ;
endmodule
仿真代码:
`timescale 1ns/1ns
module tb_vga_ctrl();
reg sys_clk ;
reg sys_rst_n ;
wire [15:0] pix_data ;
wire vga_clk ;
wire locked ;
wire rst_n ;
wire [9:0] pix_x ;
wire [9:0] pix_y ;
wire hsync ;
wire vsync ;
wire [15:0] vga_rgb ;
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk; //clk frequency
assign rst_n = (sys_rst_n && locked) ;
clk_gen clk_gen_inst (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( vga_clk ),
.locked ( locked )
);
vga_ctrl vga_ctrl_inst
(
.sys_rst_n(rst_n) ,
.vga_clk (vga_clk ) ,
.pix_data (pix_data) ,
.hsync (hsync) ,
.vsync (vsync ) ,
.pix_y (pix_y ) ,
.pix_x (pix_x ) ,
.vga_rgb (vga_rgb)
);
vga_pic vga_pic_inst
(
.vga_clk (vga_clk ) ,
.sys_rst_n (rst_n) ,
.pix_x (pix_x ) ,
.pix_y (pix_y ) ,
.pix_data (pix_data)
);
endmodule
(3).vga_pic模块波形
(3).vga_pic代码实现
RTL代码:
module vga_pic(
input wire vga_clk ,
input wire sys_rst_n ,
input wire [9:0] pix_x ,
input wire [9:0] pix_y ,
output reg [15:0] pix_data
);
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'h00ff ,
PURPLE = 16'hf81f ,
BLACK = 16'h0000 ,
WHITE = 16'hffff ,
GRAY = 16'hd69a ;
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pix_data <= BLACK ;
else if(pix_x >= 10'd0 && 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 <= PURPLE ;
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
3.顶层模块vga_colorbar代码实现
RTL代码:文章来源:https://www.toymoban.com/news/detail-765734.html
module vga_colorbar(
input wire sys_clk ,
input wire sys_rst_n ,
output wire hsync ,
output wire vsync ,
output wire [15:0] vga_rgb
);
wire vga_clk ;
wire locked ;
wire rst_n ;
wire [9:0] pix_x ;
wire [9:0] pix_y ;
wire [15:0] pix_data ;
assign rst_n = (sys_rst_n && locked);
clk_gen clk_gen_inst (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( vga_clk ),
.locked ( locked )
);
vga_ctrl vga_ctrl_inst
(
.sys_rst_n(rst_n) ,
.vga_clk (vga_clk ) ,
.pix_data (pix_data) ,
.hsync (hsync) ,
.vsync (vsync ) ,
.pix_y (pix_y ) ,
.pix_x (pix_x ) ,
.vga_rgb (vga_rgb)
);
vga_pic vga_pic_inst
(
.vga_clk (vga_clk ) ,
.sys_rst_n (rst_n) ,
.pix_x (pix_x ) ,
.pix_y (pix_y ) ,
.pix_data (pix_data)
);
endmodule
顶层模块仿真代码:文章来源地址https://www.toymoban.com/news/detail-765734.html
`timescale 1ns/1ns
module tb_vga_colorbar();
reg sys_clk ;
reg sys_rst_n ;
wire hsync ;
wire vsync ;
wire [15:0] vga_rgb ;
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 sys_clk = ~sys_clk; //clk frequency
vga_colorbar vga_colorbar_inst
(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n ) ,
.hsync (hsync ) ,
.vsync (vsync ) ,
.vga_rgb (vga_rgb )
);
endmodule
到了这里,关于FPGA学习笔记:verilog基础代码与modelsim仿真(六)——vga显示模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!