zoukankan      html  css  js  c++  java
  • Verilog 加法器和减法器(8)-串行加法器

          如果对速度要求不高,我们也可以使用串行加法器。下面通过状态机来实现串行加法器的功能。

         设A=an-1an-2…a0, B=bn-1bn-2…b0,是要相加的两个无符号数,相加的和为:sum=sn-1sn-2…s0。我们现在要设计一个电路,在时钟周期内处理一位相加的串行加法。加法过程一开始进行a0,b0的相加,在下一个时钟周期完成 a1,b1和第0位进位的相加,并依次完成所有的加法。

          下图的方案中,3个移位寄存器用来保存A,B以及和Sum。假设这些寄存器有并行加载功能,先将加A,B的值载入这些寄存器,在时钟的每个周期,通过加法器FSM控制每位相加,在周期的最后把输出的结果移入Sum寄存器。我们使用上升沿触发的触发器,这样所有数据在时钟的上升沿及各个触发器的传播延迟后发生变化,此时三个移位寄存器内容右移:将加法结果移入Sum,并将下一对 ai,bi加载至加法器FSM。


    image


          下面是加法器FSM的图:

    image



          我们来设计状态机,假设有两个状态:状态G,进位为0,状态H,进位为1。则状态图如下,输出s取绝与当前状态(进位)和输入a,b的值,所以这是mealy型状态机。

          在状态G中,输入00,则仍在状态G,输出为0,为01和10时候,仍在状态G,输出为1,如果输入为11,则转到状态H,输出0。

          在状态H中,输入11,仍在状态H,输出1,输入为01和10时候,仍在状态H,输出为0,如果输入为00,则转到状态G,输出为1。


    image


       这个mealy型串行加法器的状态表如下:

       根据状态表,利用卡诺图简化,有下列表达式,显然它就是全加器的输出表达式。

            Y = ab+ay+by

            s = a^b^y


    现在状态 下一状态(ab) 输出s
    00 01 10 11 00 01 10 11
    G G G G H 0 1 1 0
    H G H G G 1 0 0 1


    现在状态 下一状态(ab) 输出(ab)
    00 01 11 10 00 01 11 10
    y Y s
    0 0 0 1 0 0 1 0 1
    1 0 1 1 1 1 0 1 0

          下面是verilog实现代码,首先是移位寄存器的代码,该移位寄存器带有使能输入E,E=1时,寄存器的内容将在时钟的上升沿开始从左到右。E=0,可以阻止移位寄存器内容发生改变。

    module shiftrne(R,L,E,w,clk,Q);
    
       parameter n=8;
    	input [n-1:0] R;
    	input L,E,w,clk;
    	output reg [n-1:0] Q;
    
    	integer k;
    
    	always @(posedge clk) begin
    	   if(L)
    		  Q<=R;
    		else if(E) begin
    		   for(k=n-1; k>0; k=k-1)
    			   Q[k-1] <= Q[k];
    			Q[n-1] <=w;
    		end
    
    
    	end
    
    
    endmodule

    下面是mealy型串行加法的代码,代码中首先例化了三个移位寄存器。代码中还包括一个递减计数器,用来完成n位加法并输出至移位寄存器后,停止加法器。

    代码中我们采用高电平复位信号。输出端的使能信号为Run信号,只要Run信号为1,递减计数器每个时钟周期都会递减。

    module serialadd(A,B,Rst,clk,S);
      input [7:0] A,B;
      input Rst,clk;
      output wire [7:0] S;
    
      reg [3:0] Count;
      reg s,y,Y;
      wire [7:0] QA,QB;
      wire Run;
      parameter G=1'b0, H=1'b1;
    
      shiftrne #(.n(8)) shift_A(.R(A),.L(Rst),.E(1'b1),.w(1'b0),.clk(clk),.Q(QA));
      shiftrne #(.n(8)) shift_B(.R(B),.L(Rst),.E(1'b1),.w(1'b0),.clk(clk),.Q(QB));
      shiftrne #(.n(8)) shift_S(.R(8'b0),.L(Rst),.E(Run),.w(s),.clk(clk),.Q(S));
    
      //adder FSM
      //output and next state cominatioal circuit
    
      always @(QA,QB,y) begin
    
          case (y)
    		  G:
    		  begin
    		    s = QA[0]^QB[0];
    			 if(QA[0]&QB[0]) Y=H;
    			 else  Y=G;
    
    		  end
    		  H:
    		  begin
    		    s = QA[0]~^QB[0];
    			 if(~QA[0]&~QB[0]) Y=G;
    			 else  Y=H;
    
    		  end
    		 default:
    		    Y  = G;
    		endcase
      end
    
      //sequential block
      always @(posedge clk)
        if(Rst)
    	   y<=G;
    	 else
    	    y<=Y;
    
      //control shift proecess
      always @(posedge clk)
        if(Rst) Count=8;
    	 else if(Run) Count = Count-1;
    
      assign Run = |Count;
    endmodule


    testbench代码为:

    `timescale 1ns/1ns
    `define clock_period 20
    
    module serialadd_tb;
     reg clk;
     reg Rst;
    
     reg [7:0] A,B;
     wire [7:0] S;
    
     serialadd serialadd0(.A(A),.B(B),.Rst(Rst),.clk(clk),.S(S));
     //serialadd_moore serialadd_moore0(.A(A),.B(B),.Rst(Rst),.clk(clk),.S(S));
     always #(`clock_period/2) clk = ~clk;
    
     initial begin
       clk=0;
       A = 8'd35;
    	B = 8'd99;
    	Rst = 0;
    	#(`clock_period)
    	Rst = 1;
    	#(`clock_period)
    	Rst = 0;
    
    	#(`clock_period*10)
    
       $stop;
    
     end
    
    
    
    
    endmodule


    下面是mealy型串行加法的波形,输入35,99,输出134

    image


        我们把状态图做如下调整,拆分G为G0,G1,拆分H为H0,H1, 则输出之和状态有关,为moore型串行加法器状态图。

    image



    下面是该状态机的状态表:



    现在状态 下一状态(ab) 输出
    00 01 10 11 s
    G0 G0 G1 G1 H0 0
    G1 G0 G1 G1 H0 1
    H0 G1 H0 H0 H1 0
    H1 G1 H0 H0 H1 1


    现在状态 下一状态(ab) 输出
    00 01 10 11 s
    y2y1 Y2Y1
    00 00 01 01 10 0
    01 00 01 01 10 1
    10 01 10 10 11 0
    11 01 10 10 11 1

    可以推导出

    Y1=a^b^y2

    Y2=ab+ay2+by2

    s=y1

    下面是其可能的实现电路。moore型加法输出比mealy型加法多了一个时钟周期的时延。

    image


    moore型串行加法器verilog代码如下,其中也例化了3个移位寄存器。注意Count复位后为9,

    module serialadd_moore(A,B,Rst,clk,S);
      input [7:0] A,B;
      input Rst,clk;
      output wire [7:0] S;
    
      reg [3:0] Count;
      reg [1:0] y,Y;
      wire [7:0] QA,QB;
      wire s,Run;
      parameter G0=2'b00, G1=2'b01,H0=2'b10, H1=2'b11;
    
      shiftrne #(.n(8)) shift_A(.R(A),.L(Rst),.E(1'b1),.w(1'b0),.clk(clk),.Q(QA));
      shiftrne #(.n(8)) shift_B(.R(B),.L(Rst),.E(1'b1),.w(1'b0),.clk(clk),.Q(QB));
      shiftrne #(.n(8)) shift_S(.R(8'b0),.L(Rst),.E(Run),.w(s),.clk(clk),.Q(S));
    
      //adder FSM
      //output and next state cominatioal circuit
    
      always @(QA,QB,y) begin
    
          case (y)
    		  G0:
    		  begin
    			 if(QA[0]&QB[0]) Y=H0;
    			 else if(~QA[0]&~QB[0]) Y=G0;
    			 else  Y=G1;
    
    		  end
    		  G1:
    		  begin
    			 if(~QA[0]&~QB[0]) Y=G0;
    			 else if (QA[0]&QB[0])Y=H0;
    			 else  Y=G1;
    
    		  end
    		  H0:
    		  begin
    			 if(QA[0]&QB[0]) Y=H1;
    			 else if(~QA[0]&~QB[0]) Y=G1;
    			 else  Y=H0;
    
    		  end
    		  H1:
    		  begin
    			 if(~QA[0]&~QB[0]) Y=G1;
    			 else if (QA[0]&QB[0])Y=H1;
    			 else  Y=H0;
    
    		  end
    		endcase
      end
    
      //sequential block
      always @(posedge clk)
        if(Rst)
    	   y<=G0;
    	 else
    	    y<=Y;
    
      //control shift proecess
      always @(posedge clk)
        if(Rst) Count=9;
    	 else if(Run) Count = Count-1;
    
      assign Run = |Count;
      assign s = (y==H0?1'b0:(y==G0?1'b0:1'b1));
    endmodule
    `timescale 1ns/1ns
    `define clock_period 20
    
    module serialadd_tb;
     reg clk;
     reg Rst;
    
     reg [7:0] A,B;
     wire [7:0] S;
    
     //serialadd serialadd0(.A(A),.B(B),.Rst(Rst),.clk(clk),.S(S));
     serialadd_moore serialadd_moore0(.A(A),.B(B),.Rst(Rst),.clk(clk),.S(S));
     always #(`clock_period/2) clk = ~clk;
    
     initial begin
       clk=0;
       A = 8'd35;
    	B = 8'd99;
    	Rst = 0;
    	#(`clock_period)
    	Rst = 1;
    	#(`clock_period)
    	Rst = 0;
    
    	#(`clock_period*10)
    
       $stop;
    
     end
    
    
    
    
    endmodule

    输出波形为:

    image

  • 相关阅读:
    nginx 通过状态码判断url该怎么走
    php报错大全
    带有空格的字符串传给脚本当参数
    shell 命令行参数
    将图片画到canvas 上的几种方法(转)
    JS 中document.write()的用法和清空的原因浅析(转)
    网页调试js时,如何知道某个事件对应哪段js代码?
    格式化JS代码
    js new到底做了什么?如何重写new?(转)
    理解javascript中的立即执行函数(function(){})()(转)
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/10309202.html
Copyright © 2011-2022 走看看