1.状态机简介
状态机可根据控制信号完成预定的状态转换,由组合逻辑电路和寄存器组成,可由状态转换表或状态转换图描述。
输出只和当前状态有关而与输入无关成为More型状态机,输出和当前状态、输入都有关称为Mealy型状态机。
2.功能需求
本例采用CPLD: MAX V 5M240ZT100C5,目的是通过两个按键key1和key2控制一组引脚的输出状态,该组引脚作为控制信号控制一组继电器,分断一组高压线路。key1按下时系统关闭,引脚输出全为0;key2按下时系统开启,引脚输出全为1。
状态转换图如下:
3.分析
- 按键按下检测与消抖
- 三段式状态机:一段 状态转移——仅负责状态的刷新;二段 判断下一状态——仅负责下一状态的判断;三段 状态输出——仅负责根据不同状态输出不同电平。
- 复位功能
4.代码
module state_ctl(
input clk, //时钟信号
input rst, //复位信号,低电平有效
input key1, //按键,低电平表示按下
input key2,
output reg [3:0] led_output,//LED输出指示
output reg [3:0] pin_output //引脚输出
);
//参数
localparam on_state = 4'b0010,//状态机状态2
off_state = 4'b0001,//状态机状态1
rst_state = 4'b0000,//状态机状态0
rst_output = 4'b0000,//系统复位 引脚输出
on_output = 4'b1111,//系统开启 引脚输出
off_output = 4'b0000;//系统关闭 引脚输出
//计数寄存器
reg [19:0] cnt;
//状态寄存器
reg [3:0] NS; //next_state
reg [3:0] CS; //current_state
reg [1:0] low_sw; //low_switch
reg [1:0] low_sw_r;
//计数器,用于按键检测---------------------------------------------------------------------------------------------------------------
always @ (posedge clk)
begin
cnt <= cnt + 1'b1;
end
always @(posedge clk )
begin
if (cnt == 20'hfffff)
low_sw <= {key2,key1};
end
//检测按键下降沿----------------------------------------------------------------------------------------------------------------------------------------------------------------
always @ ( posedge clk )
begin
low_sw_r <= low_sw;//将当前按键状态赋给low_sw_r
end
reg [1:0] ctrl;
always @ ( posedge clk )
begin
ctrl <= low_sw_r[1:0] & ( ~low_sw[1:0]);//检测到下降沿ctrl为1 ,由于检测延时,故已消抖
end
//状态转移模块------------------------------------------------------------------------------------------------------------------------------------------------------------------
always@(posedge clk or negedge rst)
begin
if(!rst)
CS <= rst_state;
else
CS <= NS;
end
//判断状态转移------------------------------------------------------------------------------------------------------------------------------------------------------------------
always@(ctrl)
begin
case(CS)
rst_state:
begin
if(ctrl[1])
NS <= on_state;
else if(ctrl[0])
NS <= off_state;
else
NS <= rst_state;
end
off_state:
begin
if(ctrl[1])
NS <= on_state;
else
NS <= off_state;
end
on_state:
begin
if(ctrl[0])
NS <= off_state;
else
NS <= on_state;
end
default:
begin
NS <= off_state;
end
endcase
end
//描述状态输出------------------------------------------------------------------------------------------------------------------------------------------------------------------
always@(posedge clk or negedge rst)
begin
begin
case(CS)
on_state: begin
pin_output <= on_output;
led_output <= ~on_output;
end
off_state: begin
pin_output <= off_output;
led_output <= ~off_output;
end
rst_state: begin
pin_output <= rst_output;
led_output <= ~rst_output;
end
endcase
end
end
endmodule