教案状态机文档格式.docx
《教案状态机文档格式.docx》由会员分享,可在线阅读,更多相关《教案状态机文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
图7-36摩尔型状态机
米勒型状态机:
其输出与当前状态和输入都有关,且对输入的响应发生在当前时钟周期,比摩尔型状态机对输入信号的响应要早一个周期。
所以输入信号的噪声(毛刺)会直接影响输出信号,即有竞争冒险且不能消除。
图7-37米勒型状态机
2.单进程、双进程和多进程状态机
可以有3种不同的方式实现对状态机的描述:
(1)三个模块用一个进程实现,也就是说三个模块均在一个always块内,这种状态机描述称为单进程有限状态机,它既描述状态转移,又描述状态的寄存和输出。
(2)每一个模块分别用一个进程实现,也就是说三个模块对应着三个always块,这种状态机描述称为三进程有限状态机。
(3)三个模块对应着两个always块,“状态译码”、“输出译码”分配在一个进程中,“状态寄存器”用另一个进程描述。
这种状态机描述称为双进程有限状态机。
7.5.4状态机的设计流程
状态机的设计流程分为6个步骤,如图7-38所示。
图7-38状态机设计流程
7.5.5状态机的编码方式
状态机的N种状态通常需要用某种编码来表示,即状态编码,又称为状态分配。
1.顺序二进制码
最紧密的编码,使用状态向量的位数最少,类似与前述的二进制编码器。
但从一个状态转移到相邻状态时,可能会有多个比特位发生变化,易产生毛刺。
2.格雷码
在相邻状态的转换中,每次只有一个比特位发生变化,消除了产生毛刺的问题,但不适用于有很多状态跳转的情况。
3.独热码
指对任意给定的状态,状态向量中仅有一位“1”,而其余为“0”,所以N状态的状态机需要N个触发器。
4.直接输出型编码
将状态码中的某些位直接输出作为控制信号,要求状态机各状态的编码作特殊的选择,以适应控制信号的要求,该编码需要根据输出变量来定制编码。
5.无效状态的处理
在状态机的设计中,使用各种编码,尤其是独热编码后,通常会不可避免地出现大量剩余状态,即未定义的编码组合,这些状态在状态机的运行中是不需要出现的,称为无效状态。
如果没有对无效状态进行合理处理,在某些情况下,状态机有可能进入不可预测的无效状态,并有可能无法进入正常状态。
所以,需要对无效状态进行处理:
(1)在语句中对每一个无效状态都作出明确的状态转换指示;
(2)利用default语句对未提到的状态作统一处理。
7.5.6状态机容错和设计准则
7.5.7状态机设计方式
以下讨论如何通过单always模块方式、双always模块方式和三always模块方式,实现单进程、双进程和多进程状态机。
以下例子与3.3.2中例3-3相同(表现方式有点不同),检测是否连续输入3个或以上的1。
其状态机的转换图如图所示。
图7-45状态转换图
1.单always模块方式
将整个状态机的设计写到一个always模块中,即描述状态输入和输出,又描述状态转移,其特点是利用寄存器完成输出从而不易产生毛刺,易于进行逻辑综合,缺点是代码可读性差,不利于修改、完善及维护,且状态向量和输出向量均由寄存器实现,会消耗较大的芯片资源,无法实现异步米勒状态机。
(1)使用Verilog进行描述
modulefsm_single(clk,rst,ina,out);
inputclk,rst,ina;
outputout;
regout;
parameters0=2'
b00,s1=2'
b01,s2=2'
b10,s3=2'
b11;
reg[0:
1]state;
always@(posedgeclkornegedgerst)
if(!
rst)
begin
state<
=s0;
//起始状态
out=0;
end
else
case(state)//根据条件定义状态转移及输出
s0:
begin
=(ina)?
s1:
s0;
s1:
s2:
s2:
s3:
s3:
out=1;
endcase
endmodule
(2)综合结果
图7-46综合结果
(3)测试平台设计
`timescale1ns/1ns
moduletestbench;
regina,rst,clk;
wireout;
parameterclock_period=20;
always#(clock_period/2)clk=~clk;
initial
clk=0;
rst=1;
#25rst=0;
#75rst=1;
#200$finish;
initial
ina=0;
#5;
repeat(10)
#30ina=$random;
fsm_singletest_single(clk,rst,ina,out);
(4)功能验证
功能验证测试结果如下:
图7-47验证结果
从波形中可看出,结果的输出要等时钟信号到来,延迟一个时钟周期才显示出结果。
2.双always模块方式
双always模块方式其中一个always模块采用同步时序描述状态转移,另一个always模块采用组合逻辑判断状态转移条件,描述状态转移规律及输出,其优点是面积和时序的优势。
但由于输出是当前状态的组合函数,又存在下述问题:
(1)输出会产生毛刺。
(2)状态机的输出向量必须由状态向量译码,增加了状态向量到输出的延迟。
(3)组合逻辑占用了一定的传输时间,增加了驱动下一模块的输入延迟,不利于系统的综合优化。
以下设计采用双always模块方式,实现与单always模块方式相同的功能。
modulefsm_double(clk,rst,ina,out);
inputclk,rst,ina;
outputout;
regout;
parameters0=2'
reg[0:
1]pre_state,next_state;
always@(posedgeclkornegedgerst)
pre_state<
pre_state<
=next_state;
//时序状态转换
always@(pre_stateorina)//组合逻辑判断
next_state<
case(pre_state)
if(ina==1)
=s1;
=s2;
=s3;
endcase
图7-48综合结果
(3)功能验证
测试平台设计同单always模块方式,验证结果如图:
图7-49验证结果
3.三always模块方式
三always模块方式中,其中一个always模块采用同步时序描述状态转移;
一个always模块采用组合逻辑判断转移条件,描述转移规律;
另一个always模块描述状态的输出。
其优点是程序可读性强,占用芯片面积适中,无毛刺,有利于综合。
modulefsm_tri(clk,rst,ina,out);
always@(pre_stateorina)//组合逻辑判断
default:
//时序状态转换
always@(pre_state)//摩尔型
out<
=0;
case(pre_state)
=1;
endcase
end
图7-50综合结果
图7-51验证结果
拓展:
组合电路进行输出,不会产生单always设计那种延迟(一个时钟),但会有竞争冒险的问题(组合电路不可避免的问题),如果用寄存器保存输出结果再同步输出呢?
可将第三个always块的敏感事件改为时钟上升沿,则输出进程变成时序电路:
always@(posedgeclk)//摩尔型
这样仿真结果为:
可看到类似单always一样,输出要在第4个时钟上升沿才到来。
这种设计结合了状态机和寄存器逻辑,没有毛刺的产生,但慢了一拍。
能否既使用寄存器方式消除毛刺,又不慢一拍呢?
可将第三个always块作以下修改:
case(next_state)
7.5.8Moore型有限状态机的设计
1.状态转换图
图7-40状态转换图
状态转换表如表7-3。
表7-3状态转换表
输入
当前状态
indata
1
A
B/01
A/00
B
C/10
C
D/11
D
真值表如下:
异步复位
reset
(Q1Q0)
下一状态
输出
X
A(00)
00
B(01)
01
C(10)
10
D(11)
11
2.使用Verilog进行描述
modulemoore(indata,outdata,clk,reset);
inputindata,clk,reset;
output[1:
0]outdata;
reg[1:
0]pre_state,next_state;
parameterA=2'
b00,B=2'
b01,C=2'
b10,D=2'
//状态编码
always@(pre_stateorindata)//利用组合逻辑判断状态转移条件及转移规律
A:
if(indata==1)
=A;
=B;
B:
=C;
C:
=D;
D:
next_state<
always@(posedgeclkorposedgereset)//描述状态转移及起始状态
if(reset==1)
pre_state<
else
always@(pre_state)//描述状态输出
outdata<
=2'
b00;
b01;
C:
b10;
D:
3.综合结果
图7-41综合结果
4.测试平台设计
regindata,reset,clk;
wire[1:
0]outdata;
parameterclock_period=20;
always#(clock_period/2)clk=~clk;
initial
clk=0;
indata=0;
#135indata=1;
#100indata=0;
reset=0;
#75reset=1;
#30reset=0;
mooretest_moore(indata,outdata,clk,reset);
initial
#400$finish;
5.功能验证
图7-42验证结果
7.5.9Mealy型有限状态机的设计
设计要求与Moore型有限状态机的设计相同。
1.使用Verilog进行描述
输入输出定义、前两个always进程的代码,均与Moore型有限状态机的设计相同。
modulemealy(indata,outdata,clk,reset);
inputindata,clk,reset;
output[1:
reg[1:
parameterA=2'
//状态编码
always@(pre_stateorindata)//状态转移条件及转移规律
always@(posedgeclkorposedgereset)//该模块描述状态转移及起始状态
if(reset==1)
always@(pre_stateorindata)//该模块描述输出,输出与输入信号indata有关,故为Mealy型
if(indata==1)
outdata<
2.综合结果
图7-43综合结果
3.功能验证
测试平台设计与Moore型有限状态机的设计相同,验证结果如下图:
图7-44验证结果
请读者自行与Moore型有限状态机的验证结果进行对比。
7.5.10状态机设计总结
表7-4状态机设计比较
比较项目
单进程
双进程
三进程
结构化设计
否
是
代码编写/理解
不宜,理解难
宜
输出信号
寄存器输出
组合逻辑输出
有无毛刺
不产生毛刺
产生毛刺
面积消耗
大
最小
小
运行速度
最慢
最快
较快
时序约束
不利
有利
可靠性、可维护性
低
较高
最高
后端物理设计
在采用VerilogHDL语言设计状态机时,建议使用“三always模块”方式编程,相应在描述状态机的输出时,只需指定case敏感表为状态寄存器,然后直接在每个次态的case分支中描述该状态的输出即可,而不用考虑状态转移条件。