首页 > 编程知识 正文

有限状态机原理,简述状态机描述电路的思路

时间:2023-05-03 10:54:18 阅读:40137 作者:3406

关键抖动电路设计1 .关键抖动是什么2 .抖动电路设计思路3 .代码实现4 .仿真测试4.1. initial语句块赋值4.2 .调用task任务封装赋值调用$random函数

再次补充说,

此处的抖动去除可以视为开关的抖动去除,无论开关闭合还是断开,都会进行抖动去除处理,并在中途保持一定时间。

然后,解除按钮的抖动,按释放键就连接了。 此过程发出一个脉冲信号,以证明按钮已按下

1 .什么是钥匙抖动实际上的拨动开关和钥匙都是机械式设备,状态变化时可能会一次又一次地抖动,导致状态不稳定。 抖动的持续时间通常在20ms以下。 抖动去除电路的目的是对这段时间内的抖动信号进行滤波。

2 .抖动消除电路设计思路使用有限状态机思想,待输入信号稳定20ms后改变抖动后的输出值。 假设所使用的系统时钟频率为50HMz,等待20ms的时间,则使用计数器数1_000_000个clk来解决延迟问题。

根据时延思路,可以设计为每http://www.Sina.com/20ms检测完成后输出flag脉冲。

为了实现按钮的抖动去除,考虑两种情况,按下需要抖动去除,释放需要抖动去除。 状态机分为4种状态、2种稳定状态和2种抖动消除状态

IDLE :空闲状态下,不按默认键会稳定地进入高电平

FILTER_DOWN :按下按钮消除抖动的状态

DOWN :按钮按下稳定状态

FILTER_UP :按下键消除抖动的状态

抖动模块端口设计

3 .代码实现module key _ filter (output regkey _ flag,//抖动消除完成输出脉冲output reg key_state,//按钮状态输出input wire clk,//50m 参数过滤器_ down=4' b 0010; parameter DOWN=4'b0100; 参数过滤器_ up=4' b 1000; reg [3:0] next_state; reg key_temp; //wire key_nedge; //wire key_pedge; //reg en_counter; //计数器使能信号reg [19:0] counter; //计数1_000_000次//边缘检测电路//按钮信号是异步信号,在状态转移中需要对按钮边缘敏感,因此首先用一级d触发器同步key_in和clk,进行pedge和nedge key_in; //下降沿检测assign key_pedge=! 密钥_ temp ()密钥_ in ); //上升沿检测//带使能的计数器,延迟20ms的Always@(Posedgeclk ) beginif(rst==1'b0 ) begin counter=0; endelseif(en_counter==1'B1 ) begin counter=counter 1; end else begin counter=0; 结束//状态机模块always @ (posedge clk or negedge rst ) beginif(rst==1'B0 ) begin next_state=IDLE; en_counter=1'b0; key_flag=1'b0;

key_state <= 1'b1; end else begin case (next_state) IDLE: begin key_flag <= 1'b0; key_state <= 1'b1; if (key_nedge) begin next_state <= FILTER_DOWN; en_counter <= 1'b1; end else begin next_state <= IDLE; end end FILTER_DOWN: begin if (counter >= 20'd999_999) begin // 20ms时间到 key_flag <= 1'b1; // flag输出一个高脉冲,进入稳定状态 en_counter <= 1'b0; // 计数器不使能 next_state <= DOWN; end else if (key_pedge) begin // 20ms内检测到有上升沿 en_counter <= 1'b0; //计数器不使能,保持空闲状态 next_state <= IDLE; end end DOWN: begin key_flag <= 1'b0; key_state <= 1'b0; if (key_pedge) begin next_state <= FILTER_UP; en_counter <= 1'b1; end else begin next_state <= DOWN; end end FILTER_UP: begin if (counter >= 20'd999_999) begin // 20ms时间到 key_flag <= 1'b1; // flag输出一个高脉冲,进入稳定状态 en_counter <= 1'b0; // 计数器不使能 next_state <= IDLE; end else if (key_nedge) begin // 20ms内检测到有下降沿 en_counter <= 1'b0; // 计数器不使能,保持按下稳定状态 next_state <= DOWN; end end default: begin next_state <= IDLE; end endcase end end endmodule 4. 仿真测试 4.1. initial语句块赋值 `define clk_period 20 //100M系统时钟module key_filter_tb(); reg clk; //50M时钟信号 reg rst; //低电平复位 reg key_in; //按键输入 wire key_flag; //消抖完毕输出脉冲 wire key_state; //按键状态输出 //例化测试模块 key_filter key_filter_test( .clk(clk), //50M时钟信号 .rst(rst), //低电平复位 .key_in(key_in), //按键输入 .key_flag(key_flag), //消抖完毕输出脉冲 .key_state(key_state) //按键状态输出); //产生100M时钟信号 initial clk = 1; always #(`clk_period / 2) clk <= ~clk; //开始测试 initial begin rst <= 0; //系统复位 key_in <= 1; //按键处于空闲状态 #(`clk_period * 2); rst <= 1; #10_000_000; //延时10ms,方便观察按键按下现象 //开始模拟按键按下抖动 key_in <= 0; #1000; key_in <= 1; #2000; key_in <= 0; #1400; key_in <= 1; #2600; key_in <= 0; #1300; key_in <= 1; #200; //产生一个稳定的低电平大于20ms,代表按键稳定 key_in <= 0; #30_000_000; //模拟释放抖动 key_in <= 1; #2000; key_in <= 0; #1000; key_in <= 1; #2600; key_in <= 0; #1400; key_in <= 1; #200; key_in <= 0; #1300; //产生一个稳定的高电平大于20ms,代表释放稳定 key_in <= 1; #30_000_000; $stop; end endmodule


局部抖动

4.2. 调用task任务封装赋值并调用$random函数 利用$randon函数产生随机延时置模拟抖动 reg [15:0]randnum;randnum = $random % 50; //产生一个-49~49内的随机数randnum = {$random} % 50; //产生一个0 ~ 50内的随机数 利用 task / endtask 将重复代码进行封装 task <任务名>; <语句1> <语句2> <语句3> ....endtask `define clk_period 20 //100M系统时钟module key_filter_2_tb(); reg clk; //50M时钟信号 reg rst; //低电平复位 reg key_in; //按键输入 wire key_flag; //消抖完毕输出脉冲 wire key_state; //按键状态输出 reg [15:0]rand_time; //按键抖动时随机时长 //例化测试模块 key_filter key_filter_test( .clk(clk), //50M时钟信号 .rst(rst), //低电平复位 .key_in(key_in), //按键输入 .key_flag(key_flag), //消抖完毕输出脉冲 .key_state(key_state) //按键状态输出); //产生100M时钟信号 initial clk = 1; always #(`clk_period / 2) clk <= ~clk; //开始测试 initial begin rst <= 0; //系统复位 key_in <= 1; //按键处于空闲状态 #(`clk_period * 2); rst <= 1; #10_000_000; //延时10ms,方便观察按键按下现象 press_key; #10000; //第一次按下按键 press_key; #10000; //第二次按下按键 press_key; #10000; //第三次按下按键 $stop; end task press_key; begin //开始模拟按键按下抖动 repeat(50)begin rand_time = {$random} % 65536; #rand_time key_in = ~key_in; end //产生一个稳定的低电平大于20ms,代表按键稳定 key_in = 0; #30_000_000; //模拟释放抖动 repeat(50)begin rand_time = {$random} % 65536; #rand_time key_in = ~key_in; end //产生一个稳定的高电平大于20ms,代表释放稳定 key_in = 1; #30_000_000; end endtask endmodule

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。