HDLBits练习:Countbcd

题目

题目链接:Countbcd

image

题目让写一个四位的BCD计数器,可以等价看成0000~9999的计数器,进位规则和我们日常的十进制计数一样。

代码

解法一

通过例化或者修改一位的十进制计数器实现

  • 有关ena信号的处理部分,其实是与clk信号无关的;
  • 但是,也可以根据clk信号进行设计,需要注意什么时候ena有效

下述代码有关if条件语句的处理是有问题的,但是写的过程中并没有意识到

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)
            ena <= 0;
        else begin
            //这部分代码块有问题
            if(q[3:0] == 4'd8)
                ena <= 3'b001;
            else if(q[7:4]== 4'd9 && q[3:0] == 4'd8)
                ena <= 3'b011;
            else if(q[11:8] == 4'd9 && q[7:4]== 4'd9 && q[3:0] == 4'd8)
                ena <= 3'b111;
            else
                ena <= 0;
        end
    end

    decade_counter cnt0( clk, reset, 1'b1, q[3:0] );
    decade_counter cnt1( clk, reset, ena[1], q[7:4] );
    decade_counter cnt2( clk, reset, ena[2], q[11:8] );
    decade_counter cnt3( clk, reset, ena[3], q[15:12] );

endmodule

module decade_counter(
    input clk,
    input reset,        // Synchronous active-high reset
    input enable,
    output [3:0] q);

    always @(posedge clk)begin
        if(reset)
            q <= 4'd0;
        else if(enable) begin
            if(q == 4'd9)
                q <= 4'd0;
            else
                q <= q + 4'd1;
        end
        else
            q <= q;
    end
endmodule

两种修改方式:

  • 方式1:
if(q[11:8] == 4'd9 && q[7:4]== 4'd9 && q[3:0] == 4'd8)
    ena <= 3'b111;
else if(q[7:4]== 4'd9 && q[3:0] == 4'd8)
    ena <= 3'b011;
else if(q[3:0] == 4'd8)
    ena <= 3'b001;
else
    ena <= 0;
  • 方式2:
    分开单独考虑,就不会忽略掉某一位的进位
if (q[3:0]==4'd8)
    ena[1] <= 1'b1;
else
    ena[1] <= 1'b0;
	
if (q[3:0]==4'd8 && q[7:4]==4'd9)
                ena[2] <= 1'b1;
else
    ena[2] <= 1'b0;
	
if (q[3:0]==4'd8 && q[7:4]==4'd9 &&q[11:8]==4'd9)
    ena[3] <= 1'b1;
else
    ena[3] <= 1'b0;

解法二

与解法一类似,区别在于处理ena信号的方式。

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    assign ena[1] = (q[3:0]==9);
    assign ena[2] = (q[7:4]==9)&&ena[1];
    assign ena[3] = (q[11:8]==9)&&ena[2];
    
    decade_counter cnt0( clk, reset, 1'b1, q[3:0] );
    decade_counter cnt1( clk, reset, ena[1], q[7:4] );
    decade_counter cnt2( clk, reset, ena[2], q[11:8] );
    decade_counter cnt3( clk, reset, ena[3], q[15:12] );

endmodule

module decade_counter(
    input clk,
    input reset,        // Synchronous active-high reset
    input enable,
    output [3:0] q);
    
    always @(posedge clk)begin
        if(reset)
            q <= 4'd0;
        else if(enable) begin
            if(q == 4'd9)
                q <= 4'd0;
            else
                q <= q + 4'd1;
        end
        else
            q <= q;
    end
endmodule

解法三

没有使用1位十进制计数器进行例化处理,这种写法逻辑上感觉很清晰

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)
            q <= 'd0;
        else begin
            q[3:0] <= q[3:0] + 1;
            if(ena[1])begin
                q[3:0] <= 0;
                q[7:4] <= q[7:4]+1;
            end
            if(ena[2])begin
                q[3:0] <= 0;
                q[7:4] <= 0;
                q[11:8] <= q[11:8]+1;
            end
            if(ena[3])begin
                q[3:0] <= 0;
                q[7:4] <= 0;
                q[11:8] <= 0;
                q[15:12] <= (q[15:12]<9)?q[15:12] +1:0;
            end
        end
    end
    assign ena[1] = (q[3:0]==9);
    assign ena[2] = (q[7:4]==9)&&ena[1];
    assign ena[3] = (q[11:8]==9)&&ena[2];
endmodule

参考链接:
解法一中的问题是参考link1才发现的
解法三是参考link2

posted @ 2024-04-28 15:08  zianY  阅读(59)  评论(0编辑  收藏  举报