目录
一、VScode以及Verilog-HDL/SystemVerilog插件安装下载
一、VScode以及Verilog-HDL/SystemVerilog插件安装下载
1.1 VScode下载安装
官网: 下载地址
在首页找到对应的版本(Windows)点击下载
双击下载好的安装包,弹出以下界面,点击我同意此协议,下一步
接下来就是选择安装路径,默认是安装在C盘,点击浏览可以选择自己的安装路径,下一步
继续下一步,这里选择自己想要的功能,下一步
点击安装,开始安装VScode
1.2 HDL/SystemVerilog插件安装下载
安装好之后,在VScode的商店中搜索Verilog,安装插件
下载、安装完成之后,可以实现Verilog代码的语法高亮和自动补全
二、LED流水灯
在DE2-115开发板上,用Verilog设计一个LED流水灯实验:用6个LED完成周期为1秒的跑马灯效果
代码如下
module led_test #(parameter TIME_1S = 50_000_000)(
input sys_clk ,
input sys_rst_n ,
output reg [5:0] led // 控制 6 个 LED
);
reg [25:0] cnt ; // 增加位宽以支持更大的计数值
wire add_cnt ;
wire end_cnt ;
reg [2:0] cnt1;
wire add_cnt1;
wire end_cnt1;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n) begin
cnt <= 26'b0;
end
else if(add_cnt) begin
if(end_cnt) begin
cnt <= 26'b0;
end
else begin
cnt <= cnt + 1'b1;
end
end
else begin
cnt <= cnt;
end
end
// 异步复位
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)begin
cnt1 <= 3'b0;
end
else if(add_cnt1) begin
if(end_cnt1)begin
cnt1 <= 3'b0;
end
else begin
cnt1 <= cnt1 + 1'b1;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
led <= 6'b0;
end
else begin
case (cnt1)
3'b000 : led <= 6'b000001; // 第 1 个灯亮
3'b001 : led <= 6'b000010; // 第 2 个灯亮
3'b010 : led <= 6'b000100; // 第 3 个灯亮
3'b011 : led <= 6'b001000; // 第 4 个灯亮
3'b100 : led <= 6'b010000; // 第 5 个灯亮
3'b101 : led <= 6'b100000; // 第 6 个灯亮
default: led <= led; // 保持当前状态
endcase
end
end
assign add_cnt = 1'b1;
assign end_cnt = add_cnt && cnt == TIME_1S - 1;
assign add_cnt1 = (cnt == TIME_1S-1);
assign end_cnt1 = add_cnt1 && cnt1 == 3'b101; // 6 个状态(0 到 5)
endmodule
计数器cnt
用于计时,控制每个LED状态的持续时间;当cnt计数到TIME_1S-1时,表示1秒时间到,触发状态切换。
计数器cnt1
用于记录当前 LED 的状态(即哪个 LED 亮);当
cnt
计数到TIME_1S - 1
时,cnt1
加 1,切换到下一个状态;cnt1是一个 3 位宽的寄存器,可以表示 8 个状态(
3'b000
到3'b111
);在本设计中,只使用了 6 个状态(3'b000
到3'b101
),分别对应 6 个 LED 的状态;每个状态持续 1 秒,由cnt
计数器控制。当
cnt
计数到TIME_1S - 1
时,cnt1
加 1,切换到下一个状态;当cnt1
达到3'b101
(即第 6 个状态)时,cnt1
复位为3'b000
,重新开始循环。
引脚配置
实验效果如下:
三、模块化代码
顶层模块代码(LedBlink.v)
module LedBlink (
input wire clk, // 系统时钟(50 MHz)
input wire rst_n, // 复位信号(低电平有效)
output wire [5:0] led // 6 个 LED 输出
);
wire clk_1s; // 1 Hz 时钟信号
// 实例化分频模块
fenpin u_fenpin (
.clk(clk),
.rst_n(rst_n),
.clk_1s(clk_1s)
);
// 实例化显示模块
display u_display (
.clk_1s(clk_1s),
.rst_n(rst_n),
.led(led)
);
endmodule
实例化分频模块和显示模块,并将它们连接起来;提供系统时钟、复位信号和LED输出的接口
分频模块(fenpin.v)
module fenpin (
input wire clk, // 系统时钟(50 MHz)
input wire rst_n, // 复位信号(低电平有效)
output reg clk_1s // 分频后的 1 Hz 时钟信号
);
reg [25:0] cnt; // 26 位计数器,用于分频
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 26'd0;
clk_1s <= 1'b0;
end
else if (cnt == 26'd49_999_999) begin // 50 MHz / 50,000,000 = 1 Hz
cnt <= 26'd0;
clk_1s <= ~clk_1s; // 翻转时钟信号
end
else begin
cnt <= cnt + 1'b1;
end
end
endmodule
将50MHz的系统时钟分频为1Hz的时钟信号,通过一个26位计数器实现分频
显示模块(display.v)
module display (
input wire clk_1s, // 1 Hz 时钟信号
input wire rst_n, // 复位信号(低电平有效)
output reg [5:0] led // 6 个 LED 输出
);
reg [2:0] state; // 状态寄存器,用于表示当前 LED 状态
always @(posedge clk_1s or negedge rst_n) begin
if (!rst_n) begin
state <= 3'b000;
led <= 6'b000001; // 初始状态:第 1 个 LED 亮
end
else begin
case (state)
3'b000 : led <= 6'b000001; // 第 1 个 LED 亮
3'b001 : led <= 6'b000010; // 第 2 个 LED 亮
3'b010 : led <= 6'b000100; // 第 3 个 LED 亮
3'b011 : led <= 6'b001000; // 第 4 个 LED 亮
3'b100 : led <= 6'b010000; // 第 5 个 LED 亮
3'b101 : led <= 6'b100000; // 第 6 个 LED 亮
default: led <= 6'b000001; // 默认回到第 1 个 LED
endcase
state <= state + 1'b1; // 切换到下一个状态
if (state == 3'b101) begin
state <= 3'b000; // 回到初始状态
end
end
end
endmodule
根据1Hz的时钟信号,控制6个LED的流水灯效果,使用一个3位状态机表示当前LED状态
四、总结
本次实验学习了Verilog硬件描述语言的基本语法和模块化设计方法,学习使用计数器实现定时功能,并通过状态机控制LED流水灯的效果,计数器用于实现1秒的定时状态,状态机用于控制LED灯的状态切换,代码编写完成后在DE2-115开发板上下载烧录程序,实现“跑马灯”效果,不仅加深了对Verilog语言的理解,还培养了硬件设计的规范化思维。