流程
复位键:点亮最右边灯[3:0],即第0位
按键:LED依次往左移动
SW:按键,按下为1,抬起为0
消除抖动代码
/*按键消抖模块*/
module debounce(
input wire clk ,
input wire rst_n ,
input wire sw ,
output reg key
);
//50Mhz--0.02us 50个周期,1us;50*10000=10ms
//10ms500000个时钟周期,转为二进制是1111010000100100000,一共19位
reg[18:0] cnt_10ms;
parameter CNT_10MS = 30; //30仿真
reg flag;
//cnt_10ms sw按键:按下低电平;抬起高电平
always @(posedge clk or negedge rst_n)
if(rst_n == 0)
cnt_10ms <= 0;
else if((cnt_10ms==CNT_10MS+1)&&(sw==1))//CNT_10MS为499999
cnt_10ms<=CNT_10MS+1;
else if(sw==1)
cnt_10ms<=cnt_10ms+1;
else if(sw == 0)
cnt_10ms<=0;
//flag
always @(posedge clk or negedge rst_n)
if(rst_n == 0)
flag <= 0;
else if((cnt_10ms==CNT_10MS) &&(sw==1))
flag<=1;
else
flag <=0;
//key
always @(posedge clk or negedge rst_n)
if(rst_n == 0)
key <=0;
else if(flag == 1)
key <= 1;
else
key <=0;
endmodule
LED模块
//再写led灯子模块
/*led灯模块*/
module led(
input wire clk ,
input wire rst_n ,
input wire key ,
output reg[3:0] led
);
//led
always@(posedge clk or negedge rst_n)
if(rst_n == 0)
led <= 4'b0001;
else if(key == 1) //往左移动流水
led <= {led[2:0],led[3]};
endmodule
//将两个子模块在顶层模块中例化并连线。
顶层模块
/*顶层模块*/
module top(
input wire clk ,
input wire rst_n,
input wire sw ,
output wire[3:0] led
);
wire key;
debounce debounce_inst(
.clk(clk),
.rst_n(rst_n),
.sw(sw),
.key(key)
);
led led_inst(
.clk(clk),
.rst_n(rst_n),
.key(key),
.led(led)
);
endmodule
测试代码:
`timescale 1ns / 1ps
module tb();
reg clk; //因为clk要进行赋值变化,所以为reg类型。
reg rst_n; //和clk同理
reg sw;
reg[8:0] time1;
wire[3:0] led; //此处要检测led的信号,所以设置为wire类型
initial //初始化开始
begin
clk=0; //首先设置clk为0
rst_n<=0; //rst_n为0
sw<=0; //没按下,为0
time1<=0;
#100 //延时100ns,为了便于查看波形,通常会进行一段时间
rst_n<=1; //复位按键置1
end
always #10 clk=~clk; //每过10ns后,clk取反,这里clk时钟周期为20ns,50Mhz
//time1
always #20 // 21-70按下
if(time1 == 200)
time1 <= 0;
else
time1 <= time1 +1;
//sw
always #20
if((time1 < 20)||(time1>70&&time1<100))
sw <= {$random};
else if(time1 > 100)
sw <= 0;
else //按下为1
sw <=1;
top top_inst( //将模块例化,并连线
.clk (clk),
.rst_n (rst_n),
.sw (sw),
.led (led)
);
endmodule
功能仿真图
990-380=610ns>20*30=600ns