verilog实现滚动显示学号(含按键消抖)

这篇具有很好参考价值的文章主要介绍了verilog实现滚动显示学号(含按键消抖)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

verilog滚动显示学号

前言

经过了前前后后将近十个小时的时间,总算能够正确上板并写完了最终的实验报告。花费了我大量时间的实验我觉得有必要记录并分享出来。声明:本人写verilog的能力不强,看我花了这么多时间就知道了,如果代码有问题感谢指正,代码是在这位学长的基础上修改的 零时的轻语者

代码部分

  • 顶层模块:

      module top(
      input clk100mhz, //时钟信号
      input clr, //复位信号
      input s, //模式选择
      input key1, // 四个拨码开关
      input key2,
      input key3,
      input key4,
      input push, //切换按键,以按的次数来确定输入位数
      output [3:0] pos1, //两个数码管使能
      output [3:0] pos2,
      output [7:0] seg1, // 两个链接数码管的信号
      output [7:0] seg2
      );
     	wire [3:0]data;
      wire clk190hz, clk3hz;
      wire [15:0]dataBus1;
      wire [15:0]dataBus2;
      wire [2 : 0] count1;
      clkDiv U1(clk100mhz, clk190hz, clk3hz);
      GPU U2(.clk3hz(clk3hz), .clr(clr),.s(s),.n(data),.w(count1),.dataBus1(dataBus1),.dataBus2(dataBus2));
      segMsgout1 U3(clk190hz,dataBus1, pos1, seg1);//输入显示数码管
      segMsgout2 U4(clk190hz,dataBus2, pos2, seg2);//输出显示数码管
      pushin U5(key1,key2,key3,key4,clk100mhz,data);
      delayPush U6(clr, push, clk100mhz, count1); //按键消抖
      endmodule
    
  • 时钟分频:

    module clkDiv(
    input clk100mhz,
    output clk190hz,
    output clk3hz
    );
    reg [25:0]count=0;
    assign clk190hz=count[18];
    assign clk3hz=count[25];
    always@(posedge clk100mhz)
    count<=count+1;
    endmodule
    
  • GPU控制部分:

      module GPU(                                            
      input clk3hz,
      input clr,
      input s, // 控制输入显示和输出显示
      input [3:0]n, // 当前输入的十进制数
      input [2:0]w, // 当前输入的数的位数
      output reg [15:0]dataBus1, // 输入显示数据流
      output reg [15:0]dataBus2 //输出显示数据流
      );
      reg [31:0]msgArray; //存放输入的学号
    
      //处理数据流
      always@(posedge clk3hz or posedge clr)
      begin
      if(!clr)    //清零功能
      begin
              dataBus1<=16'b1100_1100_1100_1100;
              dataBus2<=16'b1010_1010_1010_1010;
      end
      else
      begin
          if(s)  //输出显示模式
          begin
                   dataBus1 <= 16'b1100_1100_1100_1100; //输出显示模式时,输入显示数据流赋值无效值
                   dataBus2 <= msgArray[31:16]; //更新输出显示数据流
          end
          else  //输入显示模式
          begin
              dataBus2[11 : 0] <= 12'b1010_1010_1010; // 输入显示模式时,输出显示数据流赋值无效值
              dataBus2[15 : 12] <= w;
              if(w>=4) // 输入的位数大于四,跳转到低四位
              dataBus1<=msgArray[15:0];
              else
              dataBus1<=msgArray[31:16]; // 截取显示前四位
          end
       end
      end
      // 处理输入的学号
      always@(posedge clk3hz or posedge clr) // 数据更新和显示输入数据的频率一样
          begin
              if(!clr)
              begin
                  msgArray <= 32'b1111_1111_1111_1111_1111_1111_1111_1111;
              end
              else 
              begin
                  if(s) //移位操作:将高四位移动到低四位,同时将27-0位移动到31-4位,这样便实现了一个数据的移动
                      begin
                          msgArray[3:0]<=msgArray[31:28];
                          msgArray[31:4]<=msgArray[27:0];
                      end
                  else 
                  case(w) // 每一位对应输入一个数字
                              0:msgArray[31:28] <= n[3:0];
                              1:msgArray[27:24] <= n[3:0];
                              2:msgArray[23:20]<= n[3:0];
                              3:msgArray[19:16]<= n[3:0];
                              4:msgArray[15:12]<= n[3:0];
                              5:msgArray[11:8]<= n[3:0];
                              6:msgArray[7:4] <= n[3:0];
                              7:msgArray[3:0] <= n[3:0];
                          default:msgArray[31:0]=32'b1111_1111_1111_1111_1111_1111_1111_1111;
                          endcase
              end
          end
      endmodule    
    
  • 数据译码模块:
    1和2几乎没有区别,为此不再赘述

        module segMsgout1(
        input clk190hz,
        input [15:0] dataBus, 
        output reg [3:0] pos,
        output reg [7:0] seg
    );
        reg [1:0] posC; 
        reg [3:0] dataP;
    always @(posedge clk190hz )begin
    case(posC)
        0: begin
        pos<=4'b1000;
        dataP<=dataBus[15:12];
        end
        1:begin
        pos <=4'b0100;
        dataP <= dataBus[11:8];
        end
        2:begin
        pos <=4'b0010;
        dataP <= dataBus[7:4];
        end
        3:begin
        pos <=4'b0001;
        dataP <= dataBus[3:0];
        end
        endcase
        posC = posC + 1;
    end
    always @(dataP)
    case(dataP)
            4'b0000:seg=8'b0011_1111;
            4'b0001:seg=8'b0000_0110;
            4'b0010:seg=8'b0101_1011;
            4'b0011:seg=8'b0100_1111;
            4'b0100:seg=8'b0110_0110;
            4'b0101:seg=8'b0110_1101;
            4'b0110:seg=8'b0111_1101;
            4'b0111:seg=8'b0000_0111;
            4'b1000:seg=8'b0111_1111;
            4'b1001:seg=8'b0110_1111;
            4'b1010:seg=8'b0100_0000;
            4'b1011:seg=8'b0000_0000;
            default:seg=8'b0000_1000;
    endcase
    endmodule
    
  • 数值输入模块:

    module pushin(
          input key1, key2, key3, key4,
          input clk,
          output reg [3:0] data
          );
          always@(posedge clk)begin
              data <= {key4, key3, key2, key1};
          end
      
      endmodule
    
  • 按键消抖模块:

    module delayPush(
          input clr,
          input key_in,
          input clk,
          output reg[2:0] count1
          );
    
          reg[25 : 0] count_high; //延迟高位信号
          reg key_out;
          parameter DelayTime = 1000000;
          always@(posedge clk)begin
              if(key_in ==1'b1)
                  count_high <= count_high + 1;
              else
                  count_high <= 0;
          end
          always@(posedge clk)begin
              if(count_high == DelayTime) 
                  key_out <=  1'b1;        
              else key_out <= 1'b0;
          end
          always@(posedge clk or negedge clr)begin
              if(!clr) count1 <= 0;
              else if(key_out == 1'b1) count1 <= count1 + 1;
          end
      endmodule
    
    

系统结构模块说明:

  • 接口说明:四个拨码开关控制输入的数字,一个按键控制输入的bit位,一个复位键,一个模式选择开关,总共7个输入接口;最终的效果都是在七段数码管上显示某些内容,所以输出接口就是数码管的使能和led。
  • 实现的大致思路:实验要求我们在两个不同的阶段,左右两端的四个数码管要显示不同的内容,(阶段的选择由拨码开关实现),那么我们可以在输入数字阶段,传输给右侧的数码管是有效的,左侧的数码管无效显示;在滚动显示阶段,让右侧数码管的显示无效,左侧开始滚动显示

实现细节

由于本实验的细节还是非常多的,而且每个人上手实验会遇到的问题也不同,这里我只将一些我觉得重要的地方

  • 为什么要分频:说到这个,我们要先看一下分频出来的两个信号190hz和3hz分别传输给了哪个模块,从代码中可以看出,前者给了两个数码管译码模块,后者给了GPU模块。先看数码管译码模块,这个时钟信号是控制4个数码管快速的依次显示,因为四个数码管公用同一个seg数据,所以无法实现真正意义上的同时点亮四个数码管,只能以很快的速度依次点亮,这在人眼观察下是一起点亮的,但是用手机录像可以发现数码管是依次点亮的。下面再来说3hz,这个时钟频率是用来控制滚动的频率的,显然滚动之前,四个数码管必须要都被点亮过,所以滚动的周期是要远远大于点亮四个数码管的时间的。

  • 模块间接口的类型确定:接口信号大体上分为两种(模块内接口和模块外接口),总结上就是这样,如果给这个信号赋值的是外部信号,那么这个信号必须实时反映该外部信号,所以为wire类型,如果给这个信号赋值的是模块内部信号,就要看当前信号在assign还是always内被赋值,前者为wire,后者为reg,注意,模块的内外是相对的,对于顶层模块中的信号,内部的实例模块中的信号就是该信号的外部信号。所以,是以该信号被赋值的情况来判断该信号的类型。我们以顶层模块中的count1信号为例,它是用来接收delayPush产生的信号的(该信号对于顶层模块属于外部信号),所以count1信号要实时反映该外部信号,定义为wire类型。

  • 按键消抖:本实验中,通过按键的按下次数来给定输入的bit位的信息,当按下按钮是,我们认为只按了一次(按下是由低转高),实际上可能会经历多次高低信号的变换后才稳定:
    如图:
    verilog实现滚动显示学号(含按键消抖),fpga开发

    我们要做的事情很简单,就是对于输入信号进行多次判定,如果该信号维持的时间足够长,则输出该信号。相当于我们只检测信号稳定的部分,信号抖动的部分我们不理睬

关于仿真

本人不太会编写仿真测试,这里就不放仿真激励了,各位自行实现。

上板效果

verilog实现滚动显示学号(含按键消抖),fpga开发
最左端显示当前输入位数,右边四个数码管实时显示学号
verilog实现滚动显示学号(含按键消抖),fpga开发
左端四个数码管开始滚动显示学号文章来源地址https://www.toymoban.com/news/detail-762687.html

到了这里,关于verilog实现滚动显示学号(含按键消抖)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Verilog实现按键消抖(状态机方法)

    按键抖动分析 常用的轻触按键内部结构为金属弹片,在手按下、松开的过程中往往会发生细微抖动。 输出的逻辑电平也会发生快速翻转,按键按下和释放的过程中,都会产生抖动,虽然时间非常短暂,但是对于单片机、FPGA这种实时性非常高的系统来说是不可接受的,为了保

    2024年02月06日
    浏览(39)
  • FPGA入门学习笔记(十三)Vivado实现按键消抖

    四种状态 按键未按下:静止状态呈高电平; 按下过程中:抖动状态呈高低电平; 按键已按下:静止状态呈低电平; 释放过程中:抖动状态呈高低电平。 按键消抖思路 :区别于单片机使用20ms延时判断电平正负,FPGA中采用电平保持计时,若时间长度超过20ms则认为发生了一次

    2024年02月04日
    浏览(65)
  • 按键消抖(Verilog&Vivado)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 按键作为基本的人机输入接口,由于其机械特性,在按键按下或松开的时候,都是会有抖动的。按键小豆的方式有很多。我的方法是通过计时来消抖,通过一个计数器,当按键输入有变化时,计数器清零

    2024年02月08日
    浏览(43)
  • 北邮22级信通院数电:Verilog-FPGA(9)第九周实验(3)实现一个具有清零功能的按键计数器,对按键进行计数并显示

    北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客   目录 一.代码部分 1.1 counter.v 1.2 debounce.v 二.管脚分配 三.实现效果

    2024年02月05日
    浏览(60)
  • 【FPGA零基础学习之旅#10】按键消抖模块设计与验证(一段式状态机实现)

    🎉欢迎来到FPGA专栏~按键消抖模块设计与验证 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 🥝 模块设计: 🥝 按键消

    2024年02月12日
    浏览(41)
  • 用verilog编写按键消抖代码

    本代码在按键按下和松开情况下均能消抖,消抖延时20ms(时钟频率为100MHz时)。 代码如下 module key3_led2( //from system input     input    clk,     input    rstn, //from external input to pl     input    ex_key1,        //按键从PL端输入 //from pl to ps     output    reg    pl_key1    //处理

    2024年02月02日
    浏览(43)
  • FPGA按键消抖

    按键是输入设备,一般来说,按键在没有按下的时候是高电平;当按键按下的时候,为低电平。 在 DE2-70 User Manual 中 Each switch provides a high logic level (3.3 volts) when it is not pressed, and provides a low logic level (0 volts) when depressed. Since the pushbutton switches are debounced, they are appropriate for use

    2024年02月15日
    浏览(51)
  • 基于FPGA的四位数码管显示按键计数器设计(verilog编程)

    软件:Vivado 2022.2 硬件:BASYS 3 设计描述:通过开发板上的四个按键,按下一次记数加一,分别由四个数码管从左到右分别显示四个按键记数情况。 例: 1.初始值为0000,意为无记数 2.当按下第一个按键,记数加一,数码管显示1000 3.再次按下一第一个按键,记数加一,数码管显

    2024年02月08日
    浏览(46)
  • 基于FPGA的按键消抖

    按键抖动:按键抖动通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。当按下一次按键,可能在A点检测到一

    2024年02月16日
    浏览(51)
  • 二、13【FPGA】按键消抖

    学习说明此文档为本人的学习笔记,注重实践,关于理论部分会给出相应的学习链接。 学习视频:是根据野火FPGA视频教程——第十六讲 https://www.bilibili.com/video/BV1nQ4y1Z7zN?p=3 按键常常作为系统复位信号和控制信号的外部输入,主要分为自锁按键、机械按键和薄膜按键等。开发

    2023年04月26日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包