Verilog HDL设计数字跑表&数码管显示

用Verilog HDL设计数字跑表&数码管显示

  用Verilog HDL设计一个数字跑表,具有复位、暂停、秒表等功能,同时为了便于显示,百分秒、秒、分钟信号均采用BCD码计数方式,并直接输出到6个数码管中
《Verilog HDL设计数字跑表&数码管显示》
  首先我们需要通过读题来理清思路,那么这里的话,很明显,我们可以通过模块之间的调用组合来实现。
  我也同步发到我自己的博客啦!戳这里 还有搭建个人博客的教程哦,毫不夸张地说这是我见过最快搭好博客的方法。

设计数字跑表

  我们通过直观的想象将这个跑表平面铺开,其实可以分为五个部分:百分秒、秒、分钟、暂停以及置位。理一理其中的逻辑哈,百分秒计数满100向秒进一位,自己清零;秒计数满60向分钟进一位,而自己同样清零;分钟则是满60就清零,并无进位;同时当暂停信号为1时暂停计数,为0时正常计数;而置位信号为1时开始置位,为0时正常计数。
  因此其实逻辑已经很清楚了,下面附上代码:

module stop_watch(input CLK,CLR,PAUSE,output [3:0] MSH,MSL,SH,SL,MH,ML);
reg [3:0] MSH,MSL,SH,SL,MH,ML;
//count_ms_s为百分秒向秒进位,count_s_m为秒向分进位
reg count_ms_s,count_s_m;
	
//百分秒,每计满100,count_ma_s产生一个进位
always @(posedge CLK or posedge CLR)
	begin
		//复位
		if(CLR)
			begin
				MSH<=0;
				MSL<=0;
				count_ms_s<=0;
			end
		//正常计数
		else if(!PAUSE)//当PAUSE为1时暂停计数,为0时正常计数
			begin
				if(MSL==9)
					begin 
						MSL<=0;
						if(MSH==9)
							begin 
								MSH<=0;
								count_ms_s<=1;
							end
						else
							MSH<=MSH+1;
					end
				else
					begin
						MSL<=MSL+1;
						count_ms_s<=0;
					end
			end
	end
//秒计数进程,每计满60,产生一个进位
always @(posedge count_ms_s or posedge CLR)
	begin
		//复位
		if(CLR)
			begin
				SH<=0;
				SL<=0;
				count_s_m<=0;
			end
		else if(!PAUSE)//当PAUSE为1时暂停计数,为0时正常计数
			begin
				if(SL==9)
					begin 
						SL<=0;
						if(SH==5)
							begin 
								SH<=0;
								count_s_m<=1;
							end
						else
							SH<=SH+1;
					end
				else
					begin
						SL<=SL+1;
						count_s_m<=0;
					end
			end
	end
//分钟计数进程,每计满60,系统自动清零
always @(posedge count_s_m or posedge CLR)
	begin 
		if(CLR)
			begin
				MH<=0;
				ML<=0;
			end
		else if(ML==9)
			begin
				ML<=0;
				if(MH==5)
					MH<=0;
				else
					MH<=MH+1;
			end
		else
			ML<=ML+1;
	end
endmodule

  激励文件我觉得其实把逻辑理清楚就很好写,为了能很好的凸显出功能,因此第一次写激励的时候先不考虑时间,先看一下产生进位是到什么时间段,然后再返回去根据这个时间来写激励,我觉得这样比较好,当然,大佬就别嘲讽我了啊哈哈哈啊哈哈啊哈哈~

initial begin
		// Initialize Inputs
		CLK = 0;
		CLR = 1;
		PAUSE = 1;
		
		#5 PAUSE=0;CLR=0;//开始计数,不清零
		#1000 PAUSE=1;//暂停一下,这个时候是有一个进位的
		#10 PAUSE=0;//继续计数
		#10 CLR=1;//清零
		#10 CLR=0;//取消清零 如果这个时候不取消清零的话,之后的波形一直都是零
	end
      always #5 CLK=~CLK;
	//信息打印
	initial begin
		$monitor ($time,"CLR=%d,PAUSE=%d,MSH=%d,MSL=%d",CLR,PAUSE,MSH,MSL);
		#1200 $stop;
		//$finish;
	end

  核心的部分就是这个了,通过标识符将信息打印出来还是比较方便的,然后由于我使用的是ISE14.7版本,因此在仿真阶段默认是只取用到1000ns,这个时候可以在仿真设置里面更改 (我没找到) 或者按F5运行全部,当然界面也有按钮可以操作。

设计数码管驱动

  先附上一张我们实验指导书上的图,这其实也就是一个二进制转BCD码了,只不过有分共阴共阳的数码管,但这无伤大雅,这部分就怎么说呢,可以将这部分代码用一个文本装起来放好,省的以后要用了还要去写,这就很nice,难道不是吗?
《Verilog HDL设计数字跑表&数码管显示》
  下面直接贴代码吧,也没啥好说的,看代码一看就明白了,这里需要注意就是case语句最后后面加上default,这个是上课老师讲过的哦~

module led(input[3:0] in,output reg[6:0] out);

always@(in)
  begin
    case(in)
	   4'd0:out=7'h3f;
		4'd1:out=7'h06;
		4'd2:out=7'h5b;
		4'd3:out=7'h4f;
		4'd4:out=7'h66;
		4'd5:out=7'h6d;
		4'd6:out=7'h7d;
		4'd7:out=7'h07;
		4'd8:out=7'h7f;
		4'd9:out=7'h6f;
		default out=7'h0;
	  endcase
	end
endmodule

激励文件

initial begin
		#10 in=0;
		#10 in=1;
		#10 in=2;
		#10 in=3;
		#10 in=4;
		#10 in=5;
		#10 in=6;
		#10 in=7;
		#10 in=8;
		#10 in=9;
	end
	initial begin
		#100 $stop;
	//$monitor ();
	end

  然后这里可能就会有小朋友问为什么他仿真的波形不太对呢,数字好像是反的或者是乱的,这个的话,那组数字你试试从右向左看是不是对的,如果还是有问题,就要检查一下是不是进制转错了。

顶层设计模块组合

  这部分就更简单了,将两个具有独立功能的模块通过代码格式调用起来组合成一个新的模块,逻辑就在于将数码管驱动模块衔接到跑表的后面,以跑表的输出输出作为数码管驱动的输入,然后再生成新的输出。

module stop_watch_led_top(input CLK,CLR,PAUSE,output wire[6:0] out1,out2,out3,out4,out5,out6);
//模块的输出不能是reg型,reg型只能作为模块内部输出或者????
wire [3:0] MSH,MSL,SH,SL,MH,ML;
//这里通过调用六次驱动模块来实现
//注意模块调用的格式以及变量
	stop_watch stop_watch_demo(CLK,CLR,PAUSE,MSH,MSL,SH,SL,MH,ML);
	led led_demo1(MSH,out1);
	led led_demo2(MSL,out2);
	led led_demo3(SH,out3);
	led led_demo4(SL,out4);
	led led_demo5(MH,out5);
	led led_demo6(ML,out6);
endmodule

  然后这里的激励和之前跑表的激励一样的就可以,你想一下是不是。然后这里有一个问题,我还在写这个的时候别人问我的,她遇到的问题就是在一个设计里面emmmmmmm她没写完,她最后的设计里面是分了两个模块,虽然我不知道我想的对不对啊,但是就目前我们学习到的,或者说我们接触到的这种格式,最后基本上都是一个工程最后会综合设计成一个完整的项目。因此,假如说现在这里剩一个按键消抖的模块和一个巴拉巴拉的模块,将他们连接起来,那么,该如何下手去写这个top文件呢?
  我的想法是思路理清晰,脑海里将两个模块连接一起,然后就想想现在这个top_module的输入输出是什么,然后就直接

module top_module(input 巴拉巴拉,output 巴拉巴拉)
endmodule

  然后就是考虑中间的连接问题,定义一些变量来作为寄存器什么什么的,视情况而定,最后就直接调用模块,直接整合成一个项目。


//调用模块是不是需要一个类似于代号的东西,有点像Java的创建对象
模块名字  X (按照你调用的模块的变量!顺序!来书写,但是注意变量是什么?)

  好的,感谢各位看官老爷耐心的看完了这部分文章,点赞~yeah

    原文作者:NothingSure
    原文地址: https://blog.csdn.net/weixin_43761491/article/details/105369216
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞