FPGA入门笔记004——BCD计数器设计与使用

发布时间 2023-11-21 14:22:46作者: Yamada_Ryo

1、设置一个最大值为10的四位计数器,Verilog代码如下:

module BCD_Counter(
	Clk,
	Cin,
	Rst_n,
	Cout,
	q
);
	input Clk;	//计数器基准时钟
	input Cin;	//计数器进位输入
	input Rst_n;	//系统复位
	
//	output Reg Cout;	//计数器进位输出
	output Cout;	//计数器进位输出
	output [3:0]q;	//计数值输出
	
	reg [3:0]cnt;	//定义计数器寄存器

//执行计数过程
	always@(posedge Clk or negedge Rst_n)
		if(Rst_n == 1'b0)
			cnt <= 4'd0;
		else if(Cin == 1'b1)begin
			if(cnt == 4'd9)
				cnt <= 4'd0;
			else
				cnt <= cnt + 1'b1;
		end
		else          
			cnt <= cnt;
			
//若为以下代码,则会产生时延错误
//	always@(posedge Clk or negedge Rst_n)
//		if(Rst_n == 1'b0)
//			Cout <= 1'b0;
//		else if(cnt == 4'd9 && Cin == 1'b1)
//			Cout <= 1'b1;
//		else
//			Cout <= 1'b0;
	
	assign Cout = (cnt == 4'd9 && Cin == 1'b1);	//产生进位输出信号
	
	assign q = cnt;
	
endmodule

2、设置仿真测试文件,代码如下:

`timescale 1ns/1ns
`define clock_period 20

module BCD_Counter_tb;
	
	reg Clk;
	reg Cin;
	reg Rst_n;
	
	wire Cout;
	wire [3:0]q;
	
	BCD_Counter BCD_Counter0(
		.Clk(Clk),
		.Cin(Cin),
		.Rst_n(Rst_n),
		.Cout(Cout),
		.q(q)
	);
	
	initial Clk = 1;
	always#(`clock_period / 2) Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		Cin = 1'b0;
		#(`clock_period * 200);
		Rst_n = 1'b1;
		#(`clock_period * 20);
		repeat(30)begin	//重复执行30次
			Cin = 1'b1;
			#`clock_period;
			Cin = 1'b0;
			#(`clock_period * 5);
		end
		#(`clock_period * 20);
		$stop;
	end

endmodule

3、将三个四位计数器相连,生成一个12位的BCD计数器,代码如下:

module BCD_Counter_top(
	Clk,
	Cin,
	Rst_n,
	Cout,
	q
);
	input Clk;	//计数器基准时钟
	input Cin;	//计数器进位输入
	input Rst_n;	//系统复位
	
	output Cout;	//计数器进位输出
	output [11:0]q;	//计数值输出
	
	wire Cout0,Cout1;
	wire [3:0]q0,q1,q2;

	assign q = {q2,q1,q0};

	BCD_Counter BCD_Counter0(
		.Clk(Clk),
		.Cin(Cin),
		.Rst_n(Rst_n),
		.Cout(Cout0),
		.q(q0)                                              
	);

	BCD_Counter BCD_Counter1(
		.Clk(Clk),
		.Cin(Cout0),
		.Rst_n(Rst_n),
		.Cout(Cout1),
		.q(q1)
	);

	BCD_Counter BCD_Counter2(
		.Clk(Clk),
		.Cin(Cout1),
		.Rst_n(Rst_n),
		.Cout(Cout),
		.q(q2)
	);

endmodule 

4、设置仿真测试文件,代码如下:

`timescale 1ns/1ns
`define clock_period 20

module BCD_Counter_top_tb;
	
	reg Clk;
	reg Cin;
	reg Rst_n;
	
	wire Cout;
	wire [11:0]q;
	
	BCD_Counter_top BCD_Counter_top0(
		.Clk(Clk),
		.Cin(Cin),
		.Rst_n(Rst_n),
		.Cout(Cout),
		.q(q)
	);
	
	initial Clk = 1;
	always#(`clock_period / 2) Clk = ~Clk;
	
	initial begin
		Rst_n = 1'b0;
		Cin = 1'b0;
		#(`clock_period * 200);
		Rst_n = 1'b1;
		#(`clock_period * 20);
		Cin = 1'b1;
		#(`clock_period * 5000);
		$stop;
	end

endmodule