Verilog гонки с делителем часов с использованием флопов - PullRequest
0 голосов
/ 06 октября 2018

Я сделал базовый пример на игровой площадке eda, который получил.Допустим, у меня есть два часа 1x и 2x.2x делится с 1x с использованием делителя флопа.

У меня есть два регистра a и b.a синхронизируется в 1x, b синхронизируется в 2x.

b является значением выборки a.

Когда у нас есть нарастающий фронт в 1x и 2x тактах, b не принимает ожидаемое значениеa, но он принимает значение следующего цикла.

Это из-за этой схемы деления часов, если мы делаем деление с использованием icgs и en, он работает нормально.Но есть ли способ заставить его работать, используя эту схему делителей часов с флопами?

EDA игровая площадка: https://www.edaplayground.com/x/map#

module race_test;

  logic clk1x = 0;
  logic clk2x = 0;

  always
    #5ns clk1x = !clk1x;

  int a, b;


  always @(posedge clk1x) begin
    a <= a+1;
    clk2x <= !clk2x;
  end

  // Problem here is that b will sample postpone value of a
  // clk2x is not triggering at the same time than clk1x but a bit later
  // This can be workaround by putting blocking assignment for clock divider
  always @(posedge clk2x) begin
    b <= a;
  end

  initial begin
    $dumpfile("test.vcd");
    $dumpvars;
    #1us
    $stop;
  end
endmodule

1 Ответ

0 голосов
/ 06 октября 2018

Цифровые тактовые делители представляют проблемы как с симуляцией, так и с физической синхронизацией.

Неблокирующий оператор присваивания Verilog предполагает, что все читающие и записывающие одни и те же переменные синхронизируются с одним и тем же тактовым событием.Используя запись NBA в clk2x, вы сместили чтение a в другое delta time *, и, как вы обнаружили, a уже обновлено.

В реальном оборудовании существуют значительные задержки распространения, которые обычно избегают этой ситуации.Однако вы используете тот же D-flop для присвоения clk2x, поэтому там также будут задержки распространения.Ваш последний always блок теперь представляет проблему пересечения часового домена.Таким образом, в зависимости от перекоса между двумя часами, у вас все еще может быть состояние гонки.

Один из способов исправить это - использовать модуль тактового генератора с тактовой частотой даже более высокой частоты

always #2.5ns clk = !clk;

always @(posedge clk) begin
       clk1x <= !clk1x;
       if (clk1x == 1)
         clk2x = !clk2x;
...