Verilog: How to delay an input signal by one clock cycle?

user3330840 picture user3330840 · Oct 14, 2016 · Viewed 30.6k times · Source

I would like to delay an input signal by one complete clock cycle.
I have the code below which basically tries to change the signal at posedge of the clock.
However, the test bench shows that it doesn't always delay by 1 cycle.
In some cases, it changes at the same time the input signal changes.

Is there any way to solve this kind of problem?

module delay_one_cycle(
  input clk,
  input[3:0] original_signal,
  output reg[3:0] delayed_signal
);

  always @(posedge clk) begin
    delayed_signal <= original_signal;
  end


endmodule

module delay_one_cycle_tb();
  reg clk;
  reg[3:0] original_signal;  
  wire[3:0] delayed_signal;

  delay_one_cycle doc_inst (clk, original_signal, delayed_signal);  

  // Initial setup
  initial begin  
    clk                 = 0;

    original_signal     = 4'd9;
    #5 original_signal  = 4'd10;
    #5 original_signal  = 4'd11;    
    #4 original_signal  = 4'd12;
    #3 original_signal  = 4'd13;

    // finish the simulation
    #5 $finish;
  end  

  // clock
  always begin
    #1 clk = !clk;
  end
endmodule

Here is the waveform: enter image description here The waveform shows, for example, when input signal changes on the clock edge to 1010, output also changes at the same time.
the delayed_signal is not actually delayed to next cycle!

Answer

e19293001 picture e19293001 · Oct 14, 2016

This question is quite similar to your question Why is my D Flip Flop not waiting for the positive edge of the clock?

You might want to try this convention to avoid race condition:

@(posedge clk);

Try to avoid setting input signals to your RTL code with blocking assignments. Use non-blocking assignment instead as what @Morten Zilmer suggests.

Your test bench should somehow look something like this:

module delay_one_cycle(
  input clk,
  input[3:0] original_signal,
  output reg[3:0] delayed_signal
);

  always @(posedge clk) begin
    delayed_signal <= original_signal;
  end


endmodule

module delay_one_cycle_tb();
  reg clk;
  reg[3:0] original_signal;  
  wire[3:0] delayed_signal;

  delay_one_cycle doc_inst (clk, original_signal, delayed_signal);  

  // Initial setup
  initial begin  

    original_signal     <= 4'd9;
    repeat (5) @(posedge clk);
    original_signal  <= 4'd10;
    repeat (5) @(posedge clk);
    original_signal  <= 4'd11;
    repeat (4) @(posedge clk);
    original_signal  <= 4'd12;
    repeat (3) @(posedge clk);
    original_signal  <= 4'd13;

    // finish the simulation
   repeat (5) @(posedge clk);
   $finish;
  end  

  initial begin
    clk                 = 0;
    forever begin
       #1 clk = !clk;
    end
  end 
endmodule

Hope that helps.