【 FPGA 】四位16进制的数码管动态显示设计

版权声明:本博客内容来自于个人学习过程中的总结,参考了互联网、数据手册、帮助文档、书本以及论文等上的内容,仅供学习交流使用,如有侵权,请联系,我会重写!转载请注明地址! https://blog.csdn.net/Reborn_Lee/article/details/85881999

数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。

分时复用的扫描显示利用了人眼的视觉暂留特性,如果公共端的控制信号刷新速度足够快,人眼就不会区分出LED的闪烁,认为4个数码管是同时点亮。

如下图:

D1、D2、D3、D4就是公共控制端口,也就是片选端,控制哪一个数码管被选中。

而abcdefg是段选,用来控制数码管的显示内容。

下面代码中的an就是片选端,以及控制信号一致的输出段码信号sseg。片选控制信号的刷新速度必须足够快才能避免闪烁感,但也不能太快,以免影响数码管的开关切换,最佳的工作频率为1000Hz左右。如果FPGA的时钟为50MHz,那么至少跑5*10^4个周期,也即50000个周期刷新一次才行,我们知道2^16=65536,2^15=32768。

所以,用16位2进制数来控制技术吧,技术满了刷新一次。

代码中采用的是18位2进制数,高2位控制片选,低16位计数满一次,进位一次,高两位的变化时00——01——10——11——00——...,分别选中数码管的其中之一,使用case语句即可完成这个功能。

下面代码中的hex0、hex1、hex2、hex3是输入信号,用来控制数码管显示的数字,dp_in用来控制小数点的亮灭。

Verilog HDL描述如下:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    21:03:02 01/05/2019 
// Design Name: 
// Module Name:    scan_led_hex_disp 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module scan_led_hex_disp(
    input clk,
    input reset,
    input [3:0] hex0, //第一个数码管显示的数字
    input [3:0] hex1,
    input [3:0] hex2,
    input [3:0] hex3,
    input [3:0] dp_in, //小数点控制
    output reg [3:0] an,   //片选
    output reg [7:0] sseg  //段选
    );
	
	localparam N = 18; //使用低16位对50Mhz的时钟进行分频(50MHZ/2^16)
	reg [N-1:0] regN; //高两位作为控制信号,低16位为计数器,对时钟进行分频
	reg [3:0] hex_in; //段选控制信号
	reg dp; 
	
	always@(posedge clk, posedge reset)
	begin
		if(reset)
			regN <= 0;
		else
			regN <= regN + 1;
	end
	
	always@ *
	begin
		case(regN[N-1:N-2])
		2'b00:begin
			an = 4'b1110; //选中第1个数码管
			hex_in = hex0; //数码管显示的数字由hex_in控制,显示hex0输入的数字;
			dp = dp_in[0]; //控制该数码管的小数点的亮灭
		end
		2'b01:begin
			an = 4'b1101; //选中第二个数码管
			hex_in = hex1;
			dp = dp_in[1];
		end
		2'b10:begin
			an = 4'b1011;
			hex_in = hex2;
			dp = dp_in[2];
		end
		default:begin
			an = 4'b0111;
			hex_in = hex3;
			dp = dp_in[3];
		end
		
		endcase
	
	end

	always@ *
	begin
		case(hex_in)
			4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
			4'h1: sseg[6:0] = 7'b1001111;
			4'h2: sseg[6:0] = 7'b0010010;
			4'h3: sseg[6:0] = 7'b0000110;
			4'h4: sseg[6:0] = 7'b1001100;
			4'h5: sseg[6:0] = 7'b0100100;
			4'h6: sseg[6:0] = 7'b0100000;
			4'h7: sseg[6:0] = 7'b0001111;
			4'h8: sseg[6:0] = 7'b0000010;
			4'h9: sseg[6:0] = 7'b0000100;
			4'ha: sseg[6:0] = 7'b0001000;
			4'hb: sseg[6:0] = 7'b1100000;
			4'hc: sseg[6:0] = 7'b0110001;	
			4'hd: sseg[6:0] = 7'b1000010;
			4'he: sseg[6:0] = 7'b0110000;
			default: sseg[6:0] = 7'b0111000;
		endcase
		sseg[7] = dp;
	end
	
	

endmodule

共阳极数码管码表:

            4'h0: sseg[6:0] = 7'b0000001; //共阳极数码管
            4'h1: sseg[6:0] = 7'b1001111;
            4'h2: sseg[6:0] = 7'b0010010;
            4'h3: sseg[6:0] = 7'b0000110;
            4'h4: sseg[6:0] = 7'b1001100;
            4'h5: sseg[6:0] = 7'b0100100;
            4'h6: sseg[6:0] = 7'b0100000;
            4'h7: sseg[6:0] = 7'b0001111;
            4'h8: sseg[6:0] = 7'b0000010;
            4'h9: sseg[6:0] = 7'b0000100;
            4'ha: sseg[6:0] = 7'b0001000;
            4'hb: sseg[6:0] = 7'b1100000;
            4'hc: sseg[6:0] = 7'b0110001;    
            4'hd: sseg[6:0] = 7'b1000010;
            4'he: sseg[6:0] = 7'b0110000;

为了验证上述代码的实际效果,用下列代码调用上述代码来测试:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:05:56 01/06/2019 
// Design Name: 
// Module Name:    scan_led_hex_disp_test 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module scan_led_hex_disp_test(
    input clk,
	input [3:0] sw,
    output [3:0] an,
    output [7:0] sseg
    );
	wire [3:0] a,b;
	wire [7:0] sum;
	assign a = {2'b00,sw[1:0]};
	assign b = {2'b00,sw[3:2]};
	assign sum = {4'b0,a}+{4'b0,b};
	
	scan_led_hex_disp uu1(
	.clk(clk),.reset(1'b0),
	.hex3(sum[7:4]),.hex2(sum[3:0]),
	.hex1(b),.hex0(a),
	.dp_in(4'b1011),.an(an),.sseg(sseg)
	);
	


endmodule

功能是两个数码管用来显示数字a和b,而其他两个数码管显示a和b之和。

猜你喜欢

转载自blog.csdn.net/Reborn_Lee/article/details/85881999