HDLBits—Countbcd的改正和两种实现方法

Countbcd

构建一个4位BCD模10计数器,实现个十百千四位的计数器。每个十进制数字使用4位进行编码:q[3:0]是个位,q[7:4]是十位,q[11:8]是百位,q[15:12]是千位,以此类推。每个进制上的进位时也需输出一个使能信号ena。
在这里插入图片描述
最开始自己写的代码,采用四个always语句块进行赋值,但是就是时序图对不上,之后发现最重要是有两方面问题:
第一个是always语句块中变量必须是reg类型,自己压根没有意识到;
第二个是使能端信号其实只受数值变化影响,不受时钟信号控制,这部分应该用组合逻辑进行赋值,时序图一直对应不上的原因也是这个,后面的时序结果图也说明了使能端没有拉高,导致变成了模16计数器。(后面附上了这个代码的时序图)

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);

    always@(posedge clk)begin
        if(!reset)begin
            q[3:0]<=q[3:0]+4'd1;
            ena[1]<=0;
        end
        else if(!reset && q[3:0]==4'd9)begin
            q[3:0]<=4'b0;
            ena[1]<=1;
        end
        else
            q[3:0]<=4'b0;
    end

    always@(posedge clk)begin
        if(!reset && ena[1]==1)begin
            q[7:4]<=q[7:4]+4'd1;
            ena[2]<=0;
        end
        else if(!reset && q[7:4]==4'd9 && q[3:0]==4'd9)begin
            q[7:4]<=4'b0;
            ena[2]<=1;
        end
        else
            q[7:4]<=4'b0;
    end
        
    always@(posedge clk)begin
        if(!reset && ena[2]==1&& ena[1]==1)begin
            q[11:8]<=q[11:8]+4'd1;
            ena[3]<=0;
        end
        else if(!reset && q[11:8]==4'd9 && q[7:4]==4'd9 && q[3:0]==4'd9)begin
            q[11:8]<=4'b0;
            ena[3]<=1;
        end
        else
            q[11:8]<=4'b0;
    end
    
    always@(posedge clk)begin
        if(!reset && ena[3]==1 && ena[2]==1 && ena[1]==1)begin
            q[15:12]<=q[15:12]+4'd1;
        end
        else if(!reset && q==15'd9999)begin
            q[15:12]<=4'b0;
        end
        else
            q[15:12]<=4'b0;
    end
        
endmodule

在这里插入图片描述
在这里插入图片描述

之后参考了别人的代码,此代码是正确代码,还有更简便的其实是再写一个module,直接进行四次实例化,这个方法我也附在后面。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    reg [3:0] ones;
    reg [3:0] tens;
    reg [3:0] hundreds;
    reg [3:0] thousands;
    
    always @(posedge clk) begin
        if(reset)begin
            ones <= 4'b0;
        end
        else if(ones == 4'd9)begin
            ones <=4'b0;
        end
        else begin
            ones <= ones + 4'd1;
        end
    end
    
    always @(posedge clk)begin
        if(reset)begin
            tens <= 4'b0;
        end
        else if(tens == 4'd9 && ones == 4'd9)begin
            tens <= 4'b0;
        end
        else if(ones == 4'd9)begin
            tens <= tens + 4'd1;
        end
    end
    
    always @(posedge clk)begin
        if(reset)begin
            hundreds <= 4'b0;
        end
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
            hundreds <= 4'b0;
        end
        else if(tens == 4'd9 && ones == 4'd9) begin
            hundreds <= hundreds + 4'd1;
        end
    end
    
    always @(posedge clk)begin
        if(reset)begin
            thousands <= 4'b0;
        end
        else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
            thousands <= 4'b0;
        end
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)begin
            thousands <= thousands + 4'd1;
        end
    end
    
    assign q = {thousands,hundreds,tens,ones};
    assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
    assign ena[3] = ((ones == 4'd9) && (tens == 4'd9) && (hundreds == 4'd9)) ? 1'b1: 1'b0;

endmodule

这个是module实例化版本的代码

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);

    wire [3:0] valid,q0,q1,q2,q3;
    assign valid = {{(q2 == 9)&&(q1 == 9)&&(q0 == 9)},{(q[7:4] == 9)&&(q[3:0] == 9)},{q0 == 9},1'b1};
    assign ena = {{(q2 == 9)&&(q1 == 9)&&(q0 == 9)},{(q[7:4] == 9)&&(q[3:0] == 9)},q[3:0] == 9};
    assign q = {q3,q2,q1,q0};
    
    count count0(clk,reset,q0,valid[0],1'b1);
    count count1(clk,reset,q1,valid[1],{(q[7:4] == 9)&&(q[3:0] == 9)});
    count count2(clk,reset,q2,valid[2],{(q2 == 9)&&(q1 == 9)&&(q0 == 9)});
    count count3(clk,reset,q3,valid[3],{(q3 == 9)&&(q2 == 9)&&(q1 == 9)&&(q0 == 9)});
            
endmodule

module count(clk,reset,q_a,vld,ena);
    input clk;
    input reset;
    input vld;
    input ena;
    output [3:0] q_a;
    
    always@(posedge clk) begin
        if(reset)
            q_a <= 4'd0;
        else if((q_a == 4'd9)&&(ena))
            q_a <= 0;
        else if (vld)begin
            q_a <= q_a + 1'b1;
        end
    end
endmodule

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值