EDA技术实用教程 | 复习十三 | 计数器

计数器的设计

计数器属于时序电路的范畴,其应用十分普遍。计数器可分为:加法计数器、减法计数器及可逆计数器等。最常用的是加法计数器。加法计数器的原理就是当时钟脉冲CP为上升沿时,计数器会将计数值加1。计数的范围为0~2n-1。(其中n为计数器的位数)。

一、10进制计数器设计:

具有异步复位,同步计数使能和可预置型的十进制计数器。

module CNT10 (CLK, RST, EN, LOAD, COUT, DOUT, DATA);
	input CLK, EN, RST, LOAD;  //时钟,时钟使能,复位,数据加载控制信号
	input [3 : 0] DATA;		   //4位并行加载数据
	
	output[3 : 0] DOUT		   //4位计数输出
	output COUT;			   //计数进位输出
	
	reg [3 : 0] Q1;
	reg COUT;
	assign DOUT = Q1;			//将内部寄存器的技术结果输出至DOUT

	always @(posedge CLK or negedge RST)		//时序过程
		begin
				if(!RST)
						Q1 <= 0;	//RST=0时,对内部寄存器单元异步清0
				else if(EN)			//同步使能EN=1,则允许加载或计数
					begin
							if(!LOAD)
									Q1 <= DATA;		//当LOAD=0,向内部寄存器加载数据
							else if(Q1 < 9)			//当Q1小于9时,允许累加
									Q1 <= Q1 + 1;
							else					//否则一个时钟后清0返回初值
									Q1 <= 4'b0000;
					end
		end

	always @(Q1)			//组合过程
		begin
				if(Q1 == 4'h9)
						COUT = 1'b1;
				else
						COUT = 1'b0;
		end
endmodule

时序仿真图如下:
在这里插入图片描述

二、100进制计数器设计:(例化法)

电路连接参考图如下:
在这里插入图片描述
用已经写好的10进制计数器构成100进制计数器:10进制计数器设计如一所示。
代码如下:

module CNT100(clk,aclr,set,up_down,data,q,co);
input clk;
input aclr; // low active
input set; //
input up_down;// up_down =1, 加法, up_down = 0, 减法
input[7:0] data;
output[7:0] q;
output co;
wire net1, net2, net3;

CNT10 U1(.clk(clk),.aclr(aclr),.set(set),.up_down(up_down),.data(data[3:0],.q(q[3:0]),.co(net1));
	not	U2(net1, net2);
CNT10 U3(.clk(net2),.aclr(aclr),.set(set),.up_down(up_down),.data(data[7:4],.q(q[7:4]),.co(net3));
	and	U4(co,net1,net3);
二、1000进制计数器设计:(行为级描述)

电路连接图如下:
在这里插入图片描述
代码如下:

module CNT_1000(CLK_1Hz,aclr,set,up_down,data,Q,co);
	input CLK_1Hz; 
	input aclr;     // 异步清零,低电平有效
	input set;      //	异步置数,低电平有效 
	input up_down;  //  up_down =1,加一计数器, up_down = 0, 减一计数器
	input[11:0] data;
	output[11:0] Q;
	output co;

	reg[3:0] Q1,Q2,Q3;
	reg co1,co2,co3;
	
	
	always @(posedge CLK_1Hz or negedge aclr or negedge set)//个位
		begin
				if(aclr == 0)
						Q1 <= (up_down) ? 4'd0 : 4'd9;
				else if(set ==0)
						Q1 <= data[3:0]; //置数
				else if(up_down == 1)   //加法计数器
					begin
						if(Q1 < 4'd9)
							Q1 <= Q1 + 4'd1;
						else
							Q1 <= 4'd0;
					end
				else
					begin
						if(Q1 > 4'd0)
							Q1 <= Q1 - 4'd1;
						else if(Q1 == 4'd0)
							Q1 <= 4'd9;
					end
		end
		
	always @(negedge co1 or negedge aclr or negedge set)//十位
		begin
				if(aclr == 0)
						Q2 <= (up_down) ? 4'd0 : 4'd9;
				else if(set ==0)
						Q2 <= data[7:4]; //置数
				else if(up_down == 1)   //加法计数器
					begin
						if(Q2 < 4'd9)
							Q2 <= Q2 + 4'd1;
						else
							Q2 <= 4'd0;
					end
				else if(up_down == 0)
					begin
						if(Q2 > 4'd0)
							Q2 <= Q2 - 4'd1;
						else if(Q2 == 4'd0)
							Q2 <= 4'd9;
					end
		end
		
	always @(negedge co2 or negedge aclr or negedge set)//百位
		begin
				if(aclr == 0)
						Q3 <= (up_down) ? 4'd0 : 4'd9;
				else if(set ==0)
						Q3 <= data[11:8]; //置数
				else if(up_down == 1)   //加法计数器
					begin
						if(Q3 < 4'd9)
							Q3 <= Q3 + 4'd1;
						else
							Q3 <= 4'd0;
					end
				else if(up_down == 0)
					begin
						if(Q3 > 4'd0)
							Q3 <= Q3 - 4'd1;
						else if(Q3 == 4'd0)
							Q3 <= 4'd9;
					end
		end
		
	always @(Q1)
		begin
				if(up_down == 1 && Q1 == 4'd9)
					co1 = 1;
				else if((up_down == 0) && (Q1 == 4'd0))
					co1 = 1;
				else
					co1 = 0;
		end
		
	always @(Q2)
		begin
				if(up_down == 1 && Q2 == 4'd9)
					co2 = 1;
				else if((up_down == 0) && (Q2 == 4'd0))
					co2 = 1;
				else
					co2 = 0;
		end
		
	always @(Q3)
		begin
				if(up_down == 1 && Q3 == 4'd9)
					co3 = 1;
				else if((up_down == 0) && (Q3 == 4'd0))
					co3 = 1;
				else
					co3 = 0;
		end	
	assign co = co1&&co2&&co3;
	assign Q = {Q3,Q2,Q1};
endmodule 

时序仿真图如下所示:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值