首页 > 其他分享 >FPGA实例——数码管(下)

FPGA实例——数码管(下)

时间:2024-11-09 14:43:49浏览次数:3  
标签:wire FPGA seg 数码管 实例 key parameter reg

前言:

上一篇文章的话是介绍了关于数码管的基础知识和静态数码管的verilog代码,那本章的话将去介绍如何实现动态数码管以及它的verilog代码和展示


动态数码管:

简易计数器:

这里的话主要去介绍一个简易的计数器,由按键控制开始和结束,每秒自加1,从0计到9999,计满后清零

动态数码管显示:

运用余晖效应和数码管特性的结合。通过位选信号去控制数码管点亮,每位点亮的数码管显示的段选位字符都是独立,互不影响的。

余晖效应:

又称视觉暂留现象。简单可以理解成在观察高速移动的物体时,视网膜的图像不会完全在人脑消失,而会驻留一定时间才会消失

数码管特性:

数码管在点亮或熄灭时,往往不会一瞬间就点亮或熄灭,这是一个存在短暂延迟的过程。


思路分析:

为了代码逻辑更加清晰明了,将以三段式状态机来进行RTL的编写,可以分成三个模块,首先有一个顶层模块,其次是一个数码管的显示模块,最后一个是译码模块,还需要再加一个按键模块,可以使用之前的IP核


38译码器:

verilog代码:

数码管动态:
module SMG_DT (
    input  wire        sysclk   ,//系统时钟
    input  wire        rst_n    ,//复位
    input  wire        key_flag ,//按键控制是否开始
    output reg  [3:0]  num      ,//输出的数据
    output reg  [3:0]  sel       //四位位选位
);

parameter IDLE = 5'b00001;//空闲态
parameter GE   = 5'b00010;//个位
parameter SHI  = 5'b00100;//十位
parameter BAI  = 5'b01000;//百位
parameter QIAN = 5'b10000;//千位
reg [4:0] c_state , n_state;//现态和次态

reg en;//使能信号,长信号
parameter delay_1ms = 50_000;//1ms内部晶振次数
parameter delay = 50_000_000;//1s内部晶振次数
reg [26:0] cnt_1s;//1s计时器
reg [15:0] cnt_1ms;//1ms计时器
reg [13:0] number;//计数器,每1s加一次,记到9999清零

wire [3:0] ge   = number%10;
wire [3:0] shi  = number/10%10;
wire [3:0] bai  = number/100%10;
wire [3:0] qian = number/1000;

//对en赋值
always @(posedge sysclk) begin
    if(!rst_n)
       en <= 0;
    else if(key_flag)
       en <= ~en;
    else
       en <= en;
end

//1ms计时器
always @(posedge sysclk) begin
    if(!rst_n)
       cnt_1ms <= 0;
    else if(en)begin
        if(cnt_1ms == delay_1ms - 1)
            cnt_1ms <= 0;
        else 
            cnt_1ms <= cnt_1ms + 1;
    end
    else
        cnt_1ms <= 0;
end

//1s计时器
always @(posedge sysclk) begin
    if(!rst_n)
       cnt_1s <= 0;
    else if(en)begin
        if(cnt_1s == delay - 1)
            cnt_1s <= 0;
        else
            cnt_1s <= cnt_1s + 1;
    end
    else
        cnt_1s <= 0;
end 

//对number进行赋值
always @(posedge sysclk) begin
    if(!rst_n)
       number <= 0;
    else if(cnt_1s == delay - 1 && en)begin
        if(number == 9999)
            number <= 0;
        else
            number <= number + 1;
    end
    else
       number <= number;
end

//状态机第一段
always @(posedge sysclk) begin
    if(!rst_n)
       c_state <= IDLE;
    else
       c_state <= n_state;
end

//状态机第二段
always @(*) begin
    if(!rst_n)
       n_state = IDLE;
    else
       case (c_state)
        IDLE:begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = GE;
            else
               n_state = IDLE;
        end
        GE  :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = SHI;
            else
               n_state = GE;
        end
        SHI :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = BAI;
            else
               n_state = SHI;
        end
        BAI :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = QIAN;
            else
               n_state = BAI;
        end
        QIAN:begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = GE;
            else
               n_state = QIAN;
        end 
        default:n_state = IDLE;
       endcase
end

//状态机第三段
always @(posedge sysclk) begin
    if(!rst_n)begin
       num <= 0;
       sel <= 4'b1111;
    end
    else
       case (c_state)
        IDLE:begin
            num <= 0;
            sel <= 4'b1111;
        end
        GE  :begin
            num <= ge;
            sel <= 4'b0001;
        end
        SHI :begin
            num <= shi;
            sel <= 4'b0010;
        end
        BAI :begin
            num <= bai;
            sel <= 4'b0100;
        end
        QIAN:begin
            num <= qian;
            sel <= 4'b1000;
        end
        default:begin
            num <= 0;
            sel <= 4'b1111;
        end
       endcase       
end

endmodule
译码模块:
module yima (
    input  wire [3:0] num    ,
    output reg  [7:0] seg
);
    
always @(*) begin
    case (num)
        0:seg = 8'b1100_0000;
        1:seg = 8'b1111_1001;
        2:seg = 8'b1010_0100;
        3:seg = 8'b1011_0000;   
        4:seg = 8'b1001_1001;   
        5:seg = 8'b1001_0010;   
        6:seg = 8'b1000_0010;   
        7:seg = 8'b1111_1000;   
        8:seg = 8'b1000_0000;   
        9:seg = 8'b1001_0000;   
        default:seg = 8'b1111_1111;
    endcase
end

endmodule
顶层模块:
module SMG_TOP (
    input  wire       sysclk ,
    input  wire       rst_n  ,
    input  wire       key    ,
    output wire [3:0] sel    ,
    output wire [7:0] seg
 );

wire [3:0] num;
wire key_flag;

SMG_DT SMG_DT_u(
    .  sysclk      (sysclk  ) ,//系统时钟
    .  rst_n       (rst_n   ) ,//复位
    .  key_flag    (key_flag) ,//按键控制是否开始
    .  num         (num     ) ,//输出的数据
    .  sel         (sel     )  //四位位选位
);

yima yima_u(
    . num   (num)   ,
    . seg   (seg)
);

key_flag_0 key_flag_0_u (
  .clk(sysclk),            // input wire clk
  .rst_n(rst_n),        // input wire rst_n
  .key(key),            // input wire key
  .key_flag(key_flag)  // output wire key_flag
);    

    
endmodule
现象展示:
<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="i8lUMbdy-1730939907353" src="https://live.csdn.net/v/embed/432905"></iframe>

数码管简易计数器

总结:

通过以上的模块等就可以去实现一个数码管的简易计数器,它主要的话是通过余晖效应和根据数码管的一些特征,运用三段式状态机去实现该实验


简易计时器:

计时器和计数器的话其实大致都差不多,最主要的就是再计时器模块需要去考虑如何在计时满59的时候向前进位,只需要修改我们的数码管显示模块,其它的可以保持不动

verilog代码:

module SMG_time (
    input  wire        sysclk   ,
    input  wire        rst_n    ,
    input  wire        key_flag ,
    output reg  [3:0]  num      ,
    output reg  [3:0]  sel 
);
    
parameter IDLE = 5'b00001;
parameter GE   = 5'b00010;
parameter SHI  = 5'b00100;
parameter BAI  = 5'b01000;
parameter QIAN = 5'b10000;
reg [4:0] c_state , n_state;

parameter delay_1ms = 50_000;
parameter delay_1s  = 50_000_000;
reg [25:0] cnt_1s;//1s内部时钟晶振
reg [15:0] cnt_1ms;//1ms内部时钟晶振
reg [6:0] miao;
reg [6:0] fen;
reg en;//按键使能信号

//按键使能信号en
always @(posedge sysclk) begin
    if(!rst_n)
       en <= 0;
    else if(key_flag)
       en <= ~en;
    else
       en <= en;
end 

//1s计时器
always @(posedge sysclk) begin
    if(!rst_n)
        cnt_1s <= 0;
    else if(en)begin
        if(cnt_1s == delay_1s - 1)
           cnt_1s <= 0;
        else
           cnt_1s <= cnt_1s + 1;
    end
    else
        cnt_1s <= 0;
end

//1ms计时器
always @(posedge sysclk) begin
    if(!rst_n)
        cnt_1ms <= 0;
    else if(en)begin
        if(cnt_1ms == delay_1ms - 1)
           cnt_1ms <= 0;
        else
           cnt_1ms <= cnt_1ms + 1;
    end
    else
        cnt_1ms <= 0;
end

//对miao和fen赋值
always @(posedge sysclk) begin
    if(!rst_n)begin
        miao <= 0;
        fen  <= 0;
    end
    else if(cnt_1s == delay_1s - 1 && en)begin
            if(miao < 59)
               miao <= miao + 1;
            else begin
               miao <= 0;
            if(fen < 59)
               fen <= fen + 1;
            else
               fen <= 0;
            end               
    end
    else begin
        miao <= miao;
        fen  <= fen;
    end      
end    

//状态机第一段
always @(posedge sysclk) begin
    if(!rst_n)
       c_state <= IDLE;
    else
       c_state <= n_state;
end

//状态机第二段
always @(*) begin
    if(!rst_n)
       n_state = IDLE;
    else
       case (c_state)
        IDLE :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = GE;
            else
               n_state = IDLE;
        end
        GE   :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = SHI;
            else
               n_state = GE;
        end
        SHI  :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = BAI;
            else
               n_state = SHI;
        end
        BAI  :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = QIAN;
            else
               n_state = BAI;
        end
        QIAN :begin
            if(en && cnt_1ms == delay_1ms - 1)
               n_state = GE;
            else
               n_state = QIAN;
        end
        default:n_state = IDLE ;
       endcase
end

//状态机第三段
always @(posedge sysclk) begin
    if(!rst_n)begin
        num <= 0;
        sel <= 4'b1111;
    end
    case (c_state)
        IDLE :begin
            num <= 0;
            sel <= 4'b1111;
        end
        GE   :begin
            num <= miao%10;
            sel <= 4'b0001;
        end
        SHI  :begin
            num <= miao/10;
            sel <= 4'b0010;
        end
        BAI  :begin
            num <= fen%10;
            sel <= 4'b0100;
        end
        QIAN :begin
            num <= fen/10;
            sel <= 4'b1000;
        end
        default:begin
            num <= 0;
            sel <= 4'b1111;
        end 
    endcase
end

endmodule

这个的话就是我们计时器的一个数码管显示代码,将它给例化到之前的那个数码管顶层文件里去替换掉计数器代码,然后绑定管脚上板,管脚的绑定方法在上一章节里已经提过了,有需要的可以自行去查看

现象展示:

<iframe allowfullscreen="true" data-mediaembed="csdn" frameborder="0" id="iqFHbMsi-1730939936636" src="https://live.csdn.net/v/embed/432906"></iframe>

数码管简易计时器

总结:

本次的话主要是以两个小的实例去展示了动态数码管的一个思路和方法,关于数码管的实例还有很多,感兴趣的朋友可以自行去研究。数码管的知识到这里就结束了,有错误的地方希望大家可以指出,谢谢!

标签:wire,FPGA,seg,数码管,实例,key,parameter,reg
From: https://blog.csdn.net/joker0518/article/details/143571465

相关文章

  • 看一遍就会用——面向对象:类和对象,实例属性,实例方法,字符串表示
    python面向对象1.类和对象2.实例属性3.实例方法4.字符串表示1.__str__方法2.__repr__方法1.类和对象在Python中,类和对象是面向对象编程(OOP)的核心概念。类(Class)是创建对象的蓝图或模板,它定义了对象将拥有的属性和方法。对象(Object)则是根据类创建的具体实例,它包含了类......
  • FPGA 第二讲 初始FPGA
    时间:2024.11.4-11.5一、学习内容1.FPGA是什么1.1名词解释:FPGA(FieldProgrammableGateArray,简称FPGA),现场可编程门阵列,一种以数字电路为主的集成芯片,属于可编程逻辑器件PLD(ProgrammableLogicDevice)的一种。 1.2发展历程集成电路:我们常说的IC,就是把一定数量的常用的......
  • Lattice、Xilinx FPGA reg初始化赋值问题
    一、起因最近在开发Lattice的一款低功耗FPGA时,遇到了reg初始化复位问题,经过在网上搜寻相关资料整理如下;二、FPGA中reg的初始化方式在定义时初始化,例如:regr_test=1'b1;在复位语句中,对reg进行赋值,例如:regr_test;always@(posedgesys_clk)beginif(~sys_rst_n)beg......
  • Hadoop及Spark环境配置与运行实例
    一、参考资料重要说明本文章为大数据分析课程实验之Hadoop与Spark平台配置记录及示例演示,其中Hadoop配置部分绝大多数内容源自参考资料:华为云:Hadoop安装教程(单机/伪分布式配置)、CSDN:Hadoop安装教程(单机/伪分布式配置)(两文章内容相同且均为同一作者:@华东设计之美);Spark配置部分......
  • C++ 模板显式实例化
    //template.hpptemplate<typenameT>classDylan{public:Dylan(Tt);Tm_data;};//template.cpp#include"template.hpp"template<typenameT>Dylan<T>::Dylan(Tt){m_data=t;}templateclassDylan<int&g......
  • fpga LCD屏幕显示
    目录matlab生成coe文件150x150的JPG转化为coe文件 ROMip核配置​编辑LCD显示驱动代码 原理和vga一致。 vga_parameter_cfg,v gen_data vga_driver vga_toptop_pin_xdc上板验证matlab生成coe文件150x150的JPG转化为coe文件%实现将图片的格式转换为数据处......
  • 基于Zynq FPGA对雷龙SD NAND的测试
    一、SDNAND特征1.1SD卡简介雷龙的SDNAND有很多型号,在测试中使用的是CSNP4GCR01-AMW与CSNP32GCR01-AOW。芯片是基于NANDFLASH和SD控制器实现的SD卡。具有强大的坏块管理和纠错功能,并且在意外掉电的情况下同样能保证数据的安全。其特点如下:接口支持SD2......
  • 【YOLOv11[基础]】实例分割Seg | 导出ONNX模型 | ONN模型推理以及检测结果可视化 | py
    本文将导出YOLO-Seg.pt模型对应的ONNX模型,并且使用ONNX模型推理以及结果的可视化。话不多说,先看看效果图吧!!!目录一导出ONNX模型二推理及检测结果可视化1代码2效果图......
  • 2、51单片机实现数码管的数值显示
    2.1、实验目的8位共阴数码管显示8位以内的数字2.2、实验环境普中51开发板(stc89c52、74HC245、74HC138、8位共阴数码管)2.3、实验代码#include<reg52.h> #include<intrins.h> typedefunsignedcharu8; typedefunsignedintu16;staticu8digital_buffer[8]......
  • 使用C++和QT开发应用程序入门以及开发实例分享
    目录1、搭建开发环境(VS2010和QT4.8.2)2、创建一个QT窗口3、在QT窗口中添加子窗口4、QT界面布局5、QT信号(SIGNAL)和槽(SLOT)6、最后C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/125529931C/C++实......