计数器的设计
计数器属于时序电路的范畴,其应用十分普遍。计数器可分为:加法计数器、减法计数器及可逆计数器等。最常用的是加法计数器。加法计数器的原理就是当时钟脉冲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
时序仿真图如下所示: