Неочаквано поведение при използване на троичния оператор (Verilog)

В следващия модул на Verilog бих искал да разбера защо присвояването на блокиране, използващо конкатенация, не дава същия резултат като 2-те коментирани присвоявания на блокиране.

Когато стартирам програмата на FPGA, тя дава очаквания резултат с 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


person Olivier Sohn    schedule 25.11.2018    source източник
comment
1/ Трябва да използвате неблокиращи присвоявания. 2/ i+1 ще бъде широк 32 бита и ще наруши вашия {count , i+1} битов ред.   -  person Oldfart    schedule 25.11.2018
comment
@Oldfart Мисля, че използването на блокиращо или неблокиращо присвояване не променя нищо тук, тъй като има едно присвояване. нали   -  person Olivier Sohn    schedule 25.11.2018
comment
Винаги използвайте неблокиращи присвоявания в тактова секция. (Да, дори и да е едно задание!)   -  person Oldfart    schedule 25.11.2018
comment
@Oldfart можеш ли да обясниш защо или да ме насочиш към някакво подходящо обяснение?   -  person Olivier Sohn    schedule 25.11.2018
comment
Защото това е поведението, което съответства на действителния хардуер. Търсене за блокиране/неблокиране. Има десетки публикации по темата.   -  person Oldfart    schedule 25.11.2018
comment
@Oldfart от това, което прочетох, понякога е оправдано да има блокиращи задачи.   -  person Olivier Sohn    schedule 25.11.2018
comment
Нека продължим тази дискусия в чата.   -  person Olivier Sohn    schedule 25.11.2018


Отговори (1)


Причината е, че ширините на count+1 и i+1 са 32 бита. Неоразмереното число е широко 32 бита (1800-2017 LRM раздел 5.7.1), а ширината на оператора за добавяне е размера на най-големия операнд (LRM раздел 11.6.1). За да накарате кода си да работи, добавете подходящ размер към цифровите си литерали

 {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
person dave_59    schedule 25.11.2018
comment
Благодаря! Знаете ли дали има начин компилаторът да генерира предупреждение в този случай (като нещото отдясно е по-голямо от това отляво)? И как бихте опростили този код? - person Olivier Sohn; 25.11.2018
comment
За съжаление повечето инструменти няма да генерират предупреждение, тъй като Verilog е слабо въведен. - person dave_59; 25.11.2018
comment
това е наистина жалко... предполагам, че VHDL ще се справи добре с този случай (чух, че е строго въведен) - person Olivier Sohn; 25.11.2018
comment
Въпросът, който публикувахте, е идеален пример за това колко лесно се прави грешка с конкатенация - person dave_59; 25.11.2018
comment
Инструментът за линтинг на код трябва да реши този вид проблем - person nguthrie; 28.11.2018