概述
1.状态机分为2类,米里型和摩尔型
组成要素有:输入(包括复位),状态(包括当前状态的操作),状态转移条件,状态输出条件
设计FSM总结起来为2大类。
用状态机去实现时序逻辑
(1)将状态转移和状态的操作和判断等写到一个模块中:如
parameter IDLE= 4'd0;
parameter START1 = 4'd1;
parameter ADD1 = 4'd2;
parameter ACK1 = 4'd3;
parameter ADD2 = 4'd4;
reg[3:0] cstate; //状态寄存器
always @ (posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
cstate <= IDLE;
end
else
case (cstate)
IDLE:
begin
cstate <= START1;
end
START1:
begin
cstate <= ADD1;
end
default: cstate <= IDLE;
endcase
end
(2)将状态转移单独写一个模块,将状态的操作和判断等写在另一个模块中。如:
parameter IDLE= 4'd0,
WRT0 = 4'd1,
WRT1 = 4'd2,
REA0 = 4'd3,
REA1 = 4'd4;
reg[3:0] cstate,nstate;
always @ (posedge clk or negedge rst_n)
if(!rst_n)
cstate <= IDLE;
else
cstate <= nstate;
always @ (cstate or sram_wr_req or sram_rd_req or cnt)//always 后面是一些可以引起状态变化的量
case (cstate)
IDLE:
if(sram_wr_req)
nstate <= WRT0;//进入写状态
else if(sram_rd_req)
nstate <= REA0;//进入读状态
else nstate <= IDLE;
WRT0:
if(`DELAY_80NS)
nstate <= WRT1;
else
nstate <= WRT0;//延时等待160ns
WRT1:
nstate <= IDLE;//写结束,返回
REA0:
if(`DELAY_80NS)
nstate <= REA1;
else
nstate <= REA0;//延时等待160ns
REA1:
nstate <= IDLE;//读结束,返回
default: nstate <= IDLE;
endcase
2个always 块一个为时序模块,一个为组合逻辑。
Binary、gray-code 编码使用最少的触发器,较多的组合逻辑。而 one-hot 编码反之。由于 CPLD 更多的提供组合逻辑资源,而 FPGA 更多的提供触发器资源,所以 CPLD 多使用gray-code,而 FPGA 多使用one-hot 编码。另一方面,对于小型设计使用gray-code 和binary 编码更有效,而大型状态机使用one-hot更高效。
推荐在 24个状态以上会用格雷码,在 5~24个状态会用独热码,在 4 个状态以内用二进制码,肯定独热码比二进制码在实现 FSM部分会占更多资源,但是译码输出控制简单,所以如果状态不是太多,独热码较好。状态太少译码不会太复杂,二进制就可以了。状态太多,前面独热码所占资源太多,综合考虑就用格雷码了
2.编码风格:
(1)避免生成锁存器
一个完备的状态机应该具有初始化(reset)状态和默认(default)状态
当芯片加电或者复位后,状态机应该能够自动将所有判断条件复位,并进入初始化状态。 状态机也应该有一个默认(default )状态,当转移条件不满足,或者状态发生了突变时,要能保证逻辑不会陷入“死循环”。
检查所有的状态是“并行的”(parallel),也就是说在同一时间只有一个状态能够成立。
(2)参数定义用 parameter
状态的定义用paramet er 定义,不推荐使用`defin e 宏定义的方式,因为‘defi ne 宏定义在编译时自动替换整个设计中所定义的宏,而par am et e r 仅仅定义模块内部的参数,定义的参数不会与模块外的其他状态机混淆。
(3)一定要使用“<=”非阻塞赋值方式
采用非阻塞赋值方式消除很多竞争冒险的隐患。
最后
以上就是平常狗为你收集整理的状态机的全部内容,希望文章能够帮你解决状态机所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复