4. 基础时序逻辑IP

任务目标

在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

运行与验证

  1. 引脚约束:将seg_sel[3:0]连接至4位位选引脚,seg_data[6:0]连接至a~g段引脚(共阴极接法)。
  2. 输入赋值:在顶层模块中例化本模块,将bcd0~bcd3分别连接至拨码开关或直接赋常量(如bcd0=4'd5, bcd1=4'd2, bcd2=4'd0, bcd3=4'd1)。
  3. 综合下载:完成综合、实现并生成比特流下载至FPGA。

通过条件:数码管稳定显示“1205”(千位1、百位2、十位0、个位5),无闪烁或明显暗亮不均。若显示乱码,检查段码极性(共阴/共阳)与位选有效电平是否匹配。

关键说明

  • 扫描频率约1kHz(每位点亮1ms),远高于人眼闪烁融合频率,显示稳定。
  • 段码表按共阴极定义,若板卡为共阳极需将seg_data逐位取反。
  • 位选信号低有效,若板卡高有效需将seg_sel取反。