模块框图:
top代码:
module key_led_top(
input sys_clk,
input sys_rst_n,
input key_in0,
input key_in1,
output [3:0] led
);
wire key_flag0,key_flag1;
wire key_state0,key_state1;
key_filter u_key_filter0(
.clk (sys_clk) ,
.Rst_n (sys_rst_n) ,
.key_in (key_in0) ,
.key_flag (key_flag0) ,
.key_state(key_state0)
);
key_filter u_key_filter1(
.clk (sys_clk) ,
.Rst_n (sys_rst_n) ,
.key_in (key_in1) ,
.key_flag (key_flag1) ,
.key_state(key_state1)
);
led_ctrl(
.clk (sys_clk),
.rst_n (sys_rst_n),
.key_flag0 (key_flag0), //按键1
.key_flag1 (key_flag1),
.key_state0 (key_state0), //按键1
.key_state1 (key_state1),
.led(led)
);
endmodule
模块代码:
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;
localparam
IDEL = 4'b0001,
FILTER0 = 4'b0010,
DOWN = 4'b0100,
FILTER1 = 4'b1000;
reg [3:0]state;
reg [19:0]cnt;
reg en_cnt;
reg cnt_full;//计数满标志信号
reg key_tmp0,key_tmp1;
wire pedge,nedge;
//异步信号同步处理
reg key_in_s0;
reg key_in_s1;
always @(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
key_in_s0 <= 0 ;
key_in_s1 <= 0 ;
else
key_in_s0 <= key_in ;
key_in_s1 <= key_in_s0 ;
end
assign key_in_s1 = key_in_s1 ;
always @(posedge clk or negedge Rst_n)
begin
if(!Rst_n)
begin
key_tmp0 <= 1'b0;
key_tmp1 <= 1'b0;
end
else
begin
key_tmp0 <= key_in;
key_tmp1 <= key_tmp0;
end
end
assign nedge = (!key_tmp0)&key_tmp1;
assign pedge = key_tmp0&(!key_tmp1);
always @(posedge clk or negedge Rst_n)
if(!Rst_n)
begin
state <= IDEL;
en_cnt <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end
else begin
case(state)
IDEL:
begin
key_flag <= 1'b0;
if(nedge)begin
state <= FILTER0;
en_cnt<=1'b1;
end
else
state <= IDEL;
end
FILTER0:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b0;
state <= DOWN;
en_cnt <= 1'b0;
end
else if(pedge)begin
state <= IDEL;
en_cnt <= 1'b0;
end
else
state <= FILTER0;
DOWN:
begin
key_flag <= 1'b0;
if(pedge)begin
state <= FILTER1;
en_cnt <= 1'b1;
end
else
begin
state <= DOWN;
end
end
FILTER1:
if(cnt_full)begin
key_flag <= 1'b1;
key_state <= 1'b1;
state <= IDEL;
end
else if(nedge)
begin
en_cnt <= 1'b0;
state <= DOWN;
end
else
begin
state <= FILTER1;
end
default:
begin
state <= IDEL;
en_cnt <= 1'b0;
key_flag <= 1'b0;
key_state <= 1'b1;
end
endcase
end
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)
cnt_full <= 1'b1;
else
cnt_full <= 1'b0;
endmodule
module led_ctrl(
input clk,
input rst_n,
input key_flag0, //按键1
input key_flag1,
input key_state0, //按键1
input key_state1,
output reg [3:0] led
);
// wire key_flag0,key_flag1;
// wire key_state0,key_state1;
wire led0;
always @(posedge clk or negedge rst_n) //两个按键按下部分
begin
if(!rst_n)
led <= 4'b0000;
else if(key_flag0 & (!key_state0))
led <= 4'b0000 + 1 ;
else if(key_flag1 & (!key_state1))
led <= 4'b0000 + 1 ;
else
led <= led;
end
assign led0 = led ;
endmodule
task写法:
//task 写法
//目的:函数调用 取代了写50次的模拟按键与释放
reg [15:0] myrand;
tassk press_key;
begin
repeat(50) begin //模拟50次的抖动现象
myrand = {&random} %65536 ; //引入随机生成数
#myrand key_in =~ key_in;
end
key_in = 0 ;
#50000000 ; //最后趋向于稳定
repeat(50) begin //模拟50次的抖动现象
myrand = {&random} %65536 ; //引入随机生成数
#myrand key_in =~ key_in;
end
key_in = 1 ;
#50000000 ; //最后趋向于稳定
end
//然后调用函数
initial begin
key_in = 1;
press_key;
#100000;
press_key;
#100000;
press_key;
$stop;
end
学习心得:
1.异步信号转同步:两个寄存器打拍(异步信号与系统时钟无关)
2.状态机的一段式
3.多个模块的学习
因为我的板子是ZYNQ 7020,原理图上的N15 N16 按键的引脚貌似出问题了……