目录
一、实验目标
学习和掌握System Verilog基本语法,在DE2-115开发板上设计驱动VGA显示器,在640x480@60显示模式下完成十种颜色等宽彩条的显示。
二、模块代码
1、时钟分频模块:将50MHZ的系统时钟分频成25MHZ,fpga系统时钟为50MHZ,而640x480@60显示模式下时钟频率为25.175MHZ,由于25.175MHZ的频率不太方便生成。为了便于时钟的生成,这里使用25MHZ代替25.175MHZ,时钟分频模块采用pll锁相环。
2、VGA_ctrl模块:生成rgb[15:0]、hsync、vsync三路信号,以及图像的横纵坐标
cpp
`timescale 1ns/1ns
module vga_ctrl ( //VGA控制模块
input logic vga_clk ,
input logic sys_rst_n ,
input logic [15:0] pix_data ,//图像数据
output logic [9:0] pix_x ,
output logic [9:0] pix_y ,
output logic hsync ,//行扫描信号
output logic vsync ,//场扫描信号
output logic [15:0] 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_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 ; //场扫描周期
reg [9:0] cnt_h ;
reg [9:0] cnt_v ;
wire pix_data_req ;
wire rgb_valid ; //图像有效信号,行扫描信号位于有效图像范围并且场扫描信号位于有效图像范围时图像有效信号为高电平
//cnt_h:行同步信号计数器
always_ff @(posedge vga_clk or negedge sys_rst_n ) begin
if(sys_rst_n == 1'b0)
cnt_h <= 10'd0;
else if(cnt_h == H_TOTAL - 1'b1 )
cnt_h <= 10'd0;
else
cnt_h <= cnt_h + 10'd1;
end
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//cnt_v:场同步信号计数器
always_ff @(posedge vga_clk or negedge sys_rst_n ) begin
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 -10'd1 )
cnt_v <= cnt_v + 1'd1;
else
cnt_v <= cnt_v;
end
//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//图像有效信号
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;
//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
3、图像信息生成模块:产生等宽十色彩条数据。
cpp
`timescale 1ns/1ns
module vga_pic
(
input logic vga_clk , //输入工作时钟,频率25MHz
input logic sys_rst_n , //输入复位信号,低电平有效
input logic [9:0] pix_x , //输入VGA有效显示区域像素点X轴坐标
input logic [9:0] pix_y , //输入VGA有效显示区域像素点Y轴坐标
output logic [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'h001F, //蓝色
PURPPLE = 16'hF81F, //紫色
BLACK = 16'h0000, //黑色
WHITE = 16'hFFFF, //白色
GRAY = 16'hD69A; //灰色
always_ff@(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
4、顶层模块:完成各模块的实例化
cpp
`timescale 1ns/1ns
module vga_colorbar
(
input logic sys_clk ,
input logic sys_rst_n ,
output logic hsync ,
output logic vsync ,
output logic [15:0] rgb
);
logic vga_clk ;
logic locked ;
logic rst_n ;
logic [9:0] pix_x ;
logic [9:0] pix_y ;
logic [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
(
.vga_clk (vga_clk ),
.sys_rst_n (rst_n ),
.pix_data (pix_data ),
.pix_x (pix_x ),
.pix_y (pix_y ),
.hsync (hsync ),
.vsync (vsync ),
.rgb (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
5、tb文件
cpp
`timescale 1ns/1ns
module tb_vga_ctrl ();
logic sys_clk ;
logic sys_rst_n ;
logic [15:0] pix_data ;
logic vga_clk ;
logic locked ;
logic rst_n ;
logic hsync ;//行扫描信号
logic vsync ;//场扫描信号
logic [9:0] pix_x ;
logic [9:0] pix_y ;
logic [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;
assign rst_n = (sys_rst_n & locked);
always_ff@(posedge vga_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 1'b0)
pix_data <= 16'h0000;
else if( (pix_x >=10'd0 &&pix_x <=10'd639)&&(pix_y >=10'd0 &&pix_y <=10'd479))
pix_data <= 16'hffff;
else
pix_data <= 16'h0000;
end
clk_gen clk_gen_inst (
.areset ( ~sys_rst_n ),
.inclk0 ( sys_clk ),
.c0 ( vga_clk ),
.locked ( locked )
);
vga_ctrl vga_ctrl_inst (
. vga_clk (vga_clk ) ,
. sys_rst_n (rst_n ) ,
. pix_data (pix_data) ,//图像数据
. hsync (hsync ) ,//行扫描信号
. vsync (vsync ) ,//场扫描信号
. pix_x (pix_x ) ,
. pix_y (pix_y ) ,
. vga_rgb (vga_rgb )
);
endmodule
三、实验结果
仿真波形:
彩条显示:
四、总结
通过本次实验,我学习了SystemVerilog并完成了VGA彩条设计与仿真,SystemVerilog 在语言特性和功能上相对于 Verilog 更加强大和灵活,尤其在测试和验证方面有明显优势。