共阴极数码管:低电平端接的都是0,高电平端哪里设置为1 ,哪里就亮~
共阳极数码管与之相反~
视觉暂留:
对于三位的共阴极数码管
第0.01s:让数码管0的a段亮,其他数码管全灭
Sel0为高电平,sel1和sel2为低电平
A段为低电平
第0.02s:让数码管1的b、c段亮,其他数码管全灭
Sel1为高电平,sel0和sel2为低电平
B和C段为低电平
第0.03s:让数码管2的e段亮,其他数码管全灭
Sel2为高电平,sel0和sel1为低电平
E段为低电平
数码管动态扫描
所以,通过这种方式,可以节约引脚~
抽象原理图:
在fpga设计中尽量使用使能时钟去驱动寄存器,而不是门控时钟,因为门控时钟的质量非常差
使用门控时钟,将门控时钟直接作为DFF的工作时钟,没有ENA的情况下忽略ENA
使用使能时钟的情况,DFF的工作时钟继续全局高质量时钟,而将使能时钟作为DFF的使能信号使用
在能使用时序逻辑的情况下,尽量使用时序逻辑
顶层模块:
module hex8_test(
input Clk,
input Reset,
output [7:0]SEL,
output [7:0]SEG
);
wire [31:0]Disp_Data;
hex8_2 hex8_2(
Clk,
Reset,
Disp_Data,
SEL,
SEG
);
assign Disp_Data=32'h12359bdf;
endmodule
主模块
module hex8(
input Clk,
input Reset,
input [31:0]Disp_Data,
output reg [7:0]SEL,
output reg [7:0]SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
);
reg clk_1k;
reg [14:0]div_cnt;
always@(posedge Clk or negedge Reset)begin
if(!Reset)
div_cnt<=0;
else if(div_cnt>=25000-1)
div_cnt<=0;
else
div_cnt<=div_cnt+1;
end
always@(posedge Clk or negedge Reset)begin
if(!Reset)
clk_1k<=0;
else if(div_cnt>=25000-1)
clk_1k<=~clk_1k;
end
reg[2:0]reg_num;
always@(posedge clk_1k or negedge Reset)begin
if(!Reset)
reg_num<=0;
else if(reg_num>=7)
reg_num<=0;
else
reg_num<=reg_num+1;
end
always@(*)begin
case(reg_num)
0:SEL=8'b0000_0001;
1:SEL=8'b0000_0010;
2:SEL=8'b0000_0100;
3:SEL=8'b0000_1000;
4:SEL=8'b0001_0000;
5:SEL=8'b0010_0000;
6:SEL=8'b0100_0000;
7:SEL=8'b1000_0000;
endcase
end
reg[3:0] disp_temp;
always@(*)begin
case(reg_num)
7:disp_temp=Disp_Data[31:28];
6:disp_temp=Disp_Data[27:24];
5:disp_temp=Disp_Data[23:20];
4:disp_temp=Disp_Data[19:16];
3:disp_temp=Disp_Data[15:12];
2:disp_temp=Disp_Data[11:8];
1:disp_temp=Disp_Data[7:4];
0:disp_temp=Disp_Data[3:0];
endcase
end
always@(*)begin
case(disp_temp)
0:SEG=8'hc0;
1:SEG=8'hf9;
2:SEG=8'ha4;
3:SEG=8'hb0;
4:SEG=8'h99;
5:SEG=8'h92;
6:SEG=8'h82;
7:SEG=8'hf8;
8:SEG=8'h80;
9:SEG=8'h90;
4'ha:SEG=8'h88;
4'hb:SEG=8'h83;
4'hc:SEG=8'hc6;
4'hd:SEG=8'ha1;
4'he:SEG=8'h86;
4'hf:SEG=8'h8e;
endcase
end
endmodule
改进后的主模块
module hex8_2(
input Clk,
input Reset,
input [31:0]Disp_Data,
output reg [7:0]SEL,
output reg [7:0]SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
);
reg clk_1k;
reg [15:0]div_cnt;
always@(posedge Clk or negedge Reset)begin
if(!Reset)
div_cnt<=0;
else if(div_cnt>=50000-1)
div_cnt<=0;
else
div_cnt<=div_cnt+1;
end
always@(posedge Clk or negedge Reset)begin
if(!Reset)
clk_1k<=0;
else if(div_cnt>=50000-1)
clk_1k<=1;
else
clk_1k<=0;
end
reg[2:0]reg_num;
always@(posedge Clk or negedge Reset)begin
if(!Reset)
reg_num<=0;
else if(clk_1k)
reg_num<=reg_num+1;
else
reg_num<=reg_num;
end
always@(posedge Clk)begin
case(reg_num)
7:SEL=8'b0000_0001;
6:SEL=8'b0000_0010;
5:SEL=8'b0000_0100;
4:SEL=8'b0000_1000;
3:SEL=8'b0001_0000;
2:SEL=8'b0010_0000;
1:SEL=8'b0100_0000;
0:SEL=8'b1000_0000;
endcase
end
reg[3:0] disp_temp;
always@(posedge Clk)begin
case(reg_num)
0:disp_temp=Disp_Data[31:28];
1:disp_temp=Disp_Data[27:24];
2:disp_temp=Disp_Data[23:20];
3:disp_temp=Disp_Data[19:16];
4:disp_temp=Disp_Data[15:12];
5:disp_temp=Disp_Data[11:8];
6:disp_temp=Disp_Data[7:4];
7:disp_temp=Disp_Data[3:0];
endcase
end
always@(posedge Clk)begin
case(disp_temp)
0:SEG=8'hc0;
1:SEG=8'hf9;
2:SEG=8'ha4;
3:SEG=8'hb0;
4:SEG=8'h99;
5:SEG=8'h92;
6:SEG=8'h82;
7:SEG=8'hf8;
8:SEG=8'h80;
9:SEG=8'h90;
4'ha:SEG=8'h88;
4'hb:SEG=8'h83;
4'hc:SEG=8'hc6;
4'hd:SEG=8'ha1;
4'he:SEG=8'h86;
4'hf:SEG=8'h8e;
endcase
end
endmodule
测试模块文章来源:https://www.uudwc.com/A/Vm9Bz/
`timescale 1ns / 1ps
module hex8_tb(
);
reg Clk;
reg Reset;
reg [31:0]Disp_Data;
wire [7:0]SEL;
wire [7:0]SEG;
hex8 hex8(
Clk,
Reset,
Disp_Data,
SEL,
SEG//seg[0]对应a,seg[1]对应b~~~~seg[7]对应h
);
initial Clk=0;
always#10 Clk=!Clk;
initial begin
Reset=0;
Disp_Data=32'h0000_0000;
#201
Reset=1;
#2000
Disp_Data=32'h1234_5678;
#10000000
Disp_Data=32'h9abc_def0;
#10000000
$stop;
end
endmodule
时钟质量在FPGA设计中重要的原因
1:时钟延迟不确定,而且比较大
2:使得时钟的波形变差
3:驱动能力文章来源地址https://www.uudwc.com/A/Vm9Bz/