FPGA数码管


前言

  本系列文章来源于FPGA学习开源网站fpga4fun,网站由浅入深的介绍了26个FPGA工程,通过工程的学习,可以了解什么是FPGA以及它是如何工作的。本人仅用于学习和记录,如有侵权,速删。


一、工程介绍

  本工程使用FPGA驱动LED数码管。

1.1 LED显示原理

  LED是一个发光二极管,当加正向电压,LED点亮,加反向电压,LED熄灭,在实际连接电路上,FPGA引脚通过一个电阻连接LED,电阻值一般在100Ω-1KΩ之间,实际连接电路如下所示:
在这里插入图片描述

1.2 控制LED的发光强度

  首先,看一下如何通过verilog代码实现LED的开关,代码类似用verilog代码实现蜂鸣器,具体代码如下所示:

module LEDBlink(
	input clk_i,		//时钟一般在10MHz-50MHz
	output LED_o
);

	reg [31:0] cnt;
	
	always@(posedge clk_i)begin
		cnt <= cnt + 1;
	end

	assign LED_o = cnt[22];	//这里使用的是计数器23bit控制开关的频率,使用不同的计数器位数实现不同的开关频率

endmodule 

  其次,看一下如何控制LED实现半亮这种状态,一般由两种解决方案:一是将与FPGA、LED串联的电阻的阻值提高一倍;二是让FPGA输出不停的翻转,使得LED点亮和熄灭的时间一样,这样可以看到半亮的状态,具体代码如下所示:

module LEDhalflit(
	input clk_i,
	output LED_o
);

	reg toggle;

	always@(posedge clk_i)begin
		toggle <= ~toggle;			//在时钟的一半进行翻转
	end

	assign LED = toggle;

endmodule

  然后,看一下如何控制LED的强度,一般可以使用pwm的思想。下面是一个使用4bit输入控制LED在16个亮度级别之间进行选择的例子,具体代码如下所示:

module LED_PWM(
	input 		clk_i,
	input [3:0] pwm_i,		//16个亮度级别
	output 		LED_o
);

	reg [4:0] pwm;

	always@(posedge clk_i)begin
		pwm <= pwm[3:0] + pwm_i;
	end
	
	assign LED = pwm[4];

endmodule

  最后,看一下如何使LED看起来会发光,一般是使用计数器结合pwm的思想,具体代码如下所示:

module LEDglow(
	input clk_i,
	output LED_o
);

	reg [23:0] cnt;
	reg [ 4:0] pwm;

	wire [3:0] intensity = cnt[23] ? cnt[22:19] : ~cnt[22:19] //亮度在亮暗切换

	always@(posedge clk_i)begin
		cnt <= cnt + 1;
	end

	always@(posedge clk_i)begin
		pwm <= pwm[3:0] + intensity;
	end
	
	assign LED = PWM[4];
	
endmodule

1.3 7段发光二极管显示

  数码管由8个发光二极管组成,8个二极管命名为‘A’到‘G’,还有一个DP(点)。这8个二极管并不是独立的,一般会将阴极或者阳极接到一起,实际物理器件最少有九个引脚,如下图所示:
在这里插入图片描述
在这里插入图片描述
  FPGA驱动数码管,最简单的方案是使用8个IO引脚,如下图所示,以显示数字2为例,具体代码如下:
在这里插入图片描述

module LED_7seg(
	output segA_o,
	output segB_o,
	output segC_o,
	output segD_o,
	output segE_o,
	output segF_o,
	output segG_o,
	output segDP_o
);

	assign {segA_o,segB_o,segC_o,segD_o,segE_o,segF_o,segG_o,segDP_o} = 8'b11011010;

endmodule

  下面使用FPGA驱动数码管实现一个10进制计数器,具体代码如下所示:

module LED_7seg(
	input  clk_i,
	output segA_o,
	output segB_o,
	output segC_o,
	output segD_o,
	output segE_o,
	output segF_o,
	output segG_o,
	output segDP_o
);

	reg [23:0] cnt;		//使用24bit计数器
	always@(posedge clk_i)begin
		cnt <= cnt + 24'h1;
	end

	wire cntovf = &cnt;		//归约与,&cnt=cnt[0]&cnt[1]&....&cnt[23],每计满24位,cntovf值为1,如果时钟设置好,可以实现1s置1一次

	reg [3:0] BCD;
	always@(posedge clk_i)begin
		if(cntovf)beign		//每一秒,计数器加1
			BCD <= (BCD==4'h9 ? 4'h0 : BCD+4'h1);	//from 0 to 9
		end
	end

	reg [7:0] SevenSeg;
	always@(*)begin
		case(BCD)
			4'h0: SevenSeg = 8'b1111_1100;
			4'h1: SevenSeg = 8'b0110_0000;
			4'h2: SevenSeg = 8'b1101_1010;
			4'h3: SevenSeg = 8'b1111_0010;
			4'h4: SevenSeg = 8'b0110_0110;
			4'h5: SevenSeg = 8'b1011_0110;
			4'h6: SevenSeg = 8'b1011_1110;
			4'h7: SevenSeg = 8'b1110_0000;
			4'h8: SevenSeg = 8'b1111_1110;
			4'h9: SevenSeg = 8'b1111_0110;
			default: SevenSeg = 8'b0000_0000;
		endcase
	end
	assign {segA_o,segB_o,segC_o,segD_o,segE_o,segF_o,segG_o,segDP_o} = SevenSeg;

endmodule

  下面使用FPGA驱动数码管实现一个10进制平滑计数器,效果实现淡入淡出,具体代码如下所示:

module LED_7seg(
	input  clk_i,
	output segA_o,
	output segB_o,
	output segC_o,
	output segD_o,
	output segE_o,
	output segF_o,
	output segG_o,
	output segDP_o
);

	reg [23:0] cnt;		//使用24bit计数器
	always@(posedge clk_i)begin
		cnt <= cnt + 24'h1;
	end

	wire cntovf = &cnt;		//归约与,&cnt=cnt[0]&cnt[1]&....&cnt[23],每计满24位,cntovf值为1,如果时钟设置好,可以实现1s置1一次

	reg [3:0] BCD_new;
	reg [3:0] BCD_old;
	always@(posedge clk_i)begin
		if(cntovf)beign		//每一秒,计数器加1
			BCD_new <= (BCD_new==4'h9 ? 4'h0 : BCD_new+4'h1);	//from 0 to 0
		end
	end
	
	always@(posedge clk_i)begin
		if(cntovf)beign		
			BCD_old <= BCD_new;			//将计数器打一拍
		end
	end

	reg [4:0] pwm;
	wire [3:0] pwm_input = cnt[22:19];
	always@(posedge clk_i)begin
		pwm <= pwm[3:0] + pwm_input;		//通过pwm控制实现淡入淡出效果
	end
	wire [3:0] BCD = (cnt[23] | pwm[4]) ? BCD_new : BCD_old;
	
	reg [7:0] SevenSeg;
	always@(*)begin
		case(BCD)
			4'h0: SevenSeg = 8'b1111_1100;
			4'h1: SevenSeg = 8'b0110_0000;
			4'h2: SevenSeg = 8'b1101_1010;
			4'h3: SevenSeg = 8'b1111_0010;
			4'h4: SevenSeg = 8'b0110_0110;
			4'h5: SevenSeg = 8'b1011_0110;
			4'h6: SevenSeg = 8'b1011_1110;
			4'h7: SevenSeg = 8'b1110_0000;
			4'h8: SevenSeg = 8'b1111_1110;
			4'h9: SevenSeg = 8'b1111_0110;
			default: SevenSeg = 8'b0000_0000;
		endcase
	end
	assign {segA_o,segB_o,segC_o,segD_o,segE_o,segF_o,segG_o,segDP_o} = SevenSeg;

endmodule

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值