博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
状态机实例-寄存器拷贝
阅读量:5954 次
发布时间:2019-06-19

本文共 5135 字,大约阅读时间需要 17 分钟。

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

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

      数据转换过程如下步骤:控制信号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。

      由于有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

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

Y1=w~y1+y2~y1

Y2=~y2y1+y2~y1

R2out=R3in=~y2y1

R1out=R2in=y2~y1

R1in=R3out=Done=y2y1

实现的时序电路如下:

如果我们用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

Y2的真值表:

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

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

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

Y2=y1

R2out=R3in=~y2y1

R1out=R2in=y2y1

R1in=R3out=Done=y2~y1

实现的电路图如下:

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

现在状态 下一状态 输出
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

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

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

      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 20module 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;  endendmodule

生成的波形图为:

      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

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 20module 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

转载于:https://www.cnblogs.com/mikewolf2002/p/10294647.html

你可能感兴趣的文章
python学习之网络编程
查看>>
64位Java开发平台的选择,如何区分JDK,Tomcat,eclipse的32位与64版本
查看>>
谈Win32汇编
查看>>
sqlserver_identity
查看>>
其他的AdapterView——Spinner
查看>>
iOS UIWebView打电话
查看>>
java高质量图片压缩
查看>>
源码解读Linux的limits.conf文件
查看>>
cisco 增强型内部网关路由协议EIGRP笔记
查看>>
exchange 2010 无人值守安装
查看>>
java this关键字的使用
查看>>
linux基础1
查看>>
Google地球查看香港地形
查看>>
jquery之统计数字parseFloat
查看>>
20161121
查看>>
Nginx服务器开启gzip压缩功能额必要性
查看>>
ZeroMQ研究与应用分析
查看>>
Linux基础命令--grep/find
查看>>
NTFS(Windows)、ext4(RHEL6)和xfs(RHEL7)文件系统的误删除恢复和备份
查看>>
[python] raw string,反斜杠\,re Lib
查看>>