一、设计背景:
边沿检测电路:如上图,为我们待检测信号,可以看出边沿的特性:边沿两侧信号的电平发生了变化。红色为上升沿,绿色为下降沿。上升沿之前电平为低,上升沿之后电平为高。下降沿之前为电平为高,下降沿之后电平为低。
二、设计需求:
设计边沿检测电路,可检测上升沿和下降沿。
三、设计方案:
实序图:
五、代码
module check_edge(clk,rst_n,signal,pos_edge,neg_edge);
input clk;
input rst_n;
input signal;
output pos_edge;
output neg_edge;
reg buffer1;
reg buffer2;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
buffer1 <= 1'b0;
end
else
begin
buffer1 <= signal;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
buffer2 <= 1'b0;
end
else
begin
buffer2 <= buffer1;
end
end
assign pos_edge = buffer1 && (!buffer2);//上升沿
assign neg_edge = buffer2 && (!buffer1);//下降沿
endmodule
六、仿真验证:
如下
`timescale 1ns/1ns
module tb_check_edge();
reg clk;
reg rst_n;
reg signal;
wire pos_edge;
wire neg_edge;
check_edge check_edge_inst(
.clk(clk),
.rst_n(rst_n),
.signal(signal),
.pos_edge(pos_edge),
.neg_edge(neg_edge)
);
initial
begin
clk = 1;
rst_n = 0;
signal = 0;
#100
rst_n = 1;
#100
signal = 1;
#100
signal = 0;
#100
signal = 1;
#200
signal = 0;
#2000
$stop;
end
always #10 clk = ~clk;
endmodule
练习:
利用按键消抖和边沿检测,实现按键按下(检测下降沿),完成LED点亮,抬起(检测上升沿),LED灯点亮(第二个)。要求:1设计架构;2设计方案;3仿真测试4下板验证。
1、框架图:
2、代码实现:
顶层代码:
//顶层
module key_edge_led(clk,rst_n,key_in,led);
input clk;
input rst_n;
input key_in;
output [1:0]led;
wire flag;
wire pos_edge;
wire neg_edge;
/*#(.cnt_num(4)) */
//#(.cnt_num(4))
filter /*#(.cnt_num(4)) */ filter_inst(
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.neg(neg)
);
check_edge check_edge_inst(
.clk(clk),
.rst_n(rst_n),
.signal(neg),
.pos_edge(pos_edge),
.neg_edge(neg_edge)
);
key_led key_led_inst(
.pedge(pos_edge),
.nedge(neg_edge),
.rst_n(rst_n),
.clk(clk),
.led(led)
);
endmodule
按键消抖模块:
//按键消抖模块:利用尖峰脉冲信号来对按键的动作中作一次处理
module filter(clk,rst_n,key_in,neg);
input clk;
input rst_n;
input key_in;
output reg neg;//输出的尖峰脉冲信号(按键稳定的标志信号)
reg[31:0] cnt;
reg state;//状态寄存器:两个状态(按下和抬起)
reg flag;
`define s0 1'b0
`define s1 1'b1
parameter cnt_num = 50_000_000/100-1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cnt <= 32'b0;
state <= `s0;
flag <= 1'b0;
end
else
begin
case(state)
`s0:begin
if(!key_in )//有按键按下
begin
if(cnt < cnt_num)//未达到消抖时间
begin
cnt <= cnt + 1'b1;
flag <= 1'b0;
end
else//达到消抖时间
begin
cnt <= 32'b0;
flag <= 1'b1;
state <= `s1;
end
end
else //没有按键按下
begin
state <= `s0;//等待按键按下
cnt <= 32'b0;
flag <= 1'b0;
end
end
`s1:begin
flag <= 1'b0;
if(key_in)//按键抬起
begin
if(cnt < cnt_num)//没有到消抖时间
begin
cnt <= cnt + 1'b1;
flag <= 1'b0;
end
else//到达消抖时间
begin
cnt <= 32'd0;
flag <= 1'b1;
state <= `s0;
end
end
else//按键未抬起
begin
state <= `s1;//等待按键抬起
end
end
default : state <= `s0;
endcase
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
neg <= 1'b1;
end
else
begin
if((flag == 1) && (key_in == 1))
begin
neg <= 1'b1;
end
else if((flag == 1) && (key_in == 0))
begin
neg <= 1'b0;
end
end
end
endmodule
边沿检测:
module check_edge(clk,rst_n,signal,pos_edge,neg_edge);
input clk;
input rst_n;
input signal;
output pos_edge;
output neg_edge;
reg buffer1;
reg buffer2;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
buffer1 <= 1'b0;
end
else
begin
buffer1 <= signal;
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
buffer2 <= 1'b0;
end
else
begin
buffer2 <= buffer1;
end
end
assign pos_edge = buffer1 && (!buffer2);//上升沿
assign neg_edge = buffer2 && (!buffer1);//下降沿
endmodule
LED显示:
module key_led(clk,rst_n,pedge,nedge,led);
input pedge;
input nedge;
input rst_n;
input clk;
output reg [1:0]led;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
led <= 2'b00;
else
begin
if(nedge)
led <= 2'b10;
else if(pedge)
led <= 2'b01;
end
end
endmodule
3、仿真验证
下板与仿真相符。