FPGA巩固基础:秒表的设计

设计要求:

6位8段数码管,低三位显示毫秒计数,最高位显示分钟,其余两位显示秒计数。

开始案件与暂停按键,复位按键直接全部归零。

扩展部分:每计满一次,led移位一次。

框图设计:

 

思路讲解:

首先按键信号经过消抖再用,然后把产生的标志信号传给控制模块,由于控制逻辑很简单就把这部分控制逻辑放进“数据产生模块中了”;

然后把数码管与led接口模块interface放进去。

按理来讲,应该重新定义个接口模块再把led与nixie放进去,比较规范。

模块讲解:

值得一提就是数据产生模块与数码管接口模块:

数据产生模块:

 其实输出端口是几个级联得计数器。

代码奉上:

`include "para.v"
module data_gen (
    input		wire				sys_clk         ,
    input		wire				sys_rst_n       ,
    input       wire                start_flag      ,
    input       wire                stop_flag       ,

    output      reg     [3:0]       po_data_one     ,
    output      reg     [3:0]       po_data_two     ,
    output      reg     [3:0]       po_data_thr     ,
    output      reg     [3:0]       po_data_fou     ,
    output      reg     [3:0]       po_data_fiv     ,
    output      reg     [3:0]       po_data_six     ,
    output      reg                 minute_flag     
);
    // localparam
    localparam      IDLE    = 3'b001 ,
                    WORKING = 3'b010 ,
                    STOP    = 3'b100 ;
    // reg signal 
    reg     [15:0]      cnt_1ms     ;
    reg     [2:0]       state_c     ;
    reg     [2:0]       state_n     ;

    // wire signal
    wire                add_cnt_1ms     ;
    wire                end_cnt_1ms     ;
    wire                IDLEtoWORKING   ;
    wire                WORKINGtoSTOP   ;
    wire                STOPtoWORKING   ;   
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/
    // // reg signal 
    // reg     [2:0]       state_c     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            state_c <= IDLE ;
        else 
            state_c <= state_n ;
    end
    // reg     [2:0]       state_n     ;
    always @(*) begin
        if(~sys_rst_n)
            state_n = IDLE ;
        else 
        case(state_c)
        IDLE   :    if(IDLEtoWORKING)
                        state_n = WORKING ;
                    else 
                        state_n = IDLE ;
        WORKING:    if(WORKINGtoSTOP)
                        state_n = STOP ;
                    else 
                        state_n = WORKING ;
        STOP   :    if(STOPtoWORKING)
                        state_n = WORKING ;
                    else 
                        state_n = STOP ;
        default:        state_n = IDLE ;
        endcase
    end

    assign  IDLEtoWORKING   = (state_c == IDLE      ) && (start_flag) ;
    assign  WORKINGtoSTOP   = (state_c == WORKING   ) && (stop_flag ) ;
    assign  STOPtoWORKING   = (state_c == STOP      ) && (start_flag) ;

    // reg     [15:0]      cnt_1ms     ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_1ms <= 16'd0 ;
        else if(add_cnt_1ms) begin
            if(end_cnt_1ms)
                cnt_1ms <= 16'd0 ;
            else 
                cnt_1ms <= cnt_1ms + 1'b1 ;
        end
        else if(state_c == IDLE) 
            cnt_1ms <= 16'd0 ; 
        else 
            cnt_1ms <= cnt_1ms ;// 注意这里,是保持还是归零。
    end
    // wire                add_cnt_1ms ;
    assign  add_cnt_1ms = (state_c == WORKING   ) ;
    // wire                end_cnt_1ms ;
    assign  end_cnt_1ms = add_cnt_1ms && (cnt_1ms == `MAX_CNT_1MS - 1) ;

    // output signal description
    // output		reg     [3:0]       po_data_one    ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_one <= 4'd0 ;
        else if(end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1)
            po_data_one <= 4'd0 ;
        else if(end_cnt_1ms)
            po_data_one <= po_data_one + 1'b1 ;
        else
            po_data_one <= po_data_one ;
    end
    // output      reg     [3:0]       po_data_two     ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_two <= 4'd0 ;
        else if((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)
            po_data_two <= 4'd0 ;
        else if(end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1)
            po_data_two <= po_data_two + 1'b1 ;
        else
            po_data_two <= po_data_two ;
    end
    // output      reg     [3:0]       po_data_thr     ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_thr <= 4'd0 ;
        else if((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1))
            po_data_thr <= 4'd0 ;
        else if(((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1))
            po_data_thr <= po_data_thr + 1'b1 ;
        else
            po_data_thr <= po_data_thr ;
    end
    // output      reg     [3:0]       po_data_fou     , 显示秒的个位 0 ~ 9
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_fou <= 4'd0 ;
        else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1))
            po_data_fou <= 4'd0 ;
        else if((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1))
            po_data_fou <= po_data_fou + 1'b1 ;
        else
            po_data_fou <= po_data_fou ;
    end
    // output      reg     [3:0]       po_data_fiv     , 显示秒的十位 0 ~ 5
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_fiv <= 4'd0 ;
        else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5))
            po_data_fiv <= 4'd0 ;
        else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1))
            po_data_fiv <= po_data_fiv + 1'b1 ;
        else
            po_data_fiv <= po_data_fiv ;
    end
    // output      reg     [3:0]       po_data_six     ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            po_data_six <= 4'd0 ;
        else if((((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5)) && (po_data_six == `MAX_CNT_NUM - 1))
            po_data_six <= 4'd0 ;
        else if(((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5))
            po_data_six <= po_data_six + 1'b1 ;
        else
            po_data_six <= po_data_six ;
    end
    // reg minute_flag
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            minute_flag <= 1'b0 ;
        else if((((((end_cnt_1ms && po_data_one == `MAX_CNT_NUM - 1) && po_data_two == `MAX_CNT_NUM - 1)) && (po_data_thr == `MAX_CNT_NUM - 1)) && (po_data_fou == `MAX_CNT_NUM - 1) && (po_data_fiv == `MAX_CNT_NUM - 5)) && (po_data_six == `MAX_CNT_NUM - 1))
            minute_flag <= 1'b1 ;
        else 
            minute_flag <= 1'b0 ;
    end
    
endmodule

状态机设计:

当复位按键按下,现态与次态都需要回到IDLE状态。
在代码层面,给state_n设置一个复位情况。

数码管模块: 

创新点,与以往不同的代码设计,这次用了“函数”,function。

代码奉上:

`include "para.v"
module nixie (
    input		wire				sys_clk         ,
    input		wire				sys_rst_n       ,
    input       wire     [3:0]      pi_data_one     ,
    input       wire     [3:0]      pi_data_two     ,
    input       wire     [3:0]      pi_data_thr     ,
    input       wire     [3:0]      pi_data_fou     ,
    input       wire     [3:0]      pi_data_fiv     ,
    input       wire     [3:0]      pi_data_six     ,

    output		reg     [5:0]       sel             , 
    output		reg     [7:0]       dig              
);
    // reg 
    reg                     dot             ; // 数码管上的小数点。
    reg     [31:0]          cnt_time        ; // 移位寄存器的移位时间,计数器。
    // wire
    wire                    add_cnt_time    ;      
    wire                    end_cnt_time    ;      
/******************************************************************************************
********************************************main code**************************************
*******************************************************************************************/   
    // reg signal description 
    // reg     [31:0]          cnt_time    ; // 移位寄存器的移位时间。
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            cnt_time <= 32'd0 ;
        else if(add_cnt_time) begin
            if(end_cnt_time)
                cnt_time <= 32'd0 ;
            else 
                cnt_time <= cnt_time + 1'b1 ;
        end
        else 
            cnt_time <= 32'd0 ; // 注意这里,是保持还是归零。
    end
    // reg         dot ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            dot <= 1'b1 ;
        else 
            dot <= 1'b1 ;
    end

    // wire signal description 
    assign  add_cnt_time = 1'b1 ;
    assign  end_cnt_time = add_cnt_time && (cnt_time == `MAX_CNT_TIES - 1) ;
    // task
    // task       nixie_dig ;
    //     input   [3:0]   data_num    ;
    //     output  [7:0]   po_dig      ;
    //     case (data_num)
    //     0      :    po_dig  = {dot, `ZERO  } ;
    //     1      :    po_dig  = {dot, `ONE   } ;
    //     2      :    po_dig  = {dot, `TWO   } ;
    //     3      :    po_dig  = {dot, `THREE } ;
    //     4      :    po_dig  = {dot, `FOUR  } ;
    //     5      :    po_dig  = {dot, `FIVE  } ;
    //     6      :    po_dig  = {dot, `SIX   } ;
    //     7      :    po_dig  = {dot, `SEVEN } ;
    //     8      :    po_dig  = {dot, `EIGHT } ;
    //     9      :    po_dig  = {dot, `NINE  } ;
    //     default:    po_dig  = 8'd0   ;
    //     endcase
    // endtask
    // function
function [6:0]  dig_num;
    input   [3:0]   data_in ;
    case (data_in)
    0      :    dig_num  = `ZERO  ;
    1      :    dig_num  = `ONE   ;
    2      :    dig_num  = `TWO   ;
    3      :    dig_num  = `THREE ;
    4      :    dig_num  = `FOUR  ;
    5      :    dig_num  = `FIVE  ;
    6      :    dig_num  = `SIX   ;
    7      :    dig_num  = `SEVEN ;
    8      :    dig_num  = `EIGHT ;
    9      :    dig_num  = `NINE  ;
    default:    dig_num  = 7'd0   ;
    endcase
endfunction
    // Output signal description
    // output		reg     [5:0]       sel             , 
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            sel <= 6'b111_110 ;
        else if(end_cnt_time)
            sel <= {sel[4:0],sel[5]} ;
        else 
            sel <= sel ;
    end
    // output		reg     [7:0]       dig  
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) 
            dig <= 8'd0 ;
        else 
        case (sel)
        6'b111_110: dig <= {dot, dig_num(pi_data_one)} ;
        6'b111_101: dig <= {dot, dig_num(pi_data_two)} ;
        6'b111_011: dig <= {dot, dig_num(pi_data_thr)} ;
        6'b110_111: dig <= {1'b0, dig_num(pi_data_fou)} ;
        6'b101_111: dig <= {dot, dig_num(pi_data_fiv)} ;
        6'b011_111: dig <= {1'b0, dig_num(pi_data_six)} ;
        default   : dig <= {dot, `SIX  }        ;
        endcase
    end

endmodule

函数或者任务的使用,是使得代码写起来更方便,设计起来更节省时间。

减少重复劳动。

要灵活使用。多观察,多分析,多获取信息。找到相关性,相似性。

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

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

相关文章

功能测试转向自动化测试 。10 年 心路历程——愿测试人不再迷茫

十年测试心路历程&#xff1a; 由于历史原因&#xff0c;大部分测试人员&#xff0c;最开始接触都是纯功能界面测试&#xff0c;随着工作年限&#xff0c;会接触到一些常用测试工具&#xff0c;比如抓包&#xff0c;数据库&#xff0c;linux 等。 我大学学的计算机专业&#…

AI创作系统ChatGPT网站源码+搭建部署教程文档,AI绘画,支持TSS GPT语音对话功能

一、AI创作系统 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI…

利用有限制通配符来提升API的灵活性

在Java中&#xff0c;有限制通配符&#xff08;bounded wildcard&#xff09;允许你在泛型中指定一个范围&#xff0c;从而提升API的灵活性。通配符使得你能够编写更通用、适用于多种类型的代码。以下是一个利用有限制通配符提升API灵活性的例子&#xff1a; 假设有一个简单的…

本地生活服务商被清退怎么办,仅需多来客一套系统就可恢复业务

除了区域服务商&#xff0c;今年全国本地生活服务商全军覆没。只怪某本地生活服务平台韭菜割的太快。专割服务商的韭菜。从公示的数据来看今年至少没收服务商的保证金高达近四个亿&#xff0c;这是什么概念&#xff1f;&#xff01; 最近的一文公告更是除了区域服务商&#xf…

【Oracle】创建表

目录 方法一&#xff1a;CREATE TABLE 语法 创建表示例1&#xff1a;创建stuinfo(学生信息表) 创建表示例2&#xff1a;添加stuinfo(学生信息表)约束 方法二&#xff1a;CREATE TABLE AS 语法 创建表示例3&#xff1a; 创建表示例4&#xff1a;实现对select查询的结果进行…

flowable之三 启动一个流程并跟踪

1. 背景介绍 当我们部署一个流程并启动后&#xff0c;Flowable会按照既定流程定义及进行节点处理以及自动流转&#xff0c;从一个节点执行到下一个节点&#xff0c;直至结束。在此过程中&#xff0c;系统如何处理BPMN XML文件&#xff1f;节点如何进行流转&#xff1f;本文对f…

「Swift」Xcode多Target创建

前言&#xff1a;我们日常开发中会使用多个环境&#xff0c;如Dev、UAT&#xff0c;每个环境对应的业务功能都不同&#xff0c;但每个环境之间都只存在较小的差异&#xff0c;所以此时可以使用创建多个Target来实现&#xff0c;每个Target对应这个一个App&#xff0c;可以实现一…

离散型概率密度函数的分布列⇔分布函数

目录 一、super误区 1.分布函数的定义 二、分布列⇒分布函数 二、分布列⇐分布函数 一、super误区 我在读定义的时候陷入了一个误区&#xff0c;与大家分享一下。 1.分布函数的定义 由于是离散型的概率密度函数&#xff0c;我把他抽象到数轴上理解&#xff1a; 如下分布…

【教3妹学编程-算法题】反转二叉树的奇数层

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 3妹&#xff1a;“你不是真正的快乐&#xff0c; 你的…

Python求小于m的最大10个素数

为了找到小于m的最大10个素数&#xff0c;我们首先需要确定m的值。然后&#xff0c;我们可以使用一个简单的算法来检查每一个小于m的数字是否是素数。 下面是一个Python代码示例&#xff0c;可以找到小于m的最大10个素数&#xff1a; def is_prime(n): if n < 1: …

JAVA 反射

JAVA 反射 动态语言 动态语言&#xff0c;是指程序在运行时可以改变其结构&#xff1a;新的函数可以引进&#xff0c;已有的函数可以被删除等结构上的变化。比如常见的 JavaScript 就是动态语言&#xff0c;除此之外 Ruby,Python 等也属于动态语言&#xff0c;而 C、C则不属于…

【Idea】SpringBoot项目中,jar包引用冲突异常的排查 / SM2算法中使用bcprov-jdk15to18的报错冲突问题

问题描述以及解决方法&#xff1a; 项目中使用了bcprov-jdk15to18 pom依赖&#xff0c;但是发现代码中引入的版本不正确。 追溯代码发现版本引入的是bcprov-jdk15on&#xff0c;而不是bcprov-jdk15to18&#xff0c;但是我找了半天pom依赖也没有发现有引入bcprov-jdk15on依赖。…

JMeter下载与安装

文章目录 前言一、安装java环境&#xff08;JDK下载与安装&#xff09;二、JMeter下载三、JMeter安装1.解压缩2.配置环境变量 四、JMeter启动&#xff08;启动成功则代表JMeter安装成功&#xff09;五、JMeter汉化&#xff08;将JMeter修改成中文&#xff09;1.方法一&#xff…

MFC画折线图,基于x64系统

由于项目的需要&#xff0c;需要画一个折线图。 传统的Teechart、MSChart、HighSpeedChart一般是只能配置在x86系统下&#xff0c;等到使用x64系统下运行就是会报出不知名的错误&#xff0c;这个地方让人很苦恼。 我在进行配置的过程之中&#xff0c;使用Teechart将x86配置好…

卫星影像5天一更新的地图网站

如果全球影像每5天一更新&#xff0c;并集多种地图数据源于一体的PB级海量地图数据该怎样去管理呢&#xff1f; 这是当我了解到SOAR网站之后&#xff0c;思考过的一个问题。 全球最大的在线地图网站 在SOAR的官方网站&#xff0c;据称它是世界上最大的在线地图网站。 它是集…

大数据Doris(三十六):Duplicate 模型(冗余模型)介绍

文章目录 Duplicate 模型(冗余模型)介绍 一、创建doris表 二、插入数据

Unity中Batching优化的GPU实例化整理总结

文章目录 前言一、GPU Instancing的支持1、硬件支持2、Shader支持3、脚本支持 二、我们来顺着理一下GPU实例化的使用步骤1、GPU实例化前的C#代码准备2、在 appdata 和 v2f 中定义GPU实例化ID3、在顶点着色 和 片元着色器 设置GPU Instance ID&#xff0c;使实例化对象顶点位置正…

05-详解Nacos配置管理中心,配置拉取的方式,热更新,配置共享(优先级)的步骤

Nacos配置管理 新建配置文件 当微服务部署的实例越来越多时,如果需要修改微服务的配置就需要逐个修改配置文件并且还要重启关联的微服务十分繁琐还易出错 项目中的配置文件分为每个项目特有的配置,项目所公用的配置 每个项目特有的配置: 有些项目中需要但有些项目中又不需要…

7. 异常、断言及日志

1.异常 1).什么是异常 异常&#xff0c;就是不正常的意思。指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。 在Java等面向对象的编程语言中&#xff0c;异常本身是一个类&#xff0c;产生异常就是创建异常对象并抛出了一个异常…

软件测试职业规划

软件测试人员的发展误区【4】 公司开发的产品专业性较强&#xff0c;软件测试人员需要有很强的专业知识&#xff0c;现在软件测试人员发展出现了一种测试管理者不愿意看到的景象&#xff1a; 1、开发技术较强的软件测试人员转向了软件开发(非测试工具开发)&#xff1b; 2、业务…