- 前言
- 一、数码管驱动
- 二、数码管原理图
- 三、实验任务
- 3.1 任务描述
- 3.2 系统框图
- 3.3 模块原理图
- 3.4 模块代码
- 3.5 测试代码
- 3.6 功能仿真
- 四、引脚分配
- 五、运行效果
- 总结
前言
上期课程中,我们学习了数码管,并通过代码实现了数码管静态显示。本期课程将延续上节课的内容,讲解数码管动态显示。
提示:上节课已经学习了数码管,所以跳过数码管的讲解,直接从数码管驱动开始讲解。
一、数码管驱动 由于段选信号共用,如图2所示,所以在同一时刻只能选择一个数码管,具体选择十位还是个位由位选信号决定。
问:采用此种方式一次只能选择一种数码管,如何能够同时选择多种数码管?
答:视觉暂留现象:物体快速移动时,在大脑中残留的影响会暂留一段时间。
原理图中除了数码管的段选信号,还有数码管未选信号。数码管位选和段选信号都是低电平有效。
三、实验任务 3.1 任务描述
通过使用6位数码管动态显示,实现一个计时器,每0.5秒变化一次,显示数字123456。模块设计如图4所示,一个顶层模块调用两个子模块,time_count是计时模块,sel_led_dynamic是数码管动态显示模块,top_sel_led_dynamic是顶层模块。
- 创建time_count文件,并编写 time_count模块代码。
module time_count( input clk,//时钟频率,50MHz input rst_n,//复位信号,下降沿有效 output reg flag//一个时钟周期的脉冲信号 ); parameter MAX_NUM = 25'd25_000_000;//0.5s时钟 reg [24:0] cnt ;//时钟计数器 //计时器对时钟计数,每0.5s输出一个时钟周期脉冲信号 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin//按下复位信号时 cnt <= 25'd0;//计数器设置位0 flag <= 1'b0;//周期脉冲信号设置位0 end else if(cnt == MAX_NUM - 1'd1)begin//如果时间到 cnt <= 25'd0;//计数器清零 flag <= 1'b1;//周期脉冲信号输出为1,表示记慢一个周期 end else begin//如果时间没有到 cnt <= cnt + 1'd1;//计数器不停计数 flag <= 1'b0;//周期脉冲信号不变 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 ); endmodule3.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)//段选信号 ); endmodule3.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 |
五、运行效果
数码管动态显示
总结
本期课程中,我们讲解了数码管动态显示的原理是改变数码管的位选信号。下期课程中将基于数码管动态显示,制作一个数字时钟。敬请期待!谢谢你的观看!



