一、实验环境搭建
- 安装并打开VSCode,在扩展商店中搜索并安装
Verilog-HDL/SystemVerilog
插件,实现语法高亮和自动补全功能。
- 下载并打开Quartus 18,按顺序点击
Tools
->Options
->Preferred Text Editor
进入偏好文本编辑器,在Text editor中选择自定义文本编辑器(Custom),并在Command-line中选择VSCode的Code.exe程序所在文件位置,将VSCode与Quartus进行绑定。
- 新建
led_floa
项目以开发流水灯项目,选择合适的设备和仿真软件,例如EP4CE115F29C7设备和ModelSim-ALtera(Verilog HDL)仿真软件。
在VSCode中的项目文件夹led_floa
中创建以下文件:
LedBlink.v
(顶层模块)fenpin.v
(分频模块)display.v
(显示模块)
二、设计思路
采用层次化设计,将系统分为三个模块:
- 顶层模块(LedBlink.v):负责实例化和连接其他模块
- 分频模块(fenpin.v):将输入时钟分频到合适频率
- 显示模块(display.v):控制LED的流水灯效果
三、代码实现
代码如下:
LedBlink
module LedBlink(
input clk,//50Mhz
input rst_n,//复位信号
input pause_key,
output [5:0] led
);
//模块间连接信号
wire en_ls;
wire pause_reg;//暂停状态信号
fenpin u_fenpin(
.clk (clk),
.rst_n (rst_n),
.en (en_ls)
);
display u_display(
.clk (clk),
.rst_n (rst_n),
.en_ls (en_ls),
.pause_key (pause_key),
.pause_reg (pause_reg),
.led (led)
);
endmodule
代码说明:负责将分频模块和显示模块连接起来,并处理复位信号。
fenpin.v
module fenpin(
input clk,
input rst_n,
output reg en
);
reg [22:0] cnt;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
cnt<=23'd0;
en<=1'b0;
end else begin
if(cnt==23'd8_333_332) begin
cnt<=23'd0;
en<=1'b1;
end else begin
cnt<=cnt+1'b1;
en<=1'b0;
end
end
end
endmodule
代码说明:通过计数器实现时钟分频,用于控制流水灯的速度。
display.v
module display(
input clk,
input rst_n,
input en_ls,
input pause_key,
output reg pause_reg,
output reg [5:0] led
);
reg [1:0] sync_key;
reg key_delay;
reg [19:0] debounce_cnt;
reg key_pressed;
// 按键消抖逻辑
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
sync_key <= 2'b11;
key_delay <= 1'b1;
debounce_cnt <= 20'd0;
key_pressed <= 1'b0;
end else begin
sync_key <= {sync_key[0], pause_key};
key_delay <= sync_key[1];
if(sync_key[1] != key_delay)
debounce_cnt <= 20'd999_999;
else if (debounce_cnt != 0)
debounce_cnt <= debounce_cnt - 1;
if(debounce_cnt == 0 && sync_key[1] == 1'b0)
key_pressed <= 1'b1;
if(debounce_cnt == 0 && sync_key[1] == 1'b1)
key_pressed <= 1'b0;
end
end
reg key_release_flag; // 记录按键释放事件
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
pause_reg <= 1'b0;
key_release_flag <= 1'b0;
end else begin
// 当按键从按下状态变为释放状态时,翻转暂停状态
if(key_pressed == 1'b1 && sync_key[1] == 1'b1)
key_release_flag <= 1'b1;
else
key_release_flag <= 1'b0;
if(key_release_flag)
pause_reg <= ~pause_reg;
end
end
// LED闪烁控制逻辑
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led <= 6'b000001;
end else if(en_ls && !pause_reg) begin
led <= {led[0], led[5:1]};
end
end
endmodule
代码说明:采用状态机设计,定义6个状态分别对应6个LED点亮的位置,状态按顺序循环切换,实现流水灯效果。
- 保存全部项目后,在Quartus中点击
Files
->...
->选中.v文件
,即可添加刚才在VSCode中保存的.v文件。
- 按下Ctrl+K开始分析与综合,检查语法,编译信息没有红色,表示编译通过。如果出现undefined类错误,将LedBlink.v设置为顶层即可。
- 编译通过后没问题了,便可开始分配管脚。
- 按下Ctrl+L开始编译,准备进行烧录程序,编译通过即可开始烧录。
- 开始烧录程序
四、收获总结
通过LED流水灯实验,我学会了用Verilog做分频和状态机控制,还掌握了模块化设计和规范写代码的方法。以前觉得抽象的数字电路知识,现在通过实际操作,终于明白了怎么在FPGA里实现。动手能力也提升了不少,能更灵活地运用到以后的项目里。而且在调试过程中,也锻炼了自己解决问题的能力,遇到错误不再慌张,知道如何去分析和修正。这次实验让我对数字系统设计有了更深入的理解,也增强了我继续学习和探索的信心。