基于FPGA的数字信号处理(20)--半加器和全减器

1、前言

        既然有半加器和全加器,那自然也有半减器和全减器了。尽管在电路中减法的实现基本都是 补码 + 加法 的形式,但是正所谓技多不压身,了解一下半减器和全减器还是有一定作用的,至少能扩宽知识面嘛。

2、半减器

        最简单的减法器叫做 半减器Half Subtractor),它将2个1bit的输入数据相减,输出一个1bit的结果即 差Di(Difference),以及向高位的借位Bo(Borrow output)。例如:

  • 1 - 1 = 01 -1 = 0,不需要向高位借位,差为0,即Bo = 0,Di = 0

  • 1 - 0 = 01 -0 = 1,不需要向高位借位,差为1,即Bo = 0,Di = 1

  • 0 - 1 = 10 -1 = 1, 需要向高位借位,差为1,即Bo = 1,Di = 1

  • 0 - 0 = 00 -0 = 0,不需要向高位借位,差为0,即Bo = 0,Di = 0

        2个1bit数相减,最多只有4种情况(在上面已经例出来了),据此可以写出半减器的真值表:

被减数减数向高位借位
XYDiBo
0000
0111
1010
1100

        从这个真值表,不难推断出输出的逻辑表达式:

  • 差Di在2个输入不同时为1,所以它是输入异或的结果,即 Di = a ^ b

  • 向高位借位Bo在X = 0 且 Y = 1 时才为1,即 Bo= ~X & Y

        有了逻辑表达式后,可以很容易地画出对应的门电路结构:

image-20240426103255933

        顺便提一句,虽然半减器的基本电路是上面这个样子的,但是因为在FPGA中只有查找表LUT而没有具体的门电路,所以如果用FPGA来综合半减器的话,它的电路应该是这个样子的(因为只有2个输入和2个输出,所以只要1个LUT6就可以覆盖到所有情况):

image-20240426105010530

如果你不了解LUT,可以看看这篇文章:从底层结构开始学习FPGA(2)----LUT查找表,或者看看这个专栏:从底层结构开始学习FPGA

        IBUF和OBUF是Vivado自动添加的对输入输出管脚的缓冲,尽管上图显示的是2个LUT2(可能这样的显示更清晰一点),但是实际上就是1个LUT6,下面的资源显示情况也证明了这一点:

image-20240426105038079

        用verilog实现半减器如下:

//使用逻辑表达式来描述半减器
module half_subtractor(input   x,      //被减数input   y,      //减数output  di,     //差output  bo      //向高位借位
);
​
//根据化简结果分别表示:差 与 向高位借位
assign di = x ^ y;  
assign bo = ~x & y;endmodule

        有了RTL,接下来就该要写个对应的TB来测试电路功能是否正常。由于这个电路足够简单(一共只有4种情况),所以我们可以把所有可能的情况都穷举出来,然后观察输出是否符合预期即可。TB如下:

`timescale 1ns/1ns              //时间刻度:单位1ns,精度1ns
​
module tb_half_subtractor();            
​
//定义变量  
reg     x;
reg     y;
wire    di;
wire    bo;
​
//设置初始化条件
initial begin//第1种情况x =1'b0;    y =1'b0;    #10     //第2种情况x =1'b0;    y =1'b1;    #10     //第3种情况x =1'b1;    y =1'b0;#10     //第4种情况x =1'b1;    y =1'b1;#10 $stop();    //结束仿真  
end
​
//例化被测试模块
half_subtractor u_half_subtractor(.x      (x),.y      (y),    .di     (di),   .bo     (bo)
);endmodule

        仿真结果如下:

image-20240426105113676

        通过和真值表的对比(或者验证逻辑表达式也可以),可以发现,电路的输出是符合预期的。

3、全减器

        虽然半减器可以实现2个1bit数的减法,但在实际应用中,更常见的是要实现2个多bits数的减法,那么该如何实现?以2个2bits数的减法为例:

  1. 先把低位和高位的减法先分开。

  2. 低位是2个1bit的减法,所以可以用1个HS(半减器)来实现,它产生的差就是最终结果的低位,它产生的向高位借位要被送入到高位参与它们的减法。

  3. 高位除了要计算减数和被减数的高位外,还有1个来自低位的借位。

        好,现在问题是半减器没有设计来自低位的借位,所以它处理不了这种情况。为此,全减器被设计出来了,它在半减器的基础上,增加了来自低位的借位输入。这样多个全减器就可以级联起来实现多bits的减法了。

        全减器Full Subtractor),它处理2个1bit的输入和来自低位的借位Bi(Borrow input)输入共3个数,输出一个差Di和向高位的借位Bi。例如(格式:被减数- 减数 - 来自低位的借位):

  • 1 - 1 - 1 = 11 - 1 - 1 = 0,来自低位的借位为1, 需要向高位借位,差为0,即Bi = 1,Bo = 0,Di = 0

  • 1 - 1 - 0 = 01 - 1 - 0 = 0,来自低位的借位为0,不需要向高位借位,差为0,即Bi = 0,Bo = 0,Di = 0

  • 1 - 0 - 1 = 01 - 0 - 1 = 0,来自低位的借位为1,不需要向高位借位,差为0,即Bi = 1,Bo = 0,Di = 0

  • 1 - 0 - 0 = 01 - 0 - 0 = 0,来自低位的借位为0,不需要向高位借位,差为1,即Bi = 0,Bo = 0,Di = 1

  • ······

        3个输入一共只有8种情况,把所有情况都穷举出来,就可以列出全减器的真值表:

被减数减数来自低位的借位向高位的借位
XYBiDiBo
00000
00111
01011
01101
10010
10100
11000
11111

        从这个真值表,不难推断出两个输出的逻辑表达式:

  • Di为1的4种情况,~x&~y&bi + ~x&y&~bi + x&~y&~bi + x&y&bi=~x&(~y&bi+y&~bi)+x&(~y&~bi+y&bi) = ~x&(y^bi) + x&~(y^bi) = x ^ y ^ bi

  • Bo为1的4种情况,~x&~y&bi + ~x&y&~bi + ~x&y&bi + x&y&bi = ~x&(~y&bi+y&~bi) + (~x+x)&y&bi = ~x&(y^bi) + y&bi

        有了逻辑表达式后,就很容易画出电路图了(偷了个懒,不是画的,是用vivado生成的):

image-20240426112013178

        根据门电路,可以写出全减器的Verilog实现:

//使用逻辑表达式来描述全减器
module full_subtractor(input   x,      //被减数input   y,      //减数input   bi,     //来自低位的借位output  di,     //差output  bo      //向高位借位
);
​
//根据化简结果分别表示:差 与 向高位借位
assign di = x ^ y ^ bi; 
assign bo = ~x & (y ^ bi) | y & bi;endmodule 

        接下来写个TB测试电路,输入一共只有8个,所以依然用穷举法来测试:

`timescale 1ns/1ns              //时间刻度:单位1ns,精度1ns
​
module tb_full_subtractor();            
​
//定义变量  
reg     x;
reg     y;
reg     bi;
wire    di;
wire    bo;
​
//设置初始化条件
initial begin//第1种情况x =1'b0;    y =1'b0;    bi =1'b0;   #10     //第2种情况x =1'b0;    y =1'b1;bi =1'b0;   #10     //第3种情况x =1'b1;    y =1'b0;bi =1'b0;#10     //第4种情况x =1'b1;    y =1'b1;bi =1'b0;#10     //第5种情况x =1'b0;    y =1'b0;    bi =1'b1;#10     //第6种情况x =1'b0;    y =1'b1;bi =1'b1;#10     //第7种情况x =1'b1;    y =1'b0;bi =1'b1;#10     //第8种情况x =1'b1;    y =1'b1;bi =1'b1;   #10 $stop();    //结束仿真  
end
​
//例化被测试模块
full_subtractor u_full_subtractor(.x      (x),.y      (y),    .di     (di),.bi     (bi),.bo     (bo)
);endmodule

        仿真结果如下所示:

image-20240426112114957

        通过和真值表的对比(或者验证逻辑表达式也可以),可以发现,电路的输出是符合预期的。

4、减法器

        有了全减器后,就可以实现两个多bits数的减法了,这样的电路也被称为减法器。和行波进位加法器的结构类似,我们也可以将多个全减器级联起来搭建减法器,以4bits的减法为例,它的结构如下:

image-20240426113045693

        根据结构图,可以很快地写出它对应的Verilog代码:

//使用多个全减器建联构建减法器
module subtractor(input   [3:0]   x,  //被减数input   [3:0]   y,  //减数input           bi, //来自低位的借位output  [3:0]   di, //差output          bo  //向高位借位
);
​
wire    b1,b2,b3;   //借位连接
​
//例化全减器来构建减法器
full_subtractor u0(.x      (x[0]),.y      (y[0]), .di     (di[0]),.bi     (bi),.bo     (b1)
);
full_subtractor u1(.x      (x[1]),.y      (y[1]), .di     (di[1]),.bi     (b1),.bo     (b2)
);
full_subtractor u2(.x      (x[2]),.y      (y[2]), .di     (di[2]),.bi     (b2),.bo     (b3)
);
full_subtractor u3(.x      (x[3]),.y      (y[3]), .di     (di[3]),.bi     (b3),.bo     (bo)
);
​
endmodule

        这里记得要把之前的全减器也添加进工程。生成的示意图如下(这个排布不能很好地看出来层次结构,但确实没错):

image-20240426121705201

        然后写个TB测试一下这个减法器电路,因为4个bits即16×16=256种情况,加上低位借位的两种情况,也才256×2=512种情况,所以依然用穷举法来测试:

`timescale 1ns/1ns              //时间刻度:单位1ns,精度1ns
​
module tb_full_subtractor();            
​
//定义变量  
reg     [3:0]   x;      //被减数
reg     [3:0]   y;      //减数
reg             bi;     //来自低位的借位
wire    [3:0]   di;     //差
wire            bo;     //向高位借位
​
reg [3:0]   di_real;    //差的真实值,作为对比
reg         bo_real;    //向高位借位的真实值,作为对比
wire        di_flag;    //di正确标志信号
wire        bo_flag;    //bo正确标志信号
​
assign di_flag = di == di_real; //di结果正确时拉高该信号
assign bo_flag = bo == bo_real; //bo结果正确时拉高该信号
​
integer z,i,j;  //循环变量
//设置初始化条件
initial begin//初始化x =1'b0;    y =1'b0;    bi =1'b0;   //设定低位借位为0//穷举所有情况for(z=0;z<=1;z=z+1)beginbi = z;for(i=0;i<16;i=i+1)beginx = i;for(j=0;j<16;j=j+1)beginy = j;if((i-j-z)<0)begin                  //减法结果是负数di_real = (i - j - z)+ 5'd16;   //加上向高位的借位bo_real = 1;                    //向高位的借位为1endelse begin                          //减法结果是正数数di_real = i - j - z;            //结果就是减法本身bo_real = 0;                    //向高位的借位为0end#5;             end endend#10 $stop();    //结束仿真  
end
​
//例化被测试模块
subtractor u_subtractor(.x      (x),.y      (y),    .di     (di),.bi     (bi),.bo     (bo)
);endmodule

        TB中分别用3个嵌套循环将所有情况穷举出来,即bi=0~1、x=0~15和y=0~15的所有情况。减法运算的预期结果也是很容易就可以找出来的,就是直接写减法就行。接着构建了两个标志向量di_flag和bo_flag作为电路输出与预期结果的对比值,当二者一致时即拉高这两个信号。这样我们只要观察这两个信号,即可知道电路输出是否正确。仿真结果如下:

image-20240426122614109

        可以看到,di_flag和bo_flag都是一直拉高的,说明电路输出正确。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RESNET

ResNet 文章目录 ResNet主要内容开发背景解决两个问题&#xff1a;1. 梯度消失和梯度爆炸2. 退化问题: 解决方法1. BN&#xff08;Batch Normalization&#xff09;层2. 残差块 Pytorch实现BasicBlockBottleNeckResNet 主要内容 开发背景 残差神经网络(ResNet)是由微软研究院…

LLM大模型:十大人工智能大模型技术介绍

十大人工智能大模型技术的简介&#xff1a; 深度学习模型 深度学习是人工智能领域中一种重要的机器学习技术&#xff0c;通过构建深度神经网络来模拟人脑的认知过程。深度学习模型能够自动提取数据的特征&#xff0c;并在海量数据中进行学习和优化&#xff0c;从而在语音识别…

搭建规范化的vue2项目

项目包含的库 Vue2VuexRouterEslintPrettier 环境 vue&#xff1a;2.6.14 eslint&#xff1a;7.32.0 prettier&#xff1a;2.4.1 eslint-plugin-prettier&#xff1a;4.0.0 eslint-plugin-vue&#xff1a;8.0.3 vue/cli&#xff1a;5.0.8 步骤 全局安装cli工具 npm in…

CAE仿真软件怎样下载和安装?

CAE仿真软件是一类专业工程软件&#xff0c;通过数值计算和仿真技术&#xff0c;帮助工程师和设计师在计算机上模拟和分析各种工程问题&#xff0c;如结构强度、热传导、流体力学等&#xff0c;从而优化产品设计、减少试验成本&#xff0c;提高产品性能和质量。HyperWorks是常见…

快手文生图模型-Kolors快速上手

Kolors是什么 可图(Kolors)&#xff1a;用于真实感文本到图像合成的扩散模型的有效训练 可图&#xff0c;是快手开源的一个文生图模型&#xff0c;架构上使用了chatglm&#xff0c;比普通的sd模型在中文理解上要强大很多&#xff0c;以往sd模型的提示词理解能力往往只有两种 …

二进制部署k8s集群之cni网络插件flannel和calico工作原理

3、部署 CNI 网络组件 在 master01 节点上操作 上传flannel-v0.21.5.zip并解压 unzip flannel-v0.21.5.zipscp flannel*.tar 192.168.80.20:/opt/k8s/ scp flannel*.tar 192.168.80.30:/opt/k8s/ node两个节点操作 cd /opt/k8s/ docker load -i flannel.tar docker load -i …

nginx代理设置时能获取到源IP地址的方法

nginx通过http_x_forwarded_for限制来访IP示例_ngnix 根据header的x-forwarded-for限制接入-CSDN博客 名称ip客户端地址10.0.23.90nginx服务器地址110.0.202.48:18888&#xff0c;代理到10.0.204.82:8888nginx服务器地址210.0.204.82:8888&#xff0c;代理到10.0.204.82:8887后…

自写ApiTools工具,功能参考Postman和ApiPost

近日在使用ApiPost的时候&#xff0c;发现新版本8和7不兼容&#xff0c;也就是说8不支持离线操作&#xff0c;而7可以。 我想说&#xff0c;我就是因为不想登录使用才从Postman换到ApiPost的。 众所周知&#xff0c;postman时国外软件&#xff0c;登录经常性抽风&#xff0c;…

leetcode 1555 银行账号概要(postgresql)

需求 用户表&#xff1a; Users --------------------- | Column Name | Type | --------------------- | user_id | int | | user_name | varchar | | credit | int | --------------------- user_id 是这个表的主键。 表中的每一列包含每一个用户当前的额度信息。 交易表&…

使用 Elastic Observability 中的 OpenTelemetry 进行基础设施监控

作者&#xff1a;来自 Elastic ISHLEEN KAUR 将 OpenTelemetry 与 Elastic Observability 相结合&#xff0c;形成应用程序和基础设施监控解决方案。 在 Elastic&#xff0c;我们最近决定全面采用 OpenTelemetry 作为首要的数据收集框架。作为一名可观察性工程师&#xff0c;我…

分享5款ai头像工具,助你轻松实现社交新形象

如今&#xff0c;无论是社交媒体上的个人形象塑造&#xff0c;还是虚拟世界中的角色扮演&#xff0c;一个独特而吸引人的AI头像都能成为你个性化的代表。 例如&#xff0c;ai头像男古风通常代表着一种对传统文化的尊重和热爱&#xff1b;而现代简约头像可能代表着一种追求简洁…

Mongodb集合操作

文章目录 1、进入容器2、如果数据库不存在&#xff0c;则创建数据库&#xff0c;否则切换到指定数据库3、在 MongoDB 中&#xff0c;创建集合不是必须操作。当你插入一些文档时&#xff0c;MongoDB 会自动创建集合。4、查看数据库列表5、查看集合6、显示创建集合7、删除集合 1、…

百度竞价托管如何判断关键词出价是否偏高

在百度竞价推广中&#xff0c;关键词出价的高低直接影响着广告的展示位置、点击率以及最终的转化效果。然而&#xff0c;过高的出价不仅会增加推广成本&#xff0c;还可能导致预算的浪费。因此&#xff0c;作为百度竞价托管 www.pansem.com 的专业团队&#xff0c;如何准确判断…

springboot校园跑腿服务系统-计算机毕业设计源码15157

摘要 本文介绍了一种基于Springboot和uniapp的校园跑腿服务系统的设计与实现。该系统旨在为大学校园提供一种方便快捷的跑腿服务&#xff0c;满足学生和教职员工的日常需求。首先&#xff0c;系统采用了Springboot作为后端框架&#xff0c;利用其轻量级、高效的特性&#xff0c…

httpx,一个网络请求的 Python 新宠儿

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…

计算机网络-七层协议栈介绍

之前介绍了网络世界的构成&#xff0c;从宏观角度介绍了网络设备和网络架构&#xff0c;链接: link&#xff0c;但是这种认识过于粗糙&#xff0c;过于肤浅。网络本质上是用于主机之间的通信&#xff0c;是端对端的连接通信&#xff0c;两台计算机可能距离很远&#xff0c;主机…

thinkPHP开发的彩漂网站源码,含pc端和手机端

源码简介 后台thinkPHP架构,页面程序双分离,Mysql数据库严谨数据结构、多重数据审核机制、出票机制和监控机制,html5前端技术适用移动端,后台逻辑更多以server接口可快捷实现对接pc和ap,下载会有少量图片素材丢失,附件有下载说明前端demo账户密码和后台管理地址管理员账户密码…

C 语言动态链表

线性结构->顺序存储->动态链表 一、理论部分 从起源中理解事物&#xff0c;就是从本质上理解事物。 -杜勒鲁奇 动态链表是通过结点&#xff08;Node&#xff09;的集合来非连续地存储数据&#xff0c;结点之间通过指针相互连接。 动态链表本身就是一种动态分配内存的…

Java 8-函数式接口

目录 一、概述 二、 函数式接口作为方法的参数 三、函数式接口作为方法的返回值 四、 常用的函数式接口 简单总结 简单示例 4.1 Consumer接口 简单案例 自我练习 实际应用场景 多线程处理 4.2 Supplier接口 简单案例 自我练习 实际应用场景 配置管理 4.3 Func…

TypeError: Components is not a function

Vue中按需引入Element-plus时&#xff0c;报错TypeError: Components is not a function。 1、参考Element-plus官方文档 安装unplugin-vue-components 和 unplugin-auto-import这两款插件 2、然后需要在vue.config.js中配置webPack打包plugin配置 3、重新启动项目会报错 T…