Имеет ли следующий код verilog проблему с расой? - PullRequest
0 голосов
/ 04 марта 2020

Я работаю с модулем verilog (показан ниже), в котором всегда два блока. Не будет ли какого-либо состояния гонки, поскольку один блок устанавливает регистр, а другой использует регистр. Какие проблемы это может вызвать?

Спасибо, Стивен

module XYZ
(                               
    input  wire         CLK,    
    input  wire         Reset,    
    input  wire         nReset,   
    input  wire [15:0]  X,      
    input  wire [15:0]  A,    
    input  wire         T,  
    input  wire         B,  
    output reg          M     
);

assign C = X > A;

reg P;  
reg N;

always @(posedge CLK, negedge nReset)
begin
    if (~nReset)
    begin
        P <= 1;
        N <= 1;
    end else begin
        if (Reset)
        begin
            P <= 1;
            N <= 1;
        end else begin
            P <= T?  1:  ((C & ~M)?  0:  P);
            N <= B?  1:  ((M & ~C)?  0:  N);
        end
    end
end

always @(posedge CLK, negedge nReset)
begin
    if (~nReset)
    begin
        M <= 0;
    end else begin
        if (Reset)
        begin
            M <= 0;
        end else begin
            M <= M?  ~(N & ~C):  (P & C);
         end
    end
end

endmodule

Ответы [ 2 ]

3 голосов
/ 04 марта 2020

Нет, нет условий гонки. Verilog - это симулятор, управляемый событиями. Поседж (если в часах нет сбоя или сброса) обычно выполняется один раз за такт имитации. Если вы используете неблокирующие назначения правильно (и похоже, что вы это сделали), каждый всегда блок, инициируемый ребром, будет использовать старые версии значений входной переменной, значения, которые существовали до фронта тактовой частоты.

Вот упрощенный пример:

always @(posedge clk)
   r <= in;
always @(posedge clk)
   out <= r;

В этой ситуации происходит следующее:

  1. r будет присвоено значение in позже на отметке моделирования, после того, как были оценены всегда блоки (см. область планирования nba).

  2. , поскольку r еще не было действительно изменено, out будет назначено значение r со значением перед ребром.

Если r было 0 до края, а in было 1, в конце симуляции r станет 1 и out станет 0.

Это имитирует поведение реальных флопов на железе.

В вашем случае это может выглядеть как зависимость oop. На самом деле это не так. По той же причине, что и выше, значение M будет тем же, что и перед постановкой, и не вызовет гонки. Флопы не могут быть включены в комбинационные циклы из-за их свойств логических свойств.

1 голос
/ 04 марта 2020

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

  • Ref. номер страницы книги 135
  • Название книги: Verilog HDL: Руководство по цифровому дизайну и синтезу, второе издание Самир Пальниткар

Неблокирующие утверждения, используемые в Примере 2, исключают расу состояние. На положительном фронте часов значения всех правосторонних переменных «читаются», а правосторонние выражения оцениваются и сохраняются во временных переменных. Во время операции записи значения, хранящиеся во временных переменных, присваиваются переменным левой стороны. Разделение операций чтения и записи гарантирует, что значения регистров a и b меняются местами правильно, независимо от порядка выполнения операций записи. С другой стороны, неблокирующие назначения могут привести к снижению производительности симулятора и увеличению использования памяти.

//Example 2: Two concurrent always blocks with nonblocking
//statements
always @(posedge clock)
a <= b;
always @(posedge clock)
b <= a;

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

module XYZ
(                               
    input  wire         CLK,    
    input  wire         Reset,    
    input  wire         nReset,   
    input  wire [15:0]  X,      
    input  wire [15:0]  A,    
    input  wire         T,  
    input  wire         B,  
    output reg          M     
);

reg P,N;

always @(posedge CLK, negedge nReset)
    if (~nReset)begin
        P <= #10 1;
        N <= #10 1;
    end else if (Reset) begin
        P <= #10 1;
        N <= #10 1;
    end else begin
        P <= #10 T ?  1 :  ((C & ~M) ?  0:  P);
        N <= #10 B ?  1 :  ((M & ~C) ?  0:  N);
    end

always @(posedge CLK, negedge nReset)
    if      (~nReset) M <= #10 0 ;
    else if (  Reset) M <= #10 0 ;
    else              M <= #10 M ?  ~(N & ~C):  (P & C);

assign C = X > A;

endmodule
...