原创 7.我与FPGA的恋爱之同步和异步计数器的使用

2016-4-15 19:47 1042 21 21 分类: FPGA/CPLD 文集: 我与FPGA的恋爱

本次笔记记录的是计数器的使用

  在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;
	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

仿真波形图:

2016-03-27_111244.jpg

异步计数:

module asyn_counter(rst_n,clk,out_cnt,asyn_out);
	input clk;
	input rst_n;
	output reg out_cnt;
	output reg asyn_out;
	
	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;
	
	//always @(clk or rst_n)	
	always @(cnt)
	if(!rst_n)
		asyn_out <= 1'b1;
	else if(cnt == 8'd125) 
		asyn_out <= ~asyn_out;
	else
		asyn_out <= asyn_out;
endmodule 


//////`tb 更改一下例化就行了
asyn_counter counter(
	.rst_n(rst_n),
	.clk(clk),
	.out_cnt(out_cnt),
	.asyn_out(asyn_out)
	);	

2016-03-27_121402.jpg

 

IP 核的计数器

ip核设置如下(Quartus 15.0):

1000001733-6359468075416300004085276.jpg-g560

 

1000001733-6359468075427700006813754.jpg-g560

1000001733-6359468075509200003996123.jpg-g560

计数到100清零,此程序中 carry_in /out 可以不选

1000001733-6359468075524700008481264.jpg-g560

如上图打开 可以找到例化模块  counter(.........)

设置ip/counter.qip为顶层文件

仿真代码:

`timescale 1ns/1ns
`define clock_period 20
module counter_tb;
	reg cin;	//进位输入
	reg clk;	//计数基准时钟	
	wire cout;//进位输出
	wire [7:0] q;

	counter counter0(
		.cin(cin),
		.clock(clk),
		.cout(cout),
		.q(q)
	);
	
	initial clk = 1;
	always #(`clock_period/2)clk = ~clk;	
	initial begin
		repeat(300)begin   //
			cin = 0;
			#(`clock_period*5)cin = 1;
			#(`clock_period)cin = 0;		
		end
		#(`clock_period*200);
		$stop;
	end
endmodule

波形图:

2016-03-27_125935.jpg

上图箭头所产生的时间极短的尖峰,在此可以不考虑,等后续笔记会做"竞争冒险"讲述

 

 

由于本人能力有限,出错之处的请各位给予帮助.谢谢!

 

 

 

 更多资料参考

                发烧友小梅哥专版 http://bbs.elecfans.com/zhuti_fpga_1.html

                   梦翼师兄的炼狱传奇

 

文章评论0条评论)

登录后参与讨论
我要评论
0
21
关闭 站长推荐上一条 /2 下一条