如果按照计数器中的触发器是否同时翻转分类,可将计数器分为同步计数器和异步计数器两种。
1.基本概念:每个不同的计数器,在设计之初,被设计者设定为感应固定的波形的某一部分(一般为瞬态感应),比如方波的下降沿(或上升沿);
2.同步计数:当你所购得的计数器为同步计数器,所谓同步,就是该计数器只有当输入信号的下降沿(或上升沿)来临时,计数器才会开始处理,其他时间无论高低电平,计数器都会无视;
3.异步计数:所谓异步,就是你随时达到所设定的值,它立刻就跳转,并不等待下一个下降沿(或上升沿)的到来;
综上可以看出,同步,异步说的都是相对于输入信号,计数器在达到最大计数值时的响应是同步于该输入信号,还是异步于它;
下面我们先分别看一下同步计数器和异步计数器的实现
同步计数器:
module counter(rst_n,clk,out_cnt);
input clk;
input rst_n;
output reg out_cnt;
reg [7:0]cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 8'd0;
else if(cnt == 8'd125)
cnt <= 8'd0;
else
cnt <= cnt + 1'b1;
always @(posedge clk or negedge rst_n)
if(!rst_n)
out_cnt <= 1'b1;
else if(cnt == 8'd125)
out_cnt <= ~out_cnt;
else
out_cnt <= out_cnt;
endmodule
///////////////////`tb
`timescale 1ns/1ns
`define clock_period 20
module counter_tb;
reg clk;
reg rst_n;
wire out_cnt;
counter counter(.rst_n(rst_n),.clk(clk),.out_cnt(out_cnt));
initial clk = 1;
always #(`clock_period/2) clk = ~clk;
initial begin
rst_n = 1'b0;
#(`clock_period *20);
rst_n = 1'b1;
#(`clock_period *2000);
$stop;
end
endmodule
仿真波形图:
异步计数:
moduleasyn_counter(rst_n,clk,out_cnt,asyn_out);
inputclk;
inputrst_n;
outputregout_cnt;
outputregasyn_out;
reg[7:0]cnt;
always@(posedgeclkornegedgerst_n)
if(!rst_n)
cnt<=8'd0;
elseif(cnt==8'd125)
cnt<=8'd0;
else
cnt<=cnt+1'b1;
always@(posedgeclkornegedgerst_n)
if(!rst_n)
out_cnt<=1'b1;
elseif(cnt==8'd125)
out_cnt<=~out_cnt;
else
out_cnt<=out_cnt;
//always@(clkorrst_n)
always@(cnt)
if(!rst_n)
asyn_out<=1'b1;
elseif(cnt==8'd125)
asyn_out<=~asyn_out;
else
asyn_out<=asyn_out;
endmodule
//////`tb更改一下例化就行了
asyn_countercounter(
.rst_n(rst_n),
.clk(clk),
.out_cnt(out_cnt),
.asyn_out(asyn_out)
);
IP 核的计数器
ip核设置如下(Quartus 15.0):
计数到100清零,此程序中 carry_in /out 可以不选
如上图打开 可以找到例化模块 counter(.........)
设置ip/counter.qip为顶层文件
仿真代码:
`timescale1ns/1ns
`defineclock_period20
modulecounter_tb;
regcin; //进位输入
regclk; //计数基准时钟
wirecout;//进位输出
wire[7:0]q;
countercounter0(
.cin(cin),
.clock(clk),
.cout(cout),
.q(q)
);
initialclk=1;
always#(`clock_period/2)clk=~clk;
initialbegin
repeat(300)begin//
cin=0;
#(`clock_period*5)cin=1;
#(`clock_period)cin=0;
end
#(`clock_period*200);
$stop;
end
endmodule
波形图:
上图箭头所产生的时间极短的尖峰,在此可以不考虑。