文章目录
一、学习任务
1、从"实验3-基于Verilog HDL的数字秒表、波形发生器等设计" 任选一个完成;
2、练习基于VGA的图像显示,了解VGA协议,通过Verilog编程实现VGA端口生成彩条图案或者自定义的汉字图案;或者完成一个简单的类似贪吃蛇的VGA小游戏 (实际效果验证可在下次实验课检查)。
二、学习内容
1.基于Verilog HDL的数字秒表
1.1.仿真波形
1.1.1.异步复位功能
1.reset从1变为0时,hofs,sec,minute全被复位变成0.
2.reset从0变为1后,hofs重新计数
1.1.2.暂停功能
1.stop从0变为1时,hofs,sec,minute保持不变。
2.stop从1变成0,hofs,sec,minute继续计数。
1.1.3.计数功能
1.hofs从0计数到99,sec加一次。
2.sec从0计数到59,minute加一次。
3.minute从0计数到59,hofs,sec,minute全部清0,重新下一次的计数
1.2.相关代码
module stopwatch(
input clk,
input rst_n,
input stop,
output [5:0] minute,
output [5:0] sec,
output [6:0] hofs
);
reg [6:0] counter100;//模100的计数器,用于百分秒计数和进位
reg [5:0] counter60_s; //模60的计数器,用于秒计数和进位
reg [5:0] counter60_m;//模60的计数器,用于分计数和清零
//异步复位和暂停
// counter100
always@(posedge clk or negedge rst_n or posedge stop) begin
if(!rst_n) //复位功能,低电平有效
counter100 <= 7'b0000000;
else if(stop) //暂停功能,高电平有效,保持原值不变
counter100 <= counter100;
else if(counter100 < 7'b1100011)//实现模100的计数器,小于99,累加1
counter100 <= counter100 + 1'b1;
else
counter100 <= 7'b0000000;
end
// counter60_s
always@(posedge clk or negedge rst_n or posedge stop) begin
if(!rst_n) //复位功能,低电平有效
counter60_s <= 6'b000000;
else if(stop) //暂停功能,高电平有效,保持原值不变
counter60_s <= counter60_s;
else
if(counter60_s < 6'b111100)
if(counter100 == 7'b1100011)
counter60_s <= counter60_s + 1'b1;
else
counter60_s <= counter60_s;
else
counter60_s <= 6'b000000;
end
// counter60_m
always@(posedge clk or negedge rst_n or posedge stop) begin
if(!rst_n) //复位功能,低电平有效
counter60_m <= 6'b000000;
else if(stop) //暂停功能,高电平有效,保持原值不变
counter60_m <= counter60_m;
else if(counter60_m < 6'b111100)
if((counter60_s == 6'b111011)&&(counter100 == 7'b1100011))
counter60_m <= counter60_m + 1'b1;
else
counter60_m <= counter60_m ;
else
counter60_m <= 6'b000000;
end
//将对应模的计数器赋值给对应的百分秒、秒、分钟
assign hofs = counter100;
assign sec = counter60_s;
assign minute = counter60_m;
endmodule
`timescale 1ns / 1ns
module stopwatch_tb();
parameter CYCLE = 10;//100MHz
reg clk;
reg rst_n;//更改reset为rst_n
reg stop;
wire [6:0] hofs;
wire [6:0] counter100;
wire [5:0] minute;
wire [5:0] sec;
wire [5:0] counter60_s;
wire [5:0] counter60_m;
always #(CYCLE/2) clk = ~clk;
initial begin
clk = 1'b0;
rst_n = 1'b0;
stop = 1'b0;
#(CYCLE*5)
rst_n = 1'b1;
stop = 1'b0;
#(CYCLE*120)
rst_n = 1'b1;
stop = 1'b1;
#(CYCLE*5)
rst_n = 1'b1;
stop = 1'b0;
#(CYCLE*37000)
rst_n = 1'b0;
stop = 1'b0;
#(CYCLE*5)
rst_n = 1'b1;
stop = 1'b0;
#(CYCLE*37000)
rst_n = 1'b1;
stop = 1'b0;
#(CYCLE*10000)
$stop;
end
stopwatch U1(.clk(clk),
.rst_n(rst_n),
.stop(stop),
.minute(minute),
.sec(sec),
.hofs(hofs));
endmodule
2.基于VGA的图像显示
1.FPGA驱动VGA显示文字
1.1.生成字库
取模格式设置:
字模数组生成:
生成的数组:
{0x00,0x00,0x1F,0x98,0x10,0x84,0x11,0x04,0x11,0x04,0x10,0x88,0x10,0x70,0x00,0x00},/*"5",0*/
{0x10,0x00,0x1E,0x00,0x11,0xE0,0x00,0x1C,0x00,0x70,0x13,0x80,0x1C,0x00,0x10,0x00},/*"V",1*/
1.2.verilog代码
时序:
代码:
`define HSYNC_A 16'd128
`define HSYNC_B 16'd216
`define HSYNC_C 16'd1016
`define HSYNC_D 16'd1056
`define VSYNC_O 16'd4
`define VSYNC_P 16'd27
`define VSYNC_Q 16'd627
`define VSYNC_R 16'd628
`define RED 8'hE0
`define GREEN 8'h1C
`define BLUE 8'h03
`define YELLOW 8'hFC
`define BLACK 8'h00
module VGA
(
//输入
input CLK_50M,
input RST_N,
//输出
output reg VSYNC,
output reg HSYNC,
output reg[7:0] VGA_DATA
);
reg[15:0] hsync_cnt;
reg[15:0] vsync_cnt;
reg vga_data_valid;
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
hsync_cnt <= 16'd0;
else if(hsync_cnt == `HSYNC_D)
hsync_cnt <= 16'd0;
else
hsync_cnt <= hsync_cnt + 16'd1;
end
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
vsync_cnt <= 16'd0;
else if((vsync_cnt == `VSYNC_R) && (hsync_cnt == `HSYNC_D))
vsync_cnt <= 16'd0;
else if(hsync_cnt == `HSYNC_D)
vsync_cnt <= vsync_cnt + 16'd1;
else
vsync_cnt <= vsync_cnt;
end
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
HSYNC <= 1'b0;
else if(hsync_cnt < `HSYNC_A)
HSYNC <= 1'b0;
else
HSYNC <= 1'b1;
end
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
VSYNC <= 1'b0;
else if(vsync_cnt < `VSYNC_O)
VSYNC <= 1'b0;
else
VSYNC <= 1'b1;
end
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
vga_data_valid <= 1'b0;
else if((hsync_cnt > `HSYNC_B && hsync_cnt < `HSYNC_C) && (vsync_cnt > `VSYNC_P && vsync_cnt < `VSYNC_Q)
vga_data_valid <= 1'b1;
else
vga_data_valid <= 1'b0;
end
reg [7:0] rom_add;
wire [15:0] rom_data;
wire [15:0] vga_x;
wire [15:0] vga_y;
assign vga_x = hsync_cnt - `HSYNC_B;
assign vga_y = vsync_cnt - `VSYNC_P;
assign display_en = (vga_x >= 10'd98) && (vga_x <= 10'd116) && (vga_y >= 10'd90) && (vga_y <= 10'd106);
always@(posedge CLK_40M or negedge RST_N)
begin
if(!RST_N)
rom_add <= 8'h0;
else if(display_en)
begin
if(vga_x == 10'd98)
rom_add <= 8'h0;
else if(vga_x == 10'd106)
rom_add <= 8'h08;
else
rom_add <= rom_add + 1'b1;
end
else
rom_add <= 8'h0;
end
always@(*)
begin
if(display_en)
begin
if(rom_data[10'd106 - vga_y]
VGA_DATA <= `RED;
else
VGA_DATA <= `YELLOW;
end
else
VGA_DATA <= `BLACK;
end
ROM ROM_inst (
.address ( rom_add ),
.clock ( CLK_40M ),
.q ( rom_data )
);
wire CLK_40M;
PLL PLL_inst (
.inclk0 ( CLK_50M ),
.c0 ( CLK_40M )
);
endmodule