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

摸鱼记录 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《乱弹篇(23)读书摘录》

之前逾月&#xff0c;偷得闲遐&#xff0c;在腾迅视频看了两部以宋朝历史为背景的电视剧《后宫》和《清平乐》&#xff0c;觉得好看并觉得有所裨益&#xff0c;但之后就再也难以找到能让人有耐心去看完的一部电视剧了。在一阵儿唏嘘感叹后&#xff0c;便去读书网搜索小说书读&a…

砝码称重 蓝桥杯

在C中&#xff0c;fabs()和abs()都用于计算数字的绝对值&#xff0c;但它们之间有一些区别。 fabs(double x)&#xff1a;计算浮点数x的绝对值&#xff0c;返回一个double类型的结果。 abs(int x)&#xff1a;计算整数x的绝对值&#xff0c;返回一个int类型的结果。 数组的默…

PolarDB for PostgreSQL-概述

阿里云数据库的概述 本篇罗列了一些知识点和结构。 日志 2. 同步复制&#xff1a;下降20% 异步复制&#xff1a;数据丢失风险&#xff0c; 部署 1.示例&#xff1a; vim polarx.toml 1.测试主库和备库数据一致性 备库是否一致性读 一个节点荡掉&#xff0c;提供服务。 GMS CN…

HCIP —— BGP --- 路由反射器和联邦

目录 IBGP的水平分割 解决办法 路由反射器 --- RR 反射器的环路问题如何解决&#xff1f;&#xff1f;&#xff1f; 1.Originator_ID 起源者ID 2.Cluster_List --- 簇列表 RR的配置 联邦的配置 1.联邦和其他AS设备建EBGP对等体 2.联邦内部IBGP建立对等体 3.联邦内部E…

数据管理【总结】

大数据&#xff1a;是指极其庞大的数据集&#xff0c;通常具备五大特征&#xff08;5个V&#xff09;&#xff1a;数据量大&#xff08;Volume&#xff09;、数据类型多样&#xff08;Variety&#xff09;、数据生成速度快&#xff08;Velocity&#xff09;、数据真实性高&…

最新Claude3注册教程:解决Claude3 Opus被封无法发送手机验证码问题

Claude3注册指南&#xff1a;解决无法发送手机验证码问题 Anthropic在3月4日宣布推出最新的大型语言模型&#xff08;LLM&#xff09;系列——Claude 3。这一系列模型在多种认知任务上树立了新的性能标准&#xff0c;包括Claude 3 Haiku、Claude 3 Sonnet 和 Claude 3 Opus三个…

2024年纯前端VUE在线编辑微软Office/金山WPS的Word文档,支持私有化部署!

现在&#xff0c;随着数字化进程渗透到到各行各业&#xff0c;数据安全已经成为了数字化革命中的重要组成部分&#xff0c;而在线Office成在OA、ERP、文档系统中得到了广泛的应用&#xff0c;为我国的信息化事业也做出了巨大贡献。随着操作系统、浏览器及Office软件的不断升级和…

node的安装与介绍

安装 下载地址 node官网首页就会有两个安装选择&#xff0c;会根据当前电脑的系统自动显示对应的安装包&#xff0c;一个长期维护版&#xff08;LTS&#xff09;,一个是尝鲜版&#xff0c;记住选择LTS版本 安装指定版本下载截图 安装过程截图&#xff08;非常简单&#xff…

短剧小程序:掌中剧院,随时演绎精彩

在快节奏的现代生活中&#xff0c;人们越来越追求高效与便捷。为了满足广大用户对短剧内容的热爱和追求&#xff0c;我们推出了全新的短剧小程序&#xff0c;让精彩剧情触手可及&#xff0c;随时随地为您带来欢乐与感动。 一、轻松点播&#xff0c;随享短剧魅力 通过短剧小程…

Talk|加州大学圣地亚哥分校程旭欣:视觉反馈下足式机器人的全身操作与运动

本期为TechBeat人工智能社区第576期线上Talk。 北京时间3月6日(周三)20:00&#xff0c;加州大学圣地亚哥分校博士生—程旭欣的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “视觉反馈下足式机器人的全身操作与运动”&#xff0c;向大家系统地介绍…

【开源】JAVA+Vue.js实现大学生相亲网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询会员4.2 查询相亲大会4.3 新增留言4.4 查询新闻4.5 新增新闻 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的大学生相亲网站&#xff0c;包含了会员管理模块、新闻管…

Vue开发实例(十)Tabs标签页打开、关闭与路由之间的关系

创建标签页 一、创建标签页二、点击菜单展示新标签页1、将标签数据作为全局使用2、菜单点击增加标签页3、处理重复标签4、关闭标签页 三、点击标签页操作问题1&#xff1a;点击标签页选中菜单进行高亮展示问题2&#xff1a;点击标签页路由也要跳转 四、解决bug 先展示最终效果 …

项目管理工具进度猫:自我管理的应用

在飞速发展的现代社会中&#xff0c;每个人都面临着巨大的竞争压力&#xff0c;如何在这激烈的环境中脱颖而出&#xff0c;实现个人的成长与成功&#xff1f;答案就在我们的日常行为中——自我管理。 一、自我管理的定义 自我管理&#xff0c;简单来说&#xff0c;就是对自己…

mysql8安装配置(最新版)

目录 一、下载mysql8 二、安装mysql8 三、配置mysql 一、下载mysql8 下载链接&#xff1a;https://pan.quark.cn/s/58d9072e51c4 二、安装mysql8 双击msi文件 选择custom 根据所需选择组件 修改安装路径 选中execute&#xff0c;安装&#xff0c;弹出提示安装VS的提示框之后…

LT6813/ADBMS1818底层驱动---均衡控制

1、LT6813采用内部均衡的原理 2、平衡控制结构体 根据数据库中读取的控制值设置平衡。要为单元设置平衡&#xff0c;必须将相应的位写入配置寄存器中。LTC 驱动程序仅执行数据库中 BMS 写入的数据。 参数 ltc_stateLTC 状态机的状态pSpi接口指向 SPI 配置的指针pTxBuff &…

Android SDK2 (实操三个小目标)

书接上回&#xff1a;Android SDK 1&#xff08;概览&#xff09;-CSDN博客 今天讲讲三个实际练手内容&#xff0c;用的是瑞星微的sdk。 1 实操编译Android.bp 首先还是感叹下&#xff0c;现在的系统真的越搞越复杂&#xff0c;最早只有gcc&#xff0c;后面多了make&#xf…

2.3_9 读者-写者问题

2.3_9 读者-写者问题 &#xff08;一&#xff09;问题描述 有读者和写者两组并发进程&#xff0c;共享一个文件&#xff0c;当两个或两个以上的读进程同时访问共享数据时不会产生副作用&#xff0c;但若某个写进程和其他进程&#xff08;读进程或写进程&#xff09;同时访问共…

【nvm】nvm的安装和使用

简言 nvm(nvm-windows)的安装和使用。 nvm 允许你通过命令行快速安装和使用不同版本的 node。 nvm 适用于任何符合 POSIX 标准的 shell&#xff08;sh、dash、ksh、zsh、bash&#xff09;&#xff0c;尤其适用于以下平台&#xff1a;Unix、macOS 和 windows WSL。 不过 nvm 在…

安全防御第七次作业

拓扑图如图所示&#xff1a; 问题&#xff1a;在FW7和FW8之间建立一条IPSEC通道保证10.0.2.0/24网段 可以正常访问到192.168.1.0/24 注&#xff1a;基础配置我在此省略了 一、NAT配置 FW4&#xff1a; FW6&#xff1a; 二、在FW4上做服务器映射 三、配置IPSEC FW5&#xff…

用xshell7连接服务器,读取后台日志

有时候前端需要读取一些后台日志&#xff0c;比如&#xff0c;有时候接一些验证码啥的 或者有时候前后端不分离时&#xff0c;前端上线项目 先讲一下怎么用密码方式连接服务器 密码方式连接服务器 第一步&#xff0c;安装xshell&#xff0c;在新建会话中填写主机&#xff0…