1、 output 15 :0 sum; output cout ; reg cout ; reg cout1 ; reg7 :0 sum1 ; reg15 : always (posedge clk) begin / 低8 位相加;cout1 , sum1 = cina 7, cina 7 : 0 + cinb7, cinb 7 : 0 +cin ; end always (posedge clk) begin / 高8 位相加,并连成16位cout ,sum = cina 15, cina 15 :8 + cinb 15, cinb15 :8 + cout1 , sum1 ;endmodule
2、上述程序经过synplify Pro综合后,得到如图2-22所示的RTL级结构图。2-22 16位加法器的RTL结构图在ModelSim 6.2b中完成仿真,其结果如图2-23所示,正确地实现了16比特加法。图2-23 16位加法器的RTL结构图2乘法器的Verilog实现串行乘法器两个N位二进制数x 、y 的乘积,最简单的方法就是利用移位操作来实现,用公式可以表示为: (2.3)这样输入量随着k的位置连续地变化,然后累加。例2-25 用Verilog实现一个8位串行乘法器module ade (clk, x, y, p);input clk;input 7:0 x, y;output 15:
3、0 p;reg 15:parameter s0=0, s1=1, s2=2;reg 2:0 count;reg 1:0 state;0 p1, t; / 比特位加倍reg 7:0 y_reg;always (posedge clk) begin case (state)s0 : begin / 初始化y_reg = y;state = s1;count = 0; p1 = 0;t = 8x7,x;ends1 : begin / 处理步骤if (count = 7) /判断是否处理结束= s2;else beginif (y_reg0 = 1)p1 1; /移位= t count = count
4、 + 1;s2 : begin p = p1; state = s0;endcase上述程序在Synplify Pro中综合后,得到如图2-24所示的RTL级结构示意图。图2-24 串行乘法器的RTL结构图图2-25给出了串行乘法器模块在ModelSim中的仿真结果,验证了功能的正确性。图2-25 串行乘法器的局部仿真结果示意图从仿真结果可以看出,上述串行乘法器,速度比较慢,时延很大,但这种乘法器的优点是所占用的资源是所有类型乘法器中最少的,在低速的信号处理中有着广泛的应用。流水线乘法器一般的快速乘法器通常采用逐位并行的迭代阵列结构,将每个操作数的N位都并行地提交给乘法器。但是一般对于FPGA
5、来讲,进位的速度快于加法的速度,这种阵列结构并不是最优的。所以可以采用多级流水线的形式,将相邻的两个部分乘积结果再加到最终的输出乘积上,即排成一个二叉树形式的结构,这样对于N位乘法器需要log2(N)级来实现。一个8位乘法器,如图2-26所示。图2-26流水线乘法器结构图例2-26 用Verilog HDL实现一个4位的流水线乘法器module mul_addtree(mul_a, mul_b, mul_out, clk, rst_n);parameter MUL_WIDTH = 4; parameter MUL_RESULT = 8; input MUL_WIDTH-1 : 0 mul_a;
6、 0 mul_b; input clk; input rst_n; output MUL_RESULT-1 : 0 mul_out; reg MUL_RESULT-1 : 0 stored0; 0 stored1; 0 stored2; 0 stored3; 0 add01; 0 add23; always (posedge clk or negedge rst_n) if(!rst_n)begin /初始化寄存器变量mul_out = 8b0000_0000;stored0 stored1 stored2 stored3 add01 add23 elsebegin /实现移位相加= mul_
7、b3?1b0,mul_a,3b0: 8b0;= mul_b2?2b0,mul_a,2= mul_b1?3b0,mul_a,1= mul_b0?4b0,mul_a:add01 = stored1 + stored0;add23 = stored3 + stored2;= add01 + add23;上述程序在Synplify Pro软件中综合后,得到如图2-27所示的RTL级结构示意图。图2-27 流水线乘法器的RTL结构示意图图2-28给出了流水线乘法器模块在ModelSim中的仿真结果,验证了功能的正确性。图2-28 流水线乘法器的局部仿真结果示意图从仿真结果可以看出,上述流水线乘法器比串行
8、加法器的速度快很多,在非高速的信号处理中有着广泛的应用。至于高速信号的乘法一般需要利用FPGA芯片中内嵌的硬核DSP单元来实现。3无符号除法器的Verilog实现两个无符号二进制数(如正整数)相除的时序算法是通过“减并移位”的思想来实现的,即从被除数中重复地减去除数,直到已检测到余数小于除数。这样可以通过累计减法运算的次数而得到商;而余数是在减法运算结束时被除数中的剩余值。当除数较小时,这种基本电路都必须进行多次减法,因此效率都不高。图2-29给出了一种更加高效的除法器基本结构3。在进行两个数相除的运算时,通常采用的步骤是调整除数与被除数使其最高位相对齐,然后反复地从被除数中减去除数,并将除数
9、向被除数的最低位移动,且在高效除法器结构中可以并行运行这些操作步骤。而在具体的硬件实现中,是通过将被除数寄存器的内容不断地向除数的最高位移动来完成除法运算的。无符号二进制字自调整除法器在设计除法器结构的过程中应特别小心。在图中的减法运算步骤中,必须要将除数和被除数对齐,这取决于它们的相应大小和每个字的最高一位1的相对位置。同样,被除数寄存器也应向左扩展一位,以适应可能出现的已调整的除法寄存器内容初始值超过被除数寄存器中相应4位值的情况,在这种情况下,在进行减法操作之前,应从被除数的最高位移出一个1。例如(1100)2与(0111)2相除,应首先将被除数向左移,为下一步减法运算调整好被除数。因此
10、,该机器的控制器会变得更加复杂,而且要包括能使除数和被除数移动的控制信号,如图2-29所示。该物理结构将调整除数字与被除数的8位数据通道中的最左边4位对齐。在操作中,被除数字不断地从右向左移动,而且每一步都要从已调整的被除数的相应位中减去除数,这种操作取决于除数是否比被除数选定部分的对应值小。调整机器使得从被除数中减去的不是除数而是除数与2的幂的最大乘积,这样在当除数较小时就可以消去一些需要重复进行的减法运算。这种调整被称为是自调整的,因为它在一个除法运算序列的开始就能自动判断是否需要调整除数或被除数,这取决于它们最左非0位的相对位置。在除法运算中经常性地启动对两个字的调整使得其最高位为1的方
11、法效率较低,因为这可能会需要更多的移位。所采用的方法是在一开始就将除数移到被除数的最左非0位(而不是被除数的最低位)。有两种需要对数据通路字进行初始调整的情况:(1)被除数最左4位的值小于除数的值(例如(1100)2除以(1110)2),(2)除数的最低位为0,同时除数字节可以向左移动,而且仍然可以去除被除数(例如(1100)2除以(0101)2)。对于前者,应将被除数依次向左移动1位直到扩展1位的被除数的最左5位等于或大于除数,或者直到不能再移位为止。而对于后者,则应将除数向左移直到再移动所得到的字节不能去除被除数字节的最左4位为止(不包括扩展位)。余数位在除法运算序列结束时的物理位置取决于
12、被除数是否进行了移位调整。因此,可将调整移位记录下来,并用来控制状态机调整在执行序列结束后的余数值。图2-30给出了自调整除法器的状态转移图3。在一个给定状态下,从一个状态节点出发的支路中所使用的控制标记仅适于该支路,而在其他没有明确使用该标记离开当前状态的支路中被视为是不成立的。在任何离开一个状态节点的支路中都没有出现的标记被认为是无关紧要的。只有S_idle状态下才会给出复位信号,而在其他的所有状态上复位信号均被视为是异步动作。该机器的状态与它的动作有关。S_Adivr状态下Shift_divisor的动作是将除法调整到被除数的最高非0位;S_Adivr状态下Shift_dividend的
13、动作将调整被除数寄存器以进行减法运算;S_div状态下同时进行实际的减法运算和许多移位操作。状态S_Adivn和S_Adivr下变量Max将检测所允许的最大移位何时发生。图2-30 自调整除法器的状态转移图例2-27 用Verilog实现一个被除数为8位,除数为4位的高效除法器module divider(clock,reset,word1,word2,Start,quotient,remainder,Ready,Error); parameter L_divn = 8; parameter L_divr = 4;parameter S_idle = 0, S_Adivr = 1, S_Adi
14、vn = 2, S_div = 3, S_Err =4; parameter L_state = 3, L_t = 4, Max_t = L_divn - L_divr;input L_divn-1 : 0 word1; /被除数数据通道input L_divr-1 : 0 word2; /除数数据通道 input Start, clock, reset; output L_divn-1 : 0 quotient; /商 0 remainder; /余数output Ready, Error; reg L_state-1 : 0 state, next_state; reg Load_word
15、s, Subtract, Shift_dividend, Shift_divisor;reg L_divn-1 : reg L_divn : 0 dividend; /扩展的被除数 reg L_divr-1 : 0 divisor;reg L_t-1 : 0 num_shift_dividend, num_shift_divisor; reg L_divr : 0 parison; wire MSB_divr = divisorL_divr-1; wire Ready = (state = S_idle) & !reset); wire Error = (state = S_Err); wir
16、e Max = (num_shift_dividend= Max_t + num_shift_divisor); wire sign_bit = parisonL_divr;always(state or dividend or divisor or MSB_divr) begin /从被除数中减去除数 case(state) S_Adivr: if(MSB_divr = 0)parison = dividendL_divn : L_divn - L_divr +1b1, (divisor 1) + 1b1; L_divn - L_divr+ 1b1,divisorL_divr-1 : 0 +
17、 1default: parison = dividendL_divn :b1, divisorL_divr-1 : endcase/将余数移位来对应于整体的移位assign remainder = (dividendL_divn-1 : L_divn-L_divr) - num_shift_divisor;always(posedge clock) begin if(reset)= S_idle;= next_state;/次态与控制逻辑always(state or word1 or word2 or state or parison or sign_bit or Max) begin L
18、oad_words = 0; Shift_dividend = 0; Shift_divisor = 0; Subtract = 0;case(state) S_idle: case(Start)0: next_state = S_idle;1: if(word2 = 0) next_state = S_Err; else if(word1) begin next_state = S_Adivr; Load_words = 1; case(MSB_divr) 0: if(sign_bit = 0) begin Shift_divisor = 1; /可移动除数 else if(sign_bit = 1) begin next_state = S_Adivn; /不可移动除数 next_state = S_div; S_Adivn: case(Max, sign_bit)2b00:b01: Shift_dividend = 1;b10: Subtract = 1;b11: S_div: 2next_state = S_div; next_state =
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1