本次实验目的在于熟悉状态机的控制,需要实现的功能如下:
按下按键并保持然后松开
当保持时间小于1s时,一个led灯闪烁2次。
当保持时间小于2s大于1s时,一个led灯闪烁4次。
当保持时间大于2s时,四个led灯闪烁4次。
本次实验采用了状态机的思想控制,主要的细节包括:1.输入信号的缓冲;2输入信号的上升沿和下降沿的检测;3.不同延迟时间的跳转;4.按下计时和led闪烁计时器的各自设计;5,led闪烁的控制。
RTL代码如下:
module keykeeper(
clk,
rst,
key_in,
led,
state_out,
cnt,
cnt_led,
led_finish,
time_flag_1,
time_flag_2,
key_pos,
key_neg
);
input clk;
input rst;
input wire key_in;//输入信号
output reg [3:0]led;//led信号
output wire [1:0]state_out;//状态跳转输出
output reg [15:0]cnt; //按下计时
output reg [15:0]cnt_led;//led闪烁计时
output reg led_finish;//led完成闪烁返回信号
reg en_cnt;//按下计时使能信号
reg key_temp_1;//信号缓冲同步
reg key_temp_2;
reg key_temp_3;//边沿寄存
reg key_temp_4;
reg en_cnt_led;
output wire key_pos;//检测边沿信号
output wire key_neg;
output reg time_flag_1;
output reg time_flag_2;
//设置状态跳转
reg [1:0]state;
assign state_out = state;
localparam
s0 = 2'b00,
s1 = 2'b01,
s2 = 2'b10,
s3 = 2'b11;
//两级缓冲器对输入信号进行同步
always@(posedge clk or negedge rst)
if(!rst)
begin
key_temp_1 <= 1'b1;
key_temp_2 <= 1'b1;
end
else
begin
key_temp_1 <= key_in;
key_temp_2 <= key_temp_1;
end
//检测key_in的下降沿和上升沿
always@(posedge clk or negedge rst)
if(!rst)
begin
key_temp_3 <= 1'b1;
key_temp_4 <= 1'b1;
end
else
begin
key_temp_3 <= key_temp_2;
key_temp_4 <= key_temp_3;
end
assign key_pos = (key_temp_3)&&(!key_temp_4);
assign key_neg = (!key_temp_3)&&(key_temp_4);
//设置计数使能信