verilog数码管驱动显示

实现功能:让4个数码管每隔1s不断递增计数显示,计数范围为0-F(十六进制)。

片选信号:本例中是将公共端接到FPGA的I/O引脚上,这是数码管片选信号,如果这个I/O引脚输出低电平0,那么这个数码管就能够显示数字,输出高电平1时,关闭。

每个数码管段选信号:为了便于编写7个用于段选(不包括小数点,所以7个)的发光二极管显示不同字符,对应表如下。

数字/字符

0

1

2

3

4

5

6

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

猜你喜欢

转载自blog.csdn.net/WtMaple/article/details/81281750