FPGA学习笔记(4)——BCD计数器、计数器级联

bcd计数器

定义:4bit的counter计数到9,再进行级联,则输出值q可以直接用bcd码表示成十进制数。

例如计数456次,输出值为q为12’h456。

q[11:8]

q[7:4]

q[3:0]

4

5

6

代码如下:

counter_4bit

module counter_4bit 
#( parameter	c_number = 4'd10 )
(
	input		clk	,
	input		rst_n	,
	input		cin	,
	output	reg	cout	,
	output	reg[3:0] q
);
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		q <= 4'd0 ;
	else if(q == c_number-1'b1 && cin == 1'b1)
		q <= 4'd0 ;
	else if(cin == 1'b1)
		q <= q+1'b1;
	else	q <= q;
end
always@(*) begin
	if(q == c_number-1'b1 && cin == 1'b1)
		cout <= 1'b1;
	else	cout <= 1'b0;
end
endmodule

bcd_counter

module bcd_counter(
	input		clk  ,
	input		rst_n,
	input		cin  ,
	output		cout ,
	output	[11:0]	q
);
	wire	m1,m2;	
counter_4bit       //对counter_4bit进行三次例化
#(.c_number(10))
u1
(
	.clk	(clk  ),
	.rst_n	(rst_n),
	.cin	(cin  ),
	.cout	(m1   ),
	.q      (q[3:0])
);
counter_4bit 
u2
(
	.clk	(clk  ),
	.rst_n	(rst_n),
	.cin	(m1   ),
	.cout	(m2   ),
	.q      (q[7:4])
);
counter_4bit 
u3
(
	.clk	(clk  ),
	.rst_n	(rst_n),
	.cin	(m2   ),
	.cout	(cout ),
	.q      (q[11:8])
);
endmodule

tb

`timescale 1ns/1ns
`define	clk_period 20

module tb();
reg	clk;
reg	rst_n;
reg	cin;
wire	cout;
wire[11:0] q;

initial begin 
	clk <= 1'b1;
	cin <= 1'b0;
	rst_n <= 1'b0;
	#40 rst_n <= 1'b1;
	repeat(1200)begin
	#60	cin <= 1'b1;
	#20	cin <= 1'b1;
	end
	#1000
	$stop;
end
always #(`clk_period/2) clk <= ~clk;

bcd_counter bcd_ins1(
	  .clk  (clk  ),
	  .rst_n(rst_n),
	  .cin  (cin  ),
	  .cout (cout ),
	  .q    (q    )
);

endmodule	

综合后的电路如图1所示,仿真波形图如图2所示。

图1

图2


疑问1: 为什么u2的q不在①处发生变化呢?而是在②处才捕获到cin信号,发生变化呢?

图3

猜测:即使cout是使用组合逻辑赋值的,但cin经过了一个与门传给cout有延迟,且u1中的cout传递到u2中的cin这个过程需要时间(实际情况可参考图6中的标注处),所以才在下个时钟上升沿②处发生变化。

图4 counter_4bit

        

                             图5                                                                             图6


疑问2:若cin信号不连续,且由1变0的跳变沿与时钟上升沿重合(图5所示)这时会出现错误值(889-899-900),图7为完整波形图。

图7

图8

在实际应用中,由于DFF的setup、hold要求,cin在clk上升沿之前要稳定下来,图8所示为正常状态。边沿重合本就是不稳定的状态,设计中要完全避免,但计数信号cin是随机的,不可避免会满足图6所示的情况,该计数器存在上述问题。(存疑

Quartus中对IP核进行级联:

图9 使用counter ip核进行级联是正确的



计数器级联

参考如下链接中的内容:

74LS160计数级联 - 74ls160十进制计数器 - IC应用电路图 - 电子发烧友网 (elecfans.com)https://www.elecfans.com/dianlutu/app/20180118618280_2.html

 即疑问2中图6、图7所示的不正常状态。

 以74ls160为例,该计数器是对CP引脚(时钟脉冲输入端)计数,当CP时钟上升沿来临时,计数值加一,所以在设计计数器时应以CP为敏感条件。上述的counter_4bit中,计数值的变化以系统时钟clk为敏感条件没有实际意义,应该为当cin上升沿来临时对计数值加一,更改后的代码如下,图10是更改后的仿真波形。

counter_4bit

module counter_4bit 
#( parameter	c_number = 4'd10 )
(
	input		rst_n	,
	input		cin	,
	output	reg	cout	,
	output	reg[3:0] q
);
always@(posedge cin or negedge rst_n)
begin
	if(!rst_n)
		q <= 4'd0 ;
	else if(q == c_number-1'b1 && cin == 1'b1)
		q <= 4'd0 ;
	else if(cin == 1'b1)
		q <= q+1'b1;
	else	q <= q;
end
always@(posedge cin) begin        // 在计数器之间加上D触发器,可消除上述错误状态
	if(q == c_number-1'b1 && cin == 1'b1)
		cout <= 1'b1;
	else	cout <= 1'b0;
end
endmodule

图10

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值