Что делать, если блокировки не избежать?

Я знаю, что защелки не одобряются в оборудовании и в кодировании Verilog. Но, я иногда сталкиваюсь со случаями, когда я не могу избежать защелки. Например, в этих двух случаях:

always @ (*)
begin
    random_next = random; //default state stays the same
    count_next_r = count_r;
        
        random_next = {random[28:0], feedback}; //**shift left the xor'd every posedge clock
        

    if (count_r == 30) //if all 30 bits are shifted into register
    begin
        count_next_r = 0;
        random_done = random; //assign the random number to output after 13 shifts
    end
    else
    
        count_next_r = count_r + 1;

Здесь random_done — защелка. Я не вижу другого способа написать это. Я хочу, чтобы random_done имел данные только после 30 смен random. Если я реализую это таким образом, меня предупредят о защелке, и она не будет работать должным образом.

Аналогично, в приведенном ниже коде:

always @ (*)
begin
    state_next = state_reg; //default state stays the same
    count_next = count_reg;
    sel_next = sel;
    case(state_reg)
        idle:
            begin
                //DISPLAY HI HERE
                sel_next = 2'b00;
                if(start)
                begin
                    count_next = random_done; //get the random number from LFSR module
                    state_next = starting;
                end
            end
        starting:
            begin
                if(count_next == 750000000) // **750M equals a delay of 15 seconds. 8191 for simulation
                begin                           //and starting from 'rand' ensures a random delay
                    outled = 1'b1; //turn on the led 
                    state_next = time_it; //go to next state
                end
                
                else
                begin
                    count_next = count_reg + 1; 
                    outled = 1'b0;
                end
            end     
        time_it:
            begin
                    sel_next = 2'b01; //start the timer
                    state_next = done;                  
            end
                
        done:
            begin
                if(stop)
                    begin
                        sel_next = 2'b10; //stop the timer
                        outled = 1'b0;
                    end
                
            end
            
        endcase
        

Из приведенного выше кода проблемный раздел таков:

done:
    begin
        if(stop)
            begin
                sel_next = 2'b10; //stop the timer
                outled = 1'b0;
            end

Здесь outled определяется как защёлка и при реализации меня об этом предупреждают. Я просто хочу, чтобы светодиод становился низким при нажатии стопового бита.

Как избежать этих защелок?


person ipunished    schedule 10.03.2013    source источник


Ответы (3)


Почему бы не присвоить random_done регистру.

Создайте счетчик и заставьте его отсчитывать от тридцати, а затем, если он равен нулю, присвойте регистру random_done новое случайное значение.

reg [4:0] counter; 

always@(posedge clk) begin
  if(rst) begin
    counter <= 5'd30;
  end
  else begin
    if(counter == 0) begin
      counter <= 5'd30;
    else begin
      counter <= counter - 1;
    end
end

wire count_done;

assign count_done = (counter == 0);

reg [size-1:0] random_done

always@(posedge clk) begin
  ...
  if(count_done) random_done <= random;
  ...
end

Для меня этот код выглядит немного запутанным, не похоже, что вы описываете аппаратное обеспечение. Помните, что Verilog — это язык описания оборудования HDL. При акценте на описание.

Разделите логику для каждого регистра в своем блоке always.

Однако сначала нарисуйте RTL-схему того, что вы пытаетесь сделать. Если вы не можете нарисовать RTL-схему того, что хотите спроектировать, ваш проект, скорее всего, не будет хорошим аппаратным обеспечением.

person AxelOmega    schedule 10.03.2013
comment
Спасибо за ответ. Не могли бы вы немного рассказать о том, что вы подразумеваете под логикой для каждого регистра в своем собственном всегда блоке? Не сделает ли это дизайн очень занятым и грязным? - person ipunished; 18.03.2013
comment
Басси? Что ты имеешь в виду? с точки зрения HW это не имеет значения. Это будет то же самое. Я имею в виду, что если у вас есть счетчик, вы помещаете его в один всегда блок, если у вас есть государственный регистр, у него есть свой собственный блок и так далее. Если у вас есть регистр состояния для чтения или записи, он всегда блокируется. Посмотрите на код, который у меня был в примере. Это всегда один блок для счетчика и другой для random_done. - person AxelOmega; 20.03.2013

Вы должны быть в состоянии учесть логику outled. Что-то вроде этого.

always @(posedge clk or negedge nreset) begin
    if (!nreset) begin
        outled <= 0;
    end else if (state_reg == starting) begin
        if (count_next == 750000000) begin
            outled <= 1'b1; //turn on the led 
        end else begin
            outled <= 1'b0;
        end
    end else if ((state_reg == done) && stop) begin
            outled <= 1'b0;
    end
end
person toolic    schedule 10.03.2013

Если вы сделаете весь свой код синхронным (чувствительным к posedge clk), вы не получите защелок. И вам будет легче писать временные ограничения (в лучшем случае вам нужно только одно ограничение для периода часов!)

person Martin Thompson    schedule 11.03.2013