22-数码管的动态显示01
1.数码管动态显示
- 不同位的数码管显示不同的数值
- 使用动态扫描的方式,使用6位8段数码管显示1,2,3,4,5,6,选中第一个数码管让其显示1,显示时间位T;经过时间T之后选中第二个数码管显示2,显示时间为T,依次进行相似的操作,显示到6之后,经过时间T之后再显示1
- 显示一个周期所有的时间为6个周期,6T,如果T为1s则六位8段数码管依次显示1,2,3,4,5,6显示时间间隔为1s
- T = 0.2s,会进行闪烁显示
- T = 1ms,闪烁频率过快,肉眼不能分辨出闪烁,近似常亮
- 视觉暂留:人眼在观察景物的时候,光信号传递到大脑需要一定的时间,光的作用结束之后,视觉影像不会立刻消失,这种残留的视觉称之为后像,这种现象称之为视觉暂留。
- 数码管的余晖效应:停止向数码管供电之后,数码管的亮度还能够维持一段时间。
- 人眼可见的频率在60Hz
2.FPGA
使用6位8段数码管显示从0-999999,计数到最大值之后循环显示,每0.1s加1
2.1 模块框图
2.1.1 顶层模块框图
2.1.2 产生数据模块框图
显示的数据需要一个新的模块产生data_gen
2.1.3 数码管动态显示的模块
- 输入信号有时钟和复位信号sys_clk,sys_rst_n
- 需要输入数据生成模块生成的数据,seg_595_dynamic
- 数码管动态显示芯片经常用到,所以增加一些功能,增加显示小数点的功能,输入小数点信号point,使用的是6位8段数码管,所以小数点位数是6bit
- 增加一个符号位sign,可以用于显示符号
- 增加一个使能端口seg_en,更好的控制数码管的显示,高电平显示数据,低电平不显示数据
2.1.4 动态显示驱动模块和控制模块
参考数码管静态显示,将seg_595_dynamic模块划分为两个模块,一个是动态显示驱动模块,第二个是595控制模块
- seg_dynamic - 产生位选信号和段选信号
2.1.5 seg_595_dynamic框图
2.1.6 系统框图绘制
2.2 波形图
2.2.1 数据生成模块波形图
- 生成一个计数器cnt_100ms变量对0.1s进行计数
- 系统时钟是50MHz,周期20ns,0.1s = 100ms = 1*10^8ns
- 计数个数:5*10^6
- 计数最大值是:4999_999
- 生成计数器标志信号:cnt_flag(计数器计数到最大值减一的时候拉高一个时钟周期)
- 待显示数据生成,初值为0,在第一个0.1s内显示为0,当cnt_flag为高的时候,显示数据加1,计数到最大值,归0
- 小数点位数据,定义为高电平小数点位有效,这里一直保持无效的低电平
- 符号位波形绘制,高电平有效,这里一直保持为高电平(计数值都是正的)
- 数码管使能信号,初值为低电平,这里信号始终保持高电平,因为数码管一直有效
2.3 RTL
2.3.1 数据生成模块
module data_gen
#(
parameter CNT_MAX = 23'd4999_999,
parameter DATA_MAX = 20'd999_999
)
(
input wire sys_clk,
input wire sys_rst_n,
output reg [19:0] data,
output wire [5:0] point,
output wire sign,
output reg seg_en
);
reg [22:0] cnt_100ms;
reg cnt_flag;
always @ (posedge sys_clk or negedge sys_rst_clk)
if(sys_rst_n == 1'b0)
cnt_100ms <= 23'd0;
else if(cnt_100ms == CNT_MAX)
cnt_100ms <= 23'd0;
else
cnt_100ms <= 23'd0 + 1'b1;
always @ (posedge sys_clk or negedge sys_rst_clk)
if(sys_rst_n == 1'b0)
cnt_flag <= 1'b0;
else if(cnt_100ms == CNT_MAX-1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
always @ (posedge sys_clk or negedge sys_rst_clk)
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;
// 小数点赋值
assign point = 6'b000_000
// 符号位
assign sign = 1'b0;
// 使能信号
always @ (posedge sys_clk or negedge sys_rst_clk)
if(sys_rst_n == 1'b0)
seg_en <= 1'b0;
else
seg_en <= 1'b1;
endmodule
2.3.2 数据生成模块testbench
module tb_data_gen();
input reg sys_clk;
input reg sys_rst_n;
output wire [19:0] data;
output wire [5:0] point;
output wire sign;
output wire seg_en;
always #10 sys_clk = -sys_clk;
module data_gen
#(
.CNT_MAX (23'd4999_999),
.DATA_MAX (20'd999_999)
)
(
.sys_clk (sys_clk),
.sys_rst_n,
.data (data),
.point (point),
.sign (sign),
.seg_en (seg_en)
);
endmodule