Search code examples
verilogclocksystem-verilogxilinx-ise

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


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!


Solution

  • 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.