Why I get a syntax error when using typedef in verilog? - typedef

I don not know what is wrong here. I use a modelsim SE 6.5b. Then when I use "typedef" I get a syntax error.
`timescale 1ns/10ps
// Type define a struct
typedef struct {
byte a;
reg b;
shortint unsigned c;
} myStruct;
module typedef_data ();
// Full typedef here
typedef integer myinteger;
// Typedef declaration without type
typedef myinteger;
// Typedef used here
myinteger a = 10;
myStruct object = '{10,0,100};
initial begin
$display ("a = %d", a);
$display ("Displaying object");
$display ("a = %b b = %b c = %h", object.a, object.b, object.c);
#1 $finish;
end

typedef is a SystemVerilog keyword, not Verilog.
To enable SystemVerilog on Modelsim you need to add the -sv compile option and/or rename the file to with a .sv extension.

Your code works fine on Modelsim 10.1d. See example on EDA Playground (I had to add an endmodule but it's otherwise unmodified).
I'd suggest checking your compile flags to ensure you're enabling support for SystemVerilog during compilation.

Related

32-bit vs. 4-bit in enum declaration

When I change the enumerated type variables from 4 bit to 32 bit, my error is appeased. I am wondering why I cannot keep it at 4 bit in this code.
Here are some pertinent snippets; I have deleted code related to non-pertinent variables:
Testbench:
module ALUtestbench;
//Variable Declaration
typedef enum {ADD = 32'b00, SUB = 32'b01, INV = 32'b10, RED = 32'b11} opcode_t;
opcode_t opcode; //declare typed variable
//Module Instance
alu alu_inst(
.opcode(opcode));
initial begin
opcode = opcode.first();
#10;
do
begin
$display(opcode);
$display("For opcode %s the result is: %0h", opcode.name, result);
opcode = opcode.next;
#10;
end
while (opcode != opcode.first);
end
endmodule
Design:
module ALU;
input reg A [4:0];
inout reg B [4:0];
output reg C [4:0];
initial begin
always # (*)
begin
case(opcode)
ADD : C = A + B;
SUB : C = A - B;
INV : C = ~A;
endcase
end
endmodule
At first, I had
typedef enum {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
opcode_t opcode; //declare typed variable
and the compiler gave me the error:
SystemVerilog requires the width of a sized constant in this context
to match the width of the enumeration type.
I then changed to 32-bit, and the code now does not have this error. I am wondering why I needed to do that. Does the case statement reject anything less than 32-bit?
From IEEE Std 1800-2017, section 6.19 Enumerations:
In the absence of a data type declaration, the default data type shall
be int. Any other data type used with enumerated types shall require
an explicit data type declaration.
Since int is 32-bit, you do not get an error when your constants are 32-bit.
If you want to use 4-bit constants, you need to explicitly declare your enum as 4-bit. Change:
typedef enum {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
to:
typedef enum bit [3:0] {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;
This has nothing to do with the case statement.
If you do not explicitly declare a base type for an enumeration, the implicit datatype is int, which has a 32-bit width. Earlier versions of the SystemVerilog LRM also allowed you to use the label assignments form sized literals (i.e. ADD = 32'b00) to define the width explicitly instead of an explicit base type. But now the LRM only allows explicit base types. But it still has this rule in the IEEE 1800-2017 SystemVerilog LRM, section 6.19 Enumerations
If the integer value expression is a sized literal constant, it shall be an error if the size is
different from the enum base type, even if the value is within the representable range.
So either drop the size for the literals
typedef enum {ADD = 'b00, SUB = 'b01, INV = 'b10, RED = 'b11} opcode_t;
or write it as
typedef enum bit [3:0] {ADD = 4'b00, SUB = 4'b01, INV = 4'b10, RED = 4'b11} opcode_t;

How to initialize unpacked array of unpacked union of unpacked structs?

What is the legal method of initializing this?
module tb();
typedef struct {
logic [3:0] A;
} a_t;
typedef struct {
logic [7:0] B;
} b_t;
typedef union {
a_t a;
b_t b;
} a_b_t;
a_b_t a_b [8];
initial begin
a_b <= '{default: '{default: 0}};
end
endmodule
xrun gives this error:
xmelab: *E,APBLHS (./tmp.sv,14|23): Assignment pattern - LHS must be an array or structure [SystemVerilog].
I've tried a variety of other ways, and I can't quite get this right. I'm working around it right now by initializing each entry separately with 2 lines of initialization.
As the error message state, assignment patterns only work with struct and arrays, not unions. You would need to use a foreach loop to assign each union member.
initial
foreach (a_b[i]) begin
a_b[i].a <= '{default:0};
a_b[i].b <= '{default:0};
end
Note that unless you are using the DPI for C compatibility, unpacked unions have little usefulness in SystemVerilog. Use packed unions instead.

Is there a way to cast an SystemVerilog assignment pattern into a packed struct?

Per the System Verilog LRM "Assignment pattern format", a data structure can be printed into a string as follows:
module top;
typedef enum {ON, OFF} switch_e;
typedef struct {switch_e sw; string s;} pair_t;
pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}};
initial begin
$display("va[int] = %p;",va);
$display("va[int] = %0p;",va);
$display("va[10].s = %p;", va[10].s);
end
endmodule : top
This example may print:
va[int] = '{10:'{sw:OFF, s:"switch10"}, 20:'{sw:ON, s:"switch20"}} ;
va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}} ;
va[10].s = "switch10";
Is there a way to do the reverse? What I'd like to do is to take an assignment pattern string as a plusarg or a line read from a file, and assign that to a variable at run time, e.g.:
string assign_pattern = "'{10:'{sw:OFF, s:"switch10"}, 20:'{sw:ON, s:"switch20"}}";
$cast(va, assign_pattern); // ** This doesn't work **
If not generally possible, is there a way to do that specifically for packed struct types?
You can't do the reverse. SystemVerilog was designed as a compiled language—there's no parser available at run-time. You would have to create a parser in SystemVerilog or C smart enough to decode the assignment patterns you expect to read in.
Another option is converting the file of assignment patterns into code that could be compiled in with the rest of your code.
Another option based on your comments
You can use a bit-stream or streaming operator to parse a bit-string into a struct. The struct does not need to be packed, it just needs to be made up from fixed-sized, integral values.
module top;
typedef enum bit [1:0] {ON, OFF, INBETWEEN} switch_e;
typedef struct {switch_e sw; bit [8*8:1] s; bit [5:0] value;} trio_s; // 72 bits
typedef bit [71:0] uint72_t;
trio_s v,x;
uint72_t l;
initial begin
x = '{sw:OFF, s:"switch10", value:'h0a};
l = uint72_t'(x);
$displayh(l);
v = trio_s'(l);
$displayh("v = %p",v);
$display("v.s = %s",v.s);
end
endmodule
This displays
# 5cddda5d18da0c4c0a
# v = '{sw:OFF, s:8320234785195176240, value:10}
# v.s = switch10
pair_t va[int] = '{10:'{OFF, "switch10"}, 20:'{ON, "switch20"}};
is the same as
pair_t va[int]
initial begin
va[10].sw = OFF;
va[10].s = "switch10";
..
Saying that, you can write your own parser of a +arg string (or strings) which will assign values to the array fields in a task. This is the only possibility. For exmple:
string indx = "1";
string sw = "off";
initial begin
int i = indx.atoi();
va[i].sw = sw == "off" ? OFF : ON;
...

Using don't-care in enumeration typedef in synthesizable SystemVerilog

I have the following code:
typedef enum logic [1:0] {
CMD1 = 2'b1?,
CMD2 = 2'b01,
CMD3 = 2'b00
} cmd_t;
Basically, if the MSB is 1, it's CMD1 (I'll use the LSB for part of the index). And if the MSB is 0, then decode the rest of bits for the command.
I then try to decode using an always_comb:
cmd_t myCmd;
always_comb begin
casez(myCmd)
CMD1: isCmd1 = 1'b1;
CMD2: isCmd1 = 1'b0;
default: isCmd1 = 1'b0;
endcase
end
Unfortunately, I get this message from Spyglass:
[12EE] W467 Based number 2'b1? contains a don't-care (?) - might lead to simulation/synthesis mismatch
This code should be synthesizable, no? Can this Spyglass warning be waived safely?
I doubt this will synthesise correctly. I think the Spyglass message is misleading. In Verilog (and SystemVerilog) ? means exactly the same as z. You are specifying an enum with 4-state base type values, where CMD1 is to be represented exactly by 2'b1z.

What is advantage of structure?

I'm Verilog user, so I am unfamiliar with SystemVerilog.
Now I'm trying to study structure literals.
What is advantage of using structure?
Structure in SystemVerilog is more or less similar to structure usage in C-language, structure is a collection of different data types, variables or constants under single name. For more details you can always refer SystemVerilog LRM IEEE Std 1800-2012 ♦ 7.2 Structures
I will here explain the more common usage and advantage of structures.
The declaration of structure can be done by variable or nets, A structure as a whole can be declared as variable by using var keyword and a structure can be defined as net using Verilog data type wire or tri, when defined as net type all members of structure should be 4-state types.
structure variable:
var struct {
logic [15:0] a, b;
logic [ 7:0] data;
logic [31:0] width;
} data_word_var;
structure net:
wire struct {
logic [15:0] a, b;
logic [ 7:0] data;
logic [31:0] width;
} data_word_net;
If we don't mentioned the type of structure by default it will be net type and note that a net type variable cannot be declared inside a structure despite a whole structure can be of net type.
Structure can be initialized as a whole
data_word_net dw = ’{16'hf0f0, 16'h1010, 8’d3, 0};
or individual members can be initialized
data_word_net dw;
dw.data = 8'b1011_1111;
It is also possibe that we can initialize using member names
data_word_net dw = ’{a:16'hf0f0, b:16'h1010, data:8’d3, width:0}; // legal
data_word_net dw = ’{a:16'hf0f0, data:8’d3, b:16'h1010, width:0}; // legal
data_word_net dw = ’{a:16'hf0f0, 8’d3, 16'h1010, width:0}; // illegal(all members should be mentioned do not mix both)
Also members can be initialized to their default values by using default keyword
typedef struct {
real r0, r1;
int i0, i1;
logic [ 7:0] a;
logic [23:0] addr;
} data_word;
data_word dw;
dw = ’{ real:1.0, default:0, r1:3.1415 };
Structure can be used through module ports
package my_pkg;
typedef struct {
logic [31:0] a, b;
} input_ports;
typedef struct {
logic [63:0] y;
} output_ports;
endpackage
module alu
(input my_pkg::input_ports inp,
output my_pkg::output_ports outp,
input wire clock);
...
endmodule
Structure can also be used as arguments to tasks and functions
module dut (...);
...
typedef struct {
logic [31:0] a, b;
logic [63:0] width;
logic [15:0] addr;
} i_pins;
function alu (input i_pins connect);
...
endfunction
endmodule
In addition to the above advantages language also supports array of structures in packed and unpacked format as shown below
typedef struct packed { // packed structure
logic [7:0] a;
logic [7:0] b;
} packet_t;
packet_t [15:0] packet_array; // packed array of 16 structures
typedef struct { // unpacked structure
int a;
real b;
} data_t;
data_t data_array [15:0]; // unpacked array of 16 structures