数码管动态显示(一)

静态显示的内容都是一样的(段选信号是连接在一起的),此处引出动态显示,使得每个数码位独立地显示内容。


前言

数码动态显示的工作原理是动态扫描,利用了两个现象:人眼视觉暂留特性:光信号传入大脑神经需要一段时间,光的作用结束之后,人的视觉影像并不会立刻消失,这种残留的视觉被称为后向,这种现象成为视觉暂留;第二个现象是数码管的余晖效应:当停止向发光二极管供电时,LED的亮度仍能维持一段时间。

选中第一个数码位sel[0],让其显示数字1,显示周期为T;显示完毕后,立刻只选中第二个数码位,让其显示数字2,显示周期为T…一共显示1 2 3 4 5 6 这6个数字,并以这6个数字为一周期(6T)进行循环。

令T为1ms,那么这6个数字会依次闪烁显示,每个数字显示时间为1ms,但是这些数字切换的频率太快,肉眼不能分辨这种闪烁,就会误以为这6个数码管在同时进行显示。

此次实验目标为:十进制的0记数到十进制的最大值999_999,让其归零并循环显示,每个数字每0.1s(计数器记数)让其+1。


一、系统框图

在这里插入图片描述两路输入信号,四路输出信号。这4路输出都是传输到595芯片。

定义一个新的子功能模块用于产生所需要的数据(数据产生模块):两路输入(时钟和复位),一路输出(data)。由于动态显示模块功能增加(输入部分point、sign、en),数据生成模块也要输出相应的模块,此时为4路输出。
在这里插入图片描述
在这里插入图片描述

数码管的显示模块涉及温湿度的显示,故增加小数点的输入端口(point),因为是6位8段数码管,故有6位位宽。
数码管的显示模块还涉及电压的显示,故增加一个符号位(sign),可以进行负数的显示。
最后增加一个使能端口(seg_en),当使能信号为有效的高电平时,数码管正常显示;为低电平时不工作。

对动态显示模块继续进行功能的划分:第一个模块是动态显示驱动(seg_dynamic),第二个模块是595控制模块(hc595_ctrl)。
在这里插入图片描述划分的原因是595控制模块在静态显示中已经实现,可以直接调用。使用动态显示驱动模块生成位选信号和段选信号,595控制模块将位选信号和段选信号转换成ds、oe、shcp和stcp四路信号传入到595控制芯片。
在这里插入图片描述
系统框图:
在这里插入图片描述


二、波形图

在这里插入图片描述十进制的999999对应20位二进制;小数点没有用,point为0;由于输出为0到最大值,没有负号,sign为低电平;使能信号初始值为0,当复位信号无效时将其拉高。


三、rtl代码

//数据生成模块代码
module  generat
#(
    parameter   CNT_MAX = 23'd4999_999, //100ms计数值
    parameter   DATA_MAX= 20'd999_999   //显示的最大值
)
(
    input   wire            sys_clk     ,   //系统时钟,频率50MHz
    input   wire            sys_rst_n   ,   //复位信号,低电平有效

    output  reg     [19:0]  data        ,   //数码管要显示的值
    output  wire    [5:0]   point       ,   //小数点显示,高电平有效
    output  reg             seg_en      ,   //数码管使能信号,高电平有效
    output  wire            sign            //符号位,高电平显示负号
);

reg     [22:0]  cnt_100ms   ;   //100ms计数器,十进制的4999999对应23位二进制
reg             cnt_flag    ;   //100ms标志信号

assign  point   =   6'b000_000;
assign  sign    =   1'b0;

//cnt_100ms:用50MHz时钟从0到4999_999计数即为100ms
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_100ms   <=  23'd0;
    else    if(cnt_100ms == CNT_MAX)
        cnt_100ms   <=  23'd0;
    else
        cnt_100ms   <=  cnt_100ms + 1'b1;

//cnt_flag:每100ms产生一个标志信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_flag    <=  1'b0;
    else    if(cnt_100ms == CNT_MAX - 1'b1)
        cnt_flag    <=  1'b1;
    else
        cnt_flag    <=  1'b0;

//数码管显示的数据:0-999_999
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data    <=  20'd0;
    else    if((data == DATA_MAX) && (cnt_flag == 1'b1))
        data    <=  20'd0;
    else    if(cnt_flag == 1'b1)
        data    <=  data + 1'b1;
    else
        data    <=  data;

//数码管使能信号给高即可
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg_en  <=  1'b0;
    else
        seg_en  <=  1'b1;

endmodule

四、测试代码

`timescale  1ns/1ns
module  tb_generat();

reg     sys_clk     ;
reg     sys_rst_n   ;

wire     [19:0]  data;  
wire    [5:0]   point;
wire             seg_en;
wire            sign; 

initial
    begin
        sys_clk     =   1'b1;
        sys_rst_n   <=  1'b0;
        #30
        sys_rst_n   <=  1'b1;
    end

//clk:产生时钟
always  #10 sys_clk <=  ~sys_clk;

generat
#(
    .CNT_MAX (9), //100ms计数值
    .DATA_MAX(9)  //显示的最大值
)
generat_inst
(
    .sys_clk   (sys_clk   )  ,   //系统时钟,频率50MHz
    .sys_rst_n (sys_rst_n )  ,   //复位信号,低电平有效
    .data      (data      )  ,   //数码管要显示的值
    .point     (point     )  ,   //小数点显示,高电平有效
    .seg_en    (seg_en    )  ,   //数码管使能信号,高电平有效
    .sign      (sign      )      //符号位,高电平显示负号
);
endmodule

五、仿真结果

在这里插入图片描述复位信号首先为低电平,然后拉高;
计数器(cnt_100ms)初值为0,当计数器记数到最大值归零;
flag信号初值为低电平,当计数器记数到最大值-1时,flag信号保持一个周期的高脉冲;
待显示数据data初值为0,flag信号对应高电平时data自+1,当data记数到最大值且flag为高电平时归零;
小数点信号point始终为0;
符号位sign始终为低电平;
使能信号初始为低电平,复位信号无效时保持高电平。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小年痴槑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值