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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM