module dtube_control_4(
input clk, //时钟信号,50Mhz
input rst_n, //复位信号,低电平有效
input [15:0] display_num, //数码管显示数据,
// [15:12]——数码管千位,[11:8]——数码管百位,[7:4]——数码管百位,[3:0]——数码管个位,
output reg [7:0] dtube_seg, //数码管的段选端(包括小数点)
output reg [3:0] dtube_sel //数码管的位选端
);
//共阴型数码管,数码管显示0-f对应的段选输出信号
// parameter NUM0 = 8'h3f,
// NUM1 = 8'h06,
// NUM2 = 8'h5b,
// NUM3 = 8'h4f,
// NUM4 = 8'h66,
// NUM5 = 8'h6d,
// NUM6 = 8'h7d,
// NUM7 = 8'h07,
// NUM8 = 8'h7f,
// NUM9 = 8'h6f,
// NUMA = 8'h77,
// NUMB = 8'h7c,
// NUMC = 8'h39,
// NUMD = 8'h5e,
// NUME = 8'h79,
// NUMF = 8'h71,
// NDOT = 8'h80;
//共阳型数码管,数码管显示0-f对应的段选输出信号
parameter NUM0 = 8'hc0,
NUM1 = 8'hf9,
NUM2 = 8'ha4,
NUM3 = 8'hb0,
NUM4 = 8'h99,
NUM5 = 8'h92,
NUM6 = 8'h82,
NUM7 = 8'hf8,
NUM8 = 8'h80,
NUM9 = 8'h90,
NUMA = 8'h88,
NUMB = 8'h83,
NUMC = 8'hc6,
NUMD = 8'ha1,
NUME = 8'h86,
NUMF = 8'h8e,
NDOT = 8'h7f;
//数码管位选端,4位数码管
//位选端设置为0点亮,恒创电路板,与一般数码管不同
parameter CSN = 4'b1111,
CS0 = 4'b1110,
CS1 = 4'b1101,
CS2 = 4'b1011,
CS3 = 4'b0111;
//分时显示数据控制单元
reg [3:0] current_display_num; //当前显示数据
reg [14:0] div_cnt; //分时计数器
//分时计数器
always@(posedge clk or negedge rst_n)
if(!rst_n)
div_cnt <= 15'd0;
else
div_cnt <= div_cnt + 1'b1;
//显示数据
always@(posedge clk or negedge rst_n)
if(!rst_n)
current_display_num <= 4'h0;
else begin
case(div_cnt[14:13])
2'b00: current_display_num <= display_num[3:0];
2'b01: current_display_num <= display_num[7:4];
2'b10: current_display_num <= display_num[11:8];
2'b11: current_display_num <= display_num[15:12];
default:;
endcase
end
//段选数据译码
always@(posedge clk or negedge rst_n)
if(!rst_n)
dtube_seg <= 8'h00;
else begin
case(current_display_num)
4'h0: dtube_seg <= NUM0;
4'h1: dtube_seg <= NUM1;
4'h2: dtube_seg <= NUM2;
4'h3: dtube_seg <= NUM3;
4'h4: dtube_seg <= NUM4;
4'h5: dtube_seg <= NUM5;
4'h6: dtube_seg <= NUM6;
4'h7: dtube_seg <= NUM7;
4'h8: dtube_seg <= NUM8;
4'h9: dtube_seg <= NUM9;
4'ha: dtube_seg <= NUMA;
4'hb: dtube_seg <= NUMB;
4'hc: dtube_seg <= NUMC;
4'hd: dtube_seg <= NUMD;
4'he: dtube_seg <= NUME;
4'hf: dtube_seg <= NUMF;
default:;
endcase
end
//位选译码
always@(posedge clk or negedge rst_n)
if(!rst_n)
dtube_sel <= CSN;
else begin
case(div_cnt[14:13])
2'b00: dtube_sel <= CS0;
2'b01: dtube_sel <= CS1;
2'b10: dtube_sel <= CS2;
2'b11: dtube_sel <= CS3;
default:;
endcase
end
endmodule
// testbench
`timescale 1ns/1ns
module dtube_control_4_tb();
reg clk;
reg rst_n;
reg [15:0] display_num;
wire [7:0] dtube_seg;
wire [3:0] dtube_sel;
parameter NUM0 = 8'hc0,
NUM1 = 8'hf9,
NUM2 = 8'ha4,
NUM3 = 8'hb0,
NUM4 = 8'h99,
NUM5 = 8'h92,
NUM6 = 8'h82,
NUM7 = 8'hf8,
NUM8 = 8'h80,
NUM9 = 8'h90,
NUMA = 8'h88,
NUMB = 8'h83,
NUMC = 8'hc6,
NUMD = 8'ha1,
NUME = 8'h86,
NUMF = 8'h8e,
NDOT = 8'h7f;
dtube_control_4 inst0(
.clk (clk),
.rst_n (rst_n),
.display_num (display_num),
.dtube_seg (dtube_seg),
.dtube_sel (dtube_sel)
);
initial begin
clk = 0; rst_n = 0; display_num = 16'h0000; #50;
@(posedge clk); #2;
rst_n =1; display_num = 16'h4321;
#50_000;
$stop;
end
always #10 clk = ~clk;
reg [15:0] display_seg; //模拟显示数码管的数据
reg [3:0] dtube_seg_decode;
always@(dtube_seg)begin
case(dtube_seg)
NUM0: dtube_seg_decode <= 4'h0;
NUM1: dtube_seg_decode <= 4'h1;
NUM2: dtube_seg_decode <= 4'h2;
NUM3: dtube_seg_decode <= 4'h3;
NUM4: dtube_seg_decode <= 4'h4;
NUM5: dtube_seg_decode <= 4'h5;
NUM6: dtube_seg_decode <= 4'h6;
NUM7: dtube_seg_decode <= 4'h7;
NUM8: dtube_seg_decode <= 4'h8;
NUM9: dtube_seg_decode <= 4'h9;
NUMA: dtube_seg_decode <= 4'ha;
NUMB: dtube_seg_decode <= 4'hb;
NUMC: dtube_seg_decode <= 4'hc;
NUMD: dtube_seg_decode <= 4'hd;
NUME: dtube_seg_decode <= 4'he;
NUMF: dtube_seg_decode <= 4'hf;
default:;
endcase
end
always@(*)begin
case(dtube_sel)
4'b1110: display_seg[3:0] <= dtube_seg_decode;
4'b1101: display_seg[7:4] <= dtube_seg_decode;
4'b1011: display_seg[11:8]<= dtube_seg_decode;
4'b0111: display_seg[15:12]<= dtube_seg_decode;
default:;
endcase
end
endmodule