1、7段数码管动态扫描驱动模块概述
功能:通过动态扫描方式驱动6位共阳极7段数码管
特性:
(1)支持6位数码管显示(24位输入数据,每4位代表一个数字)
(2)采用动态扫描技术,降低功耗
(3)支持十六进制显示(0-F)
(4)带异步复位功能
2、7段数码管模块硬件原理图+6位一体共阳极数码管
3、7段数码管动态扫描驱动模块的Verilog描述
1 module disp7led_dyna( 2 3 input wire clk, // 系统时钟输入(50MHz) 4 input wire rst_n, // 异步复位信号,低电平有效 5 input wire [23:0] data_in, // 24位显示数据输入,[23:20]为第1位,[3:0]为第6位 6 output reg [5:0] sel6, // 6位数码管位选信号(低电平有效,sel6[0]对应第1位) 7 output reg [7:0] seg7 // 7段+小数点输出(低电平有效,seg7[7]为小数点) 8 ); 9 10 parameter DELAY_1MS = 16'd50_000; // 1ms延时计数值,数码管扫描时间 11 12 // 内部寄存器定义 13 reg [15:0] count; // 1ms定时计数器(16位宽度可支持最大65535个周期) 14 reg [2:0] cnt; // 当前显示位计数器(0-5对应6位数码管) 15 reg [3:0] show_data; // 当前要显示的数字(4位二进制,可表示0-15) 16 17 18 //------------------------------------------------------------------ 19 // 1ms定时器生成逻辑 20 // 功能:产生精确的1ms时间间隔,用于数码管动态扫描 21 // 工作原理:在50MHz时钟下,每计数50,000次产生一个1ms标志 22 //------------------------------------------------------------------ 23 always@(posedge clk or negedge rst_n)begin 24 if(rst_n == 1'b0) 25 count <= 16'b0; // 异步复位,计数器清零 26 else if(count < DELAY_1MS - 1'b1) 27 count <= count + 1'b1; // 计数器递增 28 else 29 count <= 16'b0; // 达到1ms时计数器归零 30 end 31 32 //------------------------------------------------------------------ 33 // 数码管位选择计数器 34 // 功能:循环计数0-5,对应6位数码管 35 // 扫描频率:每1ms切换一位,6ms完成一个完整扫描周期(约167Hz刷新率) 36 //------------------------------------------------------------------ 37 always@(posedge clk or negedge rst_n)begin 38 if(rst_n == 1'b0) 39 cnt <= 3'd0; // 复位时指向第1位数码管 40 else if(count == DELAY_1MS - 1'b1)begin // 每1ms更新一次 41 if(cnt < 3'd6) 42 cnt <= cnt + 1'b1; // 循环计数0→1→2→3→4→5 43 else 44 cnt <= 3'd0; // 计数到5后归零 45 end 46 else 47 cnt <= cnt; // 保持当前计数值 48 end 49 50 //------------------------------------------------------------------ 51 // 数据选择器(多路复用器) 52 // 功能:根据当前位选择对应4位数据输出 53 // 注意:这是组合逻辑电路,无时钟延迟 54 //------------------------------------------------------------------ 55 always@(*)begin 56 case(cnt) 57 3'd0: show_data = data_in[23:20]; // 选择第1位数据(最高4位) 58 3'd1: show_data = data_in[19:16]; // 选择第2位数据 59 3'd2: show_data = data_in[15:12]; // 选择第3位数据 60 3'd3: show_data = data_in[11:8]; // 选择第4位数据 61 3'd4: show_data = data_in[7:4]; // 选择第5位数据 62 3'd5: show_data = data_in[3:0]; // 选择第6位数据(最低4位) 63 default: show_data = 4'b0000; // 默认情况(理论上不会发生) 64 endcase 65 end 66 67 //------------------------------------------------------------------ 68 // 7段译码器(带小数点) 69 // 功能:将4位二进制数转换为7段数码管控制信号 70 // 编码规则(共阳极数码管,低电平有效): 71 // seg7[7] = dp (小数点) 72 // seg7[6:0] = g f e d c b a (从高位到低位) 73 // 注意:此实现未使用小数点(默认熄灭) 74 //------------------------------------------------------------------ 75 always@(posedge clk or negedge rst_n)begin 76 if(rst_n == 1'b0) 77 seg7 <= 8'b1111_1111; // 复位时关闭所有段 78 else 79 case(show_data) 80 4'd0: seg7 = 8'b1100_0000; // 显示"0" 81 4'd1: seg7 = 8'b1111_1001; // 显示"1" 82 4'd2: seg7 = 8'b1010_0100; // 显示"2" 83 4'd3: seg7 = 8'b1011_0000; // 显示"3" 84 4'd4: seg7 = 8'b1001_1001; // 显示"4" 85 4'd5: seg7 = 8'b1001_0010; // 显示"5" 86 4'd6: seg7 = 8'b1000_0010; // 显示"6" 87 4'd7: seg7 = 8'b1111_1000; // 显示"7" 88 4'd8: seg7 = 8'b1000_0000; // 显示"8" 89 4'd9: seg7 = 8'b1001_0000; // 显示"9" 90 4'd10:seg7 = 8'b1000_1000; // 显示"A" 91 4'd11:seg7 = 8'b1000_0011; // 显示"b" 92 4'd12:seg7 = 8'b1100_0110; // 显示"C" 93 4'd13:seg7 = 8'b1010_0001; // 显示"d" 94 4'd14:seg7 = 8'b1000_0110; // 显示"E" 95 4'd15:seg7 = 8'b1000_1110; // 显示"F" 96 default: seg7 <= 8'b1111_1111; // 默认关闭所有段 97 endcase 98 end 99 100 //------------------------------------------------------------------ 101 // 位选信号生成器 102 // 功能:根据当前位计数器生成对应的位选信号 103 // 特性: 104 // - 低电平有效(0表示选中对应位数码管) 105 // - 每次只选中一位,实现动态扫描 106 //------------------------------------------------------------------ 107 always@(posedge clk or negedge rst_n)begin 108 if(rst_n == 1'b0) 109 sel6 <= 6'b11_1111; // 复位时关闭所有位数码管 110 case(cnt) 111 3'd0: sel6 <= 6'b11_1110; // 选中第1位数码管(sel6[0]=0) 112 3'd1: sel6 <= 6'b11_1101; // 选中第2位数码管(sel6[1]=0) 113 3'd2: sel6 <= 6'b11_1011; // 选中第3位数码管(sel6[2]=0) 114 3'd3: sel6 <= 6'b11_0111; // 选中第4位数码管(sel6[3]=0) 115 3'd4: sel6 <= 6'b10_1111; // 选中第5位数码管(sel6[4]=0) 116 3'd5: sel6 <= 6'b01_1111; // 选中第6位数码管(sel6[5]=0) 117 default: sel6 <= 6'b11_1111; // 默认关闭所有位数码管 118 endcase 119 end 120 121 endmodule
4、7段数码管动态扫描驱动模块的测试平台
功能:对disp7led_dyna模块进行仿真测试
测试内容:复位功能测试、动态扫描时序测试、数据显示正确性测试

1 `timescale 1ns/1ns // 仿真时间单位1ns,精度1ns 2 3 module disp7led_dyna_tb(); 4 5 // 测试信号定义 6 reg clk; // 模拟系统时钟信号(50MHz,周期20ns) 7 reg rst_n; // 模拟异步复位信号,低电平有效 8 reg [23:0] data_in; // 模拟24位显示数据输入,[23:20]为第1位,[3:0]为第6位 9 10 wire [5:0] sel6; // 监测位选信号输出(低电平有效,sel6[0]对应第1位) 11 wire [7:0] seg7; // 监测段选信号输出(低电平有效,seg7[7]为小数点) 12 13 // 实例化被测模块 14 disp7led_dyna uut( 15 .clk (clk), // 连接测试时钟 16 .rst_n (rst_n), // 连接测试复位信号 17 .data_in (data_in), // 连接测试数据输入 18 .sel6 (sel6), // 连接位选信号输出 19 .seg7 (seg7) // 连接段选信号输出 20 ); 21 22 // 修改被测模块参数(缩短仿真时间) 23 // 将原1ms扫描间隔缩短为50个时钟周期(1us) 24 defparam uut.DELAY_1MS = 50; 25 26 // 时钟信号生成(50MHz) 27 initial clk = 1'b0; // 初始时钟置0 28 always #10 clk = ~clk; // 每10ns翻转一次(周期20ns) 29 30 // 测试激励生成 31 initial begin 32 rst_n = 1'b0; // 复位信号有效(低电平) 33 data_in = 24'h123456; // 测试数据:6位数码管显示1-2-3-4-5-6 34 #203; // 等待203ns(超过10个时钟周期) 35 rst_n = 1'b1; // 释放复位(开始正常工作) 36 37 // 观察完整扫描周期 38 // 等待2个完整扫描周期(6位数×50周期×2次) 39 #(20*50*6*2); 40 $stop; // 停止仿真(在Modelsim等工具中暂停) 41 end 42 43 endmodule
提示:当数码管的段选段(seg7)和位选段(sel)不同步时,就会导致选中的管子和想要显示的数字不是完全同步的,由于不同步的时间相对比较少,所以显示出错误的数字的时间较短,点亮的程度就会比较小,称为“鬼影”。
5、7段数码管动态扫描驱动顶层模块+开发板测试
-
主要用于测试和展示disp7led_dyna模块的功能
-
实际使用时,可将data_in替换为需要显示的真实数据
1 // 7段数码管动态扫描驱动顶层模块 2 // 功能:实例化动态扫描驱动模块并提供测试数据 3 // 特性: 4 // 1. 连接系统时钟和复位信号 5 // 2. 提供固定的24位测试数据(0x123456) 6 // 3. 输出数码管位选和段选信号 7 module disp7led_dyna_top( 8 input wire clk, // 系统时钟输入(50MHz) 9 input wire rst_n, // 异步复位信号,低电平有效 10 output wire [5:0] sel6, // 6位数码管位选信号输出,低电平有效,sel6[0]对应最左边的数码管 11 output wire [7:0] seg7 // 7段数码管段选信号输出(包含小数点) 12 ); 13 14 // 内部信号定义 15 wire [23:0] data_in; // 24位显示数据线 16 17 assign data_in = 24'h123456; // 将24'h123456固定赋值给data_in 18 19 // 动态扫描驱动模块实例化 20 // 将顶层模块的端口与驱动模块连接 21 disp7led_dyna uut( 22 .clk (clk), // 连接系统时钟 23 .rst_n (rst_n), // 连接复位信号 24 .data_in (data_in), // 连接显示数据 25 .sel6 (sel6), // 连接位选信号输出 26 .seg7 (seg7) // 连接段选信号输出 27 ); 28 29 endmodule