SystemVerilog всегда_комб не переоценивает, если меняется список подразумеваемой чувствительности - PullRequest
0 голосов
/ 12 марта 2019

Вот фрагмент кода с 3 различными операторами всегда, который должен быть синтезируемым. Проблемы со следующим:

always_comb
  begin
    c_cntr1 = cntr1;
    c_func_val1 = diff (0, c_cntr1);

    if (read)
       c_cntr1 = cntr1+1;

  end

Я ожидал, что Always_comb будет переоценен при изменении c_cntr1, вызове функции и повторной оценке c_func_val1, но это не так. Я неправильно интерпретирую LRM?

Вот полный тестовый пример, который показывает неправильное поведение, а 2 других блока всегда дают правильный результат. Я управлял этим с NC. Я не проверял другие симуляторы или инструменты синтеза.

Полный тестовый кейс

module test_always_comb();

reg clk, resetn, read;

initial 
  begin
    clk = 0;
    resetn = 0;
    forever #5 clk = ~clk;
  end

initial 
  begin
    resetn = 0;
    read = 0;
    @(posedge clk);
    @(posedge clk);
    resetn = 1;
    for (int i = 0; i < 10; i++)
      begin
        @(posedge clk);
        if (i%2 == 0)
          read= 1;
        else
          read= 0;
      end
    $finish;
  end

always@(posedge clk)
  if (resetn)
   begin
      $display("Value of c_func_val1 is %d, cntr is %d, c_cntr is %d\n", c_func_val1, cntr1, c_cntr1);
      $display("Value of c_func_val2 is %d, cntr is %d, c_cntr is %d\n", c_func_val2, cntr2, c_cntr2);
      $display("Value of c_func_val3 is %d, cntr is %d, c_cntr is %d\n", c_func_val3, cntr3, c_cntr3);
   end

// Synesizable Design Code


   function automatic [4:0] diff 
     (
      input [4:0] num1,
      input [4:0] num2
      );
      return num2;
   endfunction // diff

logic [4:0] c_cntr1, c_cntr2, c_cntr3, c_func_val1, c_func_val2, c_func_val3;
reg [4:0] cntr1, cntr2, cntr3;

always_comb
  begin
    c_cntr1 = cntr1;
    c_func_val1 = diff (0, c_cntr1);

    if (read)
       c_cntr1 = cntr1+1;

  end

always_comb
  begin
    c_cntr2 = cntr2;
    if (read)
      c_cntr2 = cntr2+1;
    c_func_val2 = diff (0, c_cntr2);
  end

always @(*)
  begin
    c_cntr3 = cntr3;
    if (read)
      c_cntr3 = cntr3+1;
    c_func_val3 = diff (0, c_cntr3);
  end

always_ff @(posedge clk or negedge resetn)
   begin
     if (~resetn)
       begin
        cntr1 <= 0;
        cntr2 <= 0;
        cntr3 <= 0;
       end
     else
       begin
        cntr1 <= c_cntr1;
        cntr2 <= c_cntr2;
        cntr3 <= c_cntr3;
       end
   end


endmodule

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 12 марта 2019

Это одно из различий между always @* и always_comb.Always_comb не будет переоценивать в соответствии со стандартом (в то время как всегда @ * будет).

Вы описали условие, известное как read before write, что означает, что внутри блока вы читаете переменную, прежде чем записать в нее.

always @* может генерировать сбои в такой ситуации или зависать в цикле с нулевой задержкой.Always_comb никогда не будет зацикливаться.

Единственный способ проверить это, кроме визуального осмотра, - запустить подкладочный инструмент с включенными соответствующими правилами.

...