带有always_comb结构的Systemverilog问题

发布于 2024-11-08 16:00:55 字数 3342 浏览 2 评论 0原文

我对这个 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

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

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

为什么会发生这种情况?

I have a problem with this SystemVerilog code. Here is the code:

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

I'm trying write a multiplicator with inputs of 32 bits and a product of 64 bits using
the Booth's algorithm. This error occur:

always_comb construct does not infer purely combinational logic

Why does this happens?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鲸落 2024-11-15 16:00:55

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

在您的情况下,您有一些总线没有在 case 语句的每个分支中分配值,例如 mcand 没有在分支 nao_multiplicar 中为其分配值> 和fim

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

另一种解决方案是在 case 语句之前的 always_comb 中为所有变量写入“默认”值。这样,每次 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     

When describing combinational logic in always blocks, you have to make sure that all your variables are assigned to a value in all paths in your code. Otherwise a latch will be inferred. It's easy to miss something like this in traditional always blocks, so the always_comb block was introduced in SystemVerilog to explicitly check for this.

In your case, you've a few buses which are not assigned values in each branch of the case statement, for example mcand hasn't a value assigned to it in branches nao_multiplicar and fim.

There are 2 solutions. First is to, well, assign to all your variables in all your code branches.

Another solution is to write 'default' values for all of the variables in the always_comb before the case statement. In this way, each variable will always be assigned to a value each time the always_comb block triggers, and there'll be no warnings. YOur case statement then only needs to deal with the variables that need to change:

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     
溺渁∝ 2024-11-15 16:00:55

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

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

always_ff 过程强加了
限制它包含一个和
只有一个事件控制,无阻塞
时序控制。上的变量
作业的左侧
一个always_ff过程,包括
a 的内容中的变量
称为函数,不应写成
通过任何其他进程。

always_comb 有一个类似的引用。

该文档可以从 IEEE 轻松获得。您的模拟器还应该有文档。

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

All the compile errors are eliminated when I get rid of the initial block. I'm using simulators from Cadence and Synopsys.

Here is a quote from the IEEE Std, 1800-2009, section 9.2.2.4 "Sequential logic always_ff procedure":

The always_ff procedure imposes the
restriction that it contains one and
only one event control and no blocking
timing controls. Variables on the
left-hand side of assignments within
an always_ff procedure, including
variables from the contents of a
called function, shall not be written
to by any other process.

There is a similar quote for always_comb.

The documentation is readily available from the IEEE. Your simulator should also have documentation.

The error message you receive from your tool seems not to be very helpful in this case.

反目相谮 2024-11-15 16:00:55

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

always_comb will infer combinational logic, however, in your always_comb block you are doing assignments like C code, e.g:

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

Here you are asking to make a combinational logic with feedback.

If you want to store values in time, you have to put your assignments in an always_ff block, which will infer sequential logic.

always_ff @(posedge clk)
begin
  ...
  cont <= cont + 1;
  ...
end
偏爱自由 2024-11-15 16:00:55

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

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

The LRM is the most useful documentation I use for system verilog

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文