FPGA动态扫描数码管

功能:用两个数码管显示0-99的数,每隔一秒加1。
由于数码管的段选段是连在一起的,要想两个数码管显示不一样的值,就必须动态地扫描数码管。因为人眼地时间分辨率是20ms,只要扫描数码管地的周期小于20ms,就可以使用残影让数码管显示数值,给人的感觉就是数码管同时显示了两个数字。
使用到的模块:
1.查找表,将数码管要显示的数值翻译成数码管的段选信号,从低位到告位分别对应着hgfedcba
2.分频模块,每隔1ms扫描一次数码管,所以要一个1kHz的时钟
3.用1kHz的信号去扫描数码管的位选端
4.获取相应数码管的显示值
5.计数模块,产生0-99
顶层模块代码

module test_top(clk_50M,reset,select,seg);
	input clk_50M;
	input reset;
	output [1:0]select;
	output[7:0]seg;
	
	reg [7:0]datain;
	reg [25:0]cnt;//4999_9999计时1秒
	reg [3:0]gewei,shiwei;
	
	//产生datain
	always@(posedge clk_50M,negedge reset)
		if(!reset)begin
			datain<=8'h00;
			gewei<=4'h0;
			shiwei<=4'h0;
			end
		else if(cnt==26'd4999_9999) begin
			if(shiwei>4'h9 && gewei>4'h9)begin
				gewei<=4'h0;
				shiwei<=4'h0;
				datain<={shiwei,gewei};
				end
			else if( gewei>4'h9)begin
				gewei<=4'h0;
				shiwei<=shiwei+1'b1;
				datain<={shiwei,gewei};
			    end
			else begin
			gewei<=gewei+1'b1;
			shiwei<=shiwei;
			datain[3:0]<=gewei;
			end
			cnt<=26'd0;
		end
		
		else begin
			shiwei<=shiwei;
			gewei<=gewei;
			cnt<=cnt+1'b1;
			datain<=datain;
		end
			
		
		
	test0 u0(
        	    .clk_50M(clk_50M),
		    .reset(reset),
                    .datain(datain),
		    .select(select),
		    .seg(seg)
		);

endmodule

底层模块代码:

module test0(clk_50M,reset,datain,select,seg);
	input clk_50M,reset;
	input [7:0]datain;
	output [1:0]select;
	output reg [7:0]seg;
	reg [3:0]data_disp;
	
	//分频时钟,产生频率为1k的时钟
	reg [14:0]cnt;//24999
	reg clk_1k;
	always@(posedge clk_50M,negedge reset)
		if(!reset) begin
			cnt<=15'd0;
			clk_1k<=1'b0;
			end
		else if(cnt==24999) begin
			clk_1k<=~clk_1k;
			cnt<=0;
			end
		else begin
			clk_1k<=clk_1k;
			cnt<=cnt+1'b1;
			end
	//数码管的位选
	reg [1:0]select_r;
	always@(posedge clk_1k,negedge reset)
		if(!reset) begin
			select_r<=2'b10;
			end
		else begin
			case(select_r)
				2'b10:select_r<=2'b01;
				2'b01:select_r<=2'b10;
				default: select_r<=2'b10;
			endcase
		end
	
	assign select=select_r;
	
	//获取相应数码管的显示值
	always@(*)	
		case(select_r)
			2'b10:data_disp=datain[3:0];
			2'b01:data_disp=datain[7:4];
			default:data_disp=4'h0;
		endcase
			
	
	
	//将显示值通过查找表翻译成数码管的段
	always@(*)
	case(data_disp)
		4'h0:seg=8'b11000000; 
		4'h1:seg=8'b11111001;
		4'h2:seg=8'b10100100;
		4'h3:seg=8'b10110000;
		4'h4:seg=8'b10011001;
		4'h5:seg=8'b10010010;
		4'h6:seg=8'b10000010;
		4'h7:seg=8'b11111000;
		4'h8:seg=8'b10000000;
		4'h9:seg=8'b10010000;
	default:seg=8'b11111111;
	endcase

endmodule

这段代码还存在的问题:在0-10的显示过程中,会执行两轮0-9的显示,才会显示10,并且,在整十数显示的时候,个位先不会有数字显示,下一秒才显示0,比如到了29,下一秒就应该显示30,但是它是十位显示3,个位不显示,接下来的一秒,个位才显示0,不知道是怎么回事。我找到问题之后再来改正。

猜你喜欢

转载自blog.csdn.net/whocarea/article/details/83476554