前言
实现一个测试过程,该过程包括启动准备状态、启动测试、停止测试、查询测试结果、显示测试结果、测试结束返回初始化6个状态;用时间来控制该过程,90秒内完成该过程;
一、什么是状态机
现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如自动门的状态就是两个 open 和 closed 。
状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型。说白了,一般就是指一张状态转换图。例如,根据自动门的运行规则,我们可以抽象出下面这么一个图。
自动门有两个状态,open 和 closed ,closed 状态下,如果读取开门信号,那么状态就会切换为 open 。open 状态下如果读取关门信号,状态就会切换为 closed 。
状态机的全称是有限状态自动机,自动两个字也是包含重要含义的。给定一个状态机,同时给定它的当前状态以及输入,那么输出状态时可以明确的运算出来的。例如对于自动门,给定初始状态 closed ,给定输入“开门”,那么下一个状态时可以运算出来的。
这样状态机的基本定义我们就介绍完毕了。重复一下:状态机是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
二、代码实现
1.计时器模块
module timer_cont(
input clk,
input rst_n,
output reg sec_15
);
parameter MAX_NUM = 30'd749_999_999;
reg [29:0] cnt_15;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_15 <= 30'd0;
end
else if(cnt_15 == MAX_NUM)begin
cnt_15 <= 30'd0;
end
else begin
cnt_15 <= cnt_15 + 1'd1;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
sec_15 <= 1'b0;
end
else if(cnt_15 == MAX_NUM)begin
sec_15 <= 1'b1;
end
else begin
sec_15 <= 1'b0;
end
end
endmodule
2.状态机模块
module fsm(
input clk,
input rst_n,
input wire sec_15
);
reg [2:0] cstate;
reg [2:0] nstate;
parameter S0 = 0;
parameter S1 = 1;
parameter S2 = 2;
parameter S3 = 3;
parameter S4 = 4;
parameter S5 = 5;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cstate <= S5;
else
cstate <= nstate;
end
always@(*)begin
if(!rst_n)
begin
nstate = S5;
end
else
case(cstate)
S5: begin
if(sec_15 == 1'b1)
nstate = S0;
else
nstate = nstate;
end
S0: begin
if(sec_15 == 1'b1)
nstate = S1;
else
nstate = nstate;
end
S1: begin
if(sec_15 == 1'b1)
nstate = S2;
else
nstate = nstate;
end
S2: begin
if(sec_15 == 1'b1)
nstate = S3;
else
nstate = nstate;
end
S3: begin
if(sec_15 == 1'b1)
nstate = S4;
else
nstate = nstate;
end
S4: begin
if(sec_15 == 1'b1)
nstate = S5;
else
nstate = nstate;
end
default: nstate = S5;
endcase
end
endmodule
3.顶层模块
module top(
input clk,
input rst_n
);
wire sec_15;
timer_cont inst_timer_cont(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
fsm inst_fsm(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
endmodule
三、原理图
四、检测10010串的状态机
1、设计思路
我们可以利用两个按键来表示输入1和0,当完成前一个状态后进入下一个状态。如果在输入过程中输错一个,那么会回到初始状态。当全部输入成功后,4个led灯会闪烁一段时间,之后回到初始状态。
2、代码实现
1、按键消抖模块
module key_debounce(
input clk,
input rst_n,
input key,
output key_value,
output flag
);
parameter TIME_20MS = 20'd1_000_000;
reg [19:0] cnt_20ms;
reg key_value_r;
reg flag_r;
reg key_reg;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_20ms <= 20'd0;
key_reg <= 1'b1;
end
else begin
key_reg <= key;
if(key_reg == 1'b1 && key == 1'b0)
cnt_20ms <= TIME_20MS;
else if(cnt_20ms <= 20'd0)
cnt_20ms <= 20'd0;
else
cnt_20ms <= cnt_20ms -20'd1;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
flag_r <= 1'b0;
else if(cnt_20ms == 20'd1)
flag_r <= 1'b1;
else
flag_r <= 1'b0;
end
assign flag = flag_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
key_value_r <= 1'b1;
else if(cnt_20ms == 20'd1)
key_value_r <= ~key;
else
key_value_r <= key_value_r;
end
assign key_value = key_value_r;
endmodule
2、状态机模块
module fsm(
input clk,
input rst_n,
input [1:0] key,
output wire [3:0] led
);
parameter MAX_TIME = 26'd49_999_999;
parameter TIME_200MS = 24'd9_999_999;
reg [2:0] cstate;
reg [2:0] nstate;
parameter S0 = 0;
parameter S1 = 1;
parameter S2 = 2;
parameter S3 = 3;
parameter S4 = 4;
parameter S5 = 5;
reg [3:0] led_r;
reg [25:0] cnt_1s;
reg [23:0] cnt_200ms;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_1s <= 26'd0;
else if(cnt_1s == MAX_TIME)
cnt_1s <= 26'd0;
else
cnt_1s <= cnt_1s + 26'd1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_200ms <= 24'd0;
else if(cnt_200ms == TIME_200MS)
cnt_200ms <= 24'd0;
else
cnt_200ms <= cnt_200ms + 24'd1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cstate <= S0;
else
cstate <= nstate;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
nstate <= S0;
end
else
case(cstate)
S0: begin
if(key[1] )
nstate <= S1;
else if(key[0])
nstate <= S0;
else
nstate <= nstate;
end
S1: begin
if(key[0] )
nstate <= S2;
else if(key[1])
nstate <= S0;
else
nstate <= nstate;
end
S2: begin
if(key[0] )
nstate <= S3;
else if(key[1])
nstate <= S0;
else
nstate <= nstate;
end
S3: begin
if(key[1] )
nstate <= S4;
else if(key[0] )
nstate <= S0;
else
nstate <= nstate;
end
S4: begin
if(key[0] )
nstate <= S5;
else if(key[1] )
nstate <= S0;
else
nstate <= nstate;
end
S5: begin
if(cnt_1s == MAX_TIME)
nstate <= S0;
else
nstate <= S5;
end
default: nstate <= S0;
endcase
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
led_r <=4'b0000;
else
case(cstate)
S5:begin
if(cnt_200ms == TIME_200MS)
led_r <= ~led_r;
else
led_r <= led_r;
end
default: led_r <= 4'b0000;
endcase
end
assign led = led_r;
endmodule
3、顶层模块
module top(
input wire clk,
input wire rst_n,
input wire [1:0] key,
output wire [3:0] led
);
wire [1:0] flag;
wire [1:0] key_value;
key_debounce inst_key_debounce(
.clk (clk ),
.rst_n (rst_n ),
.key (key[0] ),
.flag (flag[0] ),
.key_value(key_value[0])
);
key_debounce inst_key_debounce1(
.clk (clk ),
.rst_n (rst_n ),
.key (key[1] ),
.flag (flag[1] ),
.key_value(key_value[1])
);
fsm(
.clk (clk ),
.rst_n(rst_n ),
.key ({key_value[1]&&flag[1],key_value[0]&&flag[0]}),
.led (led)
);
endmodule
3、原理图
|