2015-02-27 3 views
1

Я обнаружил очень странное поведение при проектировании моего ALU, надеюсь, что кто-то может это посмотреть и рассказать мне, что происходит.Комбинационная логика «IF» и «присваивать» утверждение в systemverilog

Вот код

module adder (
output logic signed[31:0] y, 
output logic Cout, 
input logic signed[31:0] a, b, 
input logic Cin, sub 
); 

logic [31:0] adder_b; 

assign adder_b = b^{32{sub}}; 
assign {Cout, y} = {a[31],a} + {adder_b[31],adder_b} +Cin; 

endmodule 

//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 



module andlogic (
output logic [31:0] y, 
input logic [31:0] a, b 
); 

assign y = a & b; 

endmodule 



//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 

module orlogic (
output logic [31:0] y, 
input logic [31:0] a, b 
); 

assign y = a | b; 

endmodule 

//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 
//////////////////////////////////////////////////// 


module xorlogic (
output logic [31:0] y, 
input logic [31:0] a, b 
); 

assign y = a^b; 

endmodule 


/////////////////////////////////////////////////// 
/////////////////////////////////////////////////// 
/////////////////////////////////////////////////// 

module ALU(
output logic signed[31:0] Result, 
output logic N,Z,C,V, 
input logic signed[31:0] a, b, 
input logic [2:0] ALU_control 
); 

wire [31:0] adder_rlt, and_rlt, or_rlt, xor_rlt; 
logic Cin; 


adder adder (
     .y (adder_rlt), 
    .a (a), 
    .b (b), 
    .Cin (Cin), 
    .Cout (Cout), 
    .sub (sub) 
); 

andlogic andlogic (
     .y (and_rlt), 
    .a (a), 
    .b (b) 
); 

orlogic orlogic (
     .y (or_rlt), 
    .a (a), 
    .b (b) 
); 

xorlogic xorlogic (
     .y (xor_rlt), 
    .a (a), 
    .b (b) 
); 


assign C = Cout; 
assign sub = ALU_control[1]; 
assign Cin = ALU_control[1]; 
assign N = Result[31]; 
//assign Z = (Result ==0)? 1:0; 
assign V = {{~a[31]} & {~b[31]} & Result[31]}|{a[31] & b[31] & {~Result[31]}}; 

always_comb 
begin 

if (Result == 0) Z = 1; 
else Z = 0; 

case(ALU_control) 

3'b001: Result = adder_rlt; 

3'b010: Result = adder_rlt; 

3'b011: Result = and_rlt; 

3'b100: Result = or_rlt; 

3'b101: Result = xor_rlt; 

default: Result = 0; 

endcase 

end 

endmodule 

Первые 4 модулей являются отдельными функциями моего АЛУ, сумматор содержит как сложение и вычитание. Тогда вот странное дело:

Моего ALU имеет 4 флагов, Z представляют собой Зеро, он устанавливает, когда значение выходного сигнала Result 0. Если я использую эти символы, чтобы описать поведение Z

always_comb 
begin 

if (Result == 0) Z = 1; 
else Z = 0; 

Результат моделирования неверен, Z некоторое время равно 1, а некоторое время равно 0, и похоже, что оно не зависит от значения Result.

Что более странно, это результат результата синтеза. Здесь изображение показывает часть моего результата синтеза synplify.

Synthesis result

Уровень ворот выглядит правильно, Z представляет собой логический элемент И все перевернутого результат сигналов, которые, когда результат == 0, выходной сигнал Z должен быть 1.

Однако я тратить все мой день вчера попытался выяснить, как исправить эту ошибку, я понимаю, что если я использую инструкцию assign вместо использования if, то симуляция дает правильное поведение. assign Z = (Result ==0)? 1:0;

Я думал, что это две версии описания Z должны быть одинаковыми! После того, как я изменил мой код, используя

assign Z = (Result ==0)? 1:0; 

Результат синтеза еще такой же, как картина, которую я показал выше ...

Может кто-нибудь сказать мне, что происходит? Большое спасибо !!!

+0

Извините за моего бедного английского, надеюсь, мой вопрос имеет смысл для вас, ребята. –

+0

В testbench мне удалось установить значение Result равное единице, добавив два нуля и вычесть две одинаковые переменные величины. Для первого результата Z равен 0, для второго результата Z - 1. –

ответ

4

Я считаю, что проблема связана с вашим порядком работы. always_comb блоки выполняются процедурно, сверху вниз. В моделировании Z обновляется сначала с существующим значением Result (с предыдущего времени выполнялся всегда блок). Обновлен Result, и Z не переоценивается. Result не входит в список чувствительности, поскольку это левое значение. Поэтому Z не будет обновляться до тех пор, пока не изменится сигнал, который назначает Result.

Синтез отличается, он соединяет эквивалентные логические ворота, которые могут привести к асинхронной обратной связи. Логический эквивалент не совпадает с функциональным эквивалентом. Вот почему синтез дает вам то, что вы логически намереваетесь, и симуляция RTL дает то, что вы функционально писали. Объяснение причин различий выходит за рамки этого вопроса.

При кодировании комбинационной блок RTL, просто сделать небольшой Самоконтроль и спросить себя:

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

В случае с ALU, tt является простым решением. Изменение:

always_comb begin 
    if (Result==0) Z = 1; // <-- Z is evaluated using the previous value of Result 
    else Z = 0; 

    /*Logic to assign Result*/ // <-- change to Result does not re-trigger the always 
end 

To:

always_comb begin 
    /*Logic to assign Result*/ // <-- update Result first 

    if (Result==0) Z = 1; // <-- Z is evaluated using the final value of Result 
    else Z = 0; 
end 

альтернативное решение (которое я отговаривают) заключается в замене always_comb с IEEE1364-1995 стиле комбинационной логики. Если список чувствительности определяется вручную. Здесь вы можете добавить Result, чтобы получить обратное обновление:

always @(ALU_control or adder_rlt or add_rlt or or_rtl or xor_rtl or Result) 

Я отговаривает, потому что легко пропустить необходимый сигнал, unessary сигналов траты время моделирования, создает риск нулевого момента времени бесконечного цикла, и вы по-прежнему не получаете гарантийного функционального эквивалента между RTL и синтезом.

+1

Назначения 'Z' также могут быть помещены в отдельный блок всегда. – Morgan

+1

@Morgan, да это может. Я предпочитаю держать всю гребенку loigc в том же домене в одном всегда-блоке. Это делает RTL более абстрактным, я видел, что он дает некоторому синтезатору немного большей гибкости для нахождения общей логики (в ожидании других ограничений), и симуляторы, как правило, дают мне лучшую производительность во время исполнения. Это мой опыт работы с большими проектами. Отдельным всегда-блоком является лучшее решение, а затем список ручной чувствительности. – Greg

+0

О, боже мой, ваш ответ так велик! Спасибо за помощь, это мне очень помогает! –