Verilog 加法器和减法器(5)
前面二进制加法运算,我们并没有提操作数是有符号数,还是无符号数。其实前面的二进制加法对于有符号数和无符号数都成立。比如前面的8位二进制加法运算,第一张图我们选radix是unsigned,表示无符号加法,第二张图我们选radix是decimal,表示有符号数,从图中可知结果都是正确的。对于有符号数来说,负数默认是补码的形式存在。假设二进制数是n位,则对于无符号数来说,表示范围是0~(2^n) -1 ,对于有符号数,表示的范围是-(2^(n-1))~2^(n-1) - 1
对于有符号数来说,通常还要知道加法结果数据是否溢出。有一种直观的方法判断结果是否溢出,就是如果两个加数有相同的符号,但是它们的和与它们有不同的符号,则产生溢出。假设有n位有符号二进制数x,y,它们的和为s,则它们和溢出判断公式是 overflow = xn_1&yn-1&~sn-1 + ~xn_1&~yn-1&sn-1
修改后的有符号数加法代码为:
module addern_signed(x, y, s, cout, overflow);
parameter n=8;
input [n-1:0] x;
input [n-1:0] y;
output reg[n-1:0] s;
output reg cout;
output reg overflow;
reg [n:0] c;
integer k; always @(x,y) begin
c[0] = 1'b0;
for(k = 0; k < n; k = k + 1) begin
s[k] = x[k]^y[k]^c[k];
c[k+1] = (x[k]&y[k])|(x[k]&c[k])|(y[k]&c[k]);
end
cout = c[n];
overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]);
end endmodule
module addern_signed(x, y, s, cout, overflow);
parameter n=8;
input [n-1:0] x;
input [n-1:0] y;
output [n-1:0] s;
output cout;
output overflow;
integer k; assign {cout, s} = x + y ;
assign overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]); endmodule
修改后的testbench文件为:
`timescale 1ns/1ns
`define clock_period 20 module addern_signed_tb;
reg [7:0] x,y; wire cout;
wire [7:0] s;
reg clk; addern_signed #(.n(8)) addern_signed_0(
.x(x),
.y(y),
.s(s),
.cout(cout)
); initial clk = 0;
always #(`clock_period/2) clk = ~clk; initial begin
x = 0;
repeat(20)
#(`clock_period) x = $random; end initial begin
y = 0;
repeat(20)
#(`clock_period) y = $random; end initial begin
#(`clock_period*20)
$stop;
end endmodule
功能验证的波形图如下:
对于有符号数的减法,我们也可以用加法来做,但是对于减数,我们要做以下变化,如果减数为正数,则变其为补码表示的负数,如果其为补码表示的负数,则把它转化为正数。
assign y1 = y[n-1]?(~{y[n-1:0]}+1'b1):(~{1'b0,y[n-2:0]}+1'b1);
module subn_signed(x, y, s, cout, overflow);
parameter n=8;
input [n-1:0] x;
input [n-1:0] y;
output reg[n-1:0] s;
output reg cout;
output reg overflow;
wire [n-1:0] y1;
reg [n:0] c;
integer k; //y commplement, if y=0, to negative with commplement,if y=1, to positive number.
assign y1 = y[n-1]?(~{y[n-1:0]}+1'b1):(~{1'b0,y[n-2:0]}+1'b1); always @(x,y1) begin
c[0] = 1'b0;
for(k = 0; k < n; k = k + 1) begin
s[k] = x[k]^y1[k]^c[k];
c[k+1] = (x[k]&y1[k])|(x[k]&c[k])|(y1[k]&c[k]);
end
cout = c[n];
overflow = (x[n-1]&y1[n-1]&~s[n-1])|(~x[n-1]&~y1[n-1]&s[n-1]);
end endmodule
module subn_signed(x, y, s, cout, overflow);
parameter n=8;
input [n-1:0] x;
input [n-1:0] y;
output [n-1:0] s;
output cout;
output overflow;
wire [n-1:0] y1;
integer k;
//y commplement, if y=0, to negative with commplement,if y=1, to positive number.
assign y1 = y[n-1]?(~{y[n-1:0]}+1'b1):(~{1'b0,y[n-2:0]}+1'b1);
assign {cout, s} = x + y1 ;
assign overflow = (x[n-1]&y1[n-1]&~s[n-1])|(~x[n-1]&~y1[n-1]&s[n-1]); endmodule
testbench代码为:
`timescale 1ns/1ns
`define clock_period 20 module subn_signed_tb;
reg [7:0] x,y; wire cout;
wire overflow;
wire [7:0] s;
reg clk; subn_signed #(.n(8)) subn_signed_0(
.x(x),
.y(y),
.s(s),
.cout(cout),
.overflow(overflow)
); initial clk = 0;
always #(`clock_period/2) clk = ~clk; initial begin
x = 0;
repeat(20)
#(`clock_period) x = $random; end initial begin
y = 0;
repeat(20)
#(`clock_period) y = $random; end initial begin
#(`clock_period*20)
$stop;
end endmodule
从功能验证的波形图中,我们可以看到见过是正确的。
Verilog 加法器和减法器(5)的更多相关文章
- Verilog 加法器和减法器(8)-串行加法器
如果对速度要求不高,我们也可以使用串行加法器.下面通过状态机来实现串行加法器的功能. 设A=an-1an-2-a0, B=bn-1bn-2-b0,是要相加的两个无符号数,相加的和为:sum=sn-1s ...
- Verilog 加法器和减法器(4)
类似于行波进位加法器,用串联的方法也能够实现多位二进制数的减法操作. 比如下图是4位二进制减法逻辑电路图. 8位二进制减法的verilog代码如下: module subn(x, y, d,cin) ...
- Verilog 加法器和减法器(7)
在计算机中浮点数 表示通常采用IEEE754规定的格式,具体参考以下文章. https://www.cnblogs.com/mikewolf2002/p/10095995.html 下面我们在Veri ...
- Verilog 加法器和减法器(6)
为了减小行波进位加法器中进位传播延迟的影响,可以尝试在每一级中快速计算进位,如果能在较短时间完成计算,则可以提高加法器性能. 我们可以进行如下的推导: 设 gi=xi&yi, pi = xi ...
- Verilog 加法器和减法器(3)
手工加法运算时候,我们都是从最低位的数字开始,逐位相加,直到最高位.如果第i位产生进位,就把该位作为第i+1位输入.同样的,在逻辑电路中,我们可以把一位全加器串联起来,实现多位加法,比如下面的四位加法 ...
- Verilog 加法器和减法器(2)
类似半加器和全加器,也有半减器和全减器. 半减器只考虑当前两位二进制数相减,输出为差以及是否向高位借位,而全减器还要考虑当前位的低位是否曾有借位.它们的真值表如下: 对半减器,diff = x ^y, ...
- Verilog 加法器和减法器(1)
两个一位的二进制数x,y相加,假设和为s,进位为cout,其真值表为: 从真值表中,我们可以得到:s = x^y, cout = x&y,实现两个一位数相加的逻辑电路称为半加器. 实现该电路的 ...
- 基于Xilinx的Synthesize
所谓综合.就是讲HDL语言.原理图等设计输入翻译成由与.或.非们和RAM.触发器登记本逻辑单元的逻辑连接(即网表).并依据目标和要求(约束条件)优化生成的逻辑连接. ISE-XST XST是Xilin ...
- FPGA综合工具--Synplify Pro的常用选项及命令
最近要用到Synplify,但以前没使用过,无基础,找到一篇帖子,隧保存下来. 本文转自:http://blog.sina.com.cn/s/blog_65fe490d0100v8ax.html Sy ...
随机推荐
- 高能天气——团队Scrum冲刺阶段-Day 4
高能天气--团队Scrum冲刺阶段-Day 4 今日完成任务 于欣月:基本实现课程表功能:每一个设置课程表的地方设置一个EditText和一个TextView,根据我们学校的课程情况设置了25个Edi ...
- 算法初级面试题01——认识时间复杂度、对数器、 master公式计算时间复杂度、小和问题和逆序对问题
虽然以前学过,再次回顾还是有别样的收获~ 认识时间复杂度 常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作. 时间复杂度为一个算法流程中,常数操作数量的指标.常 ...
- JAVAEE——SpringBoot入门:简介、微服务、环境准备、helloworld与探究、快速构建项目
一.Spring Boot 入门 1.Spring Boot 简介 简化Spring应用开发的一个框架: 整个Spring技术栈的一个大整合: J2EE开发的一站式解决方案: 2.微服务 2014,m ...
- ASCII UTF-8 编码
1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...
- oracle中listagg()和wmsys.wm_concat()基本用法
一.LISTAGG() 简介 介绍:其函数在Oracle 11g 版本中推出,对分组后的数据按照一定的排序进行字符串连接. 其中,“[,]”表示字符串连接的分隔符,如果选择使用[over (parti ...
- Top 10 Revit Architecture 2014 books
Revit Architecture, along with ArchiCAD, is most used BIM software in architectural design. Although ...
- BZOJ2973 : 石头游戏
考虑到$lcm(1,2,3,4,5,6)=60$,所以操作序列每60秒一个循环. 将操作表示成转移矩阵的形式,预处理出前60秒的转移矩阵以及它们的乘积$B$. 那么t秒的转移矩阵为前$t\bmod 6 ...
- Maven入门指南② :Maven 常用命令,手动创建第一个 Maven 项目
1.根据 Maven 的约定,我们在D盘根目录手动创建如下目录及文件结构: 2.打开pom.xml文件,添加如下内容: <project xmlns="http://maven.apa ...
- 【转】Java类成员变量默认初始化规则
一个变量作为类成员使用的时候,如果没有被初始化,java会为其分配默认值: -------------------------------------------------------------- ...
- Golang 处理 Json(二):解码
golang 编码 json 还比较简单,而解析 json 则非常蛋疼.不像 PHP 一句 json_decode() 就能搞定.之前项目开发中,为了兼容不同客户端的需求,请求的 content-ty ...