静态显示的内容都是一样的(段选信号是连接在一起的),此处引出动态显示,使得每个数码位独立地显示内容。
前言
数码动态显示的工作原理是动态扫描
,利用了两个现象:人眼视觉暂留特性:光信号传入大脑神经需要一段时间,光的作用结束之后,人的视觉影像并不会立刻消失,这种残留的视觉被称为后向,这种现象成为视觉暂留;第二个现象是数码管的余晖效应:当停止向发光二极管供电时,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始终为低电平;
使能信号初始为低电平,复位信号无效时保持高电平。