Generate random values in VHDL function
Asked Answered
D

3

5

I have a design were I'm writing/reading to/from a RAM and perform some computation on the read values. In some cases, I read values from RAM locations where I haven't written anything to yet. This is intentional because in the cases where this happens, the uninitialized values don't affect the computation: in these cases, the uninitialized values are multiplied with 0.

However, multiplying an unsigned/signed type which contains 'U' bits results in a "don't care" output (i.e. all bits of the multiplication output are 'X') even if the other operand is 0. Therefore, I can't check the final computation output in my testbench because it becomes "don't care" (it seems like "don't care" outputs are interpreted as 0).

To avoid this problem, I wrote a function that resolves any 'U' or 'X' bits in a std_logic_vector to '0'. The functions looks as follows

function f(x : std_logic_vector) return std_logic_vector is
  variable y : std_logic_vector (x'range);
begin
  y := x;
  -- pragma synthesis off
  for i in 0 to x'length-1 loop
    case x(i) is
      when 'U' | 'X' => y(i) := '0';
      when others    => y(i) := x(i);
    end case;
  end loop;  -- i
  -- pragma synthesis on
  return y;
end;

Now I'd like to expand the function by not only setting 'X' and 'U' bits to '0' but to randomly set them to either '0' or '1'. I've tried using the uniform function within f. The problem is that when I define the two seeds within the function, that each time the function f is called it returns the same std_logic_vector (when it is given the same std_logic_vector). As I take it from the uniform function description, I should pass the two seeds from outside the function f because they are modified by the uniform function for the next call to uniform.

Is there a possibility how this can be achieved using a function?

Disulfiram answered 7/5, 2013 at 13:10 Comment(0)
E
8

There's a very good random library as part of the Open Source VHDL Verification Methodology here. There is a description and download link here:

https://osvvm.org/

It allows you to randomise much more than just a simple uniform distribution of floating point numbers. As well as isolating you from the state storage problem you have noted.

Regarding your specifics:

As I take it from the uniform function description, I should pass the two seeds from outside the function f because they are modified by the uniform function for the next call to uniform.

Yes, you should. Like this:

PROCESS
  VARIABLE seed1, seed2: positive; -- Seed and state values for random generator
  VARIABLE rand: real;             -- Random real-number value in range 0 to 1.0
BEGIN
    UNIFORM(seed1, seed2, rand);     

So in your case, you'll have to pass those "state" variables into (and out of) your function too - which in practice means it has to be a procedure.

Or use the OSVVM library linked above which allows you to have a shared variable of protected type, which you can use from a variety of places. This keeps its own state "inside" the protected type.

Entablement answered 7/5, 2013 at 14:20 Comment(2)
Thanks for the hint. For the moment, a simple uniform distribution is adequate for my needs. If I pass the seeds into the function, I'll have to return them again to pass the modified seeds to the function the next time it is called. Can I achieve this using a function or do I have to use a procedure?Disulfiram
Although you are happy with Uniform, I still think it would be worth your while to use the OSVVM package. Otherwise you end up passing lots of seeds around the place and it'll get unpleasant enough (eventually) to make you want to to do it :) Answer tweaked to mention that for making the seeds inouts you'll need a procedure.Entablement
S
2

Can I achieve this using a function or do I have to use a procedure?

Functions do not allow parameters to be inout, pointers, or protected types (see below for update). This limits your choices. OSVVM's randompkg uses a protected type to hide the seed and uses an impure function to access it. It is pretty easy to use. Just download the package from https://github.com/OSVVM/OsvvmLibraries. RandomPkg is in the osvvm directory (OSVVM Utility Library) and the documentation is at Documentation/RandomPkg_user_guide.pdf.

You can probably get what you are trying to do to work, however, it is going to be a challenge. You can define a signal or pair of signals in your package and use an impure function (YMMV, I have only used impure functions inside of protected types). You can initialize the seeds in the signal declarations.

Even with OSVVM, you will need to use an impure function and declare the randomization object as a shared variable.

--- Returning 10+ years later

Functions do not allow parameters to be inout, pointers, or protected types.

We fixed this in VHDL-2019. Impure functions now allow these.

Simulator support for VHDL-2019 is still emerging (in 2024), however, Aldec simulators support it and newer versions of Questa (2024.2 and beyond) support this feature.

As a result, OSVVM has introduced a RandomPkg2019 that allows you to do the same with impure functions

Strap answered 9/5, 2013 at 21:15 Comment(0)
W
0

about printing the instance name from a VHDL component: ... I made most of my work with the free VHDL simulator GHDL. It has a simple, yet powerful, c interface. Random can be done using c code:... http://bknpk.ddns.net/my_web/MiscellaneousHW/vhdl_func_rand.html

Wadsworth answered 27/12, 2014 at 15:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.