Simulink HDL Coder FPGA初级开发实践(三) 按键消抖

前言: 本栏目除特别说明以外,均采用的黑金AX7103开发板,该开发板时钟频率为200M,并且是双端时钟,因此在每个项目中都有一段原语将双端时钟变成200MHz的单端时钟。文章仅作为学习记录,如有不足请在评论区指出,博主不会对各位的问题作出解答,请谅解。博主深知网络上关于HDL Coder的资料十分稀少,特别是中文资料几乎没有,并且官方给出的例子大多挺难不适合入门,因此将自己摸索的过程记录下来,希望给后人一些启发。

文章目录

    • 1. Simulink 模型
    • 2. 生成HDL代码
    • 3. 完整代码
    • 4. 完整使用流程

1. Simulink 模型

Simulink HDL Coder FPGA初级开发实践(三) 按键消抖_第1张图片

key_debounce 模块内部结构
Simulink HDL Coder FPGA初级开发实践(三) 按键消抖_第2张图片
通过比较当前时刻和前一时刻的输入值判断是否发生了变化,来复位一个计数器,计时为20ms。如果成功计时到20ms则说明按键稳定,就可以取当前按键的输入值,否则保持按键的上一次的值,下面的count表示按下的次数,用于点亮LED灯。

2. 生成HDL代码

// -------------------------------------------------------------
// 
// File Name: hdlsrc\key_debounce_mbd\key_debounce.v
// Created: 2022-03-24 21:13:10
// 
// Generated by MATLAB 9.12 and HDL Coder 3.20
// 
// 
// -- -------------------------------------------------------------
// -- Rate and Clocking Details
// -- -------------------------------------------------------------
// Model base rate: 1
// Target subsystem base rate: 1
// 
// -------------------------------------------------------------


// -------------------------------------------------------------
// 
// Module: key_debounce
// Source Path: key_debounce_mbd/key_debounce
// Hierarchy Level: 0
// 
// -------------------------------------------------------------

`timescale 1 ns / 1 ns

module key_debounce
          (clk,
           reset,
           key_in,
           count,
           key_out);


  input   clk;
  input   reset;
  input   key_in;
  output  [3:0] count;  // ufix4
  output  key_out;


  reg  Delay_out1;
  wire [31:0] count_step;  // uint32
  wire edge_detec;
  wire [31:0] count_from;  // uint32
  wire [31:0] count_reset;  // uint32
  reg [31:0] Time_counter_out1;  // uint32
  wire [31:0] count_1;  // uint32
  wire need_to_wrap;
  wire [31:0] count_value;  // uint32
  wire [31:0] count_2;  // uint32
  wire Compare_To_Constant_out1;
  wire switch_compare_1;
  reg  Delay1_out1;
  wire Switch_out1;
  wire NOT_out1;
  wire negedge_detec;
  wire [3:0] count_step_1;  // ufix4
  wire [3:0] count_from_1;  // ufix4
  reg [3:0] LED_counter_out1;  // ufix4
  wire [3:0] count_3;  // ufix4
  wire need_to_wrap_1;
  wire [3:0] count_value_1;  // ufix4
  wire [3:0] count_4;  // ufix4


  always @(posedge clk or negedge reset)
    begin : Delay_process
      if (reset == 1'b0) begin
        Delay_out1 <= 1'b0;
      end
      else begin
        Delay_out1 <= key_in;
      end
    end


  // Count limited, Unsigned Counter
  //  initial value   = 0
  //  step value      = 1
  //  count to value  = 2000000
  assign count_step = 32'b00000000000000000000000000000001;


  assign edge_detec = Delay_out1 ^ key_in;


  assign count_from = 32'b00000000000000000000000000000000;


  assign count_reset = 32'b00000000000000000000000000000000;


  assign count_1 = Time_counter_out1 + count_step;


  assign need_to_wrap = Time_counter_out1 == 32'b00000000000111101000010010000000;


  assign count_value = (need_to_wrap == 1'b0 ? count_1 :
              count_from);


  assign count_2 = (edge_detec == 1'b0 ? count_value :
              count_reset);


  always @(posedge clk or negedge reset)
    begin : Time_counter_process
      if (reset == 1'b0) begin
        Time_counter_out1 <= 32'b00000000000000000000000000000000;
      end
      else begin
        Time_counter_out1 <= count_2;
      end
    end


  assign Compare_To_Constant_out1 = Time_counter_out1 == 32'b00000000000111101000010010000000;


  assign switch_compare_1 = Compare_To_Constant_out1 > 1'b0;



  assign Switch_out1 = (switch_compare_1 == 1'b0 ? Delay1_out1 :
              Delay_out1);


  always @(posedge clk or negedge reset)
    begin : Delay1_process
      if (reset == 1'b0) begin
        Delay1_out1 <= 1'b0;
      end
      else begin
        Delay1_out1 <= Switch_out1;
      end
    end


  assign NOT_out1 =  ~ Switch_out1;


  assign negedge_detec = Delay1_out1 & NOT_out1;


  // Count limited, Unsigned Counter
  //  initial value   = 0
  //  step value      = 1
  //  count to value  = 10
  assign count_step_1 = 4'b0001;


  assign count_from_1 = 4'b0000;


  assign count_3 = LED_counter_out1 + count_step_1;


  assign need_to_wrap_1 = LED_counter_out1 == 4'b1010;


  assign count_value_1 = (need_to_wrap_1 == 1'b0 ? count_3 :
              count_from_1);


  assign count_4 = (negedge_detec == 1'b0 ? LED_counter_out1 :
              count_value_1);


  always @(posedge clk or negedge reset)
    begin : LED_counter_process
      if (reset == 1'b0) begin
        LED_counter_out1 <= 4'b0000;
      end
      else begin
        LED_counter_out1 <= count_4;
      end
    end


  assign count = LED_counter_out1;

  assign key_out = Switch_out1;

endmodule  // key_debounce

3. 完整代码

链接:https://pan.baidu.com/s/1yFnr_PZX30wJDrBOwORPqA?pwd=1111
提取码:1111
–来自百度网盘超级会员V6的分享

4. 完整使用流程

如果对HDL Coder的使用流程不熟悉,请根据另一篇文章从头练习一边,见Simulink HDL Coder FPGA开发实践之 基本使用流程介绍。

你可能感兴趣的:(#,HDL,Coder,FPGA,Matlab,笔记,fpga开发)