Can the indivdual variables of a SystemVerilog struct be incremented with ++? - struct

I have defined a structure with three integers, then created a dynamic array of the structure. Later in the code, I want to increment some of the integer values in the structure:
typedef struct {
integer tc;
integer pass;
integer fail;
} score_t;
score_t scorecard[];
integer tc_count;
initial
....
scorecard = new[`MAX_TC];
....
scorecard[tc_count].fail = 0;
....
scorecard[tc_count].fail++;
However, when I compile in Aldec Active-HDL I get the following error:
Error: VCP2615 ../../../m3_test_load_tb.sv : (283, 33):
scorecard[tc_count].fail is not l-value.
Is this a limitation of the language? I can assign to a temporary variable to do the increment operation and then put the value back in the struct, but that seems clumsy.

The code compiles with modelsim 10.1d. I have tested it on EDA Playground.
Seems the Aldec tool does not like the line:
scorecard[tc_count].fail++;
As a workaround you can replace the line with:
scorecard[tc_count].fail += 1;
Now it compiles with Aldec tool as well. http://www.edaplayground.com/x/VpV

Related

Pass 2D real array to a function in System Verilog

I am trying to pass 2D real array to an SV function and return the same but I'm not able to execute this task successfully. Here is a simple reproducible code:
module Two_d_array_pass();
real x[2][2]='{'{1.0,2.0},'{3.0,4.0}};
real y[2][2]='{'{2.0,2.0},'{2.0,2.0}};
real z[2][2];
int i,j;
initial begin
foreach(x[i,j]) $display("x[%0d][%0d]=%0f",i,j,x[i][j]);
foreach(y[i,j]) $display("y[%0d][%0d]=%0f",i,j,y[i][j]);
z=mult(x,y);
end
function real mult(x,y);
real c[2][2];
int i,j;
foreach(c[i,j])
c[i][j]=x[i][j]*y[i][j];
return c;
endfunction
endmodule
and here is the error I get:
file: Two_d_array_pass.sv
c[i][j]=x[i][j]*y[i][j];
|
xmvlog: *E,DIMERR (Two_d_array_pass.sv,18|10): Bit-select or part-select dimensions do not match declaration.
c[i][j]=x[i][j]*y[i][j];
|
xmvlog: *E,DIMERR (Two_d_array_pass.sv,18|18): Bit-select or part-select dimensions do not match declaration.
Can anyone correct the code to achieve this task?
You need to change the arguments to be 2x2 dimensional as well.
function real mult(real x[2][2],y[2][2]);
But you also need to do it for the return type, but because of syntax limitations, unpacked array need a typedef for the return type.
typedef real real2x2[2][2];
function real2x2 mult(real x[2][2],y[2][2]);
Then you might as well use the typedef everywhere
module Two_d_array_pass();
typedef real real2x2[2][2];
real2x2 x='{'{1.0,2.0},'{3.0,4.0}};
real2x2 y='{'{2.0,2.0},'{2.0,2.0}};
real2x2 z;
initial begin
foreach(x[i,j]) $display("x[%0d][%0d]=%0f",i,j,x[i][j]);
foreach(y[i,j]) $display("y[%0d][%0d]=%0f",i,j,y[i][j]);
z=mult(x,y);
end
function real2x2 mult(real2x2 x,y);
foreach(x[i,j])
mult[i][j]=x[i][j]*y[i][j];
endfunction
endmodule
P.S. you do not declare the iterating variables i and j separately, they are implicit and local to the scope of the foreach statement. If you declare them separately, they become extra variables unused by the foreach loop.

How do I generate parameters dependent onf previous parameters in systemverilog

I recently switched from VHDL to SystemVerilog and I am converting some of my codes. I want to generate an array of local parameters based on 3 parameters SZ,L,max.
module test #(
parameter int SZ = 1024,
parameter int L = 35,
parameter int MAX = 4
)()
//...
localparam int n[MAX:0] = ;//...
for(genvar i = 0; i < max; i++) begin: gg
//n[i] and n[i+1] will be used here
//There is a second generate loop here that uses n[i+1] and therefore n[i+1] has to be parameter.
end
I tried using a function to generate localparams but I get an error that element assignment in function is not constant. I never had this issue in VHDL.
The only other option I can think of is to create the params inside the for generate but how would I reference the initial value? Is there any other solution?
The simulator I am using is Verilator but I also want the design to work in Xilinx Vivado.
Edit: I do not want to generate the parameters from an external script because I lose the ability to use Vivado's ability to run multiple synthesis/implementation in the same project with different parameters. That was what I used to do in VHDL.
You can use a function to initialize a parameter, you just have to have the output of the entire array as the result of the function. To do that, you need a typedef
typedef int array_type[MAX:0];
function array_type f();
f[0]=SZ;
for(int i=0;i<MAX;i++)
f[i+1]=f[i]-((2*i)+1)*L)/2;
endfunction
localparam array_type n = f();
I got it working by using packed array of 32-bits. Verilator doesn't support unpacked int with constants. Packed int is also not supported so I had to change the type to pack of 32-bits.
typedef [MAX:0][31:0] array_type;
function array_type f();
f[0]=SZ;
for(int i=0;i<MAX;i++)
f[i+1]=f[i]-((2*i)+1)*L)/2;
endfunction
localparam array_type n = f();

How to vary a struct going through a port in system verilog - generate doesnt work

module testy
#(
parameter W = 10,
parameter C = 2
)
(
aa
);
generate
if (W == 8)
begin:W8
if(C == 1)
begin:W8C1
typedef struct {
logic [8:0] so;
}my_struct;
end
if(C == 2)
begin:W8C2
typedef struct {
logic [10:0] so;
}my_struct;
end
end
endgenerate
input my_struct aa;
endmodule
I get this error:
irun(64): 14.20-p001: (c) Copyright 1995-2015 Cadence Design Systems, Inc.
file: testy.v
input my_struct aa;
|
ncvlog: *E,SVNOTY (testy.v,30|14): Syntactically this identifier appears to begin a datatype but it does not refer to a visible datatype in the current scope.
module worklib.testy:v
errors: 1, warnings: 0
ncvlog: *F,NOTOPL: no top-level unit found, must have recursive instances.
irun: *E,VLGERR: An error occurred during parsing. Review the log file for errors with the code *E and fix those identified problems to proceed. Exiting with code (status 2).
I thought generates were statically determined but I have problems compiling it - since parameters cant be overridden in packages and couldn't think of a way to do this in design which needs to be synthesized and didn't want to add interfaces or classes. Is there a bettwe way to do this. My struct has over 100 entries if I include all the combinations and use only what I want but I thought using generates I could trim it to what I want based on a set of parameters.
Thanks
Your problem is the scope of the typedef is local to the blocks inside your generate statements. If all you need to do is change the size of a data type, you can use a constant function call, with is statically determined. But then you run into another problem with your unpacked struct declaration - it is still local to the module and you will not be able to connect another struct to it with a matching data type. An interface would be a better solution and is synthesizable.
Another possibility is passing down a type parameter.

Can't use a typedef enum to store state information

hi - I'm using the XC16 C compiler with a Microchip dsPIC33F CPU. I'm trying to use an enum to store the state of a device. I have accessors to get and set the device state. The state is (or should be) captured in a variable called "currentNodeState" which is declared with the following:
`
typedef enum NodeState currentNodeState;
I then use it in the set accessor with:
void SetNodeState(NodeState state)
{
currentNodeState = state;
}
which results in the following compiler error:Node_IO.c:168:22: error: expected identifier or '(' before '=' token
any suggestions as to why the error message
Jim
You need to define what values are legal for the enum.
Cplusplus has a good write up on enums (near the bottom of the page): http://www.cplusplus.com/doc/tutorial/other_data_types/
Here's a modified example from my code:
typedef enum
{
ADJUST_NONE,
ADJUST_FINE,
ADJUST_COARSE,
ADJUST_INVALID
} adjustment_state_t;
adjustment_state_t ADJUSTER_StateUpdate(adjustment_state_t currentState,
uint8_t thresholdViolation);
Valid inputs to the function are any of the values in the enum. ADJUST_NONE = 0, and each subsequent value is 1 higher than the last. That makes ADJUST_INVALID = 3.

Potentially uninitialized local variable used? Why?

When I write this code and compile with /W4
long r;
__try { r = 0; }
__finally { }
return r;
I get:
warning C4701: potentially uninitialized local variable 'r' used
Why does this happen?
The compiler can't be sure the code inside of the try block will successfully run. In this case it always will, but if there's additional code in the try block r = 0 may never execute. In that case r is uninitialized hence the error.
It's no different than if you said:
long r;
if(something) {
r = 0;
}
return r;
(where 'something' is pretty much anything other than a constant true value).
Because long r; creates r but it is not initialized; it is null.
So it warns you that the variable is not initialized. In certain cases it will cause Null Pointers.
Adding this as an answer as it is of more interest than in just a comment:
The error never appeared until a labeled-statement: was inserted before the variable. Remove the goto & associated label and there is no warning.
This might have something to do with how namespace pathing is setup with a similar warning C4702 generated on a line number before the insertion of a goto block. MVCE still to be generated if anyone is interested.

Resources