使用always_comb构造的Systemverilog问题

时间:2011-05-19 03:11:11

标签: verilog system-verilog

我对此Systemverilog代码有疑问。 我是这种语言的新手,非常困难 查找有关此语言的相关文档。 这是代码:

模块mult(被乘数,乘数,乘积,clk,clear,Startm,endm);

input [31:0] multiplicand;
input [31:0] multiplier  ;
input clk;
input clear; 
input Startm;

output logic [63:0] Product;
output logic endm;


enum logic [1:0] { inicio, multiplicar, nao_multiplicar, fim } estados;
logic [1:0] state;

logic [31:0] mplier;
logic [31:0] mplier_aux;
logic [31:0] mcand ;
logic [31:0] mcand_aux;
logic [63:0] Prod  ;
logic [63:0] Prod_aux;
logic [5:0] cont;
logic [5:0] cont_aux;

initial begin
    mplier     = multiplier;
    mplier_aux = multiplier;
    mcand     = multiplicand;
    mcand_aux = multiplicand;
    Prod      = 0;
    Prod_aux  = 0;
    state     = inicio;
    cont      = 0;
    cont_aux  = 0; 
end

always_ff @( posedge clk )
begin
    if( clear ) 
    begin
        state <= inicio;
    end
    else if ( Startm )
    begin
        case( state )
        inicio :
        begin
                    if( mplier[0] == 0 )
                    begin
                        state <= nao_multiplicar;
                    end
                    else if( mplier[0] == 1 )
                    begin
                        state <= multiplicar;
                    end
        end
        multiplicar :
        begin
                    if( cont == 32 )
                        state <= fim;
                    else if( mplier[0] == 0 )
                    begin
                        state <= nao_multiplicar;
                    end
                    else if( mplier[0] == 1 )
                    begin
                        state <= multiplicar;
                    end
        end
        nao_multiplicar:
        begin
                    if( cont == 32 )
                        state <= fim;
                    else if( mplier[0] == 0 )
                    begin
                        state <= nao_multiplicar;
                    end
                    else if( mplier[0] == 1 )
                    begin
                        state <= multiplicar;
                    end
        end
        fim:
        begin
                    state <= inicio;
        end
        endcase
    end
end
    always_comb
    begin
        case(state)
        inicio:
        begin
                    mplier = multiplier;
                    mcand  = multiplicand;
                    Prod   = 0;
                    cont_aux = cont + 1;
                    cont = cont_aux;
        end
        multiplicar:
        begin   
                    mcand_aux  = mcand  << 1;
                    mcand      = mcand_aux  ;
                    mplier_aux = mplier >> 1;
                    mplier     = mplier_aux ;
                    Prod_aux   = Prod + mcand;
                    Prod       = Prod_aux;
                    cont_aux   = cont + 1;
                    cont       = cont_aux;
        end
        nao_multiplicar:
        begin
                    cont_aux = cont + 1;
                    cont     = cont_aux;
        end
        fim:
        begin
                    Product = Prod;
                    endm    = 1;
        end
        endcase
    end     

endmodule

我正在尝试使用32位输入和64位乘积来编写乘法器 布斯的算法。发生此错误:“always_comb构造不会推断出纯粹的组合逻辑”。为什么会这样?

4 个答案:

答案 0 :(得分:4)

always块中描述组合逻辑时,必须确保将所有变量分配给代码中所有路径中的值。否则将推断出锁存器。在传统的always块中很容易错过这样的内容,因此在SystemVerilog中引入了always_comb块以明确检查这一点。

在您的情况下,您在case语句的每个分支中都有一些未分配值的总线,例如mcand没有在分支nao_multiplicar和{fim中分配给它的值{1}}。

有两种解决方案。首先是,分配给所有代码分支中的所有变量。

另一个解决方案是在case语句之前为always_comb中的所有变量写入'default'值。通过这种方式,每次always_comb块触发时,每个变量将始终分配给一个值,并且不会有任何警告。然后,你的案例陈述只需要处理需要改变的变量:

always_comb
begin
    // Defaults (I think I got them all)
    mplier     = multiplier;
    mcand      = multiplicand;
    Prod_aux   = 0;
    Prod       = 0;
    cont_aux   = 0;
    cont       = 0;
    Product    = 0;
    endm       = 0;

    // Now override the defaults when appropriate
    case(state)
    inicio:
    begin
                mplier = multiplier;
                mcand  = multiplicand;
                Prod   = 0;
                cont_aux = cont + 1;
                cont = cont_aux;
    end
    multiplicar:
    begin   
                mcand_aux  = mcand  << 1;
                mcand      = mcand_aux  ;
                mplier_aux = mplier >> 1;
                mplier     = mplier_aux ;
                Prod_aux   = Prod + mcand;
                Prod       = Prod_aux;
                cont_aux   = cont + 1;
                cont       = cont_aux;
    end
    nao_multiplicar:
    begin
                cont_aux = cont + 1;
                cont     = cont_aux;
    end
    fim:
    begin
                Product = Prod;
                endm    = 1;
    end
    endcase
end     

答案 1 :(得分:3)

当我摆脱initial块时,所有编译错误都被消除了。我正在使用Cadence和Synopsys的模拟器。

以下是IEEE Std,1800-2009,第9.2.2.4节“顺序逻辑always_ff过程”的引用:

  

always_ff程序强制执行   限制它包含一个和   只有一个事件控件而且没有阻塞   时间控制。关于的变量   内部任务的左侧   一个always_ff程序,包括   来自a的内容的变量   被称为函数,不得写入   通过任何其他过程。

always_comb有类似的引用。

可以从IEEE获得该文档。你的模拟器也应该有文档。

在这种情况下,您从工具收到的错误消息似乎不是很有帮助。

答案 2 :(得分:0)

LRM是我用于系统verilog的最有用的文档

http://www.vhdl.org/sv/SystemVerilog_3.1a.pdf

答案 3 :(得分:0)

always_comb将推断组合逻辑,但是,在您的always_comb块中,您正在执行C代码之类的赋值,例如:

always_comb
begin
  ...
  cont_aux   = cont + 1;
  cont       = cont_aux;
  ...
end

在这里,您要求通过反馈制作组合逻辑。

如果要及时存储值,则必须将分配放在always_ff块中,这将推断顺序逻辑。

always_ff @(posedge clk)
begin
  ...
  cont <= cont + 1;
  ...
end