实现功能:让4个数码管每隔1s不断递增计数显示,计数范围为0-F(十六进制)。
片选信号:本例中是将公共端接到FPGA的I/O引脚上,这是数码管片选信号,如果这个I/O引脚输出低电平0,那么这个数码管就能够显示数字,输出高电平1时,关闭。
每个数码管段选信号:为了便于编写7个用于段选(不包括小数点,所以7个)的发光二极管显示不同字符,对应表如下。
数字/字符 |
0 |
1 |
2 |
3 |
4 |
5 |
6
扫描二维码关注公众号,回复:
4058748 查看本文章
|
7 |
编码(十六进制) |
3f |
06 |
5b |
4f |
66 |
6d |
7d |
07 |
数字/字符 |
8 |
9 |
A |
B |
C |
D |
E |
F |
编码(十六进制) |
7f |
6f |
77 |
7c |
39 |
5e |
79 |
71 |
实现原理:首先使用一个24位 的计数器产生1s的周期定时,4位的十六进制显示数据没秒递增。数码管的4位片选信号分时选中,在单独选中某个位时,它所对应的显示数据将进行译码后送往seg_db段选输出信号。虽然是分时分别选中4个数码管位,但是由于人眼的视觉暂留效果,实际上看上去好像是同时点亮所显示的4位数据。
逻辑功能设计框图:
实现verilog代码如下:
module ex5(
clk,rst_n,
seg_db,seg_cs
);
input clk;
input rst_n;
output reg[7:0] seg_db;
output reg[3:0] seg_cs;
//------------------------------------//
reg[24:0] cnt;
always@(posedge clk or negedge rst_n)
if(!rst_n) cnt<=25'd0;
else if(cnt>=25'd25_000_000) cnt<=25'd0;
else cnt<=cnt+1'b1;
wire timer_1s=(cnt==25'd25_000_000); //1s定时标志位,高电平有效一个时钟周期
//---------------------------------------//
reg[15:0] dis_db; //显示到数码管的4个十六进制数据
always@(posedge clk or negedge rst_n)
if(!rst_n) dis_db<=16'd0;
else if(timer_1s) dis_db<=dis_db+1'b1;
else;
//-------------------------------------------//
//------分时分别选中4个数码管位,但是由于人眼的视觉暂留效果,
//实际上看上去好像是同时点亮所显示的4位数据-------//
reg[3:0] cur_dis_db; //4位寄存器,用以缓存当前数码管的片选位对应的1个十六进制数据。
always@(posedge clk or negedge rst_n)
if(!rst_n) cur_dis_db<=4'd0;
else begin
case(cnt[7:6])
2'b00:begin
seg_cs<=4'b1110;
cur_dis_db<=dis_db[3:0];
end
2'b01:begin
seg_cs<=4'b1101;
cur_dis_db<=dis_db[7:4];
end
2'b10:begin
seg_cs<=4'b1011;
cur_dis_db<=dis_db[11:8];
end
2'b11:begin
seg_cs<=4'b0111;
cur_dis_db<=dis_db[15:12];
end
endcase
end
//-----------------------------------------------------//
parameter SEG_NUM0=8'h3f, //c0
SEG_NUM1=8'h06, //f9
SEG_NUM2=8'h5b, //a4
SEG_NUM3=8'h4f, //b0
SEG_NUM4=8'h66, //99
SEG_NUM5=8'h6d, //92
SEG_NUM6=8'h7d, //82
SEG_NUM7=8'h07, //f8
SEG_NUM8=8'h7f, //80
SEG_NUM9=8'h6f, //90
SEG_NUMA=8'h77, //88
SEG_NUMB=8'h7c, //83
SEG_NUMC=8'h39, //c6
SEG_NUMD=8'h5e, //a1
SEG_NUME=8'h79, //86
SEG_NUMF=8'h71; //8e
always@(cur_dis_db)begin //将数码管的十六进制数据译码成数码管的实际段选值
case(cur_dis_db)
4'h0:seg_db<=SEG_NUM0;
4'h1:seg_db<=SEG_NUM1;
4'h2:seg_db<=SEG_NUM2;
4'h3:seg_db<=SEG_NUM3;
4'h4:seg_db<=SEG_NUM4;
4'h5:seg_db<=SEG_NUM5;
4'h6:seg_db<=SEG_NUM6;
4'h7:seg_db<=SEG_NUM7;
4'h8:seg_db<=SEG_NUM8;
4'h9:seg_db<=SEG_NUM9;
4'ha:seg_db<=SEG_NUMA;
4'hb:seg_db<=SEG_NUMB;
4'hc:seg_db<=SEG_NUMC;
4'hd:seg_db<=SEG_NUMD;
4'he:seg_db<=SEG_NUME;
4'hf:seg_db<=SEG_NUMF;
default:;
endcase
end
endmodule