verilog中边沿检测器,双边沿检测器和双边沿触发寄存器的理解和写法
单边沿检测
电路图
根据电路图很好理解, 为了让原来的信号保持一下也可以说是延迟一个时钟,就能做出上升沿的判断,后面加入一个寄存器的目的就是为了让检测延迟一个时钟显示,也保证检测只持续一个时钟。
module top_module (
input clk,
input [7:0] in,
output [7:0] pedge
);
reg [7:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
pedge <= in & ~in_reg;
end
/* //second way integer i; always@(posedge clk)begin for(i = 0; i <= 7; i = i + 1)begin if(in[i] & ~in_reg[i])begin pedge[i] = 1'b1; end else begin pedge[i] = 1'b0; end end end */
endmodule
双边沿检测
电路图
寄存器的作用同单边沿检测器,改变逻辑判断就能达到当输入改变的时候能判断现在的输入和原来的输入的变化关系,假设输入是多位变量就能很好的判断出哪些位产生了变化。
module top_module (
input clk,
input [7:0] in,
output [7:0] anyedge
);
reg [7:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
anyedge = in ^ in_reg;
end
endmodule
下降沿检测保持器件
电路图
由图可以看出反相器和与门的作用是下降沿判断,后面的或门是为了输出保持,这样检测输出就不止持续一个时钟。
module top_module (
input clk,
input reset,
input [31:0] in,
output [31:0] out
);
reg [31:0] in_reg;
always@(posedge clk)begin
in_reg <= in;
end
always@(posedge clk)begin
if(reset)begin
out <= 32'd0;
end
else begin
out <= ~in & in_reg | out;
end
end
endmodule
双边沿触发寄存器(DDR)
双边沿触发寄存器,就是在时钟上升沿和下降沿都能传递信号的寄存器。在写verilog的时候一定不能使用 always @(posedge clk or negedge clk) 这种写法。
module top_module (
input clk,
input d,
output q
);
reg q_d1;
reg q_d2;
always@(posedge clk)begin
q_d1 <= d ^ q_d2;
end
always@(negedge clk)begin
q_d2 <= d ^ q_d1;
end
assign q = q_d1 ^ q_d2;
endmodule
/* //second way always@(posedge clk)begin q_d1 <= d; end always@(negedge clk)begin q_d2 <= d; end assign q = clk ? q_d1 : q_d2; */
//endmodule
方法一使用了密码学中的想法这样可以消除clk在最终信号中的判断从而来消除毛刺现象。
密码学中的想法是一个数连续异或另一数2次还是本身。
即a ^ b ^ b = a;
方法一中
q = q_d1 ^ q_d2;
而上升沿和下降沿时
q_d1 <= d ^ q_d2;
q_d2 <= d ^ q_d1;
这样就只需要用寄存器储存的值来进行输出判断,而不需要像方法中的那样最后需要用clk来判断输出,因为clk又跟q_d1和q_d2相关,所以容易产生毛刺现象。 弄懂毛刺现象可参考另外一篇文章。