(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
struct
s 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;
logic [25:0] addr;
} instruction_j;
When I tried then to make them into a union
, I found out that Quartus II doesn't support union
s. 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;
assign instr = logic_instr;
assign instr_i = instruction_i'(instr);
assign instr_j = instruction_j'(instr);
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:
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?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
(ori
orj
) to a module that expects alogic [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!
instr
variable simultaneously both as a genericinstruction
and as the specific subtypeinstruction_r
. I think this is creating some confusion, and that you would be better off renaminginstr
to beinstr_r
(using it for only that subtype) and keepinglogic_instr
as the generic variable that you pass to sub-modules that don't expect a particular instruction subtype. \$\endgroup\$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. \$\endgroup\$