forcing a bit in a wire system verilog

不羁的心 提交于 2019-12-10 12:12:59

问题


From testbench i have to corrupt a bus ins 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 is 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.


回答1:


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;



回答2:


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



回答3:


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];
  • SOME_PARAM is a parameter
  • some_index may be a variable or a net
  • SOME_PARAM = 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.




回答4:


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


来源:https://stackoverflow.com/questions/17103209/forcing-a-bit-in-a-wire-system-verilog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!