前言
上期课程中,我们学习了数码管,并通过代码实现了数码管静态显示。本期课程将延续上节课的内容,讲解数码管动态显示。
提示:上节课已经学习了数码管,所以跳过数码管的讲解,直接从数码管驱动开始讲解。
一、数码管驱动
由于段选信号共用,如图2所示,所以在同一时刻只能选择一个数码管,具体选择十位还是个位由位选信号决定。
问:采用此种方式一次只能选择一种数码管,如何能够同时选择多种数码管?
答:视觉暂留现象:物体快速移动时,在大脑中残留的影响会暂留一段时间。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/654b47569b366db2bb4700080dc3f223.png)
二、数码管原理图
原理图中除了数码管的段选信号,还有数码管位选信号。数码管位选和段选信号都是低电平有效。
三、实验任务
3.1 任务描述
通过使用6位数码管动态显示,实现一个计时器,每0.5秒变化一次,显示数字123456。模块设计如图4所示,一个顶层模块调用两个子模块,time_count是计时模块,sel_led_dynamic是数码管动态显示模块,top_sel_led_dynamic是顶层模块。
3.2 系统框图
3.3 模块原理图
3.4 模块代码
- 创建time_count文件,并编写 time_count模块代码。
module time_count(
input clk ,//50MHz时钟信号
input rst_n,//复位信号
output reg flag//一个时钟周期的脉冲信号
);
parameter MAX_NUM = 26'd25_000_000;//计数器最大计数值
reg [25:0] cnt ; //时钟分频计数器
//计数器对时钟计数,每0.5s,输出一个时钟周期脉冲信号
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin//按复位时
flag <= 1'b0;//信号为0
cnt <= 26'd0;//计数器清零
end
else if(cnt < MAX_NUM - 1'b1)begin//如果没到时间
flag <= 1'b0;//信号为0
cnt <= cnt + 1'b1;//计数器正常累计+1
end
else begin //否则到时间
flag <= 1'b1;//信号变为1
cnt <= 26'd0;
end
end
endmodule
- 创建sel_led_dynamic文件,并编写 sel_led_dynamic模块代码。
module sel_led_dynamic(
input clk ,//时钟,50MHz
input rst_n,//复位信号,下降沿有效
input flag ,//周期信号
output reg [5:0] sel ,//位选信号,六个数码管
output reg [7:0] seg //段选信号,八段led
);
reg [2:0] cstat ;//当前状态
reg [2:0] nstat ;//下一个状态
//状态跳转
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin//下降沿有效
cstat <= 3'd0;//当前状态置0
end
else begin
cstat <= nstat;//状态跳转
end
end
//下一个状态判断(组合逻辑)
always@(*)begin
case(cstat)
3'd0: if(flag)begin
nstat = 3'd1;
end
else begin
nstat = 3'd0;
end
3'd1: if(flag)begin
nstat = 3'd2;
end
else begin
nstat = 3'd1;
end
3'd2: if(flag)begin
nstat = 3'd3;
end
else begin
nstat = 3'd2;
end
3'd3: if(flag)begin
nstat = 3'd4;
end
else begin
nstat = 3'd3;
end
3'd4: if(flag)begin
nstat = 3'd5;
end
else begin
nstat = 3'd4;
end
3'd5: if(flag)begin
nstat = 3'd0;
end
else begin
nstat = 3'd5;
end
default: nstat= 3'd1;
endcase
end
reg [2:0] value;
//各个状态下的动作(可以组合也可以时序)
always@(*)begin
if(!rst_n)begin
value = 3'd0;
end
else begin
case(cstat)
3'd0: begin
sel = 6'b111_110;//选择最右边数码管。 sel低有效
value = 3'd1;
end
3'd1: begin
sel = 6'b111_101;
value = 3'd2;
end
3'd2: begin
sel = 6'b111_011;
value = 3'd3;
end
3'd3: begin
sel = 6'b110_111;
value = 3'd4;
end
3'd4: begin
sel = 6'b101_111;
value = 3'd5;
end
3'd5: begin
sel = 6'b011_111;
value = 3'd6;
end
default: begin//默认就第1种情况
sel = 6'b111_110;
value = 3'd1;
end
endcase
end
end
//数码管seg的输出
always@(*)begin
if(!rst_n)begin
seg = 8'b00000000;
end
else begin
case(value)
3'd1: seg = 8'b11111001;//根据数码管真值表查找
3'd2: seg = 8'b10100100;
3'd3: seg = 8'b10110000;
3'd4: seg = 8'b10011001;
3'd5: seg = 8'b10010010;
3'd6: seg = 8'b10000010;
default : seg = 8'b00000000;
endcase
end
end
endmodule
- 创建top_sel_led_dynamic文件,并编写 top_sel_led_dynamic模块代码。
module top_sel_led_dynamic(
input clk ,//时钟信号,50MHz
input rst_n,//复位信号,下降沿有效
output [5:0] sel ,//位选信号
output [7:0] seg //段选信号
);
wire flag;//wire连接两个模块
parameter MAX_NUM = 25'd25_000_000;
time_count #(.MAX_NUM(MAX_NUM)) u_time_count(//实例化计时器模块
.clk (clk) ,//时钟频率,50MHz
.rst_n (rst_n),//复位信号,下降沿有效
.flag (flag) //一个时钟周期的脉冲信号
);
sel_led_dynamic u_sel_led_dynamic(//实例化数码管动态显示模块
.clk (clk) ,//时钟信号
.rst_n (rst_n),//复位信号,下降沿有效
.flag (flag) ,//周期信号
.sel (sel) ,//位选信号,六个数码管
.seg (seg) //段选信号,八段led
);
endmodule
3.5 测试代码
创建top_sel_led_dynamic_tb测试文件,并编写 top_sel_led_dynamic_tb测试模块代码。
`timescale 1ns/1ns//单位1ns/精度1ns
module top_sel_led_dynamic_tb();
reg clk ;
reg rst_n;
wire [5:0] sel ;
wire [7:0] seg ;
parameter CYCLE = 5'd20 ;//20ns
parameter MAX_NUM = 7'd100;//计时100x20ns
always #(CYCLE/2) clk = ~clk;//10ns翻转时钟
initial begin
clk = 1'b0 ;//时钟置0
rst_n = 1'b0 ;//复位信号置0
#(CYCLE) ;//延迟20ns
rst_n = 1'b1 ;//复位信号置1
#(MAX_NUM * CYCLE * 6);//观看六个数码管的情况
$stop ;//停止
end
top_sel_led_dynamic #(.MAX_NUM(MAX_NUM)) u_top_sel_led_dynamic(
.clk (clk) ,//时钟信号,50MHz
.rst_n (rst_n),//复位信号,下降沿有效
.sel (sel) ,//位选信号
.seg (seg)//段选信号
);
endmodule
3.6 功能仿真
在功能仿真中,与数码管静态显示不同的地方就是sel位选信号不停改变。seg是段选信号,不同的段选信号对应1—6个数字。
四、引脚分配
元件 | 管脚 |
---|---|
SEL0 | A4 |
SEL1 | B4 |
SEL2 | A3 |
SEL3 | B3 |
SEL4 | A2 |
SEL5 | B1 |
DIG0 | B7 |
DIG1 | A8 |
DIG2 | A6 |
DIG3 | B5 |
DIG4 | B6 |
DIG5 | A7 |
DIG6 | B8 |
DIG7 | A5 |
CLOCK(时钟) | E1 |
KEY1 | E15 |
五、运行效果
数码管动态显示
总结
本期课程中,我们讲解了数码管动态显示的原理是改变数码管的位选信号。下期课程中将基于数码管动态显示,制作一个数字时钟。敬请期待!谢谢你的观看!