`timescale 1ns / 1ps `default_nettype none // ----------------------------------------------------------------------------- // cpu21_seg7 —— Nexys4DDR 板载 8 位数码管的动态扫描驱动。 // // 输入:seg_data_i 每 4 位一个十六进制数字(低 4 位 = 最右边那个数码管), // an_en_i 每一位对应一个数码管的使能(1 = 显示,0 = 熄灭)。 // 输出:an_o[7:0] 位选(低有效)、seg_o[6:0] 段选 a..g(低有效)、dp_o 小数点。 // // 扫描频率:CLK_DIV 分频后约 1 kHz 切换一位(8 位 => 每位数码管 125 Hz 刷新)。 // 板载数码管是共阳极:位选拉低选中,段选拉低点亮。 // ----------------------------------------------------------------------------- module cpu21_seg7 #( parameter integer REFRESH_DIV = 50000 // 50 MHz / 50000 = 1 kHz ) ( input wire clk, input wire reset, input wire [31:0] seg_data_i, // 8 个十六进制数字 input wire [ 7:0] an_en_i, // 每位是否显示 output reg [ 7:0] an_o, // 位选,低有效 output reg [ 6:0] seg_o, // 段选 a..g,低有效 output reg dp_o // 小数点,低有效 ); // --------------------------------------------------------------------------- // 刷新计数与当前位 // --------------------------------------------------------------------------- reg [15:0] div_q; reg [2:0] digit_q; wire tick = (div_q == (REFRESH_DIV - 1)); always @(posedge clk or posedge reset) begin if (reset) begin div_q <= 16'd0; digit_q <= 3'd0; end else if (tick) begin div_q <= 16'd0; digit_q <= digit_q + 3'd1; end else begin div_q <= div_q + 16'd1; end end // 当前要显示的十六进制数字 reg [3:0] nib; always @* begin case (digit_q) 3'd0: nib = seg_data_i[3:0]; 3'd1: nib = seg_data_i[7:4]; 3'd2: nib = seg_data_i[11:8]; 3'd3: nib = seg_data_i[15:12]; 3'd4: nib = seg_data_i[19:16]; 3'd5: nib = seg_data_i[23:20]; 3'd6: nib = seg_data_i[27:24]; default: nib = seg_data_i[31:28]; endcase end // --------------------------------------------------------------------------- // 十六进制 -> 七段码(bit0=a ... bit6=g,1 表示该段点亮) // --------------------------------------------------------------------------- reg [6:0] seg_on; always @* begin case (nib) 4'h0: seg_on = 7'b0111111; 4'h1: seg_on = 7'b0000110; 4'h2: seg_on = 7'b1011011; 4'h3: seg_on = 7'b1001111; 4'h4: seg_on = 7'b1100110; 4'h5: seg_on = 7'b1101101; 4'h6: seg_on = 7'b1111101; 4'h7: seg_on = 7'b0000111; 4'h8: seg_on = 7'b1111111; 4'h9: seg_on = 7'b1101111; 4'hA: seg_on = 7'b1110111; 4'hB: seg_on = 7'b1111100; 4'hC: seg_on = 7'b0111001; 4'hD: seg_on = 7'b1011110; 4'hE: seg_on = 7'b1111001; default: seg_on = 7'b1110001; // F endcase end // --------------------------------------------------------------------------- // 位选与段选输出(共阳极 => 低有效) // --------------------------------------------------------------------------- always @(posedge clk or posedge reset) begin if (reset) begin an_o <= 8'hFF; seg_o <= 7'h7F; dp_o <= 1'b1; end else if (tick) begin an_o <= ~(8'b0000_0001 << digit_q) | ~an_en_i; seg_o <= ~seg_on; dp_o <= 1'b1; // 不用小数点 end end endmodule `default_nettype wire