# How to reference subsets of logic[31:0] in SystemVerilog?

(I have two questions for you at the end.)

I'm using SystemVerilog to do various exercises (for personal edification) in Digital Design and Computer Architecture's chapter 7. I'm using Altera's Quartus II 13.1.2 Web Edition and ModelSim Altera Starter Edition 10.1d (Revision 2012.11 dated Nov 2 2012) for software on Windows 7 x64, and my hardware isn't relevant right now (it's an Altera DE2-115 though).

One thing I have to do is decode a 32-bit logic signal into various different fields in order to do instruction decoding. There are three separate decoding possibilities for the 32-bit MIPS instructions the book uses. So, I made separate packed structs for each one:

typedef struct packed {
logic [5:0] op;
logic [4:0] rs, rt, rd, shamt;
logic [5:0] funct;
} instruction_r;

typedef struct packed {
logic [5:0] op;
logic [4:0] rs, rt;
logic [15:0] imm;
} instruction_i;

typedef struct packed {
logic [5:0] op;
} instruction_j;


When I tried then to make them into a union, I found out that Quartus II doesn't support unions. Drat.

So, I made another typedef and used some casting to make these all the same, just with different names:

typedef logic [31:0] instruction;

// usage in a module...

instruction logic_instr;
instruction_r instr;
instruction_i instr_i;
instruction_j instr_j;



This works in both Quartus II and ModelSim.

However, the need for the additional instruction type was to work around a problem that ModelSim gave me that didn't bother Quartus II. In this next snip, the first declaration works in both, but the second works only in Quartus II.

  // Works in both
floper #(32) instruction_reg(clk, reset, c_irwrite, readdata, logic_instr);

// Works only in Quartus II (and allows me to remove the logic_instr entirely)
floper #(32) instruction_reg(clk, reset, c_irwrite, readdata, instruction'(instr));

// For reference: Enabled, resettable flipflop
module floper #(parameter WIDTH = 8)
(input  logic             clk, reset, en,
input  logic [WIDTH-1:0] d,
output logic [WIDTH-1:0] q);
// ...
endmodule


The error ModelSim gives is "(vsim-3053) Illegal output or inout port connection for "port 'q'". It doesn't give the error at compilation time, just simulation time.

My questions for StackExchange are:

1. Is there a more elegant way I can have a simple logic [31:0] variable that can be easily referred to by various subsets of its wires without going through all of this verbose rigamarole?

2. Is there a syntax I can use with Quartus II and ModelSim that allows me to avoid having yet another extra variable when sending the struct instruction_r (or i or j) to a module that expects a logic [31:0]?

I feel certain there has to be a better way to do this sort of thing as it seems like something that would likely be very common in any sort of large scale design.

Thanks!

• I'm not totally familiar with the requirements of System Verilog, but it seems that you're trying to use the instr variable simultaneously both as a generic instruction and as the specific subtype instruction_r. I think this is creating some confusion, and that you would be better off renaming instr to be instr_r (using it for only that subtype) and keeping logic_instr as the generic variable that you pass to sub-modules that don't expect a particular instruction subtype. Feb 23, 2014 at 14:34
• Dave, that's exactly right. That's what a union does - it allows a single variable to have multiple personalities that take the same space (use the same wires). But, Quartus II doesn't support it, and I have to imagine that Quartus II or SV supports some sort of way to do this, which seems like it would be a common thing. Thanks. Feb 23, 2014 at 16:57

1. Is there a more elegant way I can have a simple logic [31:0] variable that can be easily referred to by various subsets of its wires without going through all of this verbose rigamarole?
2. Is there a syntax I can use with Quartus II and ModelSim that allows me to avoid having yet another extra variable when sending the struct instruction_r (or i or j) to a module that expects a logic [31:0]?

The answer to both is yes. Simple data types such as logic [31:0] and struct packed {...} can be directly assigned; casting isn't necessary especially if they are the same width.

Since everything is the same size (32 bits), direct assignment is allowed (example1):

instruction_r instr_r;
instruction_i instr_i;
instruction_j instr_j;

floper #(32) instruction_reg_r(.en(c_irwrite), .d(readdata), .q(instr_r), .* );

always_comb begin
instr_i = instr_r;
instr_j = instr_r;
end


The curly brackets ({}) can even be used (example2):

logic [5:0] op;
logic [4:0] rs, rt;
logic [15:0] imm;
logic [4:0] rd, shamt;
logic [5:0] funct;

always_comb begin
imm = {rd,shamt,funct};
end


Another approach is to use type parameters. See IEEE Std 1800-2012 § 6.20.3 Type parameters. In this case change the definition of floper to:

module floper #(parameter WIDTH = 8, parameter type INSTR_TYPE = logic[WIDTH-1:0] )
(input  logic             clk, reset, en,
input  logic [WIDTH-1:0] d,
output INSTR_TYPE        q);
// ...
endmodule


Then update the parameter value in the instantiations of floper. example3:

instruction_r instr_r;
instruction_i instr_i;
instruction_j instr_j;

floper #(32,instruction_r) instruction_reg_r(.en(c_irwrite), .d(readdata), .q(instr_r), .* );
floper #(32,instruction_i) instruction_reg_i(.en(c_irwrite), .d(readdata), .q(instr_i), .* );
floper #(32,instruction_j) instruction_reg_j(.en(c_irwrite), .d(readdata), .q(instr_j), .* );


Streaming operators ({<<{}} and {>>{}}) are needed when translating between packed/unpacked values, see IEEE Std 1800-2012 § 11.4.14 Streaming operators, Casting is required for assignments that do not have a 1-to-1 relationship. Casting can also be used for tuncating or padding which is useful for avoiding size mismatch warnings. IEEE Std 1800-2012 § 6.24 Casting a full description and examples.

• That's really interesting. I'm very new to SystemVerilog (and there doesn't seem to be a good book on just it) and I didn't know there were generic types available. I will have to try this. I'm also unfamiliar with the dot syntax in the earlier example. Neither of these were presented in the aforementioned book. Finally, the EDA playground is very interesting, almost like a pastebin for HDL. Thanks! Feb 26, 2014 at 5:19
• I'll put my reference recommendation in a separate comment as it's an opinion. I found SystemVerilog for Design by Stuart Sutherland, et al, to be a great resource that focuses on synthesis-able design; it intentionally leaves out assertions & classes. I list several papers/tutorials in my profile. I like digging though the IEEE Std 1800-2012. This is all opinion & I am sure there are other great resources out there. End of the day you need to experiment with all your tools as some features are not fully supported or optimized.
– Greg
Feb 26, 2014 at 19:48
• Hi Greg. I would upvote it but my reputation on this StackExchange site isn't high enough. I was hoping to get the other part of my question answered before I choose an "answer" though. That was the part about "Is there a more elegant way I can have a simple logic [31:0] variable that can be easily referred to by various subsets of its wires without going through all of this verbose rigamarole?" If I don't get anything in the next few days, however, I will definitely choose your answer as accepted. Feb 26, 2014 at 20:35
• @SoftwareEngineer, Thanks for the feed back. I redid my answer to better suit your question.
– Greg
Feb 28, 2014 at 21:49