64位乘法器实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
64位乘法器实验报告
64位乘法器设计实验是我在科大的第一个课程设计,verilog程序的熟练掌握对于微电
子专业的学生来讲是非常必要的,对于此次设计我也花费了很长时间。
本设计分为3个部分,即控制和(1)状态选择部分,(2)乘法器部分,(3)加法器部
分。以下我将按此顺序进行说明。需要指出的是,在实际设计中的顺序恰好是颠倒的,这
与设计思路有关,在刚开始的时候由于对整体没有一个很好的把握就先选择最简单的一部分
几加法器开始入手,然后就是乘法器,最后作乐一个状态控制电路将两部分联系起来。
状态选择部分设计:
本电路状态选择部分设计比较简单,只有一个控制信号sel来控制电路的工作状态,我
选定的状态是:sel为00的时候做加法,sel为01时做减法,sel为10时做乘法。从节省功
耗的角度出发,当电路处于加法状态的时候,乘法器最好是能够不工作,反之也一样在乘法
器工作时要求加法器也处于不工作状态。我在设计中在两个电路块的输入上都加了一个二选
一开关,使不处于工作状态的电路块的输入始终为0,可是使电路减少由动态翻转产生的功
耗。
加法器的设计:
为了能更好地掌握加法器的设计过程,本部分采用门级描述语言,本加法器采用
流水线的设计方案。实际上该部分是不需要流水,因为乘法器是本电路的关键路径,即使乘
法器采用流水线的设计方案延迟也肯定比加法器要大。为了能够掌握流水线设计,加法器也
采用了流水线来实现。加法器的整体结构见附图(1),有超前进位产生电路,和超前进位电
路来实现。
超前进位产生电路是对两个64位输入按位进行异或和与从而产生超前进位电路的
输入信号P,Q。教材上在此处也产生了部分和结果S,但我认为在此处产生结果不妥,因
为要产生部分和结果必须有上一级的进位信号,对于本加法器进位信号将在下一步才产生。
所以我将作后结果的产生放在了最后一拍来完成将P与产生的进位信号按位异或即可得到
最后结果。但要注意P与进位信号CP产生的时间是不一致的,所以P信号要送到寄存器中
等待一拍。以与CP信号保持时序上的一致。
毋庸置疑64位加法器的设计肯定要采用超前进位电路来实现。考虑到一般的与门或或
门的扇入不大于4的原则,我对超前进位电路采取每4组一个超前进位块,同时分层超前进
位来实现。这样做的好处是能降低每个超前进位块的设计复杂程度,实现电路在性能和复杂
性之间的一个优化。电路超前进位部分的总体结构见附图(2)。超前进位按设计要求是产生
除最高进位之外的所有进位信号。同时最高位的进位信号是由一个额外的组合电路来实现。
CP[63]=G[63]|(P[63] & G[62])|(P[63] & P[62] & G[61])|(P[63]&P[62]&P[61]&G[60])|(P[63]&P[62]&P[61]&P[60]&G[59]);
在所有进位信号产生之后加法器的输出就是:
sum[64:0]<={CP[63],(P_sec[63:0]^{CP[62:0],sel[0]})};
sel[0]下面将对此做出解释。我设定sel信号为01时做减法,sel为00时做加法。减法
电路设计比较简单只要在sel为0是将输入信号Y取反再加1即可。为了减法不增加额外的
开销,我将sel[0]作为加法器的最低位进位信号,这样就可以解决加1的问题。需要注意的是减法器的最高位不是进位信号,而是借位信号。为1表明输入X小于Y。
乘法器电路设计:
该部分是本电路设计的重点,我采用的方法是将乘数Y分为4段,每段16位分别与乘数X相乘,该部分采用booth编码算法,在得到结果后再将4个部分积移位相加即得到乘法结果。结构图见图(3)。
Booth算法采用相加和相减的操作计算补码数据的乘积。Booth算法对乘数从低位开始判断,根据两个数据位的情况决定进行加法、减法还是仅仅移位操作。判断的两个数据位为当前位及其右边的位(初始时需要增加一个辅助位0),移位操作是向右移动。在上例中,第一次判断被乘数0110中的最低位0以及右边的位(辅助位0),得00;所以只进行移位操作;第二次判断0110中的低两位,得10,所以作减法操作并移位,这个减法操作相当于减去2a 的值;第三次判断被乘数的中间两位,得11,于是只作移位操作;第四次判断0110中的最高两位,得01,于是作加法操作和移位,这个加法相当于加上8a的值,因为a的值已经左移了三次。
一般而言,设y=y0,y l y2…y n为被乘数,x为乘数,y i是a中的第i位(当前位)。根据y j 与y i+1的值,Booth算法表示如下表所示,其操作流程如下图所示。在Booth算法中,操作的方式取决于表达式(y i+1-y i)的值,这个表达式的值所代表的操作为:
0 无操作
+1 加x
-1 减x
Booth算法操作表示
y i y i+1操作说明
0 0 无处于0串中,不需要操作
0 1 加x 1串的结尾
1 0 减x 1串的开始
1 1 无处于1串中,不需要操作
乘法器的设计要真正实现比较复杂,我的设计也只能是大概地实现其功能,所以对移位相加,就没有在详细地编写程序。
不管怎么样这次设计我还是收获颇丰,由于本科不是这个专业,所以在变成方面相当有欠缺。在设计过程中漏洞百出,经过长时间调试终于解决所有问题。下面是我总结的一些修改谬误的经验,总结的相当不全面,请多见谅:
在编程中的错误小结:
always @ (posedge sclk or negedge rst) // Bring the clock scl by way of sclk
begin //And the frequency of scl is half of sclk's
if (!rst)
scl<=1;
else
scl<=~sclk; !!!!!正确应该为scl<=~scl;
end
该错误的后果是导致scl的输出波形一直为1,不能实现对sclk的2分频
在模拟波形的时候将会出现错误!!!注意在写分频程序的时候应该避免此类错误。
2)在line_data_singdate.v 中单词singdate 被写成sigdate,该错误导致在top文件中的singdata mo(.sclk(sclk),.data(data),.d_ena(d_ena));
语句中将出现未定义的错误。
3)为语法错误,在循环或条件语句中,应该让这些语句的头尾对应出现,是个好习惯否则在程序较长的时候可能会漏掉end语句。
** Error: E:/verilog/16_adder/main_programme.v(72): Undefined variable: b0.
错误之处
always@(P[0]or G[0] or P[1] or G[1] or P[2] or G[2] or P[3] or 1‘b0) always敏感变量中不应该有常数值
begin
CP[0]<=G[0]|(P[0]&1’b0); 此处1’b0 不多余不应该存在下同
CP[1]<=G[1]|(P[1]&G[0])|(P[1]&P[0]&1’b0);
CP[2]<=G[2]|(P[2]&G[1])|(P[2]&P[1]&G[0])|(P[2]&P[1]&P[0]&1’b0);
** Error: E:/verilog/16_adder/main_programme.v(73): near ")": syntax error
在上述错误修正之后该错误消失,说明该错误为有其他错误所引起的。
// bring result,
always@(P_sec or G_sec or CP)
begin
if(!rst)
sum[64:0]<=65'b0;
else
sum[64:0]<={CP[63],(P[63:0]^{1'b0,CP[62:0]})}; 此处的错误要尽量避免位数上对应不上P的最底位应与1‘b0相异或。应注意在高低位安排上要保持一致。
end
endmodule