2
\$\begingroup\$

I have written this example to try to answer the question. There is one input, x, the clock, and three outputs. The clock pulses on and off, and x becomes 1 at random times for the positive edge of the clock.

The output should move the input of x from z1 to z3 with every clock pulse. For example, when x is equal to 1, three clock pulses in a row, the output should be 111. Similarly, if x is 1, 0, then 0, the outputs of z1, z2, and z3 should be 0, 0, and 1 respectively.

z1 works in my simulation. However, z2 and z3 remain constant at zero. It appears that the T flip-flop module does not change the value of q. However, I have simulated the flip-flop module by itself with no issue.

When I run the top level module, I get a warning message that t1, t0, q1, and q0 remain constant at zero. However, from the equations, t0 should become one the moment x becomes one, because of "t0 = ~q0&x + ..."

I have tried many variations of this code; putting the always function in and around different sections of code, initiating and not initiating values for the t's and q's, defining the t's and q's as wires and or regs. I have also tried blocking and nonblocking variations on the equations, when inside always blocks.

module TwoFFwithEquations(
    input x, 
     input clk,
    
     output reg z1, 
     output reg z2, 
     output reg z3 
     
     );
     
     reg t1, t0;
     wire q1, q0;
     
        initial begin
            t1 = 0;
            t0 = 0;
        end
     
        TFF tff1(t1, clk, q1);
        TFF tff0(t0, clk, q0);

        always@(posedge clk) begin   

             t1 = q1&~q0 + ~q1&q0;
             t0 = ~q0&x + q0&~x;    
            
             z1 = x; 
             z2 = q0; 
             z3 = q1; 
        end
endmodule
module TFF(
    input T,
     input clk,
     
     output reg Q
     );
     
     initial begin
        Q = 0;
     end
     
     always@(posedge clk) begin
        case(T)
            1'b0: Q<=Q;
            1'b1: Q<=~Q;
        endcase
    end
endmodule

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The problem with your code is operator precedence. There are 3 types of operators in the expression:

~q0&x + q0&~x
  1. Unary ~ has the highest precedence
  2. Binary + has the next highest
  3. Binary & is the lowest of the 3 operators.

Refer to IEEE Std 1800-2017, section 11.3.2 Operator precedence. That means that Verilog evaluates the expression as:

(~ q0) & (x + q0) & (~ x)

You should use parentheses to have it evaluate the way that you want:

         t0 <= (~q0 & x) + (q0 & ~x);

When I make that change and a similar change for the t1 assignment, I see z2 and z3 go to 1.


Although it did not make a difference in your simlation, for sequential logic, you should use nonblocking assignments:

    always @(posedge clk) begin
         t1 <= (q1&~q0) + (~q1&q0);
         t0 <= (~q0&x) + (q0&~x);
         z1 <= x;
         z2 <= q0;
         z3 <= q1;
    end
\$\endgroup\$
1
  • \$\begingroup\$ In general, when using any programming language, you should use parentheses rather than using the built-in operator precedence. Operator precedence provides an endless source of programming errors. If it were up to me, programming languages would report an error if an expression was encountered that would be ambiguous except for the rules of operator precedence. An expression which might be ambiguous to a human, should be treated as if it really is ambiguous, rather than being given a default interpretation. \$\endgroup\$ Apr 16 at 19:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.