本篇内容来源于中国大学mooc《计算机组成与CPU设计实验》 (江苏大学)中的课程视频、PPT等相关资料。
本篇内容为《计算机组成与CPU设计实验》——状态机
参考视频:
多数控制逻辑都可以用有限状态机描述
状态机
状态机是组合逻辑和时序逻辑的特殊组合
- 时序逻辑用于存储状态
- 组合逻辑用于产生次态和产生输出
状态的数量是有限的,故称为有限状态机(Finite State Machine,简称为FSM)
状态机分类
摩尔Moore型状态机结构
输出仅取决于当前状态。
在整个状态周期内输出保持不变,即使输入信号有变化。
米利Mealy型状态机结构
除当前状态外,输出还直接受输入影响,变化可能出现在任何时刻。
例子:玩具小车的速度档位
玩具小车汽车的速度有四个状态:停止、低速、中速、高速。
速度由刹车brake和加速器accelerator绝决定
状态图
- stop
- stop->low speed 刹车没有启动, 启动加速器brake=0 accelerator=1
- low speed->medium speed 刹车没有启动, 启动加速器brake=0 accelerator=1
- medium speed->high speed 刹车没有启动, 启动加速器brake=0 accelerator=1
- high speed->medium speed 刹车启动 brake=1
- medium speed->low speed 刹车启动 brake=1
- low speed->stop 刹车启动 brake=1
Verilog描述( Moore型状态机)
输出仅取决于当前状态。
module FSM(
input Clk,Reset,
input brake,//刹车
input acc,//加速
output [1:0] speed
);
reg [1:0]state; //现态
reg [1:0 ]next_state;//次态
localparam STOP = 2'b00;
localparam LOW = 2'b01;
localparam MEDI = 2'b10;
localparam HIGH = 2'b11;
//状态转换 时序逻辑
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算 组合逻辑
always@(*)
case(state)
STOP:
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
//输出逻辑 组合逻辑
assign speed = state;
endmodule
Mealy型状态机的描述
假设按下easy这个按钮,玩具小车以一档(低速)行驶。 和当前是什么状态没有关系。
module FSM(
input Clk,Reset, brake, acc,
input easy,//输入信号
output [1:0] speed
);
reg [1:0]state; //现态
reg [1:0 ]next_state;//次态
localparam STOP = 2'b00;
localparam LOW = 2'b01;
localparam MEDI = 2'b10;
localparam HIGH = 2'b11;
//状态转换
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算
always@(*)
case(state)
STOP:
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
//输出逻辑
assign speed =easy? 2'b01:state;
//输出speed除了和当前状态有关,也直接受easy输入影响。
endmodule
状态编码
前面使用的是二进制数编码,除此之外,格雷码、约翰逊码等都可以用来状态机编码。
1、Sequential和Gray码使用的触发器最少
2、Johnson和Gray码的相邻编码只有一位不同,有利于减少电路噪声(依赖于转移状态)
3、One-hot编码
- 所有位中只有一个1
- 使用的触发器较多,但计算次态的组合电路较小
- 适合于FPGA采用
One-hot状态编码
例子:玩具小车的速度档位(使用one hot编码)
module onehot_FSM(
input Clk,Reset,
input brake,//刹车
input acc,//加速
output [1:0] speed
);
reg [1:0]state; //现态
reg [1:0 ]next_state;//次态
localparam STOP = 4'b0001;
localparam LOW = 4'b0010;
localparam MEDI = 4'b0100;
localparam HIGH = 4'b1000;
//状态转换 时序逻辑
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算 组合逻辑
always@(*)
case(state)
STOP:
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
//输出逻辑 组合逻辑
always@(state)
case(state)
STOP: speed = 2'b00;
LOW: speed = 2'b01;
MEDI: speed = 2'b10;
HIGH: speed = 2'b11;
endcase
endmodule
状态编码的定义方法
1、用parameter或localparam语句
localparam STOP = 4'b0001;
localparam LOW = 4'b0010;
localparam MEDI = 4'b0100;
localparam HIGH = 4'b1000;
2、用`define语句(不推荐)
3、用枚举类型(SystemVerilog)
(1)默认情况下,枚举类型里元素的类型为int型,第一个元素的值为0,第二个为1,...
enum {STOP, LOW, MEDIUM, HIGH } state;
(2)显式定义枚举元素的类型和值
enum bit[3:0]{STATE0 = 4'b0001,
STATE1= 4'b0010,
STATE2 = 4'b0100,
STATE3 = 4'b1000,
} state,next_state;
用枚举类型定义状态编码
例子:玩具小车的速度档位(使用枚举定义编码)
module FSM(
input Clk,Reset,
input brake,//刹车
input acc,//加速
output [1:0] speed
);
//默认情况下,枚举类型里元素的类型为int型,第一个元素的值为0,第二个为1,...
enum { STOP ,//0
LOW ,//1
MEDI ,//2
HIGH //3
} state,next_state;//现态、次态
//状态转换 时序逻辑
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算 组合逻辑
always@(*)
case(state)
STOP:
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
//输出逻辑 组合逻辑
assign speed = state;
endmodule
用枚举类型定义One-hot编码
例子:玩具小车的速度档位(使用枚举定义one hot编码)
module onehot_FSM(
input Clk,Reset,
input brake,//刹车
input acc,//加速
output [1:0] speed
);
enum bit[3:0]{STOP = 4'b0001,
LOW = 4'b0010,
MEDI = 4'b0100,
HIGH = 4'b1000,
} state,next_state;
//状态转换 时序逻辑
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算 组合逻辑
always@(*)
case(state)
STOP:
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
//输出逻辑 组合逻辑
always@(state)
case(state)
STOP: speed = 2'b00;
LOW: speed = 2'b01;
MEDI: speed = 2'b10;
HIGH: speed = 2'b11;
endcase
endmodule
状态机的描述风格
状态机描述的3段式结构
- 状态转换
- 次态计算
- 输出逻辑
//FSM分为4块:状态定义,状态转换,次态计算,输出计算。
//状态变量声明
reg [N-1:]state, next_state;
//状态定义
localparam S0=... , S1=... , S2=..., S3=......;
//状态转换
always@(posedge clk or posedge reset)
if(reset) state <= ...;
else state <= next_state;
//次态计算
always @(*)
begin
case (state)
... next_stat = ...
end
//输出逻辑
always @(...)
.....
状态机描述的2段式结构
合并两个组合逻辑部分
注意:合并后的框图不能分辨摩尔型和米利型。
状态机描述的 2段式结构
合并了两个组合逻辑部分,与3段式仅仅是形式不同,不易分辨摩尔型和米利型。
例子:玩具小车的速度档位(使用状态机描述的2段式结构)
本例输出speed只受状态影响。
module onehot_FSM(
input Clk,Reset,
input brake,//刹车
input acc,//加速
output [1:0] speed
);
enum bit[3:0]{STOP = 4'b0001,
LOW = 4'b0010,
MEDI = 4'b0100,
HIGH = 4'b1000,
} state,next_state;
//状态转换 时序逻辑
always@(posedge Clk or Reset)
if(Reset)
state <= stop;
else
state <= next_state;
//次态计算 + 输出逻辑
always@(*)
case(state)
STOP:
speed = 2'b00;
if(acc & !brake) next_state = LOW;
else next_state = STOP;
LOW:
speed = 2'b01;
if(brake) next_state = STOP;
else if(acc) next_state = MEDI;
else next_state = LOW ;
MEDI:
speed = 2'b10;
if(brake) next_state = LOW;
else if(acc) next_state = HIGH;
else next_state = MEDI ;
HIGH:
speed = 2'b11;
if(brake) next_state = MEDI;
else next_state = HIGH ;
endcase
endmodule
状态机Verilog在线编程
练习网站: