Verilog: Как задержать входной сигнал на один такт?

Я хотел бы задержать входной сигнал на один полный тактовый цикл.
У меня есть приведенный ниже код, который в основном пытается изменить сигнал при установке часов.
Однако испытательный стенд показывает, что это не всегда задержка на 1 цикл.
В некоторых случаях она изменяется одновременно с изменением входного сигнала.

Есть ли способ решить такую ​​проблему?

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

Вот форма волны:  введите описание изображения здесь Форма волны показывает, например, что когда входной сигнал изменяется на фронте тактового сигнала на 1010, одновременно изменяется и выходной сигнал.
delayed_signal на самом деле не отложено до следующего цикла!


person user3330840    schedule 14.10.2016    source источник


Ответы (3)


Этот вопрос очень похож на ваш вопрос Почему мой D Flip Flop не ждет положительного фронта часов?

Вы можете попробовать это соглашение, чтобы избежать состояния гонки:

@(posedge clk);

Старайтесь избегать установки входных сигналов для вашего кода RTL с назначениями блокировки. Вместо этого используйте неблокирующее присваивание, как предлагает @Morten Zilmer.

Ваш тестовый стенд должен как-то выглядеть примерно так:

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

Надеюсь, это поможет.

person e19293001    schedule 14.10.2016

Проблема заключается в состоянии гонки Verilog.

Таким образом, при изменении original_signal в то же время, когда возникает нарастающий фронт clk, тогда original_signal получает новое значение перед обновлением на основе clk, и в результате вы не получаете желаемой задержки.

Используйте неблокирующее назначение (<=) вместо блокирующего назначения (=) в блоках always.

Также используйте clk для управления изменением данных стимулов с помощью repeat (5) @(posedge clk);, как указывает @ e19293001, чтобы получить надежный испытательный стенд для последовательного проектирования.

Дополнительные сведения о проблеме см. В приведенном выше поиске и в этом Неблокирующие присвоения в Verilog Synthesis..

person Morten Zilmer    schedule 14.10.2016
comment
1) Что означает одиночный оператор @ (posedge clk); делать? Я видел только синтаксис вроде: always @ (posedge clk) begin .... end. 2) Что это за конструкция и как она работает с повторами выше? Например: repeat (5) @ (posedge clk); 3) Оба повторяются (5) @ (posedge clk); и отсутствие блочности (‹=) требуется выше, чтобы получить правильную симуляцию? - person user3330840; 15.10.2016

Это может быть связано с тем, что в тот момент, когда вы меняете входные данные, изменяется выходное значение, но, согласно вашему испытательному стенду, например, изменение значения на 4'd11 происходит незадолго до отсчета времени. Таким образом, блок always в исходном модуле не вводится до положения часов.

person Ritika    schedule 25.08.2020