I have a struct declared inside a module like this:
module myModule;
struct {
logic a;
logic b;
logic [A - 1:0] c[0:B - 1];
logic [C - 1:0] d;
} [D - 1:0] e [0:E - 1][0:F - 1];
endmodule
I want to use c like an unpacked array, but Verilog does not allow this. It throws an error on the line where c is defined:
Unsupported: Unpacked array in packed struct/union
Is there a way around this?
In order to have a packed array, all element must be packed. So either make the struct packed:
struct packed {
logic a;
logic b;
logic [A - 1:0] [0:B - 1] c;
logic [C - 1:0] d;
} [D - 1:0] e [0:E - 1][0:F - 1];
or make the e array all unpacked
struct {
logic a;
logic b;
logic [A - 1:0] [0:B - 1] c;
logic [C - 1:0] d;
} e [0:E - 1][0:F - 1][D - 1:0];
BTW, it is highly recommended that you use a typedef for your struct instead of having an anonymous struct type.
Related
I am trying to implement a fitness evaluation function in Verilog called Rosenbrock function (https://en.wikipedia.org/wiki/Rosenbrock_function). The issue I am facing is that if I use the following code it gives me a undefined state since there are 4 drivers to the wire fitness_val.
module test_module1 ( x, fitness);
input [4*2 -1:0] x;
output [1:0] fitness;
wire [1:0] x_i;
wire [1:0] x_im1;
wire [3:0] fitness_val;
wire [3:0] a;
wire [3:0] b;
wire [1:0] x_array1 [3:0];
genvar k;
assign fitness = fitness_val;
genvar j;
generate
for (j =0 ; j <4 ; j = j+1) begin
assign x_array1[j] = x[2*j +: 2];
end
for (k=1; k<4; k=k+1) begin
assign x_i = x_array1[k];
assign x_im1 = x_array1[k-1];
assign a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
assign b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
assign fitness_val = fitness_val + a[2:1] + b[2:1];
end
endgenerate
endmodule
module tb_tm1();
wire [1:0] fitness;
wire [4*2-1:0] x_array;
test_module1 tm1(x_array, fitness);
assign x_array = 8'b11100100;
endmodule
However if I expand the for loop in this format, I get a valid output.
assign fitness_val = 100*(x_array1[1] - x_array1[0])*(x_array1[1] - x_array1[0]) + (1 - x_array1[0])*(1 - x_array1[0])
+ 100*(x_array1[2] - x_array1[1])*(x_array1[2] - x_array1[1]) + (1 - x_array1[1])*(1 - x_array1[1])
+ 100*(x_array1[3] - x_array1[2])*(x_array1[3] - x_array1[2]) + (1 - x_array1[2])*(1 - x_array1[2]);
Is there a way to implement this recursively in Verilog?
assign statements run concurrently; not sequentially. Generate loops are static unrolled during elaborations. When two assign statements drive different values to the same net, the result will be x.
To do sequential operations you will need to an always block.
Minimum change as follows (plus ANSI style header):
module test_module1 (
input [4*2 -1:0] x,
output [1:0] fitness ); // <-- ANSI style header
reg [1:0] x_i; // 'always' block assign 'reg' type
reg [1:0] x_im1;
reg [3:0] fitness_val;
reg [3:0] a;
reg [3:0] b;
wire [1:0] x_array1 [3:0]; // 'assign' drives 'wire' type
interger k; // index for loop in an always block
genvar j; // index for a generate loop
assign fitness = fitness_val;
generate
for (j =0 ; j <4 ; j = j+1) begin
assign x_array1[j] = x[2*j +: 2];
end
endgenerate
always #* begin // #* is auto-sensitivity, use for combination logic
fitness_val = 4'b0000; // initial value, otherwise it infers a latch
for (k=1; k<4; k=k+1) begin
x_i = x_array1[k];
x_im1 = x_array1[k-1];
a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
fitness_val = fitness_val + a[2:1] + b[2:1];
end
end
endmodule
FYI: 4-bits is not enough to hold the value decimal 100. Do Do you want to make it bigger you did you intend the 100 to represent 4 in binary (4'b0100)?
I have a System Verilog module that is instantiated multiple times in the design. Each instantiation needs to use a different package. What is the best way to implement this?
package A;
parameter logic [15:0] array [0:15] = '{
16'd1,
16'd2,
.
.
16'd16
}
endpackage
package B;
parameter logic [15:0] array [0:7] = '{
16'd1,
16'd2,
.
.
16'd8
}
endpackage
module test(
);
import packageA::*;
This is how I would use it in one instantiation of the module. But in the second instantiation I would like to use packageB.
should i use:
ifdefs?
passing a package name if it is possible?
or
just pass it as a parameter to the module? even if it is a 2 dimensional array?
What is the best approach for it?
System Verilog syntax does not provide any way for passing packages as arguments to anything. It is possible to use macros which would alter module definition. Though it is possible, it is a bad practice and is not usually recommended. I'll give an example at the end.
The only way is to handle it is to parameterize the module and pass a corresponding array at the instantiation time, e.g.
package A;
parameter bit[3:0] data[4] = '{0,1,2,3};
endpackage
package B;
parameter bit[3:0] data[6] = '{5,4,3,2,1,0};
endpackage
module C#(int WDT = 1, bit [3:0] array [WDT] = '{0}) ();
initial begin
for (int i = 0; i < WDT; i++)
$display("%m: array[%0d] = %0d", i, array[i]);
end
endmodule
module D();
C #($size(A::data), A::data) c1();
C #($size(B::data), B::data) c2();
endmodule
there are other versions with types, i.e.
package A;
typedef bit[3:0] Array[4];
parameter Array array = {0,1,2,3};
endpackage
package B;
typedef bit[3:0] Array[6] ;
parameter Array array = {5,4,3,2,1,0};
endpackage
typedef bit[3:0] DefaultArray[1];
module C#(type X = DefaultArray, X array = {0}) ();
initial begin
for (int i = 0; i < $size(array); i++)
$display("%m array[%0d] = %0d", i, array[i]);
end
endmodule
module D();
D #(A::Array, A::array)d1();
D #(B::Array, B::array)d2();
endmodule
for macros you can either define the whole module in a macro. I think it is ugly
`define PMOD(NAME,PKG) module NAME (); ... import PKG""* ...
...
`PMOD(C1, A)
`PMOD(C2, B)
...
C1 c1();
C2 c2();
One can also use ifdefs withinclude. I would not recommend any of the macro-based or in particular, include-based approaches. They create readability, maintainability, code analysis, and debugging issues.
I have the following structs:
typedef struct packed {
type1_t info1;
type2_t info2;
} module_info_registers_t;
typedef struct packed {
logic [0:0] data1;
logic [2:0] data2;
logic [11:0] data3;
logic [15:0] data4;
} info1;
typedef struct packed {
logic [1:0] data1;
logic [3:0] data2;
logic [10:0] data3;
logic [14:0] data4;
} info2;
As you can see, type1_t and type2_t are defined as 32-bit data structures.
I want to instantiate the following:
module_info_registers_t myregs;
and I want to access the registers based on index (rather than having to type myreqs.info2.data4):
myregs[1].data4
This is because the definition of module_info_registers_t will change from time to time and is autogenerated, so I don't want to hardcode 'info2' in my RTL
However, I am getting an error saying that I can't have a slice on a scalar object.
I understand that for some reason I can't access the data in the way I want to. Is there another way I can do what I am trying to achieve?
There is no way in verilog to do what you want. You might get around using macros, or bit-level access to the struct fields.
Macros can be done like this:
`define ACCESS_REG(R, NUM) R.info``NUM
module_info_registers_t regs;
`ACCESS_REG(regs, 1).data1 = 0;
The above will work, assuming certain naming conventions applied to the fields.
with bit-level access you need to be able to calculate offset and width of every struct member, making declaration and usage more complicated. Here is a very simplified System Verilog example for clarity:
typedef struct packed {
logic [1:0] f1;
logic [2:0] f2;
logic [3:0] f3;
} sp_t;
sp_t sp;
sp[$bits(sp.f3) + $bits(sp.f2) +: $bits(sp.f3)] = 2'b10;
The above example will set 'sp.f1'.
So, in your case you can create arrays of parameters describing offset and widths of the corresponding fields and use them for indexing. So, something like that might work in your case:
parameter int info[2] = {0, 32};
parameter int data1Offset[2] = {31, 30};
parameter int data1Width[2] = {1, 2};
module_info_registers_t regs;
regs[info[1] + data1Offset[1] +: data1Width[1]] = 0;
Quartus compile this code without any errors.
Code.sv
module test013_LITERAL (
input A,
input B,
output C
);
struct{enum{IDLE,
SOME_STAGE_1} FSM;
logic some_register;
} first_machine;
struct{enum{IDLE,
SOME_STAGE_2} FSM;
logic some_register;
} second_machine;
assign C = A ^ B;
endmodule
testbench.vt
module testbench();
reg test_A;
reg test_B;
wire test_C;
test013_LITERAL DUT (.A(test_A),
.B(test_B),
.C(test_C));
initial begin
#100
test_A = 0;
test_B = 0;
#100
test_A = 1;
test_B = 0;
#100
test_A = 0;
test_B = 1;
#100
test_A = 1;
test_B = 1;
end
endmodule
But ModelSim-Altera show error: "Enum literal name 'IDLE' already exists."
Can I write on SystemVerilog two structs in one module and then make enum in each struct with same literal ("IDLE" for example)? Is another struct means another scope?
If not can anyone describe what structs are used for?
If yes can anyone describe to me how to win ModelSim-Altera?
P.S.
Of course if there is two enums in one module and if these enums has identical members we will have an error. But I say about enums witch placed into structs.
Example:
module test013_LITERAL (
output [3:0]first_literal,
output [3:0]second_literal
);
struct{enum{SOME_LITERAL_0_FIRST,
SOME_LITERAL_1_FIRST,
IDLE,
SOME_LITERAL_3_FIRST,
SOME_LITERAL_4_FIRST} enum_reg;
} first_struct;
struct{enum{SOME_LITERAL_0_SECOND,
SOME_LITERAL_1_SECOND,
SOME_LITERAL_2_SECOND,
IDLE,
SOME_LITERAL_4_SECOND} enum_reg;
} second_struct;
assign first_literal = first_struct.IDLE;
assign second_literal = second_struct.IDLE;
endmodule
Result of compilling on Quartus Prime 17.1.0 (MAX-10 10M02SCE144C8G):
Info (293000): Quartus Prime Full Compilation was successful. 0 errors, 32 warnings
Result on eight LED string: 0010 0011
P.P.S.
I don't understand if struct create new scope of not.
This code compile by Quartus as well as ModelSim-Altera without any errors.
module test013_LITERAL (
input A,
input B,
output C
);
logic some_register;
struct{logic some_register;} first_struct;
struct{logic some_register;} second_struct;
assign C = A ^ B;
endmodule
IEEE 1800-2012, section 6.19 says:
// Correct declaration - bronze and gold are unsized
enum bit [3:0] {bronze='h3, silver, gold='h5} medal2;
// Correct declaration - bronze and gold sizes are redundant
enum bit [3:0] {bronze=4'h3, silver, gold=4'h5} medal3;
Type checking of enumerated types used in assignments, as
arguments, and with operators is covered in
6.19.3. As in C, there is no overloading of literals; therefore, medal2 and medal3 cannot be defined in the same scope because they
contain the same names
So, I would say that it is correct to report an error with your code because the IDLE literal appears twice.
I have tried your code on three simulators. One accepts it, the other two reject it. So, in total, three simulators reject your code, one accepts it (as does Quartus). I guess the fact that your enum is declared within a struct complicates the EDA vendors' interpretation of the standard.
The fix is to change the name of one or both (eg IDLE1 and IDLE2).
Binary addition on A and B and outputs it along with proper carry bit. I'm not sure how to implement the carry bit
A and B are 4 bit inputs
C is 1 bit output that is used for the carry bit
module addop(C , O , A , B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
output C;
assign C1 = A[0] + B[0];
assign C2 = A[0] + B[1];
endmodule
You may want to use a concatenation operator {} here.
module addop(C, O, A, B);
input [3:0] A;
input [3:0] B;
output [3:0] O;
output C;
assign {C, O} = A + B;
endmodule
Your synthesis tool will be responsible in converting them
into logic gates.
See this question which is related to concatenation:
What do curly braces mean in Verilog?