[SOLVED] BCD counter Implementation using jk flops

Status
Not open for further replies.

asuri

Newbie
Joined
Jan 15, 2024
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
27
I'm working on implementing a BCD counter in SystemVerilog using T flip-flops (JK with J=K=1). The goal is to count from 0 to 9 and then reset back to 0. I'm using the clr input of a JK flip-flop, intending to reset the flip-flop when the count reaches 4'b1010. However, I'm facing an issue where, upon reaching 4'b1010, the counter resets to 4 instead of 0.

Upon examining the code, it appears that the problem may be associated with the third flip-flop. It seems to be evaluating both conditions in the always_ff block as true.
I am puzzled by this behavior. My understanding is that it should enter the always_ff block when clr is set to 0 (for out = 4'b1010), reset Q, and stop there. However, it continues to the case statement, resulting in an unexpected toggle from 0 to 1.

Any insights into why this is happening would be greatly appreciated. Thank you!

my top desgin:


Code:
module bcdCounter(
    input logic clk,
    input logic rst,
    output logic Q0,
    output logic Q1,
    output logic Q2,
    output logic Q3,
    output [3:0] out
    );
    
    
    assign out = {Q3,Q2,Q1,Q0};
    
    logic clr;
    assign clr = ~(Q3 & Q1);
    jkFlipFlop flipFlop1(.J(1'b1), .K(1'b1), .rst(rst), .clk(clk), .clr(clr), .Q(Q0));
    jkFlipFlop flipFlop2(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q0), .clr(clr), .Q(Q1));
    jkFlipFlop flipFlop3(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q1), .clr(clr), .Q(Q2));
    jkFlipFlop flipFlop4(.J(1'b1), .K(1'b1), .rst(rst), .clk(Q2), .clr(clr), .Q(Q3));
    
endmodule

flop code:

Code:
module jkFlipFlop(
    input logic J,
    input logic K,
    input logic rst,
    input logic clk,
    input logic clr,
    output logic Q
    );
    
    always_ff @(negedge clk, negedge clr ,posedge rst) begin
        if (rst) begin
            Q <= 1'b0;
        end
        else if(clr == 1'b0) begin
            Q <= 1'b0;
        end
        else begin   
            case ({J,K})
                2'b00: Q <= Q;
                2'b01: Q <= 1'b0;
                2'b10: Q <= 1'b1;
                2'b11: Q <= ~Q;
             endcase
        end
    end   
endmodule

TB:

Code:
module bcdTB();
    logic clk,rst,Q0,Q1,Q2,Q3;
    logic [3:0] out;
    bcdCounter bcdCount(.clk(clk), .rst(rst), .Q0(Q0), .Q1(Q1), .Q2(Q2), .Q3(Q3),.out(out));
    always #40 clk = ~clk;
    
    initial begin
        clk = 1'b0;
        rst = 1'b0;
        #2 rst = 1'b1;
        #2 rst = 1'b0;
      
        #1000
        $finish;
    end
endmodule

simulation:
 

My fifty cents:
- ripple counter is bad
- asynchronous clear is worse
Did you consider to design a state-of-the-art synchronous BCD counter?
 

My fifty cents:
- ripple counter is bad
- asynchronous clear is worse
Did you consider to design a state-of-the-art synchronous BCD counter?

I am working on implementing a specific BCD counter to enhance my SystemVerilog proficiency and tackle more design challenges. I can confidently confirm that the counter itself operates without issues; it effectively functions as a BCD up counter. Nevertheless, I recognize the need for improvement in the logic pertaining to the clr signal.

The current logic produces a '0' when reaching the maximum BCD count of 10 and sends this logic '0' to the clr input for a reset. However, an unexpected behavior occurs where the flip-flop with the output Q2 is triggered by a negedge of the clock, leading to a toggle from logic '0' to '1', resulting in a final count of 4 instead of the intended 0.

I am eager to understand the root cause of this issue, as it may stem from a gap in my understanding of the always_ff logic.
 

However, I'm facing an issue where, upon reaching 4'b1010, the counter resets to 4 instead of 0.
I guess you did not care about async CLEAR timing. There are several FF involved and as soon as the fastest FF becomes cleared the RESET condition is gone and the other FFs may not be cleared properly.

Klaus
 
Last edited:
It presume it's a behavioral rather than gate level simulation. To model the actual behaviour at 9->0 transistion, you'll need intentional delays, or a gate level simulation.

You can try a net delay specification
Code:
#1 logic clr;
    assign clr = ~(Q3 & Q1);

It's questionable if the asynchronous clear logic can fulfill reasonable timing constraints.
I am working on implementing a specific BCD counter to enhance my SystemVerilog proficiency and tackle more design challenges.
The goal suggests a synchronous BCD counter. The behavioral description needs just a few lines Verilog. A structural desription of synchronous BCD counter would use a decoder table (case statement) to set JK depending on counter value.
--- Updated ---

above #1 logic clr; isn't right,
wire #1 clr; works for me in ModelSim

 
Last edited:

my two cents: if you are interested in learning design paradigms instead of the constructs of the language, it would be better suited to infer registers instead of hand instantiate them. And I should also say that D-type flip-flops are predominantly used in digital design. It is important to learn how to write verilog code that will *infer* their use.
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…