文章目录
- 前言
- 一、按键简介
- 按键:通过按下或者释放来控制电路通断的电子元件
- 按键原理图
- 二、实验要求
- 三、程序设计
- 3.1思路整理
- 3.2 模型搭建
- 3.3 顶层模块
- 3.4 波形分析
- 四、代码整理
- 4.1RTL代码
- 4.2 仿真
- 只需在Testbench上增加上述一段代码即可将参数实例化,可达到在Testbench上更改参数的目的
前言
笔者将基于正点原子的达芬奇开发板,结合夏宇闻老师的Verilog数字系统设计教程,来记录自己学习FPGA的学习思路,希望能给与读者一些帮助
一、按键简介
按键:通过按下或者释放来控制电路通断的电子元件
自锁按键:按下之后能保持,类似于开发板的电源按键
轻触摸式按键:按下就通,松开即断
按键原理图
按下是低电平,断开高电平
二、实验要求
三、程序设计
3.1思路整理
3.2 模型搭建
3.3 顶层模块
3.4 波形分析
四、代码整理
4.1RTL代码
module key_led(
input sys_clk,
input sys_rst_n,
input [3:0] key,
output reg [3:0] led
);
parameter CNT_MAX = 25'd25000000;//可在仿真时改为25'd25;,对应500ns
reg [24:0] cnt;
reg [1:0] led_flag;
//计数0.5s
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt <= 25'd0;
else
if (cnt < (CNT_MAX- 25'd1))
cnt <= cnt+ 25'd1;
else
cnt <= 25'd0;
end
//LED状态切换标志位
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led_flag <= 2'd0;
else
if (cnt < (CNT_MAX- 25'd1))
led_flag <= led_flag + 2'd1;
else
cnt <= 25'd0;
end
//LED控制
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led <= 4'd0;
else
begin
case(key)
4'b1111 : led <= 4'b0000;
4'b1110 :begin
if(led_flag == 2'd0)
led <= 4'b0001;
else if(led_flag == 2'd1)
led <= 4'b0010;
else if(led_flag == 2'd2)
led <= 4'b0100;
else
led <= 4'b1000;
end
4'b1101 :begin
if(led_flag == 2'd0)
led <= 4'b1000;
else if(led_flag == 2'd1)
led <= 4'b0100;
else if(led_flag == 2'd2)
led <= 4'b0010;
else
led <= 4'b0001;
end
4'b1011 : begin
if((led_flag == 2'd0)||(led_flag == 2'd2))
led <= 4'b1111;
else
led <= 4'b0000;
end
4'b0111 : led <= 4'b1111;
default : ;
endcase
end
end
endmodule
4.2 仿真
需要注意的是,在modelsim仿真时,可以将0.5s改为20ns以缩短仿真时间,仅需将CNT_MAX改为25’d25即可
testbench代码
`timescale 1ns/1ns //仿真的单位/仿真的精度s
module tb_key_led();
parameter CLK_PERIOD = 20;
reg sys_clk; //周期20ns
reg sys_rst_n; //并非所有的输入都是reg,根据代码编写情况
reg [3:0] key;
wire [3:0] led;
initial begin
sys_clk <= 1'b0;
sys_rst_n <=1'b0;
key <= 4'b1111;
#200
sys_rst_n <= 1'b1;
#2000
key <= 4'b1110;//按下key0
#2000
key <= 4'b1111;//松开key0
#2000
key <= 4'b1101;//按下key1
#2000
key <= 4'b1111;//松开key1
#2000
key <= 4'b1011;//按下key2
#2000
key <= 4'b1111;//松开key2
#2000
key <= 4'b0111;//按下key3
#2000
key <= 4'b1111;//松开key3
end
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
key_led u_key_led (
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.key (key ),
.led (led)
);
endmodule
笔者在进行仿真分析是发现了自己代码编写的一些小错误
例如,在编写rtl代码时,输入输出信号用的是分号,而不是逗号
在编写Testbench代码的时候,笔者发现自己在进行实例化时忘记改名了
同时,在仿真时,若是每次仿真都要改RTL代码,还是比较繁琐的,为此,笔者希望可以在Testbench上进行修改,以下是笔者根据资料学习的办法
parameter CNT_MAX = 25'd25;
u_key_led #(
.CNT_MAX (CNT_MAX)
);
只需在Testbench上增加上述一段代码即可将参数实例化,可达到在Testbench上更改参数的目的
关于modelsim的用法心得:指令篇
restart -f 即重新开始仿真
run -time 即仿真时间;