Usage of random functions (e.g RandSlv)

Why OSVVM™? Forums OSVVM Usage of random functions (e.g RandSlv)

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • #1071

    Hi,

    I’m trying to use the randomisation package in a simple testbench, to evaluate the usage concepts of OSVVM.

    My idea was to write a function or procedure that contains a Random Data Generator and a Bus Function Model for the UUT.

    Since my UUT is now a simple register the BFM part is a simple assignment to the return value.

    Now my function and procedure properly sets a seed, and maybe even a second random value, but then the random generator stucks at theat value.

    I then wrote a process that basically has the same function, but needs to be triggered (see code below).

    My guess is, that the variables in the functions and procedures are not static, and so the (pseudo) random generator starts all over from the seed.

    Is there some method to overcome these problems?

     impure function DataGenerator(Data : std_logic_vector) return std_logic_vector is
        variable RandomData : RandomPType;
        variable Dummy      : std_logic_vector(Data'range);
      begin
        if Data(Data'low) = 'U' then
          RandomData.InitSeed(RandomData'instance_name);
          report "Seed generated for RandomData";
        end if;
       return  RandomData.RandSlv(0,2**Data'high-1, Data'length);
      end function;

    -----

      procedure DataGenerator (Signal Data: inout std_logic_vector) is
        variable RandomData : RandomPType;
      begin
        if Data(Data'low) = 'U' then
          RandomData.InitSeed(RandomData'instance_name);
          report "Seed generated for RandomData";
        end if;  
        Data <=    RandomData.RandSlv(2**DataIn'high-1, DataIn'length);
      end procedure;

    —-

      DataGenerator : process (DatagenTrigger) is
        variable RandomData : RandomPType;
      begin
        if Data(Data'low) = 'U' then
          RandomData.InitSeed(RandomData'instance_name);
          report "Seed generated for RandomData";
        end if;
        Data <= RandomData.RandSlv(2**DataIn'high-1, DataIn'length);
      end process;

    -- The calling lines:

         DataIn <= DataGenerator(DataIn);  --for Function Call

         DataGenerator(DataIn);            -- for procedure call


         DatagenTrigger <= not DatagenTrigger;  -- event assignment (boolean)
         DataIn         <= Data;                -- assign updated random value

    (Sorry, but highlighting could not be removed)

    Each method was compiled and ran successfully on Questa Sim 10.4.

    But as mentioned above the random values stuck in procedure and function.

    I then assigned a new seed on every call:

     if Data(Data'low) = 'U' then
          RandomData.InitSeed(RandomData'instance_name);
          report "Seed generated for RandomData";
        else
           RandomData.InitSeed(to_integer(unsigned(Data)));
        end if;

    But this just caused the random data to toggle between two values.

    Any suggestions how to deal with this?

    Kind regards

        Eilert  

    #1072
    Jim Lewis
    Member

    Hi Eilert,

    If you create a randomization object (your RandomData variable) in a procedure or function, it will only be “live” when the procedure is called.  Hence, in your procedure/function, there are only two different values of the seed, the default value (set by the package) and the value generated when InitSeed is called.  

    My recommendation is to pass the randomization object to the procedure:


    procedure DoMyRandomization(
    variable RV : InOut RandomPType ;
    . . .
    );

    Then in the process, you would need to declare an object of RandomPType.  

    There are examples in the RandomPkg User Guide that you can put loops around and try out.

    Jim

    #1073

    Hi Jim,

    thanks for that recommendation.

    Meanwhile I found another working solution too.

    For using the RandomPType QuestaSim insists that the function has to be impure. I remembered from your documentations that there’s some link between protected types, shared variables and impure functions.

    So I came up with this solution:

     shared variable RandomData : RandomPType;

     impure function DataGenerator(DataWidth : natural) return std_logic_vector is
      begin
        -- check seed for initial value (from RandomBasePkg Random Seed declaration)
        if RandomData.GetSeed = RandomSeedType(integer_vector'(1,7)) then
          RandomData.InitSeed(RandomData'instance_name);
          report "Info: Seed generated for DataGenerator:RandomData";
        end if;
        return RandomData.RandSlv(0, 2**Datawidth-1, DataWidth);
      end function;

    And calling the Function like this works just fine:

       for i in 0 to 99 loop
          wait until falling_edge(clock); -- just creating some delay
          DataIn <= DataGenerator(DataIn'length);
          wait until rising_edge(clock);
        end loop;

    I think it would work with a procedure as well. (hopefully)

    The good thing is that I do not have to double declare the RandomPType outside and inside the function and do not have to transfer the actual values. Instead I just have a constant in the function argument list.

    Thanks for reminding me about the Random Package UG.

    I saw it was there, but just read the OSVVM UG and the Protected types paper. Somehow I couldn’t resist to try it out immediately. 🙂

    Kind regards

      Eilert

    #1082
    Jim Lewis
    Member

    Hi Eilert,

    The only issue with functions and procedures of this sort is if they are called from more than one process.  When two processes share a common seed and randomize at the same time, the test will be unstable – meaning if you recompile the test, the processes may call the function/procedure in a different order (due to both requesting it during the same delta cycle and optimization changing which one gets scheduled first), and as a result the test will produce different results than it did previously.

    Hence, this is why I suggest passing the randomization object into the procedure instead.  Unfortunately when you pass in the protected type, a function is no longer possible.

    Cheers,

    Jim

Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.