Force/release in case statement

I have a very bizarre behavior in this piece of code:


// fault_if is an interface with two fields:
//   - logic active (to start/stop fault injection)
//   - fault_e option (enumeration)
always @ (fault_if.active) begin
  if(fault_if.active) // active fault injection
    case(fault_if.option)
      OPTION0: begin
        bfr = `TB.DUT.MYBLOCK0.port[0];
        force `TB.DUT.MYBLOCK0.port[0] = ~bfr;    
      end
      OPTION1: begin
        bfr = `TB.DUT.MYBLOCK1.port[0];
        force `TB.DUT.MYBLOCK1.port[0] = ~bfr;    
      end
      // more options follow
    endecase
  end else begin // inactive fault injection
    case(fault_if.option)
      OPTION0: begin
        release `TB.DUT.MYBLOCK0.port[0];
        `TB.DUT.MYBLOCK0.port[0] = bfr;
      end
      OPTION1: begin
        release `TB.DUT.MYBLOCK1.port[0];
        `TB.DUT.MYBLOCK1.port[0] = bfr;
      end
      // more options follow
    endecase
  end

This piece of code tries to inject faults in our DUT with the aim to verify if the necessary mechanisms detect such faults and take the appropriate actions to report the fault. The fault_if is an interface driven by a UVM agent that is in charge to decide when the fault is active and when it is not, together with the option. The sequence is built in a way to start an injection in one place (i.e. OPTION0), and then remove it after some time before injecting the new one. So the force/release statements go always in pairs.

The weird behavior happens at some point when in one of the options it looks like two branches of the case are active at the same time and the force is happening at the same time in two different places. When the release happens though only one of them is actually released, leaving the circuit with a permanent fault injected.

I’ve tried to step through with the simulator (Incisive), but without success.
Can anyone provide some direction? I’m kind of lost.

In reply to abs:

always @ (fault_if.active) begin

is prone to glitches. Better to make it synchronous to, say, the falling edge of a clock. Also, is this the actual code? “before” is a SystemVerilog keyword.

In reply to sbellock:

In reply to abs:

always @ (fault_if.active) begin

is prone to glitches. Better to make it synchronous to, say, the falling edge of a clock.

Well, since I need it to react to signal changes I wrote it that way, I also tried with the following, without success:

always @ (posedge fault_if.active or negedge fault_if.active) begin

By the way, the above code is equivalently sensitive to glitches, even though I have no idea where the glitches can come from since the fault_if is driven by my testbench.

Also, is this the actual code? “before” is a SystemVerilog keyword.

Indeed it is not the actual code, but it is representative. I will fix the “before” keyword.