基于状态机的按键消抖实现

news2025/1/17 3:59:20

摸鱼记录 Day_14   !(^O^)y

review

        在day_13中以按键状态判断为例学习了状态分析基于状态机的按键消抖原理-CSDN博客

        分析得到了下图:

  今日任务:完成此过程   !(^O^)y

小梅哥对应视频:

        15B 基于状态机的按键消抖Verilog实现_哔哩哔哩_bilibili

        15C 基于Verilog系统函数语法的按键抖动模拟与仿真_哔哩哔哩_bilibili

1.  design sources

module key_judge(
                 input clk , 
                 input reset_n,
                 input key,
                 output reg key_flag,
                 output reg key_state);

        // nedge_key pedge_key

         // key_now   0:IDLE   1:FILTER0   2:DOWN   3:FILTER1
        // cnt 20ms/20ns = 1000000 ;

        reg [1:0]key_now;
        reg [19:0] cnt;
        parameter cnt_N = 1000000;
        always@(posedge clk or negedge reset_n ) 
            if(!reset_n) 
              
            else 
                    case(key_now)
                        0:        IDLE                 
                        1:        FILTER0                                 
                        2:        DOWN                  
                        3:        FILTER1

                     endcase

        // 注意cnt清0

module key_judge(
                 input clk , 
                 input reset_n,
                 input key,
                 output reg key_flag,
                 output reg key_state);
                 
        // nedge_key pedge_key
        reg dff_k_0 , dff_k_1 ;
        reg r_key; 
        wire  nedge_key, pedge_key;
        always@(posedge clk )    
            dff_k_0 <= key ;
        always@(posedge clk )    
            dff_k_1 <= dff_k_0 ;
        always@(posedge clk )    
            r_key <= dff_k_1 ;
            
        assign nedge_key = (r_key == 1)&&(dff_k_1 == 0);
        assign pedge_key = (r_key == 0)&&(dff_k_1 == 1);
   
        // key_now   0:IDLE   1:FILTER0   2:DOWN   3:FILTER1
        // cnt 20ms/20ns = 1000000 ;
        reg [1:0]key_now;
        reg [19:0] cnt;
        parameter cnt_N = 1000000;
        always@(posedge clk or negedge reset_n ) 
            if(!reset_n) 
                begin
                    key_now <= 0 ;
                    cnt <= 0;
                    key_flag <= 0;
                    key_state <= 1;
                end
            else 
                begin
                    key_flag <= 0;
                    case(key_now)
                        0:
                           if(!nedge_key) key_now <= 0;
                           else 
                               begin 
                                 cnt <= 0 ;
                                 key_now <= 1; 
                               end
                               
                        1:
                            if(pedge_key) key_now <= 0;
                            else if(cnt >= cnt_N - 1) 
                                begin
                                    cnt <= 0 ;
                                    key_now <= 2;
                                    key_flag <= 1;
                                    key_state <= 0;
                                end
                            else cnt <= cnt + 1'b1;
                            
                        2:
                            if(!pedge_key) key_now <= 2;
                            else
                                begin
                                    cnt <= 0 ;
                                    key_now <= 3;
                                end
                        
                        3:
                            if(nedge_key) key_now <= 2;
                            else if(cnt >= cnt_N - 1)
                                 begin
                                    cnt <= 0 ;
                                    key_now <= 0;
                                    key_flag <= 1;
                                    key_state <= 1;
                                end
                            else cnt <= cnt + 1'b1;    
                        
                    endcase
                end

endmodule

//hhh 在每次状态变化的时候清零一下,就好用了捏  !(^O^)y

2.  key_tb

`timescale 1ns / 1ns
module key_tb( );
    reg clk ,reset_n , key;
    wire key_flag ,  key_state;
    key_judge#(.cnt_N(1000))
         key_(
                 .clk(clk) , 
                 . reset_n(reset_n),
                 . key(key),
                 . key_flag(key_flag),
                 . key_state(key_state)
                 );
   initial clk = 1 ;
   always #10 clk = ~clk ;
   initial
    begin
        reset_n = 0 ; #201;
        reset_n = 1 ;
        key = 1 ; #50;
        key = 0 ; #30;
        key = 1 ; #60;#200;
        key = 0 ;#30000;
        key = 1 ; #50;
        key = 0 ; #30;
        key = 1 ; #60;#200;
        key = 0 ;#200;
        key = 1 ;
        #30000;
        $stop;
    end 
    
endmodule

//今天调试发现这个有大概两三个时钟周期的小误差:

          判断上升/下降沿用了打拍的处理

3.  关于 testbench  优化

3.1  Verilog 语法学习

目标:

        学习task定义与调用

               erilog语法之十一:任务(task)和函数(function) - 知乎 (zhihu.com)

        学习random函数

                总结verilog产生随机数的$random和seed - super_star123 - 博客园 (cnblogs.com)

        学习循环repeat

                Verilog 循环语句(while, for, repeat, forever)_verilog while-CSDN博客

task <任务名>;      

        <端口及数据类型声明语句>      

        <语句1>      

        <语句2>      

        .....      

        <语句n>

endtask

举个栗子:

task my_task;    

        input a, b;    

        inout c;    

        output d;    

         …    

        <语句> //执行任务工作相应的语句    

        …    

        c = foo1; //赋初始值    

        d = foo2; //对任务的输出变量赋值

endtask

调用:my_task(in_a , in_b , io_c , o_d);

$random(seed)

给random传入了参数seed,因此random根据seed来产生随机数。seed不同,产生的随机数的序列也不同。而且,每执行一次$random(seed)产生一个随机数,seed也自动更新一次。

建议用deposit的方式在仿真时改变seed的初值,使$random(seed)产生不同的随机数序列

{$random(seed)}     { }取绝对值

repeat

 verilog 四种循环: while,for,repeat, forever

循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式。

while

while (condition)

        begin
            …
        end

                 while 循环中止条件为 condition 为假。

for

for(initial_assignment; condition ; step_assignment)  

        begin
            …
        end

                 initial_assignment 为初始条件,condition 为终止条件             

                 step_assignment 为改变控制变量的过程赋值语句

                 i = i + 1 不能写成 i++ ,i = i -1 也不能写成 i -- 

repeat

repeat (loop_times)

         begin
            …
         end

                  repeat 的功能是执行固定次数的循环

                  repeat 循环的次数必须是一个常量变量信号

         如果循环次数是变量信号,则循环次数是开始执行 repeat 循环时变量信号的值。即使执行期间,循环次数代表的变量信号值发生了变化,repeat 执行次数也不会改变。

forever

forever

        begin
            …
        end

         forever 语句一旦执行便无限的执行下去

        系统函数 $finish 可退出 forever

3.2  key_tb_new

`timescale 1ns / 1ns
module key_tb_new( );
    reg clk ,reset_n , key;
    wire key_flag ,  key_state;
    key_judge#(.cnt_N(1000))
         key_(
                 .clk(clk) , 
                 . reset_n(reset_n),
                 . key(key),
                 . key_flag(key_flag),
                 . key_state(key_state)
                 );
   initial clk = 1 ;
   always #10 clk = ~clk ;
   initial
    begin
        reset_n = 0 ; 
        key = 1 ;
        #201;
        reset_n = 1 ;
    key_press(2);

        $stop;
    end 
    
 reg [13:0] rand;
 task key_press;
    input[3:0]seed;
    begin
        key = 1 ;
        #30000;
        repeat(10)
            begin
                rand = {$random(seed)} % 10000;
                #rand;
                key=~key;
            end
        key = 0 ;
        #30000;
        repeat(10)
            begin
                rand = {$random(seed)} % 10000;
                #rand;
                key=~key;
            end
         key = 1 ;
        #50000;
    end
endtask
 
    
endmodule

//  摸鱼结束        !(^O^)y

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1496675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[C#]winform基于C2PNet算法实现室内和室外图像去雾

【CP2Net框架】 https://github.com/YuZheng9/C2PNet 【CP2Net介绍】 Abstract 考虑到不适定的性质&#xff0c;发展了单图像去模糊的对比正则化&#xff0c;引入了来自负图像的信息作为下界。然而&#xff0c;对比样本是非一致的&#xff0c;因为阴性通常距离清晰&#xff…

二维码门楼牌管理系统应用场景:赋能市场研究与城市决策的新动力

文章目录 前言一、市场研究的新视角&#xff1a;门牌数据揭示市场趋势二、城市规划的得力助手&#xff1a;门牌数据指导资源分配三、决策制定的科学依据&#xff1a;门牌数据提升决策准确性四、未来展望&#xff1a;二维码门楼牌管理系统的更多可能性 前言 随着信息技术的飞速…

国创证券|存钱有窍门,掌握这五个窍门利息高出不少?

大部分居民会把手中闲置的资金存入银行&#xff0c;享用安稳的收益&#xff0c;其间存在以下五个诀窍&#xff1a; 1、比照不同银行的利率 储户在去银行存钱时&#xff0c;能够比照不同银行的利率&#xff0c;尽量地挑选利率较高的银行存&#xff0c;来获取较多的收益&#x…

UML类图详解

目录 概述1 什么是UMLUML模型和图形UML2.2中一共定义了14种图示。 2 UML类图作用3 类图格式4类与类之间的关系表达 概述 我们在阅读开源项目时&#xff0c;总是希望能比较高效的整理清楚项目中的各个类之间的关系&#xff0c;那么有没有相应的工具能高效、简洁的表示清楚类关系…

CMake:开始

文章目录 在计算机上获取和安装 CMake目录结构基本 CMake 用法CMakeLists文件适用于 CMake 的 Hello World配置和生成运行 CMake GUI运行 ccmake Curses 接口从命令行运行 CMake将编译器指定为 CMake构建配置构建项目 在计算机上获取和安装 CMake 在使用 CMake 之前&#xff0…

Sharding-JDBC源码解析与vivo的定制开发

作者&#xff1a;vivo IT 平台团队 - Xiong Huanxin Sharding-JDBC是在JDBC层提供服务的数据库中间件&#xff0c;在分库分表场景具有广泛应用。本文对Sharding-JDBC的解析、路由、改写、执行、归并五大核心引擎进行了源码解析&#xff0c;并结合业务实践经验&#xff0c;总结…

Unity 轮转图, 惯性, 自动回正, 点击选择

简单的实现 2D 以及 3D 的轮转图, 类似于 Web 中无限循环的轮播图那样. 文中所有代码均已同步至 github.com/SlimeNull/UnityTests 3D 轮转图: Assets/Scripts/Scenes/CarouselTestScene/Carousel.cs2D 轮转图: Assets/Scripts/Scenes/CarouselTestScene/UICarousel.cs 主要逻…

Nodejs web服务器之GET、POST请求初次体验

一、认识http请求 步骤 1.DNS解析域名&#xff0c;找到ip地址&#xff0c;建立TCP连接&#xff0c;发起http请求 2.服务器接收到http请求&#xff0c;进行处理&#xff0c;返回数据 3.客户端接收到返回的数据&#xff0c;处理数据&#xff08;比如渲染页面&#xff09; 二、no…

新生儿睡眠抖动:温馨抚慰宝宝的安稳梦乡

引言 新生儿的睡眠过程常常伴随着轻微的抖动&#xff0c;对于许多父母来说&#xff0c;这可能会引起一些担忧。在这篇文章中&#xff0c;我们将探讨新生儿睡眠抖动的原因和注意事项&#xff0c;帮助父母更好地理解和处理宝宝的这种行为&#xff0c;为宝宝提供安心的睡眠环境。…

基于FPGA的HyeperRam接口设计与实现

一 HyperRAM 针对一些低功耗、低带宽应用&#xff08;物联网、消费产品、汽车和工业应用等&#xff09;&#xff0c;涉及到外部存储&#xff0c;HyperRAM提供了更简洁的内存解决方案。 HyperRAM具有以下特性&#xff1a; 1、超低功耗&#xff1a;200MHz工作频率下读写不到50mW…

UE5数字孪生系列笔记(一)

智慧城市数字孪生系统 虚幻引擎连接数据库 将自己的mysql版本的libmysql.dll替换掉插件里面的libmysql.dll 然后将这个插件目录复制到虚幻项目目录下 然后添加这个插件即可 新建一个UMG&#xff0c;添加一个按钮试试&#xff0c;数据库是否连接 将UI添加到视口 打印是否连接…

自研在线CAD系统介绍

去年调研了已有的在线的CAD系统(悟空CAD、维杰地图、梦想控件)&#xff0c;基本上都是按年收费&#xff0c;还相当的贵&#xff0c;基于此&#xff0c;就萌生了自己研发CAD系统的想法&#xff0c;从技术选型、框架设计、代码实现基本为都是自研实现。已经有了初步的成果。 10M…

chatGPT的耳朵!OpenAI的开源语音识别AI:Whisper !

语音识别是通用人工智能的重要一环&#xff01;可以说是AI的耳朵&#xff01; 它可以让机器理解人类的语音&#xff0c;并将其转换为文本或其他形式的输出。 语音识别的应用场景非常广泛&#xff0c;比如智能助理、语音搜索、语音翻译、语音输入等等。 然而&#xff0c;语音…

如何选择乐歌升降台,一张图带你了解全型号参数功能

在现代办公环境中&#xff0c;久坐已成为一种常态&#xff0c;而这种生活方式带来的不良影响日益凸显。乐歌办公升降电脑台应运而生&#xff0c;不仅是一种办公家具&#xff0c;更是健康办公的有力助手。让我们从多个角度深入了解这款产品的功能意义。 1. 台面层数 乐歌办公升…

mysql bug( InnoDB: Error number 22),表突然不能读取

mysql bug&#xff08; InnoDB: Error number 22&#xff09;&#xff0c;表突然不能读取 bug最开始的bug&#xff1a;表突然不能读取关闭mysql容器&#xff0c;再次重启失败 解决方案不重建容器的几种可能措施重建容器重建如果懒得打命令或者忘记命令可能的run bug&#xff1a…

MATLAB中设置输出格式

目录 设置输出中行间距的格式 设置浮点数格式 使代码换行以适应窗口宽度 隐藏输出 按页查看输出 清空命令行窗口 MATLAB 同时在命令行窗口和实时编辑器中显示输出。可以使用提供的多个选项为输出显示设置格式。 设置输出中行间距的格式 默认情况下&#xff0c;MATLAB 会…

【Qt学习】QProgressBar的使用(进度条的实现)

文章目录 1. 介绍2. 实例2.1 按钮启动进度条2.2 更改进度条样式2.3 资源文件 1. 介绍 详细的 QProgressBar 内容可以通过 查阅Qt官方文档 &#xff0c;这里进行简要的总结&#xff1a; QProgressBar 是Qt框架中的一个控件&#xff0c;用于显示进度条&#xff1a; QProgressBar…

huggingface.datasets使用说明

诸神缄默不语-个人CSDN博文目录 datasets包的官方GitHub项目&#xff1a;huggingface/datasets: &#x1f917; The largest hub of ready-to-use datasets for ML models with fast, easy-to-use and efficient data manipulation tools datasets包可以加载很多公开数据集&a…

免费SSL证书和付费SSL证书的区别

免费证书和付费证书区别还是比较大的&#xff0c;相对来说免费证书适用的环境会单一一些&#xff0c;一般使用免费证书的环境都是个人门户网站或者是小微企业的门户官网&#xff08;无隐私信息&#xff09;。 受免费证书安全等级以及安全性的限制影响&#xff0c;如果是为了自…

Python 语法高亮显示和格式化库之pygments使用详解

概要 在软件开发和编程领域,代码是我们的主要表达方式。因此,对于代码的可读性和可理解性至关重要。为了提高代码的可读性,代码语法高亮和格式化工具变得至关重要。在Python世界中,Pygments是一个强大的工具,它可以帮助开发人员高亮显示和格式化他们的代码。本文将深入探…