I have a struct with an unconstrained field and would like a function to return a value whose type is that struct, and where the unconstrained field is constrained by the size of the function input. I know how to do this in VHDL and was hoping there’s a System Verilog equivalent. Here’s my (very unsuccessful) first attempt at this:
typedef struct {
bit Vec [];
bit Parity;
} MyRec_t;
function automatic MyRec_t CreateMyRec (input Val []);
MyRec_t Rec;
Rec.Vec = new(Val.size()+4);
Rec.Vec = {4'hF,Val};
Rec.Parity = ^ Rec.Vec;
return Rec;
endfunction
In reply to craigc40:
There is no direct equivalent of VHDL’s unconstrained vector type in SystemVerilog.
For the code in your example, you need to treat Rec.Vec as an unpacked array.
function automatic MyRec_t CreateMyRec (input Val []);
MyRec_t Rec;
Rec.Vec = {>>{4'hF,Val}}; // streaming operator
Rec.Parity = Rec.Vec.xor(); // array reduction method
return Rec;
endfunction
In reply to dave_59:
Thank you Dave. This is a very elegant solution. Do you have any reason to believe I would run into trouble with synthesis support using your solution? And would you have recommended I take a different approach (such as using a parameterized class)?
In reply to craigc40:
Synthesis tools do not support variables with a dynamic array type. You would need to wrap this in a parameterized class.
module top;
virtual class myRec #(int WIDTH);
typedef bit [WIDTH-1:0] Vec_t;
typedef struct {
Vec_t Vec;
bit Parity;
} myRec_t;
static function myRec_t Create (input Vec_t Val);
myRec_t Rec;
Rec.Vec = {4'hF,Val};
Rec.Parity = ^ Rec.Vec;
return Rec;
endfunction
endclass
bit [3:0] v1 = 4'b1010;
bit [7:0] v2 = 8'b10101;
typedef myRec#($bits(v1)) v1_t;
typedef myRec#($bits(v2)) v2_t;
v1_t::myRec_t res1;
v2_t::myRec_t res2;
initial begin
res1 = v1_t::Create(v1);
res2 = v2_t::Create(v2);
$displayb("res1: %p", res1);
$displayb("res2: %p", res2);
end
endmodule