Неожиданное поведение с использованием троичного оператора (Verilog) - PullRequest
0 голосов
/ 25 ноября 2018

В следующем модуле Verilog я хотел бы понять, почему назначение блокировки с использованием конкатенации не дает тот же результат, что и 2 закомментированных назначения блокировки.

Когда я запускаю программу на ПЛИС, он дает ожидаемый результат с 2-мя блокирующими назначениями (светодиоды мигают), но не с блокирующим назначением с использованием конкатенации (светодиоды выключены).

Бонусные баллы за ответы, указывающие на спецификацию Verilog, объясняющую, чтов игре здесь!

/* Every second, the set of leds that are lit will change */
module blinky(
input clk,
output [3:0] led
);
    reg [3:0] count = 0;
    reg [27:0] i = 0;
    localparam [27:0] nTicksPerSecond = 100000000;

    assign led = {count[3],count[2],count[1],count[0]};

    always @ (posedge(clk)) begin
        // This works:
        //count = i==nTicksPerSecond ? (count + 1) : count;
        //i     = i==nTicksPerSecond ? 0 : i+1;

        // But this doesn't:
        {count,i} = i==nTicksPerSecond ? 
          {count+1, 28'b0  } :
          {count  , i+1};
    end
endmodule

PS: я использую Vivado 2018.2

1 Ответ

0 голосов
/ 25 ноября 2018

Причина в том, что ширина count+1 и i+1 составляет 32 бита.Число без размера имеет ширину 32 бита (раздел 5.7.1 LRM 1800-2017), а ширина оператора сложения равна размеру наибольшего операнда (раздел 11.6.1 LRM).Чтобы ваш код работал, добавьте правильный размер к вашим числовым литералам

 {count,i} = i==nTicksPerSecond ? 
          {count+4'd1, 28'b0  } :
          {count  , i+28'd1};

Более простой способ написать этот код -

  always @ (posedge clk) 
      if (i== nTicksPerSecond)
         begin 
           count <= count + 1;
           i <= 0;
         end
      else
         begin
           i <= i + 1;
         end
...