sv2v/test/relong/functions.sv

80 lines
2.4 KiB
Systemverilog

`default_nettype none
typedef enum {FOO, BAR} State_t;
typedef struct packed {
State_t state;
logic [31:0] data;
} MyStruct_t;
module Example(
input logic clock, clear,
input logic [7:0] dataIn,
output logic check1, check2,
output logic [63:0] checkData
);
// The automatic keyword here is super confusing, but generally does what
// you expect a C function to do. Sadly VTR doesn't support the automatic
// keyword.
function automatic State_t swapState(State_t state);
// The state variable is not shadowing the state variable in the global
// function since the function is declared above the state variable
// (Declaring functions at the start of the module before module scope
// variables is a good practice to avoid accidentally using a module scope
// in a function)
unique case(state)
FOO: return BAR;
BAR: return FOO;
endcase
endfunction : swapState
State_t state;
always_ff @(posedge clock)
if(clear)
state <= FOO;
else
state <= swapState(state);
logic [15:0] magicToken;
assign magicToken = 16'habcd;
function automatic MyStruct_t packStruct(State_t state, logic [7:0] data);
// Something interesting about system verilog is that all local variable
// declarations must be first in the function (at least for VCS to
// compile it)
logic [31:0] fullData;
State_t nextState;
// System Verilog functions can also access "local" variables from the
// module scope. This means that any variable with the same name in the
// function as something else defined in the module is shadowing the
// module variable (e.g. state in this function)
fullData = {~data, data, magicToken};
nextState = swapState(state);
return '{
state: nextState,
data: fullData
};
endfunction
MyStruct_t myStruct;
assign myStruct = packStruct(state, dataIn);
function automatic logic doCheck(MyStruct_t inputStruct);
return inputStruct.state == FOO;
endfunction : doCheck
assign check1 = doCheck(myStruct);
MyStruct_t myStruct2;
always_comb begin
myStruct2 = packStruct(swapState(state), ~dataIn);
check2 = doCheck(myStruct2);
end
assign checkData = {myStruct.data, myStruct2.data};
endmodule