数字电路设计——加法器

news2024/11/17 23:47:32

数字电路设计——加法器

半加器

半加器只有两个一位宽的输入 a a a b b b ,输出 a + b a+b a+b 所产生的本位和 s u m sum sum 和进位 c o u t cout cout。组合逻辑为:

S = A ⊕ B , C o u t = A B S = A \oplus B,Cout = AB S=AB,Cout=AB

真值表和原理图符合为:

半加器
SystemVerilog实现代码:

module hadder (
    input logic a,
    input logic b,
    output logic sum,
    output logic cout
);
    assign sum = a ^ b;
    assign cout = a & b;
endmodule

全加器

加法器一般指全加器,半加器只能实现一位加法,而全加器才能真正实现多位加法,相较于半加器,全加器考虑了上一位的进位,因此全加器有三个输入分别是 a , b , c i n a,b,cin a,b,cin ,输出 a + b + c i n a+b+cin a+b+cin 所产生的本位和 s u m sum sum 和进位 c o u t cout cout。组合逻辑为:

S = A ⊕ B ⊕ C i n , C o u t = A B + A C i n + B C i n S = A \oplus B \oplus Cin, Cout = AB + ACin + BCin S=ABCin,Cout=AB+ACin+BCin

真值表和原理图符号为:

全加器
SystemVerilog实现代码:

module fadder (
    input logic a,
    input logic b,
    input logic cin,
    output logic sum,
    output logic cout
);
    assign sum = a ^ b ^ cin;
    assign cout = a & b | a & cin | b & cin;
endmodule

进位传播加法器

单个全加器只能实现单个位的加法,若想实习多位加法,就必须考虑到位于位直接的进位问题,我们称这类模拟竖式依次进位的加法器为进位传播加法器(carry propagate adder),简称CPA。

其原理图表示为:

进位链加法器

进位链加法器

单个全加器只能实现单个位的加法,当将多个全加器进行进位链式连接的时候,就可以实现多位加法,我们称为进位链加法器(Ripple-Carry Adder),具体的,一个32位宽的进位链加法器可表示为:

进位链加法器

SystemVerilog实现代码:

module rcadder(
    input logic[31:0] a,
    input logic[31:0] b,
    input logic cin,
    output logic[31:0] sum,
    output logic cout
);

genvar i;
logic[32:0] c;

generate
    assign c[0] = cin;
    for(i = 0;i < 32;i=i+1) begin
        fadder adder_inst(
            .a (a[i]),
            .b (b[i]),
            .cin (c[i]),
            .sum (sum[i]),
            .cout (c[i + 1])
        );
    end
endgenerate

assign cout = c[32];

endmodule

显然,进位加法器的传播延迟 t r i p p l e t_{ripple} tripple 为:

t r i p p l e = N t F A t_{ripple} = Nt_{FA} tripple=NtFA

其中 N N N 为加法位宽,而 t F A t_{FA} tFA 是单个全加器的传播延迟。

超前进位加法器

进位链加法器的缺点在于进位传播的太慢,以至于进位链成为组合逻辑的关键路径,拖慢了系统时钟速率,通过巧妙的构造,可以加速这个过程,称为超前进位加法器(Carry-Lookahead Adder),简称CLA。

CLA使用生成(generate)G和传播(propagate)P两个信号来描述一个加法器如何控制进位的输入和输出。

具体的,考虑第 i i i 位全加器,我们称其生成进位而与上一位的进位无关,当且仅当 A i A_i Ai B i B_i Bi 都是1,换句话说当 A i A_i Ai B i B_i Bi 都是1的时候,该位一定进位而与上一位是否进位无关。

考虑第 i i i 位全加器,我们称其传播进位,则当上一位进位的时候,该位一定进位,此时 A i A_i Ai B i B_i Bi 有一个至少是1。

两个信号的逻辑表达式为:

G i = A i B i , P i = A i + B i G_i = A_i B_i,P_i = A_i + B_i Gi=AiBi,Pi=Ai+Bi

现在我们再考虑当前进位 C i C_i Ci 和上一位进位的关系 C i − 1 C_{i-1} Ci1 根据G和P的定义,显然有:

C i = G i + P i C i − 1 C_i = G_i + P_iC_{i-1} Ci=Gi+PiCi1

现在来考虑一个进位链加法器,我们将 G i : j G_{i:j} Gi:j 表示为第j个到第i个加法器所组成CPA的G信号,而将 P i : j P_{i:j} Pi:j 表示为第j个到第i个加法器所组成CPA的P信号。

具体的,考虑 G 3 : 0 G_{3:0} G3:0 的表示,若 G 3 : 0 G_{3:0} G3:0 成立,当且仅当 G 3 G_3 G3 成立,或是 P 3 G 2 : 0 P_3G_{2:0} P3G2:0 成立。那么:

G 3 : 0 = G 3 + P 3 G 2 : 0 G_{3:0} = G_3 + P_3G_{2:0} G3:0=G3+P3G2:0

我们发现这是一个递归定义的式子,将递归展开后得到:

G 3 : 0 = G 3 + P 3 ( G 2 + P 2 ( G 1 + P 1 G 0 ) ) G_{3:0} = G_3 + P_3(G_2 + P_2(G_1 + P_1G_0)) G3:0=G3+P3(G2+P2(G1+P1G0))

考虑 P 3 : 0 P_{3:0} P3:0 的表示,其结构类似于串联的开关:

P 3 : 0 = P 3 P 2 P 1 P 0 P_{3:0} = P_3P_2P_1P_0 P3:0=P3P2P1P0

而且下面的式子显然成立:

C i = G i : j + P i : j C j − 1 C_i = G_{i:j} + P_{i:j}C_{j-1} Ci=Gi:j+Pi:jCj1

有了上面的基础,我们就可以描述超前进位加法器的结构:

超前进位加法器
超前进位加法器利用了并行的思想,例如将32位的加法,拆成8个4位的并行加法器,每个4位加法器中仍然使用进位链加法器,不同的是,通过构造G和P,使得并行加法器之间传播进位更快了,解决了传统进位链加法器进位传播慢的特点。具体的,G和P只和当前位有关,而和进位位无关,因此对于G和P的计算结构是并行的。

一旦所有并行加法器的 G i : j G_{i:j} Gi:j P i : j P_{i:j} Pi:j 同时计算好之后, C C C 进位就可以快速的传播,只需要串行传播8次即可,相比于进位链加法器传播32次少了不少。下面是超前进位加法器的时间线:

超前进位加法器时间线
观察可以得到,超前进位加法器的传播延迟为:

t C L A = t p g + t p g b l o c k + ( N k − 1 ) t A N D / O R + k t F A t_{CLA} = t_{pg} + t_{pgblock} + (\frac{N}{k} - 1) t_{AND/OR} + kt_{FA} tCLA=tpg+tpgblock+(kN1)tAND/OR+ktFA

其中 t p g t_{pg} tpg 是计算单个 G i G_i Gi P i P_i Pi 的时间,通常是一个与门或是或门的传播时延。 t p g b l o c k t_{pgblock} tpgblock 是计算单个并行加法器的G和P的时间, N N N 是加法器的位数, k k k 的每个并行加法器的位数, t A N D / O R t_{AND/OR} tAND/OR 是从 C i C_i Ci C i + k C_{i+k} Ci+k 的时延,通常为一个或门加与门的传播时延。 k t F A kt_{FA} ktFA 是一个并行加法器的加法的传播时延。

N > 16 N > 16 N>16 的时候,超前进位加法器的时延将远大于进位链加法器。

SystemVerilog实现代码:

module rcadder4(
    input logic[3:0] a,
    input logic[3:0] b,
    input logic cin,
    output logic[3:0] sum,
    output logic cout
);

genvar i;
logic[4:0] c;

generate
    assign c[0] = cin;
    for(i = 0;i < 4;i=i+1) begin
        fadder adder_inst(
            .a (a[i]),
            .b (b[i]),
            .cin (c[i]),
            .sum (sum[i]),
            .cout (c[i + 1])
        );
    end
endgenerate

assign cout = c[4];
endmodule

module cladder(
    input logic[31:0] a,
    input logic[31:0] b,
    input logic cin,
    output logic[31:0] sum,
    output logic cout
);

genvar i;
logic[31:0] g;
logic[31:0] p;
logic[8:0] c;

generate
    assign c[0] = cin;
    for(i = 0;i < 32;i=i+1) begin
        assign g[i] = a[i] & b[i];
        assign p[i] = a[i] | b[i];
    end
    for(i = 0;i < 8;i=i+1) begin
        logic g_block;
        logic p_block;
        assign g_block = g[i * 4 + 3] | p[i * 4 + 3] & (g[i * 4 + 2] | p[i * 4 + 2] & (g[i * 4 + 1] | p[i * 4 + 1] & g[i * 4]));
        assign p_block = p[i * 4 + 3] & p[i * 4 + 2] & p[i * 4 + 1] & p[i * 4];
        assign c[i + 1] = g_block | p_block & c[i];
        rcadder4 adder4_inst(
            .a (a[(i + 1) * 4 - 1:i * 4]),
            .b (b[(i + 1) * 4 - 1:i * 4]),
            .cin (c[i]),
            .sum (sum[(i + 1) * 4 - 1:i * 4]),
            .cout ()
        );
    end
endgenerate

assign cout = c[8];
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/730149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

选读SQL经典实例笔记02_多表查询

1. 除非有必要&#xff0c;否则不要用UNION代替UNION ALL 2. 查找两个表中相同的行 2.1. 当执行连接查询时&#xff0c;为了得到正确的结果&#xff0c;必须慎重考虑要把哪些列作为连接项 2.2. 当参与连接的行集里的某些列可能有共同值&#xff0c;而其他列有不同值的时候&a…

2.4.cuda驱动API-使用驱动API进行内存分配

目录 前言1. 内存分配总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记 本次课程学习精简 CUDA 教程-Driver API 内存分配 课程大纲可见下面…

基于Java生活缴费系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【工具】录屏工具Bandicam参数测试(参数设置建议)

一款小而精美的软件&#xff0c;上手特别容易&#xff0c;学习版参见b站up视频&#xff1a;【免费】好用录屏软件推荐&#xff0c;无水印1080P你值得拥有。 我有个需求&#xff0c;要求录屏但视频文件尽可能小但保持基本清晰。 我分别用看视频环境&#xff08;b站学习教程类&…

探索全桥电机驱动模块:实现精确控制与高效驱动

全桥电机驱动模块是一种在现代工程应用中广泛使用的电机驱动方式。对于需要精确控制和高效驱动的场景&#xff0c;如机器人、无人机、电动车等&#xff0c;全桥电机驱动模块提供了理想的解决方案。本文将介绍全桥电机驱动模块的原理和实际应用场景&#xff0c;并对几种常见的全…

【高并发网络通信架构】引入IO多路复用(select,poll,epoll)实现高并发tcp服务端

目录 一&#xff0c;往期文章 二&#xff0c;基本概念 IO多路复用 select 模型 poll 模型 epoll 模型 三&#xff0c;函数清单 1.select 方法 2.poll 方法 3.epoll_create 方法 4.epoll_ctl 方法 5.epoll_wait 方法 6.struct epoll_event 结构体 四&#xff0c;代…

uniapp踩坑之项目:uniapp修改弹窗组件样式

在components文件夹里创建zz-prompt文件夹&#xff0c;再在下面创建index.vue <!--通知弹窗index.vue--> <template><view class"prompt-box" v-if"visible" touchmove"true"><view class"prompt"><view c…

1.8 用户注册_和使用的工具类

步骤1&#xff1a;在common模块下,创建对应的工具类 /** 创建性别枚举(Sex)*/ /** md5加密类(MD5Utils)*/ /** 时间转换格式化类(DateUtil)*/ /** 生成全局唯一主机id (Sid)*/步骤2&#xff1a;在pojo模块下&#xff0c;创建表单封装bo对象 /** 注册表单bo对象 UserBO*/步骤3…

怎么将桌面笔记软件中记录的内容折叠起来或展开显示?

记笔记是一种良好的习惯&#xff0c;不仅可以帮助我们整理思绪&#xff0c;还能有效地记录重要的信息。在现代科技的支持下&#xff0c;一款优秀的笔记软件已经成为我们记录和管理事项的主要工具。特别是一款能够折叠的桌面笔记软件&#xff0c;将会给用户带来更多的便利和效率…

2023.07.07 homework

孩子们有些基础不好&#xff0c;鼓励为主&#xff0c;教他们慢慢搬公式推算&#xff0c;提高准确率就好啦。每一次比上一次好一点点&#xff0c;慢慢找回自信心。 图形结合&#xff0c;话说话&#xff0c;其实数学这玩意&#xff0c;画得好也比较直观 第八题找规律的题目&#…

【如何成功加载 HuggingFace 数据集】不使用Colab,以ChnSentiCorp数据集为例

【如何成功加载 HuggingFace 数据集】不使用Colab&#xff0c;以ChnSentiCorp数据集为例 前置加载数据集尝试一&#xff1a;标准加载数据库代码尝试二&#xff1a;科学上网尝试三&#xff1a;把 Huggingface 的数据库下载到本地尝试3.5 创建 state.json彩蛋 前置 Huggingface …

DAY45——动态规划part7

爬楼梯问题 爬楼梯阶数为1...m class Solution {public int climbStairs(int n) {int[] dp new int[n 1];int m 2;dp[0] 1;for (int i 1; i < n; i) { // 遍历背包for (int j 1; j < m; j) { //遍历物品if (i > j) dp[i] dp[i - j];}}return dp[n];} } class…

基于matlab处理来自立体相机图像数据构建室外环境地图并估计相机的轨迹(附源码)

一、前言 视觉同步定位和映射 &#xff08;vSLAM&#xff09; 是指计算摄像机相对于周围环境的位置和方向&#xff0c;同时映射环境的过程。该过程仅使用来自相机的视觉输入。vSLAM 的应用包括增强现实、机器人和自动驾驶。vSLAM 只需使用单眼摄像头即可执行。但是&#xff0c…

Spring系列3 -- 更简单的读取和存储对象

前言 上一篇章总结了,Spring的创建与使用,通过创建Maven项目配置Spring的环境依赖,创建Spring框架的项目,然后通过在Resource目录下创建Spring-config.xml配置文件,添加<bean></bean>标签将我们需要的bean对象注入到容器中,然后通过ApplicationContext获取Spring上…

Mybatis-puls——条件查询的三种格式+条件查询null判定+查询投影

前言 在mybatis_plus的封装中的Wrapper<T>接口参数就是用于封装查询条件 在测试类中启动如上一个简单的查询&#xff0c;然后控制台运行会输出一大堆无关日志&#xff0c;这里先把这些日志关闭 去除无关日志文件 先新建一个XML配置文件 然后变成如下&#xff0c;这里…

[神经网络]YoloV7

Yolo系列是一类很经典的目标检测网络&#xff0c;属于anchor-base型网络&#xff0c;即需要先产生先验框然后筛选先验框得到预测框。同时它也是One-Stage网络&#xff0c;即不需要额外的网络结构来筛选先验框。这两种特点使得它具备了运算速度快和计算精度相对较高的特点。 比较…

Win10怎么用U盘重装系统?Win10用U盘重装系统步骤图解教程

Win10怎么用U盘重装系统&#xff1f;使用U盘重装系统是一种快速而有效的方法&#xff0c;可以帮助我们在电脑中进行Win10系统的重新安装。首先用户需要准备一个容量适当的U盘&#xff0c;并确保其中没有重要数据&#xff0c;然后按照小编分享的Win10用U盘重装系统步骤图解教程操…

Redis 简单入门

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 安装 Redisredis 的数据类型和使用字符串类型字典类型列表类型集合类型有序集合类型 SpringBoot 集成 Redis添加 redis 依赖配…

el-checkbox / el-checkbox-group中绑定对象无法回显的问题处理

在使用el-checkbox / el-checkbox-group时&#xff0c;发现若label绑定的是对象&#xff0c;则是无法回显的&#xff0c;参考了很多方法&#xff0c;但大多都无法解决&#xff0c;最终参考下面的方法解决&#xff0c;记录一下。 <el-checkbox :label"JSON.stringify(i…

每天一点Python——day51

#第五十一天列表和字典为可变序列&#xff0c;元组是不可变序列 为什么要将元组设计成不可变序列呢&#xff1f; 一旦创建了不可变类型的对象&#xff0c;对象内部的所有数据将不能被修改 这样就避免了由于修改数据而导致的错误 对于不可变对象&#xff0c;在多任务环境下&…