verilog中边沿检测器,双边沿检测器和双边沿触发寄存器的理解和写法

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相关,所以容易产生毛刺现象。 弄懂毛刺现象可参考另外一篇文章。


版权声明:本文为weixin_42664351原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。