数码管所谓的动态扫描,就是利用人眼的视觉暂留特性,在人眼能分辨 的变化速度以外,快速分时的点亮各个数码管及其对应的段。因为分别点亮 所有数码管一次所用时间小于人眼的视觉暂留,因此,在人们眼里看来,这 些数码管都是同时持续点亮的,并不会有闪烁的感觉。
因为数码管属于低速设备,其正常的扫描频率为500~10KHz,扫描频率 太快,会导致系统功耗增加,显示效果变暗。扫描频率太慢,会有明显的闪 烁感。本实验通过调试观察,选择以1KHz作为扫描频率,实际显示效果非常 好。 因此本实验首先就需要产生一个1KHz的扫描时钟,该时钟由系统时钟分 频得到。
设计结构:
代码如下:
//TOP
moduleHEX8(
clk,
rst_n,
En,
disp_data,
dig_sel,
dig_seg
);
inputclk,rst_n,En;
output[7:0]dig_sel;//weixuan
output[6:0]dig_seg;//duanxuan
input[31:0]disp_data;
piderpider(
.clk(clk),
.rst_n(rst_n),
.En(En),
.p_clk(p_clk)
);
// key_detectkey_detect(
// clk,
// rst_n,
// key_in
// );
//
// key_ctrlkey_ctrl(
// clk,
// rst_n,
// key_flag,
// key_value,
// data
// );
dig_driverdig_driver(
.p_clk(p_clk),
.rst_n(rst_n),
.disp_data(disp_data),
.dig_sel(dig_sel),
.dig_seg(dig_seg),
.En(En)
);
endmodule
modulepider(
clk,
rst_n,
En,
p_clk
);
inputclk,rst_n;
inputEn;
outputregp_clk;
reg[14:0]p_cnt;//25000-1
// 分频计数器计数模块
always@(posedgeclkornegedgerst_n)
if(!rst_n)
p_cnt<=15'd0;
elseif(!En)
p_cnt<=15'd0;
elseif(p_cnt==24999)
p_cnt<=15'd0;
else
p_cnt<=p_cnt+1'b1;
//1K扫描时钟生成模块
always@(posedgeclkornegedgerst_n)
if(!rst_n)
p_clk<=1'b0;
elseif(p_cnt==24999)
p_clk<=~p_clk;
else
p_clk<=p_clk;
endmodule
moduledig_driver(
p_clk,
rst_n,
disp_data,
dig_sel,
data_tmp,
dig_seg,
En
);
inputp_clk,rst_n,En;
input[31:0]disp_data;
output[7:0]dig_sel;
outputreg[3:0]data_tmp;//chazhaobiaohuancun
outputreg[6:0]dig_seg;
reg[7:0]sel;
//8位循环移位寄存器
always@(posedgep_clkornegedgerst_n)
if(!rst_n)
sel<=8'b0000_0001;
elseif(sel==8'b1000_0000)
sel<=8'b0000_0001;
else
sel<=sel<<1;
always@(*)
case(dig_sel)
8'b0000_0001:data_tmp=disp_data[3:0];
8'b0000_0010:data_tmp=disp_data[7:4];
8'b0000_0100:data_tmp=disp_data[11:8];
8'b0000_1000:data_tmp=disp_data[15:12];
8'b0001_0000:data_tmp=disp_data[19:16];
8'b0010_0000:data_tmp=disp_data[23:20];
8'b0100_0000:data_tmp=disp_data[27:24];
8'b1000_0000:data_tmp=disp_data[31:28];
default:data_tmp=4'b0000;
endcase
always@(*)
case(data_tmp)
4'h0:dig_seg=7'b1000000;
4'h1:dig_seg=7'b1111001;
4'h2:dig_seg=7'b0100100;
4'h3:dig_seg=7'b0110000;
4'h4:dig_seg=7'b0011001;
4'h5:dig_seg=7'b0010010;
4'h6:dig_seg=7'b0000010;
4'h7:dig_seg=7'b1111000;
4'h8:dig_seg=7'b0000000;
4'h9:dig_seg=7'b0010000;
4'ha:dig_seg=7'b0001000;
4'hb:dig_seg=7'b0000011;
4'hc:dig_seg=7'b1000110;
4'hd:dig_seg=7'b0100001;
4'he:dig_seg=7'b0000110;
4'hf:dig_seg=7'b0001110;
endcase
assigndig_sel=(En)?sel:8'b0000_0000;
endmodule
`timescale1ns/1ns
`defineclk_period20
moduleHEX8_tb;
regclk;
regrst_n;
regEn;
reg[31:0]disp_data;
wire[7:0]sel;//数码管位选
wire[6:0]seg;//数码管段选
HEX8HEX8(
.clk(clk),
.rst_n(rst_n),
.En(En),
.disp_data(disp_data),
.dig_sel(sel),
.dig_seg(seg)
);
initialclk=1;
always#(`clk_period/2)clk=~clk;
initialbegin
rst_n=0;
En=1;
disp_data=32'h12345678;
#(`clk_period*20);
rst_n=1;
#(`clk_period*20);
#20000000;
$stop;
end
endmodule
仿真: