数字硬件建模SystemVerilog-组合逻辑建模(3)使用函数表示组合逻辑

2023-02-14 16:43:34 浏览数 (2)

数字门级电路可分为两大类:组合逻辑和时序逻辑。锁存器是组合逻辑和时序逻辑的一个交叉点,在后面会作为单独的主题处理。

组合逻辑描述了门级电路,其中逻辑块的输出直接反映到该块的输入值的组合,例如,双输入AND门的输出是两个输入的逻辑与。如果输入值发生变化,输出值将反映这一变化,组合逻辑的RTL模型需要反映这种门级行为,这意味着逻辑块的输出必须始终反映该逻辑块当前输入值的组合。

SystemVerilog有三种在可综合RTL级别表示组合逻辑的方法:连续赋值语句、always程序块和函数。接下来几篇文章将探讨每种编码风格,并推荐最佳实践编码风格。

使用函数表示组合逻辑

当编码正确时,函数的行为和综合就像组合逻辑一样。

最佳实践指南7-7

将RTL模型中使用的函数声明为自动automatic。

为了表示组合逻辑行为,每次调用函数时都必须计算一个新的函数返回值。如果调用了静态函数,但没有指定返回值,则静态函数将隐式返回其上一次调用的值。这是锁存逻辑的行为,而不是组合逻辑。通过将RTL模型中使用的所有函数声明为自动函数(automatic),可以避免这种编码错误。

例7-2定义了一个使用Russian Peasant Multiplication算法(一系列加法和移位运算)计算乘法运算的函数。该函数被定义在一个包中,任何模块都可以使用该乘法器算法。

SystemVerilog会推断出一个与函数名称和数据类型相同的变量,示例7-2中的代码就是利用了这一点。函数名multiply_f被用作临时变量来保存for循环中的中间计算结果,函数名中存储的最终值在函数退出时成为函数返回值。

图7-2显示了综合该函数的结果,以及从连续赋值语句调用该函数的模块。

示例7-2:定义乘法运算的算法函数

代码语言:javascript复制
//`begin_keywords "1800-2012" // use SystemVerilog-2012 keywords
package definitions_pkg;
  timeunit 1ns; timeprecision 1ns;

  // Russian Peasant Multiplication Algorithm 
  function automatic [7:0] multiply_f([7:0] a, b);
    multiply_f = 0;
    for (int i=0; i<=3; i  ) begin 
      if (b == 0) continue; // all done, finish looping
      else begin 
         if (b & 1) multiply_f  = a;
         a <<= 1;  // multiply by 2
         b >>= 1;  // divide by 2
      end 
    end 
  endfunction 
endpackage: definitions_pkg
//`end_keywords 

//`begin_keywords "1800-2012" // use SystemVerilog-2012 keywords
module algorithmic_multiplier
import definitions_pkg::*;
(input  logic [3:0] a, b,
 output logic [7:0] result
);
  timeunit 1ns; timeprecision 1ns;

  assign result = multiply_f(a, b);

endmodule: algorithmic_multiplier
//`end_keywords 

图7-2:示例7-2的综合结果:作为组合逻辑的函数

最佳实践指南7-8

在可能的情况下,使用SystemVerilog运算符,如*,而不是使用循环和其他编程语句。

算法乘法器的示例7-2还说明了为什么在乘法和除法等复杂运算中最好使用SystemVerilog运算符。如果在示例7-2中使用了乘法运算符(*),则综合编译器可以将该运算符映射到ASIC或FPGA的最有效的乘法器。

设计工程师在使用算术运算符或算法来表示复杂操作时需要谨慎。RTL模型不是在具有大量内存资源的通用计算机上运行的软件程序。RTL模型是门级实现的抽象。所表示的功能需要在物理上适合目标ASIC或FPGA,并且在时间上在有限的数量或时钟周期内。之前的文章有详细介绍了在RTL模型中使用算术运算符(如乘法和除法)的指导原则。

0 人点赞