状态机基本概念
状态机,全称是有限状态机( Finite State Machine,缩写为FSM),是一种在有限个状态之间按一定规律转换的时序电路,可以认为是组合逻辑和时序逻辑的一种组合。 状态机通过控制各个状态的跳转来控制流程,使得整个代码看上去更加清晰易懂,在控制复杂流程的时候,状态机优势明显,因此基本上都会用到状态机,如SDRAM控制器等。
时钟同步的状态机结构(Mealy 状态机)
上图表示的是数字电路设计中常用的时钟同步状态机的结构。其中状态寄存器是由一组触发器组成,用来记忆状态机当前所处的状态。如果状态寄存器由n个触发器组成,这个状态机最多可以记忆2°个状态。所有的触发器的时钟端都连接在一个共同的时钟信号上,所以状态的改变只可能发生在时钟的跳变沿上。可能发生的状态的改变由正跳变还是由负跳变触发﹐取决于触发器的类型。状态是否改变,怎样改变还将取决于产生下一状态的组合逻辑F的输出,F是当前状态和输入信号的函数。状态机的输出是由输出组合逻辑G提供的,G也是当前状态和输人信号的函数。现代电路设计常用正跳变沿触发的D触发器,特别是在可编程逻辑器件上实现的用综合工具自动生成的状态机,其电路结构往往都是使用正跳变沿触发的D触发器。目前的JK触发器,其他类型的触发器和锁存器已经很少使用。图中的F和G两部分都是纯组合逻辑,它们的逻辑函数表达式如下: 下一个状态=F (当前状态,输入信号);
输出信号一G (当前状态,输入信号);
根据输出信号是否还取决于输入,状态机分为两类:
Moore(摩尔) 状态机:组合逻辑的输出只取决于当前状态;即输出信号一G (当前状态)。 Mealy (米勒)状态机:组合逻辑的输出不仅取决于当前状态,还取决于输入信号;即输出信号一G (当前状态,输入信号)
时钟同步的状态机结构(Moore 状态机)
状态机设计流程
根据设计需求画出状态转移图,确定使用状态机类型,并标注出各种输入输出信号,更有助于编程。一般使用最多的是 Mealy 型 3 段式状态机。
三段式状态机
状态机设计如下:
(0) 首先,根据状态机的个数确定状态机编码。利用编码给状态寄存器赋值,代码可读性更好。 (1) 状态机第一段,时序逻辑,非阻塞赋值,传递寄存器的状态。 (2) 状态机第二段,组合逻辑,阻塞赋值,根据当前状态和当前输入,确定下一个状态机的状态。 (3) 状态机第三代,时序逻辑,非阻塞赋值,因为是 Mealy 型状态机,根据当前状态和当前输入,确定输出信号。
`timescale 1ns/1ns
module fsm_ex(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire d3 ,
output reg out1,
output reg out2
);
reg [2 : 0] next_state, current_state;
//将输入组合起来
wire [2 : 0] data_in;
assign data_in = {d3, d2, d1};
parameter s0 = 3'd0;
parameter s1 = 3'd1;
parameter s2 = 3'd2;
parameter s3 = 3'd3;
parameter s4 = 3'd4;
parameter s5 = 3'd5;
parameter s6 = 3'd6;
//1、state transfer
//第一段:传递寄存器状态,时序逻辑,非阻塞赋值
always @(posedge clk or negedge rst) begin
if (! rst) begin
current_state <= s0;
end
else begin
current_state <= next_state;
end
end
//2、state switch, using block assignment for combination-logic
//all case items need to be displayed completely
//第二段:根据当前状态和当前输入确定下一状态,组合逻辑,阻塞赋值
always @(*) begin
if(! rst) begin
next_state = s0;
end
else begin
case(current_state)
s0: begin
case(data_in)
3'b001 : next_state = s1;
3'b010 : next_state = s2;
3'b100 : next_state = s4;
default : next_state = next_state;
endcase
end
s1: begin
case(data_in)
3'b001 : next_state = s2;
3'b010 : next_state = s3;
3'b100 : next_state = s5;
default : next_state = next_state;
endcase
end
s2: begin
case(data_in)
3'b001 : next_state = s3;
3'b010 : next_state = s4;
3'b100 : next_state = s6;
default : next_state = next_state;
endcase
end
default : next_state = s0;
endcase
end
end
//3、output logic, using non-block assignment
//第三段:Mealy状态机中,根据当前状态和当前输入确定输出,时序逻辑,非阻塞赋值
always @ (posedge clk or negedge rst) begin
if(! rst) begin
out1 <= 1'd0;
out2 <= 2'd0;
end
else begin
case(current_state)
s3 : begin
out1 <= 1'd1;
out2 <= 2'd0;
end
s4 : begin
out1 <= 1'd1;
out2 <= 2'd1;
end
s5 : begin
out1 <= 1'd1;
out2 <= 2'd2;
end
s6 : begin
out1 <= 1'd1;
out2 <= 2'd3;
end
default : begin
out1 <= 1'd0;
out2 <= 2'd0;
end
endcase
end
end
endmodule
两段式状态机
将 3 段式状态机 2、3 段描述合并,其他部分保持不变,状态机就变成了 2 段式描述。
参考文献:夏宇闻《Verilog数字系统设计》、 runoob Verilog教程
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)