在FPGA设计中,计数器的使用占据很大的比重,在后面接触的FPGA设计的,总少不了计数器的身影,有时候计数器的性能决定了一个项目的成败,本笔记中,我做了两种计数器的设计:第一种就是综合工具自动综合出来的计数器.第二种就是使用 IP 核的计数器。
如果按照计数器中的触发器是否同时翻转分类,可将计数器分为同步计数器和异步计数器两种。
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;elseout_cnt <= out_cnt;endmodule ///////////////////`tb`timescale 1ns/1ns`define clock_period 20module 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 beginrst_n = 1'b0;#(`clock_period *20);rst_n = 1'b1;#(`clock_period *2000);$stop;endendmodule
仿真波形图:
异步计数:
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;elsecnt<=cnt+1'b1;always@(posedgeclkornegedgerst_n)if(!rst_n)out_cnt<=1'b1;elseif(cnt==8'd125)out_cnt<=~out_cnt;elseout_cnt<=out_cnt;//always@(clkorrst_n)always@(cnt)if(!rst_n)asyn_out<=1'b1;elseif(cnt==8'd125)asyn_out<=~asyn_out;elseasyn_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_period20modulecounter_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;initialbeginrepeat(300)begin//cin=0;#(`clock_period*5)cin=1;#(`clock_period)cin=0;end#(`clock_period*200);$stop;endendmodule
波形图:
上图箭头所产生的时间极短的尖峰,在此可以不考虑。