基于FPGA的数字钟——(三)时钟显示模块(数码管)

基于FPGA的数字钟——(三)数码管显示模块

一、硬件原理

本设计中使用 6 个共阳数码管,可以显示 6 个数字(包含小数点) 。电路用 PNP管来反向驱动并且控制列扫描信号来选择哪个数码管。而且所有的 6 个数码管的“段选信号”(LEDA … LEDH)都共用驱动引脚(LED_A~LEDH)。数码管的所有驱动信号都是“低电平有效”。具体的原理图设计如下图所示:
基于FPGA的数字钟——(三)时钟显示模块(数码管)_第1张图片

二、数码管扫描原理

单个数码管可以采用静态显示方式,如图所示,数码管被分成 a、 b、 c、 d、e、 f、 g 和小数点,每段可以单独控制亮灭,通过点亮不同的段显示不同的数字和字符。
基于FPGA的数字钟——(三)时钟显示模块(数码管)_第2张图片
其编码表如下
基于FPGA的数字钟——(三)时钟显示模块(数码管)_第3张图片

三、驱动原理

依照一定的频率位选各数码管,利用人的视觉暂留来达到视觉上的连续感。

四、数码管解码模块

//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
// 
// Create Date: 2019/12/29 15:55:40
// Design Name: seg_decoder
// Module Name: seg_decoder
// Project Name: Clock
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module seg_decoder
(
	input clk,
	input rst,
	input[3:0]      bin_data,     // bin data input,0-f
	output reg[6:0] seg_data      // seven segments LED output
);

always@(posedge clk or negedge rst)
begin
	if(!rst)
		seg_data <= 7'b111_1111;
	else
		case(bin_data)
			4'd0:seg_data <= 7'b100_0000;
			4'd1:seg_data <= 7'b111_1001;
			4'd2:seg_data <= 7'b010_0100;
			4'd3:seg_data <= 7'b011_0000;
			4'd4:seg_data <= 7'b001_1001;
			4'd5:seg_data <= 7'b001_0010;
			4'd6:seg_data <= 7'b000_0010;
			4'd7:seg_data <= 7'b111_1000;
			4'd8:seg_data <= 7'b000_0000;
			4'd9:seg_data <= 7'b001_0000;
			4'ha:seg_data <= 7'b000_1000;
			4'hb:seg_data <= 7'b000_0011;
			4'hc:seg_data <= 7'b100_0110;
			4'hd:seg_data <= 7'b010_0001;
			4'he:seg_data <= 7'b000_0110;
			4'hf:seg_data <= 7'b000_1110;
			default:seg_data <= 7'b111_1111;
		endcase
end
endmodule

仿真波形(部分)

在这里插入图片描述

五、单段选数码管驱动

为了节省引脚资源,每个数码管共用一路段选信号,通过一定频率的分别位选来实现六位数码管的显示。则需要引入一个段选、位选控制模块

段选、位选控制模块

//////////////////////////////////////////////////////////////////////////////////
// Company: NanJing University of Information Science & Technology
// Engineer: Yang Cheng Yu
// 
// Create Date: 2019/12/29 15:55:40
// Design Name: seg_control
// Module Name: seg_control
// Project Name: Clock
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module seg_control(
	input 				clk,
	input 				rst,
	input [6:0]			seg_data_in0,//第1位数码管信号输入
	input [6:0]			seg_data_in1,//第2位数码管信号输入
	input [6:0]			seg_data_in2,//第3位数码管信号输入
	input [6:0]			seg_data_in3,//第4位数码管信号输入
	input [6:0]			seg_data_in4,//第5位数码管信号输入
	input [6:0]			seg_data_in5,//第6位数码管信号输入
	output reg[6:0]	seg_sel,		//段选信号输出
	output reg[5:0]	bit_sel		//位选信号输出
);
	reg[2:0]				state;				
	reg[15:0] 			wait_cnt;			//等待时间计数器,等待时间1ms
	reg					cnt_full;			//计数器计满信号
	reg					cnt_en;				//计数器使能信号
	localparam			START		=3'b000;//起始状态
	localparam			DISP_SEG0=3'b001;//显示第1位数据
	localparam			DISP_SEG1=3'b011;//显示第2位数据
	localparam			DISP_SEG2=3'b010;//显示第3位数据
	localparam			DISP_SEG3=3'b110;//显示第4位数据
	localparam			DISP_SEG4=3'b100;//显示第5位数据
	localparam			DISP_SEG5=3'b101;//显示第6位数据
	parameter 			WAIT_VAL=1000;//1000微秒
	localparam			WAIT_CNT_MAX=WAIT_VAL*1000/20-1;
	reg[6:0]				seg_data_reg0;//数码管0段选信号寄存器
	reg[6:0]				seg_data_reg1;//数码管1段选信号寄存器
	reg[6:0]				seg_data_reg2;//数码管2段选信号寄存器
	reg[6:0]				seg_data_reg3;//数码管3段选信号寄存器
	reg[6:0]				seg_data_reg4;//数码管4段选信号寄存器
	reg[6:0]				seg_data_reg5;//数码管5段选信号寄存器

	
	always@(posedge clk or negedge rst)begin
		if(!rst)begin
			wait_cnt <= 16'd0;
			cnt_full <= 1'b0;
		end
		else begin
			if(cnt_en)
				if(wait_cnt==WAIT_CNT_MAX)begin//1ms 计数器值为=1000_000/20=50000
					wait_cnt <= 16'd0;
					cnt_full <= 1'b1;
				end
				else begin
					wait_cnt <= wait_cnt + 1'b1;
					cnt_full <= 1'b0;
				end
			else begin
				wait_cnt <= 16'd0;
				cnt_full <= 1'b0;
			end
		end
	end
		//状态转移逻辑
	always@(posedge clk or negedge rst)begin
		if(!rst)
			state <= START;
		else
			case(state)
				START:
					state <= DISP_SEG0;
				DISP_SEG0:
					if(cnt_full)
						state <= DISP_SEG1;
					else
						state <= DISP_SEG0;
				DISP_SEG1:
					if(cnt_full)
						state <= DISP_SEG2;
					else
						state <= DISP_SEG1;
				DISP_SEG2:
					if(cnt_full)
						state <= DISP_SEG3;
					else
						state <= DISP_SEG2;
				DISP_SEG3:
					if(cnt_full)
						state <= DISP_SEG4;
					else
						state <= DISP_SEG3;
				DISP_SEG4:
					if(cnt_full)
						state <= DISP_SEG5;
					else
						state <= DISP_SEG4;
				DISP_SEG5:
					if(cnt_full)
						state <= START;
					else
						state <= DISP_SEG5;
			endcase
	end
	//状态输出逻辑
	always@(posedge clk or negedge rst)begin
		if(!rst)begin
			cnt_en <= 1'b0;
			seg_sel <= 7'b1111_111;
			bit_sel <= 6'b111_111;
		end
		else
			case(state)//起始状态先锁存输入数码管数据
				START:begin
					cnt_en <= 1'b0;
					seg_sel <= 7'b1111_111;
					bit_sel <= 6'b111_111;
					seg_data_reg0 <= seg_data_in0;
					seg_data_reg1 <= seg_data_in1;
					seg_data_reg2 <= seg_data_in2;
					seg_data_reg3 <= seg_data_in3;
					seg_data_reg4 <= seg_data_in4;
					seg_data_reg5 <= seg_data_in5;
				end
				DISP_SEG0:begin//显示第1位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg0;
					bit_sel <= 6'b011_111;
				end
				DISP_SEG1:begin//显示第2位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg1;
					bit_sel <= 6'b101_111;
				end
				DISP_SEG2:begin//显示第3位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg2;
					bit_sel <= 6'b110_111;
				end
				DISP_SEG3:begin//显示第4位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg3;
					bit_sel <= 6'b111_011;
				end
				DISP_SEG4:begin//显示第5位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg4;
					bit_sel <= 6'b111_101;
				end
				DISP_SEG5:begin//显示第6位数码管数据
					cnt_en <= 1'b1;
					seg_sel <= seg_data_reg5;
					bit_sel <= 6'b011_110;
				end
				default:begin
					cnt_en <= 1'b0;
					seg_sel <= 7'b111_1111;
					bit_sel <= 6'b111_111;
				end
			endcase
	end

endmodule
仿真波形

基于FPGA的数字钟——(三)时钟显示模块(数码管)_第4张图片
将数码管解码模块与控制模块级联就可以构成本设计中的时钟显示模块

module time_disp(
	input 			clk,
	input 			rst,
	input[3:0] 		s_ge_seg_in,
	input[3:0] 		s_shi_seg_in,
	input[3:0] 		min_ge_seg_in,
	input[3:0] 		min_shi_seg_in,
	input[3:0] 		h_ge_seg_in,
	input[3:0] 		h_shi_seg_in,
	output[6:0] 	seg_sel,
	output[5:0] 	bit_sel
);
	wire[6:0] 		s_ge;
	wire[6:0] 		s_shi;
	wire[6:0] 		min_ge;
	wire[6:0] 		min_shi;
	wire[6:0] 		h_ge;
	wire[6:0] 		h_shi;

seg_control seg_control(
	.clk(clk),
	.rst(rst),
	.seg_data_in0(s_ge),//第1位数码管信号输入
	.seg_data_in1(s_shi),//第2位数码管信号输入
	.seg_data_in2(min_ge),//第3位数码管信号输入
	.seg_data_in3(min_shi),//第4位数码管信号输入
	.seg_data_in4(h_ge),//第5位数码管信号输入
	.seg_data_in5(h_shi),//第6位数码管信号输入
	.seg_sel(seg_sel),		//段选信号输出
	.bit_sel(bit_sel)		//位选信号输出
);

seg_decoder seg_s_ge_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(s_ge_seg_in),     // bin data input,0-f
	.seg_data(s_ge)      // seven segments LED output
);

seg_decoder seg_s_shi_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(s_shi_seg_in),     // bin data input,0-f
	.seg_data(s_shi)      // seven segments LED output
);

seg_decoder seg_min_ge_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(min_ge_seg_in),     // bin data input,0-f
	.seg_data(min_ge)      // seven segments LED output
);

seg_decoder seg_min_shi_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(min_shi_seg_in),     // bin data input,0-f
	.seg_data(min_shi)      // seven segments LED output
);

seg_decoder seg_h_ge_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(h_ge_seg_in),     // bin data input,0-f
	.seg_data(h_ge)      // seven segments LED output
);

seg_decoder seg_h_shi_wei
(
	.clk(clk),
	.rst(rst),
	.bin_data(h_shi_seg_in),     // bin data input,0-f
	.seg_data(h_shi)      // seven segments LED output
);
endmodule

基于FPGA的数字钟——(三)时钟显示模块(数码管)_第5张图片

你可能感兴趣的:(FPGA基础)