FPGA实验之数码管

一、数码管驱动原理

共阴极与共阳极:公共端是接高电平还是低电平  左:共阴 右:共阳

段码:决定显示的内容

位选:选择哪一个数码管

动态扫描显示即轮流向各位数码管送出字形码和相应的
位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同
时都在显示。
如果使用 1ms 刷新时间的话由于数码管的余辉效应以及人的视觉暂留
这样就会出现数码管 0 的 LED0、数码管 1 的 LED1 以及数码管 2 的 LED2 “同
时”亮,并不会有闪烁感。

二、FPGA设计

1.1khz扫描时钟     

2. 动态扫描(8位寄存器or移位寄存器)位选

3.sel→【31:0】disp_data→[3:0]data_temp→seg段选

设计关键:

计数器

LUT→case语句

module hex8(
	Clk,
	Reset_n,
	en,
	disp_data,
	sel,
	seg
);
	input Clk;	//50M
	input Reset_n;
	input en;	//数码管显示使能,1使能,0关闭
	
	input [31:0]disp_data;
	
	output [7:0] sel;//数码管位选(选择当前要显示的数码管)
	output reg [6:0] seg;//数码管段选(当前要显示的内容)
	
	reg [14:0]divider_cnt;//25000-1
	
	reg clk_1K;
	reg [7:0]sel_r;
	
	reg [3:0]data_tmp;//数据缓存

//	分频计数器计数模块
	always@(posedge Clk or negedge Reset_n)
	if(!Reset_n)
		divider_cnt <= 15'd0;
	else if(!en)
		divider_cnt <= 15'd0;
	else if(divider_cnt == 24999)
		divider_cnt <= 15'd0;
	else
		divider_cnt <= divider_cnt + 1'b1;

//1K扫描时钟生成模块		
	always@(posedge Clk or negedge Reset_n)
	if(!Reset_n)
		clk_1K <= 1'b0;
	else if(divider_cnt == 24999)
		clk_1K <= ~clk_1K;
	else
		clk_1K <= clk_1K;
		
//8位循环移位寄存器
	always@(posedge clk_1K or negedge Reset_n)
	if(!Reset_n)
		sel_r <= 8'b0000_0001;
	else if(sel_r == 8'b1000_0000)
		sel_r <= 8'b0000_0001;
	else
		sel_r <=  sel_r << 1;
		
	always@(*)
		case(sel_r)
			8'b0000_0001:data_tmp = disp_data[3:0];
			8'b0000_0010:data_tmp = disp_data[7:4];
			8'b0000_0100:data_tmp = disp_data[11:8];
			8'b0000_1000:data_tmp = disp_data[15:12];
			8'b0001_0000:data_tmp = disp_data[19:16];
			8'b0010_0000:data_tmp = disp_data[23:20];
			8'b0100_0000:data_tmp = disp_data[27:24];
			8'b1000_0000:data_tmp = disp_data[31:28];
			default:data_tmp = 4'b0000;
		endcase
		
	always@(*)
		case(data_tmp)
			4'h0:seg = 7'b1000000;
			4'h1:seg = 7'b1111001;
			4'h2:seg = 7'b0100100;
			4'h3:seg = 7'b0110000;
			4'h4:seg = 7'b0011001;
			4'h5:seg = 7'b0010010;
			4'h6:seg = 7'b0000010;
			4'h7:seg = 7'b1111000;
			4'h8:seg = 7'b0000000;
			4'h9:seg = 7'b0010000;
			4'ha:seg = 7'b0001000;
			4'hb:seg = 7'b0000011;
			4'hc:seg = 7'b1000110;
			4'hd:seg = 7'b0100001;
			4'he:seg = 7'b0000110;
			4'hf:seg = 7'b0001110;
		endcase
		
	assign sel = (en)?sel_r:8'b0000_0000;

endmodule

三、数码管驱动(74HC595串转并)

Q0~Q7          8个数字输出(二进制)
Vcc              接电源正极
GND            接电源负极
DS    高电频输入1,低电平输入0
/OE    低电平74HC595有效使用(接地GND就好了)

/MR    低电平复位(如果不需要复位直接接电源就行)
SH_CP    高电平触发时,DS的数被存入,一次存一个
ST_CP    高电平触发时,DS存入的所有二进制数被输出
Q7'    级联使用

module hc595_driver(
	Clk,    
	Reset_n,
	data,
	s_en,

	sh_cp,
	st_cp,
	ds
);

	input Clk;
	input Reset_n;
	input [15:0]data;
	input s_en;
	
	output reg sh_cp;
	output reg st_cp;
	output reg ds;
	parameter CNT_MAX = 2;
	
	reg [15:0]r_data;
	always@(posedge Clk)
	if(s_en)
		r_data <= data;

	reg [7:0]divider_cnt;//分频计数器;
	
	always@(posedge Clk or negedge Reset_n)
	if(!Reset_n)
		divider_cnt <= 0;
	else if(divider_cnt == CNT_MAX - 1'b1)
		divider_cnt <= 0;
	else
		divider_cnt <= divider_cnt + 1'b1;
		
	wire sck_plus;
	assign sck_plus = (divider_cnt == CNT_MAX - 1'b1);
		
	reg [5:0]SHCP_EDGE_CNT;
	
	always@(posedge Clk or negedge Reset_n)
	if(!Reset_n)
		SHCP_EDGE_CNT <= 0;
	else if(sck_plus)begin
		if(SHCP_EDGE_CNT == 6'd32)
			SHCP_EDGE_CNT <= 0;
		else
			SHCP_EDGE_CNT <= SHCP_EDGE_CNT + 1'b1;
	end
	else
		SHCP_EDGE_CNT <= SHCP_EDGE_CNT;
		
	always@(posedge Clk or negedge Reset_n)
	if(!Reset_n)begin
		st_cp <= 1'b0;
		ds <= 1'b0;
		sh_cp <= 1'd0;
	end 
	else begin
		case(SHCP_EDGE_CNT)
			0: begin sh_cp <= 0; st_cp <= 1'd0;ds <= r_data[15];end
			1: begin sh_cp <= 1; st_cp <= 1'd0;end
			2: begin sh_cp <= 0; ds <= r_data[14];end
			3: begin sh_cp <= 1; end
			4: begin sh_cp <= 0; ds <= r_data[13];end	
			5: begin sh_cp <= 1; end
			6: begin sh_cp <= 0; ds <= r_data[12];end	
			7: begin sh_cp <= 1; end
			8: begin sh_cp <= 0; ds <= r_data[11];end	
			9: begin sh_cp <= 1; end
			10: begin sh_cp <= 0; ds <= r_data[10];end	
			11: begin sh_cp <= 1; end
			12: begin sh_cp <= 0; ds <= r_data[9];end	
			13: begin sh_cp <= 1; end
			14: begin sh_cp <= 0; ds <= r_data[8];end	
			15: begin sh_cp <= 1; end
			16: begin sh_cp <= 0; ds <= r_data[7];end	
			17: begin sh_cp <= 1; end
			18: begin sh_cp <= 0; ds <= r_data[6];end	
			19: begin sh_cp <= 1; end
			20: begin sh_cp <= 0; ds <= r_data[5];end	
			21: begin sh_cp <= 1; end
			22: begin sh_cp <= 0; ds <= r_data[4];end	
			23: begin sh_cp <= 1; end
			24: begin sh_cp <= 0; ds <= r_data[3];end	
			25: begin sh_cp <= 1; end
			26: begin sh_cp <= 0; ds <= r_data[2];end	
			27: begin sh_cp <= 1; end
			28: begin sh_cp <= 0; ds <= r_data[1];end			
			29: begin sh_cp <= 1; end
			30: begin sh_cp <= 0; ds <= r_data[0];end
			31: begin sh_cp <= 1; end
			32: st_cp <= 1'd1;
			default:		
				begin
					st_cp <= 1'b0;
					ds <= 1'b0;
					sh_cp <= 1'd0;
				end
		endcase
	end

endmodule
	

 四。最后顶层设计(top)

此处略去

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值