2

我对这个 SystemVerilog 代码有疑问。这是代码:

module mult ( multiplicand, multiplier, Product, 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

我正在尝试使用 Booth 算法编写一个具有 32 位输入和 64 位乘积的乘法器。出现此错误:

always_comb 构造不会推断出纯粹的组合逻辑

为什么会发生这种情况?

4

4 回答 4

6

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

在您的情况下,您有一些总线在 case 语句的每个分支中都没有分配值,例如mcand在分支nao_multiplicarfim.

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

always_comb另一种解决方案是在 case 语句之前为所有变量写入“默认”值。这样,每次块触发时,每个变量都会被分配一个值always_comb,并且不会有任何警告。然后,您的 case 语句只需要处理需要更改的变量:

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     
于 2011-05-19T06:16:53.857 回答
3

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

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

always_ff 过程施加的限制是它包含一个且仅一个事件控制并且没有阻塞时序控制。always_ff 过程中赋值左侧的变量,包括来自被调用函数内容的变量,不得被任何其他进程写入。

有一个类似的报价always_comb

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

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

于 2011-05-19T13:01:14.377 回答
1

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
于 2016-08-19T21:44:25.397 回答
0

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

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

于 2011-05-19T20:31:38.077 回答