文章目录
- 1、状态机
- 1.1、什么是状态机
- 1.2、状态机的使用
- 2、实现
- 2.1、设计思想
- 2.2、代码实现
- 3、检测10010串
- 3.1、检测10010串的状态图
- 3.2、代码部分
1、状态机
1.1、什么是状态机
状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(Finite State Machine)。
状态机主要分为两大类:
- mealy状态机:输出跟外部输入和当前状态共同决定
- moore状态机:输出只和状态有关而与输入无关
1.2、状态机的使用
根据状态机的实际写法,状态机可以分为一段式、二段式和三段式状态机。
- 一段式状态机:整个状态机写到一个 always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出。
- 二段式状态机:用两个 always 模块来描述状态机,其中一个 always 模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出。不同于一段式状态机的是,它需要定义两个状态,现态和次态,然后通过现态和次态的转换来实现时序逻辑。
- 三段式状态机:在两个 always 模块描述方法基础上,使用三个always 模块,一个always 模块采用同步时序描述状态转移,一个 always 采用组合逻辑判断状态转移条件,描述状态转移规律,另一个 always 模块描述状态输出。
2、实现
2.1、设计思想
设计一个实现一个测试过程,该过程包括启动准备状态、启动测试、停止测试、查询测试结果、显示测试结果、测试结束返回初始化6个状态;用时间来控制该过程,90秒内完成该过程,6个状态均用led灯展示:准备状态(3个led灯全亮)、启动测试(只点亮led1)、停止测试(点亮led2)、查询测试结果(点亮led3)、显示测试结果(点亮led1和led2)、测试结束返回初始化(点亮led1和led3)。90s内完成6个状态的切换。
2.2、代码实现
1、首先定义6个状态空间来存储6个状态:启动准备状态(1=001)、启动测试(2=010)、停止测试(3=011)、查询测试结果(4=100)、显示测试结果(5=101)、测试结束返回初始化(6=110)
reg [2:0] cstate;
2、根据设置的状态的所咋子时间范围切换状态
always@ (posedge clk_50 or negedge rst_n)
begin
if(!rst_n)
cstate <= 3'b000;
else if(cnt_nine > 0 && cnt_nine <= TIME_ONE)
cstate <= 3'b001;
else if(cnt_nine > TIME_ONE && cnt_nine <= TIME_TWO)
cstate <= 3'b010;
else if(cnt_nine > TIME_TWO && cnt_nine <= TIME_THREE)
cstate <= 3'b011;
else if(cnt_nine > TIME_THREE && cnt_nine <= TIME_FOUR)
cstate <= 3'b100;
else if(cnt_nine > TIME_FOUR && cnt_nine <= TIME_FIVE)
cstate <= 3'b101;
else if(cnt_nine > TIME_FIVE && cnt_nine <= TIME_SIX)
cstate <= 3'b110;
else
cstate <= 3'b000;
end
3、根据状态点亮相应的led灯
always@ (*)
begin
if(!rst_n)
led_r = 3'b000;
else
begin
case(cstate)
3'b001: led_r = 3'b111; //第一个状态,点亮三盏灯
3'b010: led_r = 3'b001; //第二个状态,点亮led1
3'b011: led_r = 3'b010; //第三个状态,点亮led2
3'b100: led_r = 3'b100; //第四个状态,点亮led3
3'b101: led_r = 3'b011; //第五个状态,点亮led1和led2
3'b110: led_r = 3'b101; //第六个状态,点亮led1和led3
default: ;
endcase
end
end
完整代码:
module system_six_top(
input wire clk_50, //时钟信号
input wire rst_n, //复位信号
output wire [2:0] led //开发板led灯输出信号
);
parameter TIME_ONE = 33'd250_000_000; //0~5s(33'd250_000_000)内为启动准备状态,仿真时取5us
parameter TIME_TWO = 33'd750_000_000; //5~15s(33'd750_000_000)内为启动测试状态,仿真时取15us
parameter TIME_THREE = 33'd1_500_000_000; //15~30s(33'd1_500_000_000)内为启动测试状态,仿真时取30us
parameter TIME_FOUR = 33'd2_500_000_000; //30~50s(33'd2_500_000_000)内为查询结果状态,仿真时取50us
parameter TIME_FIVE = 33'd3_500_000_000; //50~70s(33'd3_500_000_000)内为显示测试结果状态,仿真时取70us
parameter TIME_SIX = 33'd4_500_000_000; //70~90s内为测试结束状态,也是90s(33'd4_500_000_000)计时最大值(90s),仿真时取90us
reg [32:0] cnt_nine; //90s计数寄存器
reg [2:0] led_r;
//定义6个状态空间
//启动准备状态(1=001)、启动测试(2=010)、停止测试(3=011)、查询测试结果(4=100)、显示测试结果(5=101)、测试结束返回初始化(6=110)
reg [2:0] cstate;
//90s计时模块
always@ (posedge clk_50 or negedge rst_n)
begin
if(!rst_n)
cnt_nine <= 33'd0;
else if(cnt_nine == TIME_SIX - 1)
cnt_nine <= 33'd0;
else
cnt_nine <= cnt_nine + 1'b1;
end
//6个状态的切换
always@ (posedge clk_50 or negedge rst_n)
begin
if(!rst_n)
cstate <= 3'b000;
else if(cnt_nine > 0 && cnt_nine <= TIME_ONE)
cstate <= 3'b001;
else if(cnt_nine > TIME_ONE && cnt_nine <= TIME_TWO)
cstate <= 3'b010;
else if(cnt_nine > TIME_TWO && cnt_nine <= TIME_THREE)
cstate <= 3'b011;
else if(cnt_nine > TIME_THREE && cnt_nine <= TIME_FOUR)
cstate <= 3'b100;
else if(cnt_nine > TIME_FOUR && cnt_nine <= TIME_FIVE)
cstate <= 3'b101;
else if(cnt_nine > TIME_FIVE && cnt_nine <= TIME_SIX)
cstate <= 3'b110;
else
cstate <= 3'b000;
end
//根据不同的状态点亮不同的led灯
always@ (*)
begin
if(!rst_n)
led_r = 3'b000;
else
begin
case(cstate)
3'b001: led_r = 3'b111; //第一个状态,点亮三盏灯
3'b010: led_r = 3'b001; //第二个状态,点亮led1
3'b011: led_r = 3'b010; //第三个状态,点亮led2
3'b100: led_r = 3'b100; //第四个状态,点亮led3
3'b101: led_r = 3'b011; //第五个状态,点亮led1和led2
3'b110: led_r = 3'b101; //第六个状态,点亮led1和led3
default: ;
endcase
end
end
assign led = led_r; //将led_r的值赋给led
endmodule
4、仿真测试:测试时为了方便,将状态周期改为90us,其它的时间间隔相应改小
代码:
`timescale 1ns/1ns //时间单位/时间精度 后者不能比前者大
module system_six_top_tb;
reg clk_50;
reg rst_n;
wire [2:0] led;
//激励信号
always #10 clk_50 = ~clk_50; //每过10ns时钟取反
//初始化
initial
begin
clk_50 = 1'b0;
rst_n = 1'b0;
#20 rst_n = 1'b1;
#180000
$stop;
end
//实例化
system_six_top instance_system_six_top(
.clk_50 (clk_50), //时钟信号
.rst_n (rst_n ), //复位信号
.led (led ) //开发板外设led灯
);
endmodule
仿真结果
5、板极测试:同样为方便测试,将90s时间改为9s,其它时间间隔相应改小
3、检测10010串
3.1、检测10010串的状态图
1、根据需求画出状态图
2、其中IDLE为初始状态,S1表示检测到1、S2表示检测到10、S3表示检测到100、S4表示检测到1001、S5表示检测到10010,当检测到串10010时会输出高电平cout = 1.
3.2、代码部分
1、定义六个状态空间
parameter IDLE = 3'd0; //初始状态
parameter S1 = 3'd1; //检测到1
parameter S2 = 3'd2; //检测到10
parameter S3 = 3'd3; //检测到100
parameter S4 = 3'd4; //检测到1001
parameter S5 = 3'd5; //检测到10010
2、完整代码
module detection_top(
input wire clk_50, //时钟信号
input wire rst_n, //复位信号
input wire cin, //输入
output reg cout //输出
);
//定义六个状态空间
parameter IDLE = 3'd0; //初始状态
parameter S1 = 3'd1; //检测到1
parameter S2 = 3'd2; //检测到10
parameter S3 = 3'd3; //检测到100
parameter S4 = 3'd4; //检测到1001
parameter S5 = 3'd5; //检测到10010
//当前状态
reg [2:0] cstate;
reg [2:0] nstate;
always@ (posedge clk_50 or negedge rst_n)
begin
if(!rst_n)
begin
cstate <= IDLE;
end
else
cstate <= cstate;
end
//状态的转换
always@ (*)
begin
case(cstate)
IDLE:
begin
if(cin == 1)
nstate = S1;
else
nstate = IDLE;
end
S1:
begin
if(cin == 0)
nstate = S2;
else
nstate = IDLE;
end
S2:
begin
if(cin == 0)
nstate = S3;
else
nstate = IDLE;
end
S3:
begin
if(cin == 1)
nstate = S4;
else
nstate = IDLE;
end
S4:
begin
if(cin == 0)
nstate = S5;
else
nstate = IDLE;
end
default: nstate = IDLE;
endcase
end
always@ (posedge clk_50 or negedge rst_n)
begin
if(!rst_n)
cout <= 1'b0;
else if(cstate == S5)
cout <= 1'b1;
else
cout <= 1'b0;
end
endmodule
3、仿真代码
`timescale 1ns/1ns
module detection_top_tb();
reg clk_50;
reg rst_n ;
wire cin ;
reg [9:0] data;
wire cout ;
always #20 clk_50 = ~clk_50;
assign cin = data[9];
initial
begin
clk_50 = 1'b0;
rst_n = 1'b1;
#20 rst_n = 1'b1;
data = 10'b1_100_100_100;
#1000 $stop;
end
always@ (posedge clk_50)
begin
#2 data = {data[0],data[9:1]};
end
detection_top detection_top_inst(
.clk_50 (clk_50),
.rst_n (rst_n ),
.cin (cin ),
.cout (cout )
);
detection_top m(.clk_50(clk_50),.rst_n(rst_n),.cin(cin),.cout(cout));
endmodule
4、仿真结果