FPGA巩固基础:秒表的设计

这篇具有很好参考价值的文章主要介绍了FPGA巩固基础:秒表的设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

设计要求:

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

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

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

框图设计:

FPGA巩固基础:秒表的设计,fpga开发

FPGA巩固基础:秒表的设计,fpga开发 

思路讲解:

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

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

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

模块讲解:

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

数据产生模块:

FPGA巩固基础:秒表的设计,fpga开发

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

代码奉上:

`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

状态机设计:

FPGA巩固基础:秒表的设计,fpga开发

当复位按键按下,现态与次态都需要回到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

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

减少重复劳动。

要灵活使用。多观察,多分析,多获取信息。找到相关性,相似性。文章来源地址https://www.toymoban.com/news/detail-782613.html

到了这里,关于FPGA巩固基础:秒表的设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • FPGA设计开发(基础课题):七段数码管设计

    一、设计目的 FPGA驱动七段数码管实现十六进制计数显示。 二、设计原理 七段数码管分共阳极与共阴极两种。共阳极数码管其工作特点是,当笔段电极接低电平,公共阳极接高电平时,相应笔段可以发光。共阴极数码管则与之相反,它是将发光二极管的阴极短接后作为公共阴

    2024年02月07日
    浏览(54)
  • FPGA设计开发(基础课题):74LS160计数器芯片设计

    一、设计目的 1、学会用HDL语言设计时序电路; 2、用HDL语言设计74LS160计数器芯片的数字功能。 二、设计原理 计数器是最常用的寄存器逻辑电路,从微处理器的地址发生器到频率计都需要用到计数器。一般计数器可以分为两类:加法计数器和减法计数器。加法计数器每来一个

    2024年02月08日
    浏览(57)
  • FPGA学习—通过数码管实现电子秒表模拟

    请参阅博主以前写过的一篇电子时钟模拟,在此不再赘述。 https://blog.csdn.net/qq_54347584/article/details/130402287 项目说明:本次项目是为了通过数码管实现秒表模拟。其中,六位数码管分别显示秒表的分位,秒位,毫秒位(由于毫秒有三位,在此只取百位和十位),其中分位和秒位

    2024年02月14日
    浏览(47)
  • FPGA 开发必备:从零开始学习 FPGA 设计

    FPGA 开发必备:从零开始学习 FPGA 设计 FPGA 是一种可编程逻辑器件,可以在不用重新设计硬件电路的情况下修改其功能。它是数字电路设计中最重要的组成部分之一。FPGA 的广泛应用领域包括通信、计算机、图像处理、音频处理等。 要想成为一名合格的 FPGA 工程师,你需要了

    2024年02月07日
    浏览(60)
  • 《FPGA至简设计原理与应用》学习笔记1 —— FPGA基础

    视频:https://www.bilibili.com/video/BV14K4y1u7kH/ 资料:https://www.aliyundrive.com/s/E9H7Mc5hqhu FPGA是什么东西? FPGA全称Field-Programmable Gate Array,即现场可编程门阵列 简而言之FPGA是一个可以通过 编程 来 改变内部结构 的芯片。 如果要实现相应的功能,需要通过编程即使用硬件描述语言进行

    2024年02月08日
    浏览(48)
  • 时钟信号设计基础——FPGA

    目录/ contents ● 时钟信号设计概述 ● 时钟信号属性特征 ● 常见时钟信号概念 ● 时钟信号设计要点 01——时钟信号设计概述 时钟信号作为数字电路系统的“心脏”,始终伴随着数字电路信号的变化,在数字电路设计中具有重要意义。数字电路通常被划分为组合逻辑与时序逻

    2024年02月04日
    浏览(35)
  • 明德扬FPGA至简设计原理与应用 第一篇 FPGA基础知识 第一章 FPGA简介

    FPGA 的全称为 Field-Programmable Gate Array, 即现场可编程门阵列。FPGA 就是一个可以“改变”内部结构的芯片,而让这个芯片来实现怎样的功能,就需要通过编程即设计HDL,经过 EDA工具编译、综合、布局布线成后转换为可烧录的文件,最终加载到 FPGA 器件中去,改变 FPGA 内部的连

    2024年01月16日
    浏览(79)
  • FPGA开发设计

    FPGA是可编程逻辑器件的一种,本质上是一种高密度可编程逻辑器件。 FPGA的灵活性高、开发周期短、并行性高、具备可重构特性,是一种广泛应用的半定制电路。 采用基于SRAM工艺的查位表结构(LUT),LUT用于实现实际逻辑电路的功能,LUT本质上是一个RAM,事先将相应的结果

    2024年01月17日
    浏览(36)
  • FPGA基础设计(八):串口访问ROM

    将ROM中的数据读取出来,通过串口发送到上位机。 1、按键消抖模块 2、ROM控制器模块 3、创建ROM IP核模块 4、串口发送模块 前面已经设计好了串口发送模块和按键消抖模块,还剩ROM IP的创建和控制ROM模块的设计。 读ROM控制模块设计 : 1、 address :读地址端口 2、 q :读数据端

    2024年02月03日
    浏览(64)
  • FPGA基础设计之数码管显示

    数码管是一种半导体发光器件,其基本单元是发光二极管。一般分为七段数码管和八段数码管,多的一段是小数点。也有其他如N型、米型数码管以及16段、24段管等。本次设计的是八段数码管 公阴极数码管高电平亮,公阳极数码管低电平亮。AC620上搭载的是公阳极数码管。 数

    2023年04月26日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包