Verilog单边沿检测和双边沿检测的方法(HDLBits例题)
1.单边沿检测
边沿检测是用来检测某一信号是否发送了从0至1或者从1至0的变化,有同步和异步之分。
同步边沿检测:是使用一个基准时钟,即在同一个时钟下来检测一个信号的上升沿或者下降沿。
异步边沿检测:是利用D触发器来实现边沿检测。
HDLBits例题: 单边沿检测例题
题目:对于8位向量中的每一位,检测输入信号在一个时钟周期内从0变化到下一个时钟周期的1(类似于正边缘检测)。输出位应该在0到1转换发生后的循环中设置。
解法是让该信号再过一级触发器,令 in_r <= in; 有点像打了一拍,然后当判断到前一次信号为1(in == 1),这一次信号为0(in_r == 0)时即发生了信号0至1的跳变。这就是上升沿检测。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] in_r;
always@(posedge clk)begin
in_r <= in;
pedge <= in & ~in_r;
end
endmodule
另外检测下降沿的话也是同样的原理,让该信号再过一级触发器,令 in_r <= in; 然后当判断到前一次信号为0(in == 0),这一次信号为1(in_r == 1)时即发生了信号0至1的跳变。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] in_d;
always@(posedge clk)begin
in_d <= in;
pedge <= ~in & in_d;
end
endmodule
2.双边沿检测的方法
同样用HDLBits里的一道例题来做说明:双边沿检测例题
题目:你熟悉的触发器是在时钟的正边缘触发的,或者是在时钟的负边缘触发的。双边触发触发器是在时钟的两个边触发的。然而,fpga没有双边触发触发器,并且always @(posedge clk或negedge clk)不被接受为法律敏感性列表。
这一题乍一想,,感觉可以用always @(posedge clk或negedge clk)或者用两个触发器,即两个always语句,一个判断posedge一个判断negedge,但是这样是不行的 😭 ……
但是可以用其他方法解决,这里提供两种解法:
①:
module top_module (
input clk,
input d,
output q
);
reg [1:0] tmp;
always @ (posedge clk) begin
tmp[0] <= d;
end
always @ (negedge clk) begin
tmp[1] <= d;
end
assign q = clk?tmp[0]:tmp[1];
endmodule
这种比较常规,另一种方法会更妙一些。
②,利用两次异或等于本身的方法,即p^d ^p = d的这种想法来做:
module top_module (
input clk,
input d,
output q
);
reg n,p;
always@(posedge clk)begin
p <= d ^ n;
end
always@(negedge clk)begin
n <= d ^ p;
end
assign q = p ^ n;
endmodule
👌