基于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://xiahunao.cn/news/3280573.html

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

相关文章

RFID分体式天线如何选购?

分体式读写器天线具有可与RFID读写器分离部署&#xff0c;在远距离读写、集成应用等场景下拥有十分广泛的应用。下面我们就跟大家一起来了解一下&#xff0c;分体式天线选购的要点有哪些? 分体式天线的选购要点主要包括以下几个方面&#xff1a; 一、明确使用需求 应用场景…

机器学习(五) -- 无监督学习(2) --降维2

系列文章目录及链接 上篇&#xff1a;机器学习&#xff08;五&#xff09; -- 无监督学习&#xff08;2&#xff09; --降维1 下篇&#xff1a; 前言 tips&#xff1a;标题前有“***”的内容为补充内容&#xff0c;是给好奇心重的宝宝看的&#xff0c;可自行跳过。文章内容被…

仪器内部压力不稳定的原因分析

仪器的液路压力波动可能由多种原因引起&#xff0c;具体分析如下&#xff1a; 气泡的影响&#xff1a; 流动相未平衡或柱箱温度不稳定时&#xff0c;容易在色谱柱内产生气泡。泵作用下&#xff0c;流动相中的空气可能会分离出来&#xff0c;留在泵体内排不出去。使用梯度程序时…

vmware 设置ip

要用xshell连接vmware虚拟机&#xff0c;要指定虚拟机的ip地址。 进入虚拟机&#xff0c;用ifconfig命令&#xff0c;看下ip 试了下连接192.168.122.1 连接不上&#xff0c;需要重新设置一个。 1&#xff0c;查看电脑的IP地址 winr,输入cmd&#xff0c;再输入ipconfig 看下本…

Java刷题: 丑数判断

题目 丑数 就是只包含质因数 2、3 和 5 的正整数。 给你一个整数 n &#xff0c;请你判断 n 是否为 丑数 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 解题思路 我觉得刷题是为了扩宽思考的广度。看到这题的时候&#xff0c;我的大脑是发懵的…

letcode - string

翻转字符串 344. 反转字符串 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/reverse-string/ class Solution { public:void reverseString(vector<char>& s) {reverse(s.begin(),s.end());//直接上逆置接口} }; 函数签名: void reverseStr…

redis的代码开发

redis是什么? 前提:官网地址https://redis.io 1.Redis是一个开源的,key,value格式的,内存型数据结构存储系统;它可用作数据库、缓存和消息中间件。 value支持多种类型的数据结构如strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglo…

VMware虚拟机安装及虚拟机下安装ubuntu(附安装包)

VMware虚拟机安装及虚拟机下安装ubuntu 0 前期准备1 VMware安装2 VMware虚拟机下安装ubuntu2.1 配置虚拟机2.2 安装虚拟机ubuntu 3 在虚拟机中卸载Ubuntu参考 0 前期准备 1、VMware Wworkstation Pro安装包下载 官网-添加链接描述 百度网盘分享&#xff1a; 链接: VMware 提取…

【实践出真知】使用Docusaurus将md文档组织起来就是一个网站(写API文档,写教程、写日记、写博客的有福了)

文章目录 前言一、Docusaurus 是什么&#xff1f;二、一键生成网站框架并预览1. 系统需求2. 脚手架项目网站&#xff08;一键生成网站框架&#xff09;3. 生成的目录内容4. 网站运行与展示 总结 前言 前段时间&#xff0c;学习Flet&#xff0c;访问到Flet中文网&#xff0c;被…

Golang `os/signal`包详解:全面掌握信号处理技巧

Golang os/signal包详解&#xff1a;全面掌握信号处理技巧 1. 引言2. os/signal包简介2.1 基本功能2.2 主要用途2.3 基本概念2.4 使用方法 3. 信号的类型和使用场景3.1 常见的操作系统信号3.2 信号的使用场景3.2.1 优雅关闭程序3.2.2 重新加载配置文件3.2.3 处理子进程退出 4. …

Chapter 21 深入理解JSON

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、JSON数据格式1. 什么是JSON&#xff1f;2. JSON数据的格式 二、JSON格式数据转化三、格式化JSON数据的在线工具 前言 在当今数据驱动的世界中&#xff0c;JSON&…

【iOS】线程同步读写安全技术(锁、信号量、同步串行队列)

目录 多线程安全隐患存钱取钱问题卖票问题 解决方案1. 锁自旋锁OSSpinLockos_unfair_lockatomic 互斥锁pthread_mutex_t条件pthread_cond_t&#xff08;线程检查器&#xff09;NSLock&NSRecursiveLock&#xff08;递归锁&#xff09;NSCondition&#xff08;条件锁&#xf…

C++ | Leetcode C++题解之第307题区域和检索-数组可修改

题目&#xff1a; 题解&#xff1a; class NumArray { private:vector<int> tree;vector<int> &nums;int lowBit(int x) {return x & -x;}void add(int index, int val) {while (index < tree.size()) {tree[index] val;index lowBit(index);}}int p…

3.2.微调

微调 ​ 对于一些样本数量有限的数据集&#xff0c;如果使用较大的模型&#xff0c;可能很快过拟合&#xff0c;较小的模型可能效果不好。这个问题的一个解决方案是收集更多数据&#xff0c;但其实在很多情况下这是很难做到的。 ​ 另一种方法就是迁移学习(transfer learning…

FFplay介绍及命令使用指南

&#x1f60e; 作者介绍&#xff1a;欢迎来到我的主页&#x1f448;&#xff0c;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff08;领取大厂面经等资料&#xff09;&#xff0c;欢迎加我的…

微软Win11 24H2最新可选更新补丁26100.1301来袭!

系统之家于7月31日发出最新报道&#xff0c;微软针对Win11 24H2用户推出七月最新的可选更新KB5040529&#xff0c;本次更新为开始菜单引入了全新的账号管理器&#xff0c;也改进了任务栏上的小组件图标。接下来跟随系统之家小编来看看本次更新的详细内容吧&#xff01;【推荐下…

不同类型游戏安全风险对抗概览(下)| FPS以及小游戏等外挂问题,一文读懂!

FPS 游戏安全问题 由于射击类游戏本身需要大量数值计算&#xff0c;游戏方会将部分计算存放于本地客户端&#xff0c;而这为外挂攻击者提供了攻击的温床。可以说&#xff0c;射击类游戏是所有游戏中被外挂攻击最为频繁的游戏类型。 根据网易易盾游戏安全部门检测数据显示&#…

【排序算法】Java实现三大非比较排序:计数排序、桶排序、基数排序

非比较排序概念 非比较排序是一种排序算法&#xff0c;它不通过比较元素之间的大小关系来进行排序&#xff0c;而是基于元素的特征或属性进行排序。这种方法在特定情况下可以比比较排序方法&#xff08;如快速排序、归并排序等&#xff09;更有效率&#xff0c;尤其是在处理大…

【原创】java+ssm+mysql医生信息管理系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 开发背景&#xff1a; 随着信息技术的…

详解线程的几种状态?

详解线程的几种状态? 1. 新建状态&#xff08;New&#xff09;2. 就绪状态&#xff08;Runnable&#xff09;3. 运行状态&#xff08;Running&#xff09;4. 阻塞状态&#xff08;Blocked&#xff09;5. 死亡状态&#xff08;Dead&#xff09; &#x1f496;The Begin&#x1…