#实验一:不同长度的2补码进行运算时,先进行符号扩展和数据对齐,然后再进行加、减法运算
——————————————————————————————————————————————————————
##设计方案一
###方案描述
- **使用Verilog语言,设计两个计数器**
- **计数器1 字长3比特,无符号数制,从0计数到7**
- **计数器2 字长4比特,二补码数制,从-7计数到7**
- **设计符号扩展规则(此处采用位拼接符),将两计数器的输出扩展为相同bit数**
- **分别设计相加之后的字长为4bit与5bit,对比验证两个计数器相加之后的正确性**
###Verilog HDL程序代码以及输出仿真文件
module cnt_0to7_unsigned //cnt_counter
(
CLK , // clock_50M
CNTVAL // counter value
);
input CLK;
output [3-1:0] CNTVAL;
parameter MAX_VAL = 7;
reg [3-1:0] CNTVAL;
always @ (posedge CLK)
begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
endmodule
module cnt_fu7to7_signed //cnt_counter
(
CLK , // clock
CNTVAL // output counter value
);
input CLK;
output [4-1:0] CNTVAL;
reg signed [4-1:0] CNTVAL;
initial
begin
CNTVAL <= 4'b1001;
end
always @ (posedge CLK)
begin
if(CNTVAL[3]== 0 && CNTVAL[2]==1 && CNTVAL[1]==1 && CNTVAL[0]==1)
CNTVAL <= 4'b1001;
else
CNTVAL <= CNTVAL + 4'b0001;
end
endmodule
//以下部分代码为两计数器扩展为4bit后相加,相加字长被定义为4bit。计数器1与计数器2的代码同上显示,这里不再赘述
module and_counter
//The output values of the two counters are summed
(
CLK, //clock_50M
SUM //The sum of the outputs of the two counters
);
input CLK;
output [4-1:0] SUM;
reg signed [4-1:0] SUM;
reg signed [4-1:0] CNTVAL_1_3to4;
//The output of the second counter is converted to a four-digit binary number
wire signed [3-1:0] CNTVAL_1;
wire signed [4-1:0] CNTVAL_2;
integer A = 1'b0;
cnt_0to7_unsigned cnt_0to7_unsigned_1
(
CLK,
CNTVAL_1 //The output of the first counter
);
always @ (CNTVAL_1)
begin
CNTVAL_1_3to4 = {A,CNTVAL_1};
end
cnt_fu7to7_signed cnt_fu7to7_signed_1
(
CLK,
CNTVAL_2 //The output of the second counter
);
always @ (CNTVAL_1_3to4 or CNTVAL_2)
begin
SUM = CNTVAL_1_3to4 + CNTVAL_2;
end
endmodule
//以下部分代码为两计数器扩展为5bit后相加,相加字长被定义为5bit。计数器1与计数器2的代码同上显示,这里不再赘述
module and_counter //The output values of the two counters are summed
(
CLK, //clock
SUM //The sum of the outputs of the two counters
);
input CLK;
output [5-1:0] SUM;
reg signed [5-1:0] SUM;
reg signed [5-1:0] CNTVAL_1_3to5;
reg signed [5-1:0] CNTVAL_2_4to5;
//The output of the second counter is converted to a four-digit binary number
wire signed [3-1:0] CNTVAL_1;
wire signed [4-1:0] CNTVAL_2;
integer A = 2'b00;
integer B = 1'b0;
integer C = 1'b1;
cnt_0to7_unsigned cnt_0to7_unsigned_1
(
CLK,
CNTVAL_1 //The output of the first counter
);
always @ (CNTVAL_1)
begin
CNTVAL_1_3to5 = {A,CNTVAL_1};
end
cnt_fu7to7_signed cnt_fu7to7_signed_1
(
CLK,
CNTVAL_2 //The output of the second counter
);
always @ (CNTVAL_2)
begin
if(CNTVAL_2[3] == 0)
CNTVAL_2_4to5 = {B,CNTVAL_2};
else
CNTVAL_2_4to5 = {C,CNTVAL_2};
end
always @ (CNTVAL_1_3to5 or CNTVAL_2_4to5)
begin
SUM = CNTVAL_1_3to5 + CNTVAL_2_4to5;
end
endmodule
##设计方案二
###方案描述
##实验一总结(定点数相加字长问题):
- **首先将两个定点数扩展为相同bit数,建议与和的bit数相同**
- **简单计算相加和的最大值,从而确定和的bit数。&注意此时要考虑到符号位是否存在,若符号位存在,应预留出符号位,即扩展为实际长度+1**
——————————————————————————————————————————————————————
#实验二:2补码的溢出回绕特性
——————————————————————————————————————————————————————
##溢出回绕特性:
###原理
- **设有N个2补码数相加**
- **即使中间结果溢出**
- **如果理论计算的结果不溢出**
- **则实际运算的结果也不溢出**
###计算举例
- **-3 -7 +5 = -5**
- **1101 +1001 +0101 =1011**
##方案描述
###Verilog HDL程序代码以及输出仿真文件
- **波形仿真文件,显示计数器1的动态变化**
- **注意此时的计数值(SUM)为有符号数signed,此时计算机的输出显示方式本人选择为signed Decimal**
![这里写图片描述](https://img-blog.csdn.net/20170315161253720?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJvdG9uX2Jva2U=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
```Verilog HDL
module add_3_Twos_complment
(
A,
B,
C,
SUM
);
input [4-1:0] A;
input [4-1:0] B;
input [4-1:0] C;
output [4-1:0] SUM;
wire signed [4-1:0] A;
wire signed [4-1:0] B;
wire signed [4-1:0] C;
wire signed [4-1:0] SUM;
assign SUM = A + B + C;
endmodule
```
##实验二总结(溢出回绕特性):
###方案描述
- **相乘两数,bit数相同**
- **使用Verilog语言,设计一个计数器 字长4bit,计数范围-8到7**
- **定义参数常量A为-8,字长4bit**
- **计数器的计数值与A皆为signed有符号数输入,使其相乘,结果最大为十进制数64,7bit,但参照前面的2补码加法实验可知,追加一个符号位,故最终显示结果为8bit**
- **即两4bit2补码数相乘,结果最大为8bit**
- **验证其正确性**
###Verilog HDL程序代码以及输出仿真文件
module cnt_fu8to7_signed //cnt_counter
(
CLK , // clock_50MHz
CNTVAL // output counter value
);
input CLK;
output [4-1:0] CNTVAL;
reg signed [4-1:0] CNTVAL;
initial
begin
CNTVAL <= 4'b1000;
end
always @ (posedge CLK)
begin
if(CNTVAL[3]== 0 && CNTVAL[2]==1 && CNTVAL[1]==1 && CNTVAL[0]==1)
CNTVAL <= 4'b1000;
else
CNTVAL <= CNTVAL + 4'b0001;
end
endmodule
//由SignalTap截图可以看出,结果是正确的
module signed_int_mul //signed integer multiplication
(
CLK,
product
);
input CLK;
output [8-1:0] product;
reg signed [8-1:0] product; //The product of two numbers with signed
reg signed [7-1:0] guodu; //The product of two numbers unsigned
wire signed [4-1:0] CNTVAL_1;
parameter signed A = 4'b1000;
parameter B = 1'b0;
parameter C = 1'b1;
cnt_fu8to7_signed cnt_fu8to7_signed_1
(
CLK,
CNTVAL_1 //output -8 to 7
);
always @ (CNTVAL_1)
begin
guodu = CNTVAL_1 * A;
end
always @ (guodu or CNTVAL_1)
begin
if(CNTVAL_1 == 4'b0000)
product = {B,guodu[7-1:0]};
else
begin
if(A[3] ^ CNTVAL_1[3] == 0)
product = {B,guodu[7-1:0]};
else
product = {C,guodu[7-1:0]};
end
end
endmodule
##设计方案二
###方案描述
##实验三总结(2补码整数相乘):
- **结果不含符号位最大为两数bit数相加**
- **追加符号位**
#实验四:带小数位的定点数的加法与乘法简单验证实验
——————————————————————————————————————————————————————
##原理
###注:以下(8.8),意思为前8位为整数,后8位为小数
###谓定点小数,就是小数点的位置是固定的。我们是要用整数来表示定点小数,由于小数点的位置是固定的,所以就没有必要储存它(如果储存了小数点的位置,那就是浮点数了)。既然没有储存小数点的位置,那么计算机当然就不知道小数点的位置,所以这个小数点的位置是我们写程序的人自己需要牢记的。
###对于定点小数的二进制表示。我们把小数点之后有n位叫做Qn,例如小数点之后有12位叫做Q12格式的定点小数,而Q0就是我们所说的整数。假如我们用8位二进制表示0.07071(前二位为整数部分,后六位为小数部分)为8'b00101101,即对00.101101做了*2^6处理。
###对于加减法,由于运算前后小数点的位置不会发生变化,故只需对运算结果进行/2^6处理即可。
###对于乘除法,由于运算前后小数点的位置发生了变化,例(8.8)*(8.8)结果为(16*16),需要进行移8位操作才能保持小数点位置不动
##设计方案一(乘法)
##方案描述
- **利用Verilog HDL语言,设计使得两定点数相乘。8'b10011001(2.6)与8'b10010010(2.6)**
- **由计算可知,运算后整数为5,为3位,小数为12位。将结果分别存储为15、14、13、12、11、10、9位,其中位数的变化,只是在逐渐的舍弃小数位的低位,而整数位没有变化。则结果以9位存储时的小数点位置与运算前两数的小数点位置相同**
- **运行程序,验证**
- **计算以不同位数存储时的结果与实际值之间的误差**
###Verilog HDL程序代码以及输出仿真文件
//注:本人愚笨,翻找资料,未查到如何使数组中向量的长度为变量,故代码繁琐,若各位看客有想法可与我留言
//若使数组中向量的长度为变量,则数据的处理大为方便,计算误差也不是难事,但在这里,几个数据,本人是手工计算,笨拙,勿怪
//结果9位(3.6)存储时,误差8.9*e(-5)
//结果10位(3.6)存储时,误差8.9*e(-5)
//结果11位(3.6)存储时,误差8.9*e(-5)
//结果12位(3.6)存储时,误差8.9*e(-5)
//结果13位(3.6)存储时,误差8.9*e(-5)
//结果14位(3.6)存储时,误差0
//结果15位(3.6)存储时,误差0
module int_dec_mul //signed decimal_xiaoshu multiplication
(
CLK,
product_1,
product_2,
product_3,
product_4,
product_5,
product_6,
product_7
);
input CLK;
output [15-1:0] product_1;
output [14-1:0] product_2;
output [13-1:0] product_3;
output [12-1:0] product_4;
output [11-1:0] product_5;
output [10-1:0] product_6;
output [9-1:0] product_7;
reg [15-1:0] product_1;
reg [14-1:0] product_2;
reg [13-1:0] product_3;
reg [12-1:0] product_4;
reg [11-1:0] product_5;
reg [10-1:0] product_6;
reg [9-1:0] product_7; //The product of two numbers
reg [15-1:0] guodu;
parameter A = 8'b10011001; //8'b10.011001
parameter B = 8'b10010010; //8'b10.010010
always @ (CLK)
begin
guodu <= B * A;
end
always @ (guodu)
begin
product_1 = {guodu[14:12],guodu[11:0]};
product_2 = {guodu[14:12],guodu[11:1]};
product_3 = {guodu[14:12],guodu[11:2]};
product_4 = {guodu[14:12],guodu[11:3]};
product_5 = {guodu[14:12],guodu[11:4]};
product_6 = {guodu[14:12],guodu[11:5]};
product_7 = {guodu[14:12],guodu[11:6]};
end
endmodule
##设计方案二(加法)
##方案描述