Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
IEC 61691-3-2:2001《采用IEEE Std 1076.3-1997——标准VHDL综合程序包》规定了VHDL硬件描述语言的标准数学程序包。该标准定义了四个关键程序包:std_logic_arith、std_logic_signed、std_logic_unsigned和numeric_std,为面向逻辑综合的设计提供有符号和无符号算术运算、类型转换函数和比较运算符。
在此标准之前,VHDL设计者只能使用bit和bit_vector类型进行数值表示,这些类型缺乏实际硬件建模所需的解析信号能力。std_logic类型家族(IEEE 1164)的引入产生了能够操作这些解析类型的算术程序包的需求——而IEC 61691-3-2最终填补了这一空白。该标准在实现基于VHDL的数字信号处理、控制系统实现和可编程逻辑算法加速方面发挥了重要作用。
std_logic_arith和numeric_std通常会导致类型歧义、仿真-综合不匹配以及难以调试的数值溢出问题。| 程序包 | 用途 | 关键类型 | 关键函数 |
|---|---|---|---|
| std_logic_arith | std_logic_vector的有/无符号算术 | SIGNED, UNSIGNED | +, -, *, <, >, =, conv_integer, conv_std_logic_vector |
| std_logic_signed | std_logic_vector的有符号算术重载 | std_logic_vector(视为有符号) | +, -, *, abs, <, >, shl, shr |
| std_logic_unsigned | std_logic_vector的无符号算术重载 | std_logic_vector(视为无符号) | +, -, *, <, >, conv_integer |
| numeric_std | IEEE标准有/无符号算术 | signed, unsigned | resize, shift_left, shift_right, to_integer, to_unsigned, to_signed |
最初由Synopsys开发并在IEEE标准化之前被广泛采用,std_logic_arith定义了作为std_logic_vector子类型的独立SIGNED和UNSIGNED类型。它提供重载的算术、关系和转换运算符。该程序包支持乘法运算,但面积影响显著——由此程序包综合出的16×16有符号乘法器在FPGA中通常消耗200-400个逻辑单元。
IEEE标准的numeric_std程序包是新设计中对Synopsys程序包的推荐替代方案。它定义了与std_logic_vector更清晰分离的signed和unsigned类型。主要优势包括:标准化的溢出行为、原生移位操作、更好的综合工具兼容性,以及同时处理截断和饱和模式的明确定义的resize函数。
-- 示例:使用numeric_std实现有符号累加器
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity accumulator is
port (
clk : in std_logic;
rst : in std_logic;
input : in signed(15 downto 0);
output : out signed(31 downto 0)
);
end accumulator;
architecture behavioral of accumulator is
signal sum : signed(31 downto 0) := (others => '0');
begin
process(clk, rst)
begin
if rst = '1' then
sum <= (others => '0');
elsif rising_edge(clk) then
-- 16位到32位的自动符号扩展
sum <= sum + resize(input, 32);
end if;
end process;
output <= sum;
end behavioral;
numeric_std,避免Synopsys程序包(std_logic_arith、std_logic_signed、std_logic_unsigned)。numeric_std与仿真器和综合工具无关,且所有现代VHDL工具都保证支持。虽然不是IEC 61691-3-2:2001原版的一部分,但后续的IEEE 1076.3定点程序包(fixed_generic_pkg、fixed_float_types)直接建立在该标准奠定的基础之上。定点方法将数字表示为具有显式整数和小数位宽的sfixed或ufixed类型。例如,sfixed(7 downto -8)表示一个8.8有符号定点数,取值范围从-128到+127.9961,分辨率为2-8 = 0.00390625。
| 操作 | 精度 | FPGA逻辑片 | DSP块 | 最高频率 |
|---|---|---|---|---|
| 有符号整数加法 | 32位 | 32 | 0 | 500 MHz |
| 有符号整数乘法 | 16×16位 | 290 | 1-2 | 300 MHz |
| 定点加法 | 16.16 | 32 | 0 | 450 MHz |
| 定点乘法 | 8.8 x 8.8 | 260 | 1-4 | 250 MHz |
| 浮点加法 | 32位(IEEE 754) | 400-600 | 0-2 | 200 MHz |
| 浮点乘法 | 32位(IEEE 754) | 300-500 | 2-4 | 180 MHz |
1. 位宽管理与溢出。VHDL算术中最常见的设计错误是位宽管理不当。两个N位数相加时,结果需要N+1位以避免溢出。N位和M位数相乘时,结果需要N+M位。应显式使用numeric_std.resize函数进行宽度调整,并在截断和饱和模式之间谨慎选择。饱和算术(结果在最大可表示值处饱和)适用于控制回路,而截断(丢弃溢出位)适用于最低有效位代表噪声的信号处理。
2. 算术优化的综合属性。现代综合工具支持控制算术实现的属性。use_dsp48属性(Xilinx)或dsp_style属性(Intel/Altera)指导综合工具将算术运算映射到专用DSP块而非分布式逻辑。资源共享属性(resource_sharing)允许多个算术运算共享同一硬件,以减少面积但牺牲吞吐量。
3. 高速算术的流水线设计。算术运算通常是限制最高时钟频率的关键路径。标准方法是在关键点插入流水线寄存器:乘加(MAC)运算的乘法和加法之间、宽加法器的进位链边界处以及比较器树的输出端。无流水线的32位加法器在典型FPGA中可能将时钟速度限制在50-100 MHz;使用3-4级流水线后,同一加法器可在300-500 MHz下运行。
4. 遗留兼容性的程序包选择策略。在维护使用std_logic_arith的遗留VHDL代码时,重构为numeric_std通常不切实际。一种实用的策略是创建封装程序包,提供Synopsys风格的接口,而内部使用numeric_std函数。这可以在不破坏现有设计模块的情况下实现逐步迁移。
std_logic_arith(Synopsys)将SIGNED和UNSIGNED定义为std_logic_vector的子类型,当两个程序包同时使用时可能导致类型解析冲突。numeric_std(IEEE)将signed和unsigned定义为独立类型,提供更好的类型安全和工具兼容性。算术运算的行为几乎相同,但numeric_std是官方标准化的程序包,推荐用于所有新设计。
可以,但需谨慎。IEEE 1076.3浮点程序包支持IEEE 754单精度(32位)和双精度(64位)。然而,浮点硬件实现的逻辑资源消耗是同等定点设计的3-5倍,且最高工作频率较低。对于大多数FPGA DSP应用,推荐使用具有适当缩放因子的定点算术。
对于有符号算术,使用signed类型(来自numeric_std),采用二进制补码表示。对于解释为有符号值的std_logic_vector,使用std_logic_signed程序包。无符号类型仅表示非负值。有符号和无符号之间的类型转换应使用signed()和unsigned()强制转换函数,而不是std_logic_arith中的conv_*函数。
大多数现代工具支持整数除法和取模运算的综合,但生成的硬件面积大且速度慢。对于常量除法,使用移位运算(如除以2 = 右移1位)。对于可变除法,考虑使用CORDIC算法进行迭代除法,或实例化来自FPGA厂商的专用除法器IP核。多周期除法器比单周期实现可减少5-10倍的面积。