【FPGA入门五】数码管静态显示

本文介绍了FPGA初学者如何实现数码管静态显示,从数码管的工作原理到静态显示的设计过程,包括计时模块、数码管显示模块的创建,以及逐步改进实现数码管轮流显示1~6并考虑视觉暂留效应。最后,通过总结探讨了如何利用视觉暂留现象完成更复杂的数码管显示设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

    • 一.数码管
    • 二.数码管静态显示
      • ①数码管全部显示,以0.5s为间隔依次显示0~F
      • ②修改上述代码,数码管轮流亮,并以0.5s为间隔依次显示1~6
      • ③继续修改上述代码,以0.5s为间隔依次显示1~6,显示几就亮几个数码管
    • 三.总结

一.数码管

数码管就是由8个LED灯组成的,通过让部分LED灯亮显示相应数字
在这里插入图片描述
我的开发板是共阳极类型,给低电平发光
数字真值表:
在这里插入图片描述

段选信号,位选信号:
在这里插入图片描述

二.数码管静态显示

①数码管全部显示,以0.5s为间隔依次显示0~F

新建计时模块
time_count.v

module time_count(
	input wire clk,   //时钟,50MHZ                        
	input wire rst_n, //复位信号,下降沿有效,negative
	
	output wire sec_05//0.5s输出一个脉冲信号             
);


parameter MAX_NUM = 24_999_999;//记最大数0.5s,25_000_000次
reg [24:0] cnt_05;//计数寄存器
reg sec_05_r;


//0.5s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_05 <= 25'd0;
	end
	else if(cnt_05 == MAX_NUM)begin
		cnt_05 <= 25'd0;	
	end
	else begin
		cnt_05 <= cnt_05 + 1'd1;
	end
end


//0.5s脉冲信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		sec_05_r <= 1'b0;
	end
	else if(cnt_05 == MAX_NUM)begin
		sec_05_r <= 1'b1;
	end
	else begin
		sec_05_r <= 1'b0;
	end
end

assign sec_05 = sec_05_r;//当右边改变,立马赋值给左边 assign和always并行

endmodule

新建数码管显示模块
seg_led_static.v

module seg_led_static(
	input wire clk,//时钟
	input wire rst_n,//复位
	input wire sec_05,//0.5s脉冲信号
	
	output wire [7:0] seg,//8位数码管段选信号
	output wire [5:0] sel//6位数码管位选信号
);
reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;

//位选信号全亮
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
	   sel_r <= 6'b111_111;//复位全灭
	end
	else begin
		sel_r <= 6'b000_000;
	end
end

assign sel = sel_r;

//0~f计数功能
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		value <= 4'h0;
	end
	else if(sec_05)begin
		if(value < 4'hf)begin
			value <= value + 1'h1;
		end
		else begin
			value <= 4'h0;
		end
	end
	else begin
		value <= value;
	end
end

//数码管译码功能,组合逻辑
always@(*)begin
	case(value)
		4'h0   : seg_r = 8'b1100_0000;
		4'h1   : seg_r = 8'b1111_1001;
		4'h2   : seg_r = 8'b1010_0100;
		4'h3   : seg_r = 8'b1011_0000;
		4'h4   : seg_r = 8'b1001_1001;
		4'h5   : seg_r = 8'b1001_0010;
		4'h6   : seg_r = 8'b1000_0010;
		4'h7   : seg_r = 8'b1111_1000;
		4'h8   : seg_r = 8'b1000_0000;
		4'h9   : seg_r = 8'b1001_0000;
		4'ha   : seg_r = 8'b1000_1000;
		4'hb   : seg_r = 8'b1000_0011;
		4'hc   : seg_r = 8'b1100_0110;
		4'hd   : seg_r = 8'b1010_0001;
		4'he   : seg_r = 8'b1000_0110;
		4'hf   : seg_r = 8'b1000_1110;
		default: seg_r = 8'b1100_0000;
	endcase
end
assign seg = seg_r;
endmodule

设计顶层文件
top_seg_led.v

module top_seg_led(
	input wire clk,
	input wire rst_n,
	
	output wire [7:0] seg,
	output wire [5:0] sel
);

wire sec_05;//将两个模块的信号连接起来


//推荐变量名传值,还有位置传值
time_count inst_time_count(
.clk    (clk   ),//时钟,50MHZ                  
.rst_n  (rst_n ),//复位信号,下降沿有效,negative
                     
.sec_05 (sec_05) //0.5s输出一个脉冲信号          
);

seg_led_static inst_seg_led_static(
.clk     (clk   ),//时钟
.rst_n   (rst_n ),//复位
.sec_05  (sec_05),//0.5s脉冲信号
                
.seg     (seg   ),//8位数码管段选信号
.sel     (sel   ) //6位数码管位选信号
);

endmodule

编译:
在这里插入图片描述

查看RTL门级电路:
在这里插入图片描述

绑定引脚:
在这里插入图片描述

硬件测试:

在这里插入图片描述

②修改上述代码,数码管轮流亮,并以0.5s为间隔依次显示1~6

修改seg_led_static.v
①修改计数从1~6
②修改位选信号和计数器同步变化

module seg_led_static(
	input wire clk,//时钟
	input wire rst_n,//复位
	input wire sec_05,//0.5s脉冲信号
	
	output wire [7:0] seg,//8位数码管段选信号
	output wire [5:0] sel//6位数码管位选信号
);

reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;

//位选信号轮流亮
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
	   sel_r <= 6'b111_110;//复位
	end
	else if(sec_05)begin
		sel_r <= {sel_r[4:0],sel_r[5]};
	end
	else begin
		sel_r <= sel_r;
	end
end

//1~6计数功能
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		value <= 4'h1;
	end
	else if(sec_05)begin
		if(value < 4'h6)begin
			value <= value + 1'h1;
		end
		else begin
			value <= 4'h1;
		end
	end
	else begin
		value <= value;
	end
end

assign sel = sel_r;

//数码管译码功能,组合逻辑
always@(*)begin
	case(value)
		4'h0   : seg_r = 8'b1100_0000;
		4'h1   : seg_r = 8'b1111_1001;
		4'h2   : seg_r = 8'b1010_0100;
		4'h3   : seg_r = 8'b1011_0000;
		4'h4   : seg_r = 8'b1001_1001;
		4'h5   : seg_r = 8'b1001_0010;
		4'h6   : seg_r = 8'b1000_0010;
		4'h7   : seg_r = 8'b1111_1000;
		4'h8   : seg_r = 8'b1000_0000;
		4'h9   : seg_r = 8'b1001_0000;
		4'ha   : seg_r = 8'b1000_1000;
		4'hb   : seg_r = 8'b1000_0011;
		4'hc   : seg_r = 8'b1100_0110;
		4'hd   : seg_r = 8'b1010_0001;
		4'he   : seg_r = 8'b1000_0110;
		4'hf   : seg_r = 8'b1000_1110;
		default: seg_r = 8'b1100_0000;
	endcase
end

assign seg = seg_r;

endmodule

硬件测试:
在这里插入图片描述

③继续修改上述代码,以0.5s为间隔依次显示1~6,显示几就亮几个数码管

module seg_led_static(
	input wire clk,//时钟
	input wire rst_n,//复位
	input wire sec_05,//0.5s脉冲信号
	
	output wire [7:0] seg,//8位数码管段选信号
	output wire [5:0] sel//6位数码管位选信号
);

reg [5:0] sel_r;
reg [3:0] value;
reg [7:0] seg_r;


reg [16:0] cnt;
parameter MAX_NUM = 99_999;

//0.2s计时器
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 1'b0;
	end
	else if(cnt == MAX_NUM)begin
		cnt <= 1'b0;
	end
	else begin
		cnt <= cnt + 1'b1;
	end
end


//1~6计数功能
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		value <= 4'h1;
	end
	else if(sec_05)begin
		if(value < 4'h6)begin
			value <= value + 1'h1;
		end
		else begin
			value <= 4'h1;
		end
	end
	else begin
		value <= value;
	end
end

//位选信号显示数字几就亮几个
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
	   sel_r <= 6'b111_110;
	end
	else if(cnt == MAX_NUM)begin
		case(value)
			3'h1   : sel_r <= 6'b111_110;
			3'h2   : sel_r <= 6'b111_100;
			3'h3   : sel_r <= 6'b111_000;
			3'h4   : sel_r <= 6'b110_000;
			3'h5   : sel_r <= 6'b100_000;
			3'h6   : sel_r <= 6'b000_000;
			default: sel_r <= 6'b111_110;
		endcase
	end
	else begin
		sel_r <= sel_r;
	end
end

assign sel = sel_r;

//数码管译码功能,组合逻辑
always@(*)begin
	case(value)
		4'h0   : seg_r = 8'b1100_0000;
		4'h1   : seg_r = 8'b1111_1001;
		4'h2   : seg_r = 8'b1010_0100;
		4'h3   : seg_r = 8'b1011_0000;
		4'h4   : seg_r = 8'b1001_1001;
		4'h5   : seg_r = 8'b1001_0010;
		4'h6   : seg_r = 8'b1000_0010;
		4'h7   : seg_r = 8'b1111_1000;
		4'h8   : seg_r = 8'b1000_0000;
		4'h9   : seg_r = 8'b1001_0000;
		4'ha   : seg_r = 8'b1000_1000;
		4'hb   : seg_r = 8'b1000_0011;
		4'hc   : seg_r = 8'b1100_0110;
		4'hd   : seg_r = 8'b1010_0001;
		4'he   : seg_r = 8'b1000_0110;
		4'hf   : seg_r = 8'b1000_1110;
		default: seg_r = 8'b1100_0000;
	endcase
end

assign seg = seg_r;

endmodule

硬件测试效果:
在这里插入图片描述

思考?
在②中怎么使得数字看起来全部显示?
修改变化周期,当周期足够小时,由于余晖效应看起来就像是一直亮着一样。
余晖效应:

余晖效应即视觉暂留现象,人眼在观察景物时,光信号传入大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”。
视觉暂留现象是光对视网膜所产生的视觉在光停止作用后,仍保留一段时间的现象,其具体应用是电影的拍摄和放映。原因是由视神经的反应速度造成的。是动画、电影等视觉媒体形成和传播的根据。视觉实际上是靠眼睛的晶状体成像,感光细胞感光,并且将光信号转换为神经电流,传回大脑引起人体视觉。感光细胞的感光是靠一些感光色素,感光色素的形成是需要一定时间的,这就形成了视觉暂停的机理。

三.总结

利用case语句设计类似于查找表的结构,对相应状态有不同的操作,数码管就是使多个LED灯按照所需显示,当数码管亮灭的时间周期足够短,肉眼不能发现,利用这个特性可以完成更为复杂的设计。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值