Reputation: 108
From testbench, I have to corrupt a bus in design.
I am using a random variable to select a bit location (bit_sel
)
bit_sel = $urandom_range(0,MAX_LENGTH-1);
Bus is somewhere deep inside the RTL with a width of MAXLENGTH
.
wire [MAX_LENGTH-1:0] BUS_TO_BE_FORCED;
In TB, I am using following line to corrupt the bus:
force TOP.DUT.....BUS_TO_BE_FORCED[bit_sel] = ~TOP.DUT.....BUS_TO_BE_FORCED[bit_sel];
But, I am getting compilation error. What is the best way to do this? I want to flip only one bit.
Upvotes: 1
Views: 17979
Reputation: 202
I had a similar problem and resorted to using another vector of equal width to the signal to be corrupted. I also encapsulated this in an interface so that I could bind it to any part of the DUT as necessary. Refer to the code below:
import uvm_pkg::*;
`include "uvm_macros.svh"
interface sync_signal_fault_injector #(
parameter int SIGNAL_WIDTH = 1
) (
input clk,
input reset,
input [SIGNAL_WIDTH-1:0] signals
);
bit [SIGNAL_WIDTH-1:0] toggle_bits = '0;
class sync_signal_fault_injector_c extends uvm_object implements fivip_pkg::Injectable;
function new(string name="fault_injector");
super.new(name);
endfunction
virtual function int unsigned get_size();
return SIGNAL_WIDTH;
endfunction
virtual task inject(ref int unsigned indices[], input int unsigned delay);
repeat (delay) @(posedge clk);
foreach (indices[id]) begin
int unsigned bit_index = indices[id];
if (bit_index >= get_size()) begin
`uvm_fatal("BOUNDS",
$sformatf("Tried to access bit %0d but signal bus is only of size %0d", id, get_size())
)
end
// Prepare toggle bits
toggle_bits[bit_index] = 1;
end
force signals = signals ^ toggle_bits;
@(posedge clk);
release signals;
// Reset toggle bits
toggle_bits = '0;
endtask
endclass
sync_signal_fault_injector_c fault_injector = new;
endinterface
Upvotes: 0
Reputation: 16228
EDIT: the initial answer contained my guesses, along with completely wrong information. I should not have answered this question in the first place, therefore I had to write test-benches and confirm the following statements to compensate for the mess.
1) Bit select must be a constant (at compile time). Even the following code (perfectly reasonable in my opinion) won't pass elaboration:
integer bit_sel;
initial begin
bit_sel = 0;
force BUS_TO_BE_FORCED[bit_sel] = 1'b1;
end
2) If used inside "initial" block, the following statement is fine:
force BUS_TO_BE_FORCED[SOME_PARAM] = ~BUS_TO_BE_FORCED[some_index];
However, the same statement inside "always" block causes the simulation to hang. This issue may be resolved by adding delay:
#1 force BUS_TO_BE_FORCED[SOME_PARAM] = ~BUS_TO_BE_FORCED[some_index];
3) The answer by Eric is a very elegant way around language's limitations, but it is also subject to limitations described in section 2 above - you'll have to add delay if you want to use it in "always" block.
Upvotes: 0
Reputation: 97571
You could instead flip the bits using a XOR mask:
wire [MAX_LENGTH-1:0] corrupt_bits = 1 << $urandom_range(0,MAX_LENGTH-1);
force BUS_TO_BE_FORCED = corrupt_bits ^ BUS_TO_BE_FORCED;
Upvotes: 3
Reputation: 10281
The LHS must be a constant bit-select of a vector net (among other things). So,
force TOP.DUT.....BUS_TO_BE_FORCED[0]
is Ok, but
force TOP.DUT.....BUS_TO_BE_FORCED[bit_sel]
isn't. You could try a big case statement, because the selectors don't have to be constant:
case(bit_sel)
0: force TOP.DUT.....BUS_TO_BE_FORCED[0] = ...
...etc
Upvotes: 2