4. 数码管动态扫描显示
任务目标
在FPGA开发板上驱动4位共阴极数码管,通过动态扫描方式分时点亮各位,利用视觉暂留效应形成稳定显示。设计包含:BCD码到七段码的译码逻辑、4位扫描计数器、位选与段选输出。
环境与依赖
- 开发板:任意含4位数码管(共阴极)的FPGA板卡(如Altera DE2-115、Xilinx Basys3)
- 时钟:板载50MHz系统时钟
- 输入:4位BCD码(0~9),此处用拨码开关或直接赋值演示
核心代码
module seg_dynamic_scan (
input clk, // 50MHz
input rst_n, // 低电平复位
input [3:0] bcd0, // 个位 BCD
input [3:0] bcd1, // 十位 BCD
input [3:0] bcd2, // 百位 BCD
input [3:0] bcd3, // 千位 BCD
output reg [3:0] seg_sel, // 位选,低有效
output reg [6:0] seg_data // 段码,共阴极,a~g
);
// 扫描时钟分频:50MHz / 1000 = 50kHz,周期20us
reg [15:0] cnt;
reg scan_clk;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 16'd0;
scan_clk <= 1'b0;
end else if (cnt == 16'd999) begin
cnt <= 16'd0;
scan_clk <= ~scan_clk;
end else begin
cnt <= cnt + 1'b1;
end
end
// 2位扫描计数器
reg [1:0] scan_cnt;
always @(posedge scan_clk or negedge rst_n) begin
if (!rst_n)
scan_cnt <= 2'd0;
else
scan_cnt <= scan_cnt + 1'b1;
end
// 位选输出(低有效)
always @(*) begin
case (scan_cnt)
2'd0: seg_sel = 4'b1110; // 个位
2'd1: seg_sel = 4'b1101; // 十位
2'd2: seg_sel = 4'b1011; // 百位
default: seg_sel = 4'b0111; // 千位
endcase
end
// 当前位BCD选择
reg [3:0] current_bcd;
always @(*) begin
case (scan_cnt)
2'd0: current_bcd = bcd0;
2'd1: current_bcd = bcd1;
2'd2: current_bcd = bcd2;
default: current_bcd = bcd3;
endcase
end
// BCD→七段码译码(共阴极)
always @(*) begin
case (current_bcd)
4'd0: seg_data = 7'b0111111; // 0
4'd1: seg_data = 7'b0000110; // 1
4'd2: seg_data = 7'b1011011; // 2
4'd3: seg_data = 7'b1001111; // 3
4'd4: seg_data = 7'b1100110; // 4
4'd5: seg_data = 7'b1101101; // 5
4'd6: seg_data = 7'b1111101; // 6
4'd7: seg_data = 7'b0000111; // 7
4'd8: seg_data = 7'b1111111; // 8
4'd9: seg_data = 7'b1101111; // 9
default: seg_data = 7'b0000000; // 灭
endcase
end
endmodule
运行与验证
- 引脚约束:将
seg_sel[3:0]连接至4位位选引脚,seg_data[6:0]连接至a~g段引脚(共阴极接法)。 - 输入赋值:在顶层模块中例化本模块,将
bcd0~bcd3分别连接至拨码开关或直接赋常量(如bcd0=4'd5, bcd1=4'd2, bcd2=4'd0, bcd3=4'd1)。 - 综合下载:完成综合、实现并生成比特流下载至FPGA。
通过条件:数码管稳定显示“1205”(千位1、百位2、十位0、个位5),无闪烁或明显暗亮不均。若显示乱码,检查段码极性(共阴/共阳)与位选有效电平是否匹配。
关键说明
- 扫描频率约1kHz(每位点亮1ms),远高于人眼闪烁融合频率,显示稳定。
- 段码表按共阴极定义,若板卡为共阳极需将
seg_data逐位取反。 - 位选信号低有效,若板卡高有效需将
seg_sel取反。