一.测试过程状态机
1.新建工程
2.计时器模块
module time_count(
input wire clk,
input wire rst_n,
output wire sec_15
);
parameter MAX_NUM = 30'd749_999_999;
reg [29:0] cnt_15;
reg sec_15_r;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_15 <= 25'd0;
end
else if(cnt_15 == MAX_NUM)begin
cnt_15 <= 25'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_r <= 1'b0;
end
else if(cnt_15 == MAX_NUM)begin
sec_15_r <= 1'b1;
end
else begin
sec_15_r <= 1'b0;
end
end
assign sec_15 = sec_15_r;
endmodule
3.三段式状态机模块
module fsm(
input clk,
input rst_n,
input wire sec_15
);
reg [2:0] cstate;
reg [2:0] nstate;
//状态划分
localparam state_ready = 0;
localparam state_start = 1;
localparam state_stop = 2;
localparam state_query = 3;
localparam state_display = 4;
localparam state_initialize = 5;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cstate <= state_initialize;
else
cstate <= nstate;
end
always@(*)begin
if(!rst_n)
begin
nstate = state_initialize;
end
else
case(cstate)
state_initialize: begin
if(sec_15 == 1'b1)
nstate = state_ready;
else
nstate = state_initialize;
end
state_ready: begin
if(sec_15 == 1'b1)
nstate = state_start;
else
nstate = state_ready;
end
state_start: begin
if(sec_15 == 1'b1)
nstate = state_stop;
else
nstate = state_start;
end
state_stop: begin
if(sec_15 == 1'b1)
nstate = state_query;
else
nstate = state_stop;
end
state_query: begin
if(sec_15 == 1'b1)
nstate = state_display;
else
nstate = state_query;
end
state_display: begin
if(sec_15 == 1'b1)
nstate = state_initialize;
else
nstate = state_display;
end
default: ;
endcase
end
endmodule
4.编写顶层模块
module top_fsm(
input wire clk,
input wire rst_n
);
wire sec_15;
time_count inst_time_count(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
//例化状态机模块
fsm inst_fsm(
.clk (clk ),
.rst_n (rst_n ),
.sec_15 (sec_15)
);
endmodule
5.编译通过
二、检测10010串状态机
类似于电子锁,只有依次输入10010才能解锁,否则输入错误一位则回到起点。
1.按键消抖模块
module key_debounce(
input wire clk,
input wire rst_n,
input wire key,
output reg flag,
output reg key_value
);
reg [19:0] delay_cnt;
reg key_reg;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
key_reg <= 1'b1;
delay_cnt <= 1'b0;
end
else
begin
key_reg <= key;
if(key_reg ^ key)
delay_cnt <= 20'd1_000_000;
else if(delay_cnt > 0)
delay_cnt <= delay_cnt - 1;
else
delay_cnt <= 1'b0;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
flag <= 1'b0;
key_value <= 1'b1;
end
else
begin
if(delay_cnt == 20'd1)
begin
flag <= 1'b1;
key_value <= key;
end
else
begin
flag <= 1'b0;
key_value <= key_value;
end
end
end
endmodule
2.状态机模块
module fsm(
input clk,
input rst_n,
input [1:0] key,
output wire [3:0] led
);
parameter MAX_NUM = 24'd9_999_999;
parameter T = 4'd10;
reg [2:0] cstate;
//状态划分
localparam state_0 = 0; //初始
localparam state_1 = 1; //1
localparam state_10 = 2; //10
localparam state_100 = 3; //100
localparam state_1001 = 4; //1001
localparam state_10010 = 5; //10010
reg [3:0] cnt = 0;
reg [23:0] cnt_02 = 0;
reg time_flag;
reg [3:0] led_r;
//0.2计数器模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt_02 <= 1'b0;
else if(cnt_02 == MAX_NUM)
cnt_02 <= 1'b0;
else
cnt_02 <= cnt_02 + 1'b1;
end
//2s计数器模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 1'b0;
else if(time_flag == 1'b1)begin
if(cnt_02 == MAX_NUM)begin
if(cnt < T)begin
cnt <= cnt + 1'b1;
end
else begin
cnt <= 1'b0;
end
end
else begin
cnt <= cnt;
end
end
else begin
cnt <= 1'b0;
end
end
//状态切换模块
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
begin
cstate <= state_0;
end
else
case(cstate)
state_0: begin
if(key[1] == 1'b1)
cstate <= state_1;
else if(key[0] == 1'b1)
cstate <= state_0;
else
cstate <= state_0;
end
state_1: begin
if(key[0] == 1'b1)
cstate <= state_10;
else if(key[1] == 1'b1)
cstate <= state_0;
else
cstate <= state_1;
end
state_10: begin
if(key[0] == 1'b1)
cstate <= state_100;
else if(key[1] == 1'b1)
cstate <= state_0;
else
cstate <= state_10;
end
state_100: begin
if(key[1] == 1'b1)
cstate <= state_1001;
else if(key[0] == 1'b1)
cstate <= state_0;
else
cstate <= state_100;
end
state_1001: begin
if(key[0] == 1'b1)begin
cstate <= state_10010;
time_flag <= 1'b1;//开始计时
end
else if(key[1] == 1'b1)
cstate <= state_0;
else
cstate <= state_1001;
end
state_10010: begin
if(cnt == T)begin
cstate <= state_0;
time_flag <= 1'b0;//结束计时
end
else
cstate <= state_10010;
end
default: ;
endcase
end
//第三段:跟随状态输出
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
led_r <= 4'b0001;
else
case(cstate)
state_10010:if(cnt_02 == 24'd4_999_999)
led_r <= 4'b1111;
else if(cnt_02 == MAX_NUM)
led_r <= 4'b0000;
else
led_r <= led_r;
default : led_r <= 4'b0001;
endcase
end
assign led = led_r;
endmodule
if(key[1] == 1'b1)
nstate = state_1001;
else if(key[0] == 1'b1)
nstate = state_0;
else
nstate = state_100;
end
state_1001: begin
if(key[0] == 1'b1)begin
nstate = state_10010;
time_flag = 1'b1;//开始计时
end
else if(key[1] == 1'b1)
nstate = state_0;
else
nstate = state_1001;
end
state_10010: begin
if(cnt == T)begin
nstate = state_0;
time_flag = 1'b0;//结束计时
end
else
nstate = state_10010;
end
default: ;
endcase
end
//第三段:跟随状态输出
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
led_r <= 4'b0001;
else
case(cstate)
state_10010:if(cnt_02 == 24'd4_999_999)
led_r <= 4'b1111;
else if(cnt_02 == MAX_NUM)
led_r <= 4'b0000;
else
led_r <= led_r;
default : led_r <= 4'b0001;
endcase
end
assign led = led_r;
endmodule
3.顶层模块.
module fsm_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;
//例化按键KEY1
key_debounce inst_key_debounce(
.clk (clk ),
.rst_n (rst_n ),
.key (key[0] ),
.flag (flag[0] ),
.key_value(key_value[0])
);
//例化按键KEY2
key_debounce inst_key_debounce1(
.clk (clk ),
.rst_n (rst_n ),
.key (key[1] ),
.flag (flag[1] ),
.key_value(key_value[1])
);
fsm fsm_inst(
.clk (clk ),
.rst_n(rst_n ),
.key ({~key_value[1]&&flag[1],~key_value[0]&&flag[0]}),
.led (led)
);
endmodule