简体   繁体   中英

SystemVerilog: Creating packed arrays using variables

I would like to create a task that does the following in SystemVerilog:

  1. Receive the 3 input parameters and 1 output parameter.
  2. Randomizes a data and assign the data to a bit variable (output parameter).

     1. task rand_wr_data(input int size, int data_range_hi, int data_range_lo, output bit [31:0] data); 2. bit unsigned [(size - 1):0] rand_data_bits; 3. bit unsigned [(data_range_hi - data_range_lo):0] wr_data_bits; 4. 5. int unsigned rand_data = $urandom(); 6. wr_data_bits = rand_data; 7. data = wr_data_bits << (data_range_lo + 1); 8. endtask: rand_data 

The above code will give me an error as of Non-constant expression error on line 2 and 3 whereby I've to use a constant in declaring the range for an array. I've tried the following but to no avail.

    [parameter | localparam | const] int data_size = size;

Therefore, I've a few enquiries as follows:

  1. Is there a way to create a packed array using variables like in my code?
  2. Is there another way to do what I would like to do above?
  3. Can I receive variable size array as a task parameter instead of an array that has to have its size declared?
  4. In line 6 of my code, I would like to assign an unsigned int to a 32-bit array but I receive different result after that. How can I accomplish that?

Thank you.

Referring to the error: Non-constant expression . The size of all the packed variables must be defined at compile-time . But here you are providing a run-time size which is not feasible . Henceforth the error.

There can be a few useful and not-so-useful workarounds as follows:

Declare size , data_range_hi and data_range_lo as parameters. Since parameters are evaluated during compile/elaboration time , this shall work. But you cannot change those parameters directly at run-time.

task rand_wr_data ( output bit [31:0] data);
  parameter int size=8, data_range_hi=8,data_range_lo=0;
  bit unsigned [(size - 1):0] rand_data_bits;

As an alternative and an effective way , referring to SystemVerilog LRM 1800-2012 section 13.8:

A parameterized subroutine allows the user to generically specify or define an implementation. When using that subroutine one may provide the parameters that fully define its behavior. This allows for only one definition to be written and maintained instead of multiple subroutines with different array sizes, data types, and variable widths.

And the following paragraph:

The way to implement parameterized subroutines is through the use of static methods in parameterized classes (see 8.10 and 8.25).

The class may be declared virtual in order to prevent object construction and enforce the strict static usage of the method .

You can create a parameterized virtual class and static task inside it. Call to this task is to be made using the scope resolution operator ( :: ) and parameter overriding. Something can be done as follows:

virtual class wrapper #(parameter int size=8, int data_range_hi=8, int data_range_lo=0);
 static task rand_wr_data(output bit [31:0] data);
 bit unsigned [(size - 1):0] rand_data_bits;
 // ...
 // ...
 endtask
endclass
// ...
// in some module/class, call task
wrapper #(16,8,0)::rand_wr_data (a);
// ...

Declaring class as virtual makes sure that no objects can be created for that class. The example given in LRM section 13.8 might also be useful.

A working example is made at EDAPlayground here .

Coming to your questions :

Is there a way to create a packed array using variables like in my code?

Yes, as discussed above.

Is there another way to do what I would like to do above?

There might be other ways like define directives which can be set at run-time by user, but they'll remain constant in entire simulation.

Can I receive variable size array as a task parameter instead of an array that has to have its size declared?

Yes, as discussed above.

In line 6 of my code, I would like to assign an unsigned int to a 32-bit array but I receive different result after that. How can I accomplish that?

Bit is by-default unsigned , so no need to declare bit unsigned , just bit shall work; but that's not the problem. The problem here seems wr_data_bits is defined as bit unsigned [(data_range_hi - data_range_lo):0] wr_data_bits; while rand_data is defined as int unsigned rand_data . The size of both may vary .

In case you pass 31 as (data_range_hi - data_range_lo) , the values will match. The given sample code link shows equal values.

wr_data_bits = 5e23536 rand_data = 5e23536

I've tried googling it but didn't find much information. For more information refer this link.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM