您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > 64位乘法器实验报告
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,yly2…yn为被乘数,x为乘数,yi是a中的第i位(当前位)。根据yj与yi+1的值,Booth算法表示如下表所示,其操作流程如下图所示。在Booth算法中,操作的方式取决于表达式(yi+1-yi)的值,这个表达式的值所代表的操作为:0无操作+1加x-1减xBooth算法操作表示yiyi+1操作说明00无处于0串中,不需要操作01加x1串的结尾10减x1串的开始11无处于1串中,不需要操作乘法器的设计要真正实现比较复杂,我的设计也只能是大概地实现其功能,所以对移位相加,就没有在详细地编写程序。不管怎么样这次设计我还是收获颇丰,由于本科不是这个专业,所以在变成方面相当有欠缺。在设计过程中漏洞百出,经过长时间调试终于解决所有问题。下面是我总结的一些修改谬误的经验,总结的相当不全面,请多见谅:在编程中的错误小结:always@(posedgesclkornegedgerst)//Bringtheclocksclbywayofsclkbegin//Andthefrequencyofsclishalfofsclk'sif(!rst)scl=1;elsescl=~sclk;!!!!!正确应该为scl=~scl;end该错误的后果是导致scl的输出波形一直为1,不能实现对sclk的2分频在模拟波形的时候将会出现错误!!!注意在写分频程序的时候应该避免此类错误。2)在line_data_singdate.v中单词singdate被写成sigdate,该错误导致在top文件中的singdatamo(.sclk(sclk),.data(data),.d_ena(d_ena));语句中将出现未定义的错误。3)为语法错误,在循环或条件语句中,应该让这些语句的头尾对应出现,是个好习惯否则在程序较长的时候可能会漏掉end语句。**Error:E:/verilog/16_adder/main_programme.v(72):Undefinedvariable:b0.错误之处always@(P[0]orG[0]orP[1]orG[1]orP[2]orG[2]orP[3]or1‘b0)always敏感变量中不应该有常数值beginCP[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):syntaxerror在上述错误修正之后该错误消失,说明该错误为有其他错误所引起的。//bringresult,always@(P_secorG_secorCP)beginif(!rst)sum[64:0]=65'b0;elsesum[64:0]={CP[63],(P[63:0]^{1'b0,CP[62:0]})};此处的错误要尽量避免位数上对应不上P的最底位应与1‘b0相异或。应注意在高低位安排上要保持一致。endendmodule在编写程序的过程中添加新的输入或输出时要注意以下几点:以我在设计中加入输入信号sel信号为例1)在主程序中需要加入sel的程序块中加入sel,切记以下是容易遗漏的地方,若always块中出现sel,则always的敏感信号中也必须有sel。2)在testbench中也要有该信号的输出,并且要记住在sixty_adderm0(.X(X),.Y(Y),.sum(sum),.clk(clk),.rst(rst),.sel(sel));语句中也要把sel添加进去。在检查输出一直为0错误时的一些办法,对于这类错误系统在编译的时候没有报错,说明不是语法问题。检查起来比较困难,经我的分析,输出一直为0可能由以下几点原因造成的。1)可能乘法器的输入一直为0,在本程序中乘法器的输入是由sel选通实现的,由于sel信号还同时控制加法器的输入信号,而加法器工作正常,说明sel选通输入的程序没有问题。2)还有一个原因就是乘法器一直处于复位状态,但检查之后发现复位信号一切正常。3)能让乘法器一直为0扎还有一种可能。就是在case语句的最后default语句中乘法器的输入被一直置0,若问题出在此处,说明case语句的条件一直不成立,也就是说问题可能发生在case上。经检查发现case({Y_tmp1[0],aid})出现了问题,由于aid信号为4位信号,而定义的状态信号为两位,因此case的状态就一直是defaule,问题找到正确语句应改为case({Y_tmp1[0],aid[1]}),次错误比较不显眼,需要对程序进行仔细分析才能找到。
本文标题:64位乘法器实验报告
链接地址:https://www.777doc.com/doc-4870578 .html