单稳态多谐振荡器仿真

Monostable multivibrator simulation

monostable模块实现了一个单稳态多谐振荡器。它接受三个输入(clk、reset、trigger)并输出一个 (pulse).

触发输入触发模块。当被触发时,输出信号(pulse)将切换到高电平一段时间的时钟滴答,然后return到低电平。输出信号的脉冲宽度可以通过 PULSE_WIDTH 参数设置,该参数表示信号应保持高电平的时钟周期。

现在,发生的事情是当它被触发时,立即输出信号 (pulse) 变高。

触发后,输出信号 (pulse) 应在 clk 的下一个有效边沿为高电平。可以做哪些改变?

module monostable(
        input clk,
        input reset,
        input trigger,
        output reg pulse = 0
);
        parameter PULSE_WIDTH = 20;

        reg [4:0] count = 0;

        wire countReset = reset | (count == PULSE_WIDTH);

        always @(posedge trigger, posedge countReset) begin
                if (countReset) begin
                        pulse <= 1'b0;
                end else begin
                        pulse <= 1'b1;
                end
        end

        always @(posedge clk, posedge countReset) begin
                if(countReset) begin
                        count <= 0;
                end else begin
                        if(pulse) begin
                        count <= count + 1'b1;
                        end
                end
        end
endmodule



module monostable_tb();

reg clk;
reg reset;
reg trigger;
wire pulse;

parameter PULSE_WIDTH = 20;

monostable imonostable(.*);

initial begin
    clk=0;
    forever #50 clk=~clk;
end

initial begin
    $monitor("trigger=%b  pulse=%b, count = %0d",trigger,pulse,imonostable.count);
    $dumpfile("monostable_tb.vcd");
    $dumpvars(0,monostable_tb);

    trigger=1'b0;
    reset = 1'b0;    

    @(posedge clk) reset = 1'b1;
    @(posedge clk) reset = 1'b0;  
    @(posedge clk) trigger=1'b1;
    @(posedge clk) trigger=1'b0;

    repeat(25) @(posedge clk);

    $finish;
end  
endmodule

如果需要 1 个时钟的同步延迟,则 运行 通过触发器输出。

    module monostable(
        input clk,
        input reset,
        input trigger,
        output reg pulse = 0
);
        parameter PULSE_WIDTH = 20;

        reg [4:0] count = 0;
        reg reg_pulse_temp;

        wire countReset = reset | (count == PULSE_WIDTH);
      
        always @(posedge trigger, posedge countReset) begin
                if (countReset) begin
                        reg_pulse_temp <= 1'b0;
                end else begin
                        reg_pulse_temp <= 1'b1;
                end
        end

        always @(posedge clk, posedge countReset) begin
                if(countReset) begin
                        count <= 0;
                        // reset the flop
                        pulse <= 0;
                end else begin
                        if(pulse) begin
                        count <= count + 1'b1;
                        end
                end
          
          // flip flop
          pulse  <= reg_pulse_temp;
          
        end
endmodule

这是一个简化的设计,它在输入触发脉冲后设置输出一个周期,并保持输出高电平 20 个周期:

   module monostable(
            input clk,
            input reset,
            input trigger,
            output reg pulse = 0
    );
            parameter PULSE_WIDTH = 20;
    
            reg [4:0] count;
    
            always @(posedge clk, posedge reset) begin
                    if (reset) begin
                            pulse <= 1'b0;
                    end else if (trigger) begin
                            pulse <= 1'b1;
                    end else if (count == PULSE_WIDTH-1) begin
                            pulse <= 1'b0;
                    end
            end
    
            always @(posedge clk, posedge reset) begin
                    if(reset) begin
                            count <= 0;
                    end else if (pulse) begin
                            count <= count + 1'b1;
                    end
            end
    endmodule

它现在使用一个时钟信号,而不是 2 个。它还使用一个简单的复位信号,可以避免潜在的故障导致不需要的异步复位。

您还应该在测试台中使用非阻塞分配:

@(posedge clk) reset  <= 1'b1;
@(posedge clk) reset  <= 1'b0;  
@(posedge clk) trigger<= 1'b1;
@(posedge clk) trigger<= 1'b0;