文章目录
- 前言
- 一、按键简介
- 按键:通过按下或者释放来控制电路通断的电子元件
- 按键原理图
- 二、实验要求
- 三、程序设计
- 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;,对应500nsreg [24:0] cnt;
reg [1:0] led_flag;//计数0.5s
always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)cnt <= 25'd0;elseif (cnt < (CNT_MAX- 25'd1))cnt <= cnt+ 25'd1;else cnt <= 25'd0;end//LED状态切换标志位
always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)led_flag <= 2'd0;elseif (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) beginif(!sys_rst_n)led <= 4'd0;elsebegincase(key)4'b1111 : led <= 4'b0000;4'b1110 :beginif(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;end4'b1101 :beginif(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;end4'b1011 : beginif((led_flag == 2'd0)||(led_flag == 2'd2))led <= 4'b1111;else led <= 4'b0000;end4'b0111 : led <= 4'b1111;default : ;endcaseend
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 beginsys_clk <= 1'b0;sys_rst_n <=1'b0;key <= 4'b1111;#200 sys_rst_n <= 1'b1;#2000key <= 4'b1110;//按下key0#2000key <= 4'b1111;//松开key0#2000key <= 4'b1101;//按下key1#2000key <= 4'b1111;//松开key1#2000key <= 4'b1011;//按下key2#2000key <= 4'b1111;//松开key2#2000key <= 4'b0111;//按下key3#2000key <= 4'b1111;//松开key3endalways #(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 即仿真时间;