FPGA入门笔记007_A——按键消抖模块设计与验证(状态机、$random、仿真模型、task语法)
1.FPGA入门笔记0012.# FPGA入门笔记002——译码器3.FPGA入门笔记006——状态机设计实例4.FPGA入门笔记005——阻塞赋值和非阻塞赋值的区别5.FPGA入门笔记004——BCD计数器设计与使用6.FPGA入门笔记003——计数器IP核调用与验证7.FPGA入门笔记013——嵌入式块RAM使用之FIFO8.FPGA入门笔记012——嵌入式块RAM应用之ROM9.FPGA入门笔记011_B——搭建串口收发与存取双口RAM简易应用系统10.FPGA入门笔记011_A——嵌入式块RAM的使用11.FPGA入门笔记010——UART串口接收模块设计12.FPGA入门笔记009——UART串口发送模块设计13.FPGA入门笔记008——数码管动态扫描设计与验证
14.FPGA入门笔记007_A——按键消抖模块设计与验证(状态机、$random、仿真模型、task语法)
实验现象:
每次按下按键0,4个LED显示状态以二进制加法格式加1。
每次按下按键1,4个LED显示状态以二进制加法格式减1。
知识点:
1、testbench中随机数发生函数$random的使用;
2、仿真模型的概念
1、按键波形分析:
按键未按,FPGA管脚检测到高电平。
按键按下,FPGA管脚检测到低电平。
2、设置四个状态:
1、未按下时,空闲态;
2、抖动滤除状态;
3、按下稳定状态;
4、释放抖动滤除状态
localparam IDEL = 4'b0001, //空闲状态 FILTER0 = 4'b0010, //抖动滤除状态 DOWN = 4'b0100, //按下稳定状态 FILTER1 = 4'b1000; //释放抖动滤除状态 reg [3:0]state;
3、状态迁移图:
IDEL:空闲状态
FILTER:抖动滤除状态(过了20ms后还未出现上升沿,进入DOWN状态,否则进入IDEL状态)
DOWN:按下稳定状态
FILTER1:释放抖动滤除状态((过了20ms后还未出现下降沿,进入IDEL状态,否则进入DOWN状态))
4、消抖模块模型:
module key_filter( Clk, Rst_n, key_in, key_flag, key_state ); input Clk; //时钟信号 input Rst_n; //复位信号 input key_in; //按键输入信号 output reg key_flag; //按键状态标志信号 output reg key_state; //按键状态信号 endmodule
5、边沿检测电路:
reg key_tmp0,key_tmp1; wire pedge,nedge; always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin key_tmp0 <= 1'b0; key_tmp1 <= 1'b0; end else begin key_tmp0 <= key_in; key_tmp1 <= key_tmp0; end assign nedge = !key_tmp0 & key_tmp1; //下降沿 assign pedge = key_tmp0 & !key_tmp1; //上升沿
6、设置20ms计数器
reg [19:0]cnt; //计数器 reg en_cnt; //使能计数寄存器,控制计数器cnt reg cnt_full; //计满标志信号 always@(posedge Clk or negedge Rst_n) if(!Rst_n) cnt <= 20'd0; else if(en_cnt) cnt <= cnt + 1'b1; else cnt <= 20'd0; always@(posedge Clk or negedge Rst_n) if(!Rst_n) cnt_full <= 1'b0; else if(cnt == 999_999) //计数1_000_000次 cnt_full <= 1'b1; else cnt_full <= 1'b0;
7、设置状态机
always@(posedge Clk or negedge Rst_n) if(!Rst_n)begin en_cnt <= 1'b0; state <= IDEL; key_flag <= 1'b0; key_state <= 1'b1; end else begin case(state) IDEL:begin key_flag <= 1'b0; if(nedge)begin //出现下降沿,转到FILTER0状态 state <= FILTER0; en_cnt <= 1'b1; //开始计数 end else state <= IDEL; end FILTER0: if(cnt_full)begin //计数器计满,转到DOWN状态 key_flag <= 1'b1; key_state <= 1'b0; state <= DOWN; en_cnt <= 1'b0; //停止计数,并使计数器清零 end else if(pedge)begin //出现上升沿,转到IDEL状态 state <= IDEL; en_cnt <= 1'b0; //停止计数,并使计数器清零 end else state <= FILTER0; DOWN:begin key_flag <= 1'b0; if(pedge)begin //出现上升沿,转到FILTER0状态 state <= FILTER1; en_cnt <= 1'b1; //开始计数 end else state <= DOWN; end FILTER1: if(cnt_full)begin //计数器计满,转到IDEL状态 key_flag <= 1'b1; key_state <= 1'b1; state <= IDEL; en_cnt <= 1'b0; //停止计数,并使计数器清零 end else if(nedge)begin //出下降沿,转到DOWN状态 state <= DOWN; en_cnt <= 1'b0; //停止计数,并使计数器清零 end else state <= FILTER1; default:begin state <= IDEL; en_cnt <=1'b0; key_flag <= 1'b0; key_state <= 1'b1; end endcase end
8、状态图(State Machine Viewer):
9、设置testbench文件(仿真模型)
9.1、设置仿真模型key_model.v
`timescale 1ns/1ns module key_model(key); output reg key; reg [15:0]myrand; initial begin key = 1'b1; press_key; #10000; press_key; #10000; press_key; $stop; end task press_key; //设置press_key任务 begin repeat(50)begin myrand = {$random}%65536; //产生0~65535之间的随机数 #myrand key = ~key; end key = 0; #50000000; repeat(50)begin myrand = {$random}%65536; //0~65535之间的随机数 #myrand key = ~key; end key = 1; #50000000; end endtask endmodule
9.2、设置testbench文件key_filter_tb.v
`timescale 1ns/1ns `define clock_period 20 module key_filter_tb; reg Clk; reg Rst_n; wire key_in; //key_in在此时相当于是一根线,所以设置为wire类型 wire key_flag; wire key_state; key_filter key_filter0( .Clk(Clk), .Rst_n(Rst_n), .key_in(key_in), .key_flag(key_flag), .key_state(key_state) ); key_model key_model(.key(key_in)); initial Clk = 1; always#(`clock_period/2) Clk = ~Clk; initial begin Rst_n = 1'b0; #(`clock_period*10) Rst_n = 1'b1; #(`clock_period*10 + 1); end endmodule
9.3、将仿真模型与testbench文件链接
Assignments->Settings...->Test Benches...->Edit...
在testbench文件夹中选中key_model文件,点击Add
本文作者:Yamada_Ryo
本文链接:https://www.cnblogs.com/little55/p/17866867.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步