FPGA基础设计(五):BCD计数器

BCD码

由四位二进制数表示0~9这10个十进制数。

有权码

如:8421码、5421码、2421码

什么是有权码:4位二进制编码中每位都是固定数,称为位权。
如8421码:b3位权为 2^3 = 8、b2位权为2^2 =4、b1位权为2、b0位权为1。
同理:
5421码:b3位权为5、b2位权为4、b1位权为2、b0位权为1。

无权码

如:余3码、格雷码、余3循环码

四位BCD码计数器实现

在这里插入图片描述

计数器逻辑设计

always@(posedge Clk or negedge Rst_n)//时序逻辑
	
	    if(Rst_n == 1'b0)//复位信号,低电平有效
		   cnt <= 4'd0;
		 else if(Cin == 1'b1)begin 
		   if(cnt == 4'd9) //计数满且有进位输入,计数器清零
			  cnt <= 4'd0;  
			else 
			  cnt <= cnt + 1'b1;//当有进位输入时,计数器加1
		 end
		 
		 else //没有进位输入,保持值不变
		   cnt <= cnt; 

进位输出设计

// 计数到9且当前还有进位输入,则产生进位输出
always@(posedge Clk or negedge Rst_n)//时序逻辑
     
        if(Rst_n == 1'b0)
           Cout <= 1'b0;
         else  //计数到9且有进位输入这两个条件同时满足,才有进位输出
           if(Cin == 1'b1 && cnt == 4'd9)
              Cout <= 1'b1;
            else 
            Cout <= 1'b0;    

BCD计数器的级联

在这里插入图片描述

实现逻辑:上一级的进位输出作为当前级的进位输入,最后一级的进位输出作为整个模块的进位输出
所有级的计数器输出进行位拼接,作为整个计数器计数值的输出。

// 三个BCD计数器的级联,构成12位的BCD计数器
   BCD_Counter u1(
               .Clk(Clk),
               .Cin(Cin),
               .Rst_n(Rst_n),
               .Cout(cout1),
               .q(q1)
                );
   BCD_Counter u2(
               .Clk(Clk),
               .Cin(cout1),  // wire型cout1 将u1的进位输出和u2的进位输入连接起来 
               .Rst_n(Rst_n),  
               .Cout(cout2),
               .q(q2)
                );
                  
   BCD_Counter u3(
               .Clk(Clk),
               .Cin(cout2),  // // wire型cout2 将u2的进位输出和u3的进位输入连接起来 
               .Rst_n(Rst_n),
               .Cout(Cout),
               .q(q3)
                );

assign q = {q3,q2,q1};  // 计数器的输出进行位拼接

仿真

在这里插入图片描述

问题
1、计数到12’h999时,当上升沿来临,本应该产生顶层进位输出,但是滞后3个时钟周期才有进位输出;
2、计数到12’h999时,滞后一个时钟周期,只有个位清零;滞后两个时钟周期,十位才开始清零,滞后三个时钟周期,百位才清零,最后才产生进位信号
在这里插入图片描述

原因
由于计数器是基于D触发器构成,D触发器是一种锁存器,其输出值只能在时钟上升沿时被捕获,这样导致每一级的BCD计数器的进位输出信号均延迟了一个时钟周期,最终导致顶层进位输出Cout延迟了三个时钟周期。

改正
将进位输出Cout改成组合逻辑,不使用D触发器,输出就不会有滞后的情况。

always@(posedge Clk or negedge Rst_n)//时序逻辑
     
        if(Rst_n == 1'b0)
           Cout <= 1'b0;
         else  //计数到9且有进位输入这两个条件同时满足,才有进位输出
           if(Cin == 1'b1 && cnt == 4'd9)
              Cout <= 1'b1;  // Cout输出有滞后情况
           else 
              Cout <= 1'b0;   
     
// 修改子模块的Cout输出
assign Cout = (Cin == 1'b1 && cnt == 4'd9) ? 1'b1 : 1'b0;

在这里插入图片描述
当计数到12’h998时,上升沿来临计数到12’h999,此时通过组合逻辑立刻输出进位信号。
待下一个时钟上升沿来临,计数器清零,可以看到三个子模块的计数器值同时都为0。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值