← 2022 · 兆易创新 笔试

推荐答案 测试一下

用Verilog实现按键抖动消除电路,输入时钟频率为50Mhz,按键信号a低于设定宽度(由cnt_cfg配置:00b表示5ms,01b表示10ms,10b表示15ms,11b表示20ms)时,表示该信号是抖动,需要消除。

编程题 中等 笔试真题

参考答案

设计思路:按键消抖电路需检测输入信号a的边沿变化,当a稳定超过设定时间后输出才跟随。首先对异步输入a进行两级同步(使用两个D触发器)以消除亚稳态。然后通过边沿检测电路捕捉a的上升沿和下降沿。计数器根据同步后的信号稳定电平开始计数,计数阈值由cnt_cfg配置(00:5ms对应250000;01:10ms对应500000;10:15ms对应750000;11:20ms对应1000000)。当同步信号发生变化时计数器清零并重新开始计;若计数器计满阈值,则判定信号稳定,输出b更新为当前同步信号电平。核心代码如下: ```verilog module debounce( input clk, // 50MHz input rst_n, input [1:0] cnt_cfg, input a, // 异步按键输入 output reg b // 消抖后输出 ); reg [1:0] sync_a; // 两级同步 reg [19:0] cnt; // 20位计数器(最大1000000) reg [19:0] max_cnt; // 阈值 reg a_prev; // 用于边沿检测 // 同步器 always @(posedge clk or negedge rst_n) begin if (!rst_n) sync_a <= 2'b0; else sync_a <= {sync_a[0], a}; end // 阈值选择 always @(*) begin case(cnt_cfg) 2'b00: max_cnt = 20'd250000 - 1; 2'b01: max_cnt = 20'd500000 - 1; 2'b10: max_cnt = 20'd750000 - 1; 2'b11: max_cnt = 20'd1000000 - 1; default: max_cnt = 20'd250000 - 1; endcase end // 边沿检测与计数 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin cnt <= 20'b0; a_prev <= 1'b0; b <= 1'b0; end else begin a_prev <= sync_a[1]; // 检测到边沿(电平变化)则计数器置0 if (sync_a[1] != a_prev) begin cnt <= 20'b0; end else if (cnt < max_cnt) begin cnt <= cnt + 1'b1; end // 计数器满表示稳定,更新输出 if (cnt == max_cnt) begin b <= sync_a[1]; end end end endmodule ``` 注意:阈值减1是因为计数器从0开始;若使用边沿触发清零,则最后一次计数完成后输出更新;可在计数满后保持输出直到下次边沿。易错点:阈值计算错误(5ms/20ns=250000),忘记同步异步输入,以及边沿检测时使用组合逻辑或时序逻辑不当。

涉及知识点

  • Verilog
  • 时钟
  • verilog
← 上一题
登录后反馈错题
下一题 →