【Verilog零基础入门-边看边练】学习笔记——第五讲 时序逻辑代码设计和仿真(秒计数器)(二)

 二、用秒计数器驱动数码管实现0-9秒循环显示逻辑设计

所需软件

Verilog编程软件:Lattice Diamond(3.11.0.396.4_Diamond_x64)

Verilog仿真软件:ModelSim SE-64 10.2c(modelsim-win64-10.2c-se)

方法:用always语句实现秒计数器驱动数码管循环显示0-9秒逻辑设计

符号图: 

【Verilog零基础入门-边看边练】学习笔记——第五讲 时序逻辑代码设计和仿真(秒计数器)(二)_第1张图片

Verilog代码:

Part1:Test11_top.v文件(Verilog工程文件)

//2022-06-02
//用秒计时器驱动数码管实现0-9秒循环显示
module Test11_top(clk,res,a_g);
input					clk;
input					res;
output[6:0]				a_g;				//顶层内部信号,若只是为了连接,则定义成wire型即可

parameter				frequency_clk=24;	//假设系统时钟为24KHz
	
reg[24:0]				con_t;				//基于系统时钟的秒脉冲分频计数器。0到23999999计数,每循环一圈就是1秒。设系统时钟频率为24MHz。十进制的24兆(24000000D=?0001011011100011011000000000?B)转化为二进制需要占用25位。
reg						s_pulse;			//秒脉冲尖。1秒出现一次。两个秒脉冲尖之间表示一个系统时钟宽度。当秒脉冲分频计数器con_t计数为0后,秒脉冲尖为1;当秒脉冲分频计数器con_t计数为1后时起,秒脉冲尖为0(无秒脉冲尖),直到秒脉冲分频计数器计数再次为0后,秒脉冲尖再次为1,如此反复。
reg[3:0]				s_num=0;			//秒计数。对秒脉冲出现的次数进行计数,计数范围是0-9。
											//对s_num赋初值0
											//虽然a_g是输出端口,但是若想在always语句里赋值,也需要把它定义成reg型变量。等同于一个触发器,故需要对其复位。
reg[6:0]				a_g=7'b1111111;		//对数码管赋初值,显示“8”
 
always@(posedge clk or negedge res) begin
if(~res) begin
	con_t<=0;s_pulse<=0;s_num<=0;a_g=7'b1111111;
end
else begin
	//秒脉冲分频计数器con_t,计数范围0-23999999
	if(con_t==frequency_clk*1000-1) begin	//如果秒脉冲分频计数器con_t的计数值(1秒之内秒脉冲的个数)达到分频系数:frequency_clk*1000-1
		con_t<=0;							//对秒脉冲分频计数器清零
	end
	else begin								//如果秒脉冲分频计数器con_t的计数值(1秒之内秒脉冲的个数)未达到分频系数:frequency_clk*1000-1
		con_t<=con_t+1;						//秒脉冲分频计数器继续计数
	end
	
	//秒脉冲尖发生器s_pulse,电平状态1或0
	if(con_t==0) begin						//如果秒脉冲分频计数器con_t的计数值为零
		s_pulse<=1;							//将秒脉冲发生器s_pulse置1,秒脉冲是“尖”的形态,得到秒脉冲尖
	end
	else begin								//如果秒脉冲分频计数器con_t的计数值不为零
		s_pulse<=0;							//将秒脉冲发生器s_pulse置0,秒脉冲不是“尖”的形态
	end

	//秒(秒脉冲尖)计数器s_num,计数范围0-9
	if(s_pulse) begin						//如果秒脉冲发生器s_pulse不为0
		if(s_num==9) begin					//如果秒计数器s_num记录的秒脉冲尖(秒脉冲发生器s_pulse为1的状态)的个数已经达到9个
			s_num<=0;						//对秒计数器清零
		end
		else begin							//如果秒计数器s_num记录的秒脉冲尖(秒脉冲发生器s_pulse为1的状态)的个数未达到9个
			s_num<=s_num+1;					//秒计数器+1,用于对秒脉冲尖(秒脉冲发生器s_pulse为1的状态)计数。两个秒脉冲尖之间的时间间隔是1秒。
		end
	end
	
	//用case语句实现数码管逻辑
	case(s_num)								//用case语句实现组合逻辑
	4'd0: begin a_g<=7'b1111110; end		//当num为十进制的0时,a_g输出为1111110,数码管显示0。
	4'd1: begin a_g<=7'b0110000; end		//当num为十进制的1时,a_g输出为011_0000,数码管显示1。	
	4'd2: begin a_g<=7'b1101101; end		//当num为十进制的2时,a_g输出为110_1101,数码管显示2。	
	4'd3: begin a_g<=7'b1111001; end		//当num为十进制的3时,a_g输出为111_1001,数码管显示3。
	4'd4: begin a_g<=7'b0010011; end		//当num为十进制的4时,a_g输出为001_0011,数码管显示4。
	4'd5: begin a_g<=7'b1011011; end		//当num为十进制的5时,a_g输出为101_1011,数码管显示5。
	4'd6: begin a_g<=7'b1011111; end		//当num为十进制的6时,a_g输出为101_1111,数码管显示6。
	4'd7: begin a_g<=7'b1110000; end		//当num为十进制的7时,a_g输出为111_0000,数码管显示7。
	4'd8: begin a_g<=7'b1111111; end		//当num为十进制的8时,a_g输出为111_1111,数码管显示8。
	4'd9: begin a_g<=7'b1111011; end		//当num为十进制的9时,a_g输出为111_1011,数码管显示9。
 	//Verilog中的数字表达式:<位宽><进制><数字>
	//'b:二进制,eg 4'b1010,表示4位二进制数1010
	//'h:十六进制,eg 8'hef、4'ha
	//'d:十进制,eg 2'd3(二位的十进制数3)、4'd15(不能写16,4位最大是15,意为十进制数15,0000001111)
	default: begin a_g<=7'b0000001; end	//当num不在0-9范围时,a_g输出为000_0001,数码管显示中杠“-”。
	endcase	
	
end
end

endmodule

Part2:Test11_top_tb.v文件(Verilog仿真文件)

//2022-06-02
//用秒计时器驱动数码管实现0-9秒循环显示-testbench of Test11_top
`timescale 1ns/10ps
module Test11_top_tb;
reg							clk_in;
reg							res_in;
wire[6:0]					a_g_out;				//仿真输出变量

Test11_top Test11_top(								//s_counter:module名;U1:例化名。为module名,不要带上“_tb”
							.clk(clk_in),
							.res(res_in),
							.a_g(a_g_out)			//括号中是顶层信号名,若不是端口,则需要定义成wire型完成连接							
							);
			
initial begin
							clk_in<=0;res_in<=0;

		#17					res_in<=1;				//过17ns,解除对时钟的复位
		#3000000			$stop;					//运行时长3000000ns。24KHz,计数24000次,一次10ns,循环一周期(计数一秒)为240000ns,则完成0~9的计数需要运行2400000ns。
end
 
always	#5					clk_in<=~clk_in;		//设定一个以10ns为周期的运行时钟

endmodule

仿真波形:

【Verilog零基础入门-边看边练】学习笔记——第五讲 时序逻辑代码设计和仿真(秒计数器)(二)_第2张图片

注意事项

1、对于顶层的内部信号,若只是为了连接,则定义成wire型即可;

2、若设定系统时钟为24KHz,且把分频系数选为23999,则需计数24000次,设定计数一次用时10ns(设定运行时钟周期为10ns),则循环一周期(计数1秒)为240000ns,那么完成0~9秒的计数需要运行2400000ns。

原教学视频链接如下

Verilog零基础入门_哔哩哔哩_bilibili

你可能感兴趣的:(Lattice,学习,fpga开发,硬件工程)