问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

如何设计高效带进位的通用加法器:从原理到实现的全面解析(含有源码资料)

创作时间:
作者:
@小白创作中心

如何设计高效带进位的通用加法器:从原理到实现的全面解析(含有源码资料)

引用
CSDN
1.
https://m.blog.csdn.net/qq_62634009/article/details/145074067

带进位的通用加法器(CLA)是数字电路设计中的重要组件,广泛应用于各种需要高效运算的场景。本文将详细介绍CLA的设计目的、原理、步骤和结果分析,帮助读者深入理解其工作原理和实现方法。

一、设计目的

设计一个带进位的通用加法器(Carry-lookahead Adder,CLA)的主要目的是提高加法运算的速度和效率。相比于传统的逐位加法器,CLA通过并行处理和提前计算进位,显著减少了加法运算的延迟。具体的设计目的包括以下几个方面:

  1. 提高运算速度:传统的逐位加法器(Ripple Carry Adder,RCA)在每一位的加法运算中都需要等待前一位的进位信号,导致总延迟随着位数的增加线性增长。而CLA通过并行计算,提前生成进位信号,从而大大减少了延迟,提高了运算速度。

  2. 优化资源利用:FPGA中的资源是有限的,高效利用资源(如查找表、触发器和布线)可以在有限的面积和功耗下实现更高性能的加法器。CLA虽然结构较为复杂,但通过合理的设计可以在FPGA中高效实现。

  3. 提高系统性能:在许多数字信号处理(DSP)、计算机图形学和其他需要大量加法运算的应用中,运算器的速度直接影响整个系统的性能。通过使用CLA,可以显著提高这些系统的整体性能。

  4. 降低功耗:快速完成运算意味着可以在更短的时间内进入低功耗状态,特别是在需要大量并行计算的应用中,快速加法器可以显著降低系统的整体功耗。

设计思路

  1. 进位生成和传播:设计CLA的关键是提前计算进位信号。对于每一位,需要计算进位生成(Generate,G)和进位传播(Propagate,P)信号。具体公式如下:

通过这些信号,可以提前计算每一位的进位,从而避免逐位计算的延迟。

  1. 并行处理:通过并行计算每一位的进位信号,CLA可以在常数时间内完成加法运算,极大地提高了运算速度。

  2. 模块化设计:在FPGA设计中,模块化设计有助于代码的复用和维护。CLA可以设计成多个子模块,每个模块负责一部分位宽的加法运算,通过级联实现更大位宽的加法运算。

  3. 验证和优化:在设计完成后,需要对CLA进行仿真和验证,确保其功能正确。此外,还可以通过不同的优化手段(如管道化和并行化)进一步提高性能。

带进位的通用加法器(CLA)的设计目的在于通过并行计算和提前生成进位信号,提高加法运算的速度和效率,从而在各种需要高效运算的应用中发挥重要作用。通过合理的设计和优化,可以在FPGA中高效实现CLA,满足不同应用对速度和资源利用的需求。

二、设计原理

在本设计中,所设计的加法器将作为一个可重用的元件进行例化,其位宽将根据父程序的需求动态确定。为了实现这一灵活性,我们在设计时将两个输入向量的长度定义为一个类属参数,即变量N。该参数N的值将在元件例化时由外部环境确定,从而确保加法器能够适应不同的位宽要求。

加法器的基本原理与设计三中的加法器保持一致,均采用了高效的并行计算和进位提前生成策略,以提升运算速度和效率。原理框图如图4-1所示,清晰展示了加法器的内部结构和信号流动路径。通过这种模块化的设计,我们不仅能够实现位宽的可配置性,还能确保加法器在各种应用场景下均能稳定高效地运行。

设计源程序文件名是add_n…vhd。

三、设计步骤

在程序成功运行且无误后,您可以通过以下步骤来观察设计综合出的RTL级电路图:首先,点击工具栏中的“Tools”选项,接着在弹出的菜单中选择“Netlist Viewers”,然后进一步选择“RTL Viewer”。这一操作将使您能够详细查看设计在RTL(Register Transfer Level)层面的电路实现。

关于全加器的输入和输出管脚配置,以下是详细的说明和接线指南:

  • 输入管脚:全加器的输入管脚与拨码开关相连,具体包括9个输入管脚,分别是a0至a3、b0至b3以及cin。其中,a0至a3和b0至b3分别代表两组四位二进制数Ai0至Ai3和Bi0至Bi3,而cin则代表前一级的进位输入Ci-1。

  • 输出管脚:全加器的输出管脚与发光二极管(LED)相连,共计5个输出管脚,分别是sum0至sum3和cout。这些输出管脚中,sum0至sum3代表加法运算的结果Si0至Si3,而cout则代表当前级的进位输出Ci。

  • 接线细节:根据提供的接线信息,您需要将CPU的特定脚位与相应的设备连接。具体接线如下:

  • CPU的17脚连接至D1,18脚连接至D2,19脚连接至D3,20脚连接至D4,21脚连接至D5,22脚连接至D6,23脚连接至D7,26脚连接至D8,27脚连接至D9。

  • 同时,CPU的30脚连接至L9,31脚连接至L1,32脚连接至L2,33脚连接至L3,36脚连接至L4。

通过上述的引脚分配和接线指南,您可以确保全加器的输入和输出正确连接,从而实现预期的功能和显示效果。

如何在新建Vector Waveform File来验证设计

  1. 创建波形文件
  • 从菜单中选择File > New > Other Files,然后选择创建Vector Waveform File。
  1. 选入需要验证的引脚
  • 在新建的波形文件中,点击左边窗栏,右键选择Insert Node or Bus。在打开的对话框中,点击Node Finder。

  • 在Node Finder对话框中找到Filter,下拉选择Pins: all,然后点击List。接着点击中间第二个快捷键,将所有的信号选到右侧,点击两次OK。此时信号将被填进波形文件的左侧。注意:如果不使用设计箱,必须选择Pins: all,否则无法将波形填进来。

  1. 仿真设置
  • 在Assignments菜单中选择Settings,打开快捷键设置。在Simulator Settings选项页中,设置Function类型仿真,并将新创建的波形文件作为仿真输入。
  1. 数据格式设置
  • 对于两个加数A和B及输出的和S,统一设置为4位宽度。在仿真时,我们将加法器定为4位宽度。因此,两个加数和输出的和都为4位宽度。

  • 将鼠标放到一个加数A上,右键单击,选择Properties,把Radix下拉菜单选择为Hexadecimal(16进制表示方式)。同理,将加数B和S设置为16进制表示方式。

  1. 输入数据
  • 在加数A的前10ns区域里,用鼠标拖蓝此区域,单击左侧工具栏中带问号的蓝色快捷键,弹出输入值的窗口,输入数据。同样对加数B进行数据值输入。

  • 选中进位输入C,单击左侧工具栏中有数字“1”的蓝色快捷键,将进位输入设置为高电平。

  1. 保存设置
  • 完成以上设置后,点击保存(Save)。
  1. 功能仿真
  • 在Assignments菜单中选择Settings,打开快捷键设置。在左侧选中Simulator Settings选择页,设置Function类型仿真,并将新创建的波形文件作为仿真输入。

  • 设置完毕后,点击Processing > Generate Functional Simulator NetList,生成网表文件。

  • 生成网表文件后,点击Start Simulator,或使用快捷键,进行功能仿真。

可以完成波形文件的创建、信号选入、数据格式设置及仿真过程,从而验证逻辑功能是否正确。

四、设计过程

输入输出设置为无符号的十进制

五、设计结果与分析

定义了一个名为add_n的实体,它是一个n位加法器,其中n默认为4。这个加法器接受两个n位输入a和b,一个进位输入cin,并产生一个n位的和输出sum以及一个进位输出cout。

5.1 源代码

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity add_n is
generic (n:positive:=4);
port (	a,b:in std_logic_vector(n-1 downto 0);
            cin:in std_logic;
            sum:out std_logic_vector(n-1 downto 0);
            cout:out std_logic);
end add_n;
architecture a of add_n is
signal s:std_logic_vector(n downto 0);
begin
    s<=('0'& a) + ('0'& b) + ("0000"& cin);
    sum<=s(n-1 downto 0);
    cout<=s(n);
end a;

为了验证这个加法器的正确性,你需要编写一个测试平台(Testbench),并在硬件仿真环境中运行它。以下是一个简单的测试平台示例:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY add_n_tb IS
END add_n_tb;
ARCHITECTURE behavior OF add_n_tb IS
    -- 组件声明
    COMPONENT add_n
    GENERIC (n:positive:=4);
    PORT(
         a : IN  std_logic_vector(3 downto 0);
         b : IN  std_logic_vector(3 downto 0);
         cin : IN  std_logic;
         sum : OUT  std_logic_vector(3 downto 0);
         cout : OUT  std_logic
        );
    END COMPONENT;
   -- 测试信号
   signal a : std_logic_vector(3 downto 0) := (others => '0');
   signal b : std_logic_vector(3 downto 0) := (others => '0');
   signal cin : std_logic := '0';
   signal sum : std_logic_vector(3 downto 0);
   signal cout : std_logic;
BEGIN
   -- 实例化被测试的组件
   uut: add_n PORT MAP (
          a => a,
          b => b,
          cin => cin,
          sum => sum,
          cout => cout
        );
   -- 测试过程
   stim_proc: process
   begin
      -- 应用测试向量
      a <= "0001"; b <= "0011"; cin <= '0'; wait for 10 ns;
      a <= "1010"; b <= "0101"; cin <= '1'; wait for 10 ns;
      -- 添加更多测试向量...
      wait; -- 等待结束
   end process;
END;

在仿真平台上执行该测试平台,以监测8位加法器的sum和cout输出是否与预期值相匹配。

如果输出结果正确无误,说明设计的加法器功能正确。若发现输出结果存在偏差,则需要回头审视并验证加法器的逻辑设计和代码实现是否存在缺陷。

5.2 8位加法器源代码

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity add_n is
generic (n:positive:=8);
port (	a,b:in std_logic_vector(n-1 downto 0);
            cin:in std_logic;
            sum:out std_logic_vector(n-1 downto 0);
            cout:out std_logic);
end add_n;
architecture a of add_n is
signal s:std_logic_vector(n downto 0);
begin
    s<=('0'& a) + ('0'& b) + ("00000000"& cin);
    sum<=s(n-1 downto 0);
    cout<=s(n);
end a;

要确认代码如何处理加法运算和进位,我们需要理解代码中是如何实现两个8位数的加法以及如何处理从一个位到另一个位的进位。具体来说,以下几点是需要关注的:

  • 代码中使用的是哪种加法算法(如半加器、全加器或超前进位加法器)来逐位相加两个数。
  • 每一位的加法操作后,如何将产生的进位传递到下一位。
  • 如何将两个8位的输入向量以及一个进位输入(通常是1位)连接起来,以进行整体加法操作。
  • 如果进位输入只有1位,而输入向量是8位,那么如何在两个8位输入向量前添加0来扩展进位信号到8位宽,使其能够与输入向量对齐。
  • 确保在所有操作中,信号的位宽都是正确的,特别是在进行加法操作和连接逻辑向量时。
  • 确认sum输出是否正确反映了加法的结果,以及cout是否正确输出了最高位的进位。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号