状态机实例-寄存器拷贝

      在计算机系统中,有大量的寄存器,用来保存运行过程中的数据。如果要交换两个寄存器的内容,则通常会使用第三个寄存器为临时寄存器的方法。比如,假设要交换寄存器R1,R2的内容,可以先将R2的内容传递到第三个寄存器R3,然后将R1的内容传到R2,最后将R3的内从传递到R1。

      计算机系统的存储器通常是通过下图所示的内部网络互联的。除了与网络互联的信号线,每个寄存器还有两个控制信号,Rkout和Rkin。Rkout使得寄存器Rk的内容传输至互联网络,Rkin信号使得互联网络上的数据传输至寄存器Rk。Rkout和Rkin通过有限状态机控制电路产生。在下图电路中,我们设计当w=1时候,交换寄存器R1和R2的内容,数据交换完成时候输出Done信号。Clock是时钟信号。

image


      数据转换过程如下步骤:控制信号R2out=1,R3in=1, R2的内容传到到R3,然后R1out=1,R2in=1,R1的内容传输到R2,最后,R3out=1,R1in=1,R3的内容传输到R1,完成两个寄存器内容交换,交换完成后,设置信号Done=1。假设交换的初始条件是产生一个时钟周期的脉冲信号,则时序电路状态图如下。

      初始状态A中,没有信号传输,所有的输出信号为0,电路一直保持该状态,直到w变为1产生交换请求。在状态B中,执行R2的内容传输到R3中的请求信号生效,数据在下一个时钟有效沿传送至R3。不管w为0或者1,在这个时钟沿也使得状态进入C。在状态C中,执行R1的内容传输到R2中的请求信号生效,数据在下一个时钟有效沿传送至R2。不管w为0或者1,在这个时钟沿也使得状态进入D。在状态D中,执行R3的内容传输到R1中的请求信号生效,数据在下一个时钟有效沿传送至R1。不管w为0或者1,在这个时钟沿也使得状态进入A。


image

      由于有4个状态,所以需要2个状态变量y1,y2,最直接的分配是将状态A,B,C,D分别分配为y2y1=00,01,10,11。下面的是该电路的状态表


现在状态 下一状态 输出
w=0 w=1 R1out R1in R2out R2in R3out R3in Done
A A B 0 0 0 0 0 0 0
B C C 0 0 1 0 0 1 0
C D D 1 0 0 1 0 0 0
D A A 0 1 0 0 1 0 1


现在状态 下一状态 输出
w=0 w=1
y2y1 Y2Y1 Y2Y1 R1out R1in R2out R2in R3out R3in Done
A 00 00 01 0 0 0 0 0 0 0
B 01 10 10 0 0 1 0 0 1 0
C 10 11 11 1 0 0 1 0 0 0
D 11 00 00 0 1 0 0 1 0 1


Y1 Y1=w~y1+y2~y1
w/y2y1 00 01 11 10
0 0 0 0 1
1 1 0 0 1
Y2 Y2=~y2y1+y2~y1
w/y2y1 00 01 11 10
0 0 1 0 1
1 0 1 0 1

image

image

根据这些状态表,我们可以得到如下的输出表达式:

Y1=w~y1+y2~y1

Y2=~y2y1+y2~y1

R2out=R3in=~y2y1

R1out=R2in=y2~y1

R1in=R3out=Done=y2y1

实现的时序电路如下:

image


如果我们用10表示D,11表示C,则状态表如下:

现在状态 下一状态 输出
w=0 w=1
y2y1 Y2Y1 Y2Y1 R1out R1in R2out R2in R3out R3in Done
A 00 00 01 0 0 0 0 0 0 0
B 01 11 11 0 0 1 0 0 1 0
C 11 10 10 1 0 0 1 0 0 0
D 10 00 00 0 1 0 0 1 0 1


Y1的真值表:

w/y2y1 00 01 11 10
0 0 1 0 0
1 1 1 0 0

image

Y2的真值表:

w/y2y1 00 01 11 10
0 0 1 1 0
1 0 1 1 0


image

通过卡诺图简化,最终得到如下表达式,相比上面的表达式,这个实现方式要简单一点。

Y1=w~y2+~y2y1=(w+y1)~y2

Y2=y1

R2out=R3in=~y2y1

R1out=R2in=y2y1

R1in=R3out=Done=y2~y1

实现的电路图如下:


image


如果用独热码表示状态,则需要四个触发器。用独热码表示的状态表为:


现在状态 下一状态 输出
w=0 w=1
y4y3y2y1 Y4Y3Y2Y1 Y4Y3Y2Y1 R1out R1in R2out R2in R3out R3in Done
A 0001 0001 0010 0 0 0 0 0 0 0
B 0010 0100 0100 0 0 1 0 0 1 0
C 0100 1000 1000 1 0 0 1 0 0 0
D 1000 0001 0001 0 1 0 0 1 0 1

      我们可以从状态框图中推导出输出表达式:

      不包括复位,有两个弧线进入状态A,这两个弧线表明,如果FSM已经在状态A,且w=0时,触发器y1应该被设置为1,或者FSM已经在状态D,所以Y1=~wy1+y4,同理,如果现在状态时A,且w=1,则触发器y2被设置为1,从而Y2=wy1,如果当前状态是B或C,触发器y3和y4分别被设置为1,从而Y3=y2,Y4=Y3。输出表达式如下:


R1out=R2in=y3

R1in=R3out=Done=y4

R2out=R3in=y2

     通常用独热码表示,虽然用的触发器数量可能增多,但得到的输出表达式则相对简单,相应组合电路的实现变得简单了。


image


采用独热码的实现电路为:

image





      moore型寄存器交换的verilog代码如下:

module st_moore(clk, Rst_n, w, R1in,R1out,R2in,R2out,R3in,R3out,Done);
  input clk;
  input Rst_n;
  input w;
  output R1in,R1out,R2in,R2out,R3in,R3out,Done;
  reg [1:0] y,Y;
  parameter [1:0] A=2'b00,B=2'b01,C=2'b10,D=2'b11;

  //得到下一个状态的组合电路
  always @(w,y) begin

    case(y)
	   A:
	   	if(w)
			  Y=B;
			else
			  Y=A;
		B: Y=C;
		C: Y=D;
		D: Y=A;
	 endcase
  end

  always @(posedge clk, negedge Rst_n)
    if(Rst_n==0)
	   y<=A;
	 else
	   y<=Y;

  //定义输出
  assign R2out=(y==B);
  assign R3in=(y==B);
  assign R1out=(y==C);
  assign R2in=(y==C);
  assign R3out=(y==D);
  assign R1in=(y==D);
  assign Done=(y==D);

endmodule

testbench代码:

`timescale 1ns/1ns
`define clock_period 20

module regswap_tb;

  reg clk=0;
  reg Rst_n;
  reg w;
  wire R1in,R1out,R2in,R2out,R3in,R3out,Done;

  st_moore st_moore0(.clk(clk),.Rst_n(Rst_n),.w(w),.R1in(R1in),.R1out(R1out),.R2in(R2in),.R2out(R2out),.R3in(R3in),.R3out(R3out),.Done(Done));
  always #(`clock_period/2) clk=~clk;

  initial begin
    Rst_n=1;
	 w=0;
	 #(`clock_period)
	 w=1;
	 Rst_n=0;
	 #(`clock_period)
	 Rst_n=1;
	 #(`clock_period*20)
	 $stop;

  end



endmodule


生成的波形图为:

image


      mealy型寄存器交换状态机如下,状态A仍为复位状态,只要w从0变为1,输出控制信号R2out,R3in就被置位。它们将保持置位直到下一个时钟周期电路离开状态A,进入状态B。在状态B中,不管w=0或是1,输出控制信号R1out,R2in都被置位,最后,在状态C中,通过R3out=1,R1in=1完成交换,并置位Done=1。与moore时钟电路相比,mealy型实现的信号输出要早一个时钟周期。因为有3个状态,所以也需要2个触发器。

      如果采用独热码,则需要3个触发器。状态A,B,C分别取值为y3y2y1=001,y3y2y1=010,y3y2y1=100,类似moore型独热码信号输出公式,我们也可以得到mealy信号输出公式:

     Y1=~wy1+y3

     Y2=wy1

     Y3=y2

     R1out=R2in=y2

     R1in=R3out=Done=y3

     R2out=R3in=y1

image



mealy型的寄存器交换verilog代码为

module st_mealy(clk, Rst_n, w, R1in,R1out,R2in,R2out,R3in,R3out,Done);
  input clk;
  input Rst_n;
  input w;
  output reg R1in,R1out,R2in,R2out,R3in,R3out,Done;
  reg [1:0] y,Y;
  parameter [1:0] A=2'b00,B=2'b01,C=2'b10;

  //得到下一个状态的组合电路
  always @(w,y) begin

    case(y)
	   A:
	   	if(w) begin
			  Y=B;
			  R2out=1;
			  R3in=1;
			  R3out=0;
		     R1in=0;
		     Done=0;
			end
			else
			  Y=A;
		B:
		begin
		  Y=C;
		  R2out=0;
		  R3in=0;
		  R1out=1;
		  R2in=1;
		end
		C:
		begin
		  Y=A;
		  R1out=0;
		  R2in=0;
		  R3out=1;
		  R1in=1;
		  Done=1;
		end
		default:
		begin
		  Y=2'bxx;
		  R2out=1'bx;
		  R3in=1'bx;
		  R1out=1'bx;
		  R2in=1'bx;
		  R3out=1'bx;
		  R1in=1'bx;
		  Done=1'bx;
		end
	 endcase
  end

  always @(posedge clk, negedge Rst_n)
    if(Rst_n==0)
	   y<=A;
	 else
	   y<=Y;


endmodule

testbench代码为

`timescale 1ns/1ns
`define clock_period 20

module regswap_tb;

  reg clk=0;
  reg Rst_n;
  reg w;
  wire R1in,R1out,R2in,R2out,R3in,R3out,Done;

    st_mealy st_mealy0(.clk(clk),.Rst_n(Rst_n),.w(w),.R1in(R1in),.R1out(R1out),.R2in(R2in),.R2out(R2out),.R3in(R3in),.R3out(R3out),.Done(Done));

  always #(`clock_period/2) clk=~clk;

  initial begin
    Rst_n=1;
	 w=0;
	 #(`clock_period)
	 w=1;
	 Rst_n=0;
	 #(`clock_period)
	 Rst_n=1;
	 #(`clock_period*20)
	 $stop;

  end

image















































posted on 2019-01-20 13:19  迈克老狼2012  阅读(840)  评论(0编辑  收藏  举报

导航