4 phase req ack

I am trying to drive ack from the test-bench, where req is input to the testbench
I have the following code ;-

task main();
  reg req_accepted=0;
 reg req_deasserted=0;
 forever begin
    fork 
        begin
            thread1 capturing req;
        end
        
        begin
        @(clocking_cb) ;
                if(req && !req_accepted) begin
                    $display("\n=== 1 req_accepted=%d  req_deasserted=%d at time =  %t ===",req_accepted,req_deasserted, $time)  ;
                    req_accepted <= 1 ;
                    $display("\n===  req=%d at time =  %t ===",read_trans[index].req, $time)  ;
               
                    ack <= 1 ;
                end
                else if(req && req_accepted) begin
                    $display("\n=== 2 req_accepted=%d  req_deasserted=%d at time =  %t ===",req_accepted,req_deasserted, $time)  ;
                   $display("\n= req=%dat time =  %t ===",read_trans[index].req, $time)  ;
                    ack <= 1 ;
                end
                else if(!(req) && req_accepted) begin
                    $display("\n=== 3 req_accepted=%d  req_deasserted=%d at time =  %t ===",req_accepted,req_deasserted, $time)  ;
                   $display("\n= req=%dat time =  %t ===",read_trans[index].req, $time)  ;
                    req_deasserted <= 1 ;
                    req_accepted <= 0;
                    ack <= 1 ;
                end
                else if(req_deasserted) begin
                    $display("\n=== 4 req_accepted=%d  req_deasserted=%d at time =  %t ===",req_accepted,req_deasserted, $time)  ;
                   $display("\n===  req=%dat time =  %t ===",read_trans[index].req, $time)  ;
                    ack <= 0 ;
                    req_deasserted <= 0;
                end
                else begin
                    $display("\n=== 5 req_accepted=%d  req_deasserted=%d at time =  %t ===",req_accepted,req_deasserted, $time)  ;
                    ack <= 0 ;
                    req_accepted <= 0 ;
                    req_deasserted <= 0 ;
                end
        end
        begin
            thread 3, incremeting a variable
        end
    join_any
end
endtask

for some time instances ack is rising at the same time as req,
but for most time instances it works
can anyone help me in debugging this ?

Just comments rather than a solution to your issues:

  1. If main is not in a class, then make the task automatic
    task automatic main();
  2. Insure that the signal *req * is assigned nonblocking. I presume you did that already.
    Also
  3. should this
    else if(req_deasserted) begin
    be
    else if(!(req) && !req_accepted) begin

thanks for your reply

  1. it’s inside a class actually,
  2. req is coming from the RTL can’t control that.

It has something to do with the thread issue mostly, may be multiple threads are trying to drive ack rather than just one, is there any other solution to this rather than automatic
?

class four_phase_handshake;
semaphore ack_semaphore;
reg req_accepted = 0;
reg req_deasserted = 0;
reg ack = 0;
logic clocking_cb; // Input for the clock signal
logic req; // Input for the request signal

// Constructor
function new();
    ack_semaphore = new(1); // Initialize semaphore with 1 token
endfunction

task main();
    forever begin
        fork
            begin
                // Simulated thread for capturing req
                // This thread can be customized as needed
                @(posedge clocking_cb);
                $display("Thread 1: Capturing req at time %0t", $time);
            end

            begin
                // Main handshake logic
                @(posedge clocking_cb);
                ack_semaphore.get(); // Acquire semaphore

                if (req && !req_accepted) begin
                    $display("\n=== 1 req_accepted=%d  req_deasserted=%d at time = %t ===", req_accepted, req_deasserted, $time);
                    req_accepted <= 1;
                    ack <= 1;
                end
                else if (req && req_accepted) begin
                    $display("\n=== 2 req_accepted=%d  req_deasserted=%d at time = %t ===", req_accepted, req_deasserted, $time);
                    ack <= 1;
                end
                else if (!req && req_accepted) begin
                    $display("\n=== 3 req_accepted=%d  req_deasserted=%d at time = %t ===", req_accepted, req_deasserted, $time);
                    req_deasserted <= 1;
                    req_accepted <= 0;
                    ack <= 1;
                end
                else if (req_deasserted) begin
                    $display("\n=== 4 req_accepted=%d  req_deasserted=%d at time = %t ===", req_accepted, req_deasserted, $time);
                    ack <= 0;
                    req_deasserted <= 0;
                end
                else begin
                    $display("\n=== 5 req_accepted=%d  req_deasserted=%d at time = %t ===", req_accepted, req_deasserted, $time);
                    ack <= 0;
                    req_accepted <= 0;
                    req_deasserted <= 0;
                end

                ack_semaphore.put(); // Release semaphore
            end

            begin
                // Simulated thread for another task, such as incrementing a variable
                // This thread can be customized as needed
                @(posedge clocking_cb);
                $display("Thread 3: Incrementing variable at time %0t", $time);
            end
        join_any
    end
endtask

endclass

tried using semahores
this also didn’t work

WHy do you have a “join_any”?
If this fork ends first, you don’t finish the other 2 fork elements.

            begin
                // Simulated thread for another task, such as incrementing a variable
                // This thread can be customized as needed
                @(posedge clocking_cb);
                $display("Thread 3: Incrementing variable at time %0t", $time);
            end

Try “join” instead.

I can’t get rid of join_any(it has to stay), and just for trying I tried replacing it with join, but it again didn’t help

Without going thru the logic, you are coving 3 of the 4 possible cases. This case is not explicitly specified,

if(!(req) && !req_accepted)

maybe it is by the

else if (req_deasserted)

Take a look at your logic here.
also, can you show a waveform of the problem?


yes it’s actually the same thing,
problem req and ack getting asserted at the same time
after certain time stamp in the simulation.

I see ack <= 1; when
if (req && !req_accepted)
else if (req && req_accepted)
else if (!req && req_accepted)
I see ack <= 0 when else if (req_deasserted)
Question: what happens in the 1st 3 cases if is (req_deasserted)

I don’t know your design or rquirements, but if you are designing a verification environment for the RTL, maybe something is wrong with your logic.

else if(req_deasserted) is simply same as else if(!req & !req_accepted)
you can even remove it from the code and just use the above, it will be same

You need to analyze the logic; maybe you have some sort of latchup situation or incorrect RTL. discuss it with a colleague. Do a step-by-step trace.
Best wishes