数码管动起来

记录学习日常,此实验借鉴正点原子的例程,这次代码好长呀。第一个模块是一个计数器,让数据100ms变化一次,设置一个100ms计数器与一个计数满的标志信号。上代码:

module count(
	input clk,
	input rst_n,
	
	output reg en,
	output reg [5:0]point,
	output reg [19:0]data,
	output reg signal
);

reg flag;
reg[22:0]cnt;
//100ms数据变化一次
parameter MAX_CNT = 23'd5000_000;

always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		flag <= 1'b0;
		cnt <= 23'd0;
	end
	else if(cnt < MAX_CNT - 1)begin
		flag <= 1'b0;
		cnt <= cnt + 1'b1;
	end
	else begin
		flag <= 1'b1;
		cnt <= 23'd0;
	end
	
always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		en <= 1'b0;
		point <= 6'b0;
		data <= 20'd0;
		signal <= 1'b0;
	end
	else begin
		en <= 1'b1;
		signal <= 1'b0;
		point <= 6'b0;
		if(flag)begin
			if(data  < 20'd999_999)
				data <= data + 1'b1;
			else
				data <= 20'd0;
		end
	end
	
	endmodule
	

第二个模块代码量更大;第一步因为数码管的时钟频率为5MHZ所以对于50MHZ的开发板来说需要设置一个十分频时钟,设置一分频计数器来产生分频时钟。时钟计数器最大值应该是10/2-1当计数满4时分频时钟翻转。

always@(posedge clk or negedge rst_n)
	if(!rst_n)begin
		dri_clk <= 1'b0;
		clk_cnt <= 4'd0;
		end
	else if(clk_cnt == CLK_DIVIDE/2-1'b1)begin
		dri_clk <= ~dri_clk;
		clk_cnt <= 4'd0;
		end
	else begin
		dri_clk <= 1'b0;
		clk_cnt <= clk_cnt + 1'b1;
		end

第二部分:总共6位数码管最大数位999_999,对于每个数取模为:

assign data0 = data & 4'd10;
assign data1 = data  / 4'd10 %4'd10;
assign data2 = data  / 7'd100 %4'd10;
assign data3 = data  / 10'd1000 %4'd10;
assign data4 = data  / 14'd10000 %4'd10;
assign data5 = data  / 17'd100000;

第三部分:对于定义【23:0】num来说是因为每四位数组成一个BCD码,这里我不是很清楚为什么要有这一步。还有一种说法是:一个数码管需要显示16种状态所以一个数码管需要有【3:0】的位宽。有大佬明白的可以指导下。

always@(posedge dri_clk or negedge rst_n)
	if(!rst_n)
		num <= 24'd0;
	else begin
		if(data5 || point[5])begin
			num[23:20] <= data5;
			num[19:16] <= data4;
			num[15:12] <= data3;
			num[11:8]  <= data2;
			num[7:4]   <= data1;
			num[3:0]   <= data0;
		end
		else begin
			if(data4 || point[4])begin
				num[19:0] <= {data4,data3,data2,data1,data0};
				if(signal)
					num[23:20] <= 4'd11;
				else
					num[23:20] <= 4'd10;
			end
			 
		else begin
			if(data3 || point[3])begin
				num[15:0] <= {data3,data2,data1,data0};
				num[23:20] <= 4'd10;
				
				if(signal)
					num[19:16] <= 4'd11;
				else
					num[19:16] <= 4'd10;
			end
		else begin
			if(data2 || point[2])begin
				num[11:0] <= {data2,data1,data0};
				num[23:16] <= {2{4'd10}};
				
				if(signal)
					num[15:12] <= 4'd11;
				else
					num[15:12] <= 4'd10;
			end
		else begin
			if(data1 || point[1])begin
				num[7:0] <= {data1,data0};
				num[23:12] <= {3{4'd10}};
				
				if(signal)
					num[11:8] <= 4'd11;
				else
					num[11:8] <= 4'd10;
			end
		else begin
				num[3:0] <= data0;
				num[23:8] <= {4{4'd10}};
				
				if(signal)
					num[7:4] <= 4'd11;
				else
					num[7:4] <= 4'd10;
			end
		
		end
	end
	end
	end
	end

第四部分:

//让数码管亮1ms
always@(posedge dri_clk or negedge rst_n)
	if(!rst_n)begin
		flag <= 1'b0;
		cnt0 <= 13'd0;
	end
	else if(cnt0 < MAX_NUM - 1)begin
		flag <= 1'b0;
		cnt0 <= cnt0 + 1'b1;
	end
	else begin
		flag <= 1'b1;
		cnt0 <= 13'd0;
	end
//显示当前显示的数码管
always@(posedge dri_clk or negedge rst_n)
	if(!rst_n)	
		cnt_sel <= 3'b0;
	else if(flag)begin
		if(cnt_sel < 3'd5)
			cnt_sel <= cnt_sel + 1'b1;
		else
			cnt_sel <= 3'b0;
	end
	else
		cnt_sel <= cnt_sel;

接下来就要写数码管显示的数据部分:

always @ (posedge dri_clk or negedge rst_n) begin
 if(!rst_n) begin
		sel <= 6'b111111; //位选信号低电平有效
		num_disp <= 4'b0;
		dot_disp <= 1'b1; //共阳极数码管,低电平导通
	end
	else begin
		if(en) begin
			case (cnt_sel)
				3'd0 :begin
					sel <= 6'b111110; //显示数码管最低位
					num_disp <= num[3:0] ; //显示的数据
					dot_disp <= ~point[0]; //显示的小数点
				end
				3'd1 :begin
					sel <= 6'b111101; //显示数码管第1位
					num_disp <= num[7:4] ;
					dot_disp <= ~point[1];
					end
				3'd2 :begin
					sel <= 6'b111011; //显示数码管第2位
					num_disp <= num[11:8];
					dot_disp <= ~point[2];
				end
				3'd3 :begin
					sel <= 6'b110111; //显示数码管第3位
					num_disp <= num[15:12];
					dot_disp <= ~point[3];
				end
				3'd4 :begin
					sel <= 6'b101111; //显示数码管第4位
					num_disp <= num[19:16];
					dot_disp <= ~point[4];
				end
				3'd5 :begin
					sel <= 6'b011111; //显示数码管最高位
					num_disp <= num[23:20];
					dot_disp <= ~point[5];
				end
				default :begin
					sel <= 6'b111111;
					num_disp <= 4'b0;
					dot_disp <= 1'b1;
					end
				endcase
			end
				else begin
					sel <= 6'b111111; //使能信号为0时,所有数码管均不显示
					num_disp <= 4'b0;
					dot_disp <= 1'b1;
					end
					end
					end

最后数码管段选:

always @ (posedge dri_clk or negedge rst_n) begin
	if (!rst_n)
		seg_led <= 8'hc0;
	else begin
		case (num_disp)
			4'd0 : seg_led <= {dot_disp,7'b1000000}; //显示数字 0
			4'd1 : seg_led <= {dot_disp,7'b1111001}; //显示数字 1
			4'd2 : seg_led <= {dot_disp,7'b0100100}; //显示数字 2
			4'd3 : seg_led <= {dot_disp,7'b0110000}; //显示数字 3
			4'd4 : seg_led <= {dot_disp,7'b0011001}; //显示数字 4
			4'd5 : seg_led <= {dot_disp,7'b0010010}; //显示数字 5
			4'd6 : seg_led <= {dot_disp,7'b0000010}; //显示数字 6
			4'd7 : seg_led <= {dot_disp,7'b1111000}; //显示数字 7
			4'd8 : seg_led <= {dot_disp,7'b0000000}; //显示数字 8
			4'd9 : seg_led <= {dot_disp,7'b0010000}; //显示数字 9
			4'd10: seg_led <= 8'b11111111; //不显示任何字符
			4'd11: seg_led <= 8'b10111111; //显示负号(-)
			default:
				seg_led <= {dot_disp,7'b1000000};
 endcase
 end
 end

这些是我对动态数码管的理解。大家可以一起讨论。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值