| `default_nettype none |
| |
| // Enum's default to 32-bit, but this is a tool specific implementation detail |
| `define STATE_T\ |
| parameter FOO = 32'd0, BAR = 32'd1; |
| |
| // As an alternative to the macro based structs, they could also simply be computed |
| // typedef struct packed { |
| // State_t state; // [63:32] |
| // logic [31:0] data; // [31:0] |
| // } MyStruct_t; |
| |
| module Example( |
| input wire clock, clear, |
| input wire [7:0] dataIn, |
| output wire check1, |
| output reg check2, // Split since check2 is used in an always_comb block |
| output wire [63:0] checkData |
| ); |
| |
| `STATE_T |
| |
| // 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 [31:0] swapState(input [31:0] state); |
| case(state) |
| // To return from a function assign the function name with a variable |
| FOO: swapState = BAR; |
| BAR: swapState = FOO; |
| endcase |
| // Scope ending labels are not supported in Verilog and only provide |
| // human readability benifits (plus compiler warnings if they are |
| // incorrect) |
| endfunction |
| |
| reg [31:0] state; |
| |
| always @(posedge clock) |
| if(clear) |
| state <= FOO; |
| else |
| state <= swapState(state); |
| |
| wire [15:0] magicToken; |
| assign magicToken = 16'habcd; |
| |
| function [63:0] packStruct(input [31:0] state, input [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) |
| reg [31:0] fullData; |
| reg [31:0] nextState; |
| begin |
| fullData = {~data, data, magicToken}; |
| nextState = swapState(state); |
| packStruct = {nextState, fullData}; |
| end |
| endfunction |
| |
| wire [63:0] myStruct; |
| assign myStruct = packStruct(state, dataIn); |
| |
| function [0:0] doCheck(input [63:0] inputStruct); |
| doCheck = inputStruct[63:32] == FOO; // inputStruct.state |
| endfunction // : doCheck |
| |
| assign check1 = doCheck(myStruct); |
| |
| reg [63:0] myStruct2; |
| always @* begin |
| myStruct2 = packStruct(swapState(state), ~dataIn); |
| check2 = doCheck(myStruct2); |
| end |
| |
| assign checkData = {myStruct[31:0], myStruct2[31:0]}; // *.data |
| |
| |
| |
| endmodule |