I would like to fill in the correct signal declarations and the modport declarations so that my interface and desire code example use case compiles in Vivado. I am working in SystemVerilog with .sv file extensions. The reason that I would like to "if statement" different signal declarations is so that the instantiating and using of my interface is way more elegant. I don't want the user to have to type many [0] to specify a single element in a single element array of 1st dimension with of 1 and 2nd dimension width of 1.
Bear with me on the purpose, I had to remove all elements of this code's application in my work. I have tailored it to be a very simple example.
I do not want someone to need to select the 0th and 0th element if the 1st dimension or the array is 1 and the second dimension of the array is 1.
For example I want the user to be able to do the following, but it doesn't compile. This is my base QUESTION. How do I achieve being able to have code as elegant as the following snippet?:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 1 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data = 8'h20 ;
The error is:
[Synth 8-6038] cannot resolve hierarchical name for the item 'data' [".../File.sv":21]
Instead I find the user will have to do this for a specific signal that is 1 element total (there is no error with the following):
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 1 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus[0][0].data = 8'h20 ;
I felt that something like this should make this achievable with the following code:
interface MyInterface #(int DATA_W, ADDR_W, A1D, A2D) () ;
typedef struct packed
{ logic valid
; logic [ADDR_W-1:0] addr
; logic [DATA_W-1:0] data
; } SimpleStruct;
if ( A1D == 1 ) begin
SimpleStruct bus;
logic ready;
end
else begin
if ( A2D == 1 ) begin
SimpleStruct [A1D-1:0] bus;
logic [A1D-1:0] ready;
end
else begin
SimpleStruct [A1D-1:0][A2D-1:0] bus;
logic [A1D-1:0][A2D-1:0] ready;
end
end
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
endinterface
This didn't compile because bus and ready were "not declared" ... so I changed to a less elegant (i tried surrounding in generate just guessing, but that didn't help):
interface MyInterface #(int DATA_W, ADDR_W, A1D, A2D) () ;
typedef struct packed
{ logic valid
; logic [ADDR_W-1:0] addr
; logic [DATA_W-1:0] data
; } SimpleStruct;
if ( A1D == 1 ) begin
SimpleStruct bus;
logic ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
else begin
if ( A2D == 1 ) begin
SimpleStruct [A1D-1:0] bus;
logic [A1D-1:0] ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
else begin
SimpleStruct [A1D-1:0][A2D-1:0] bus;
logic [A1D-1:0][A2D-1:0] ready;
modport SNK (input bus, output ready);
modport SRC (output bus, input ready);
end
end
endinterface
The same desire goes for the case where the user wants to use a single dimensioned array where length > 1. For example:
imho desirable:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 3 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data[0] = 8'h20 ;
assign my_signal.bus.data[1] = 8'h21 ;
assign my_signal.bus.data[2] = 8'h22 ;
I think the code above looks better than the code below. And the whole point of me experimenting or choosing to use interfaces is code reusability and elegance. I don't want the user to constantly be fighting with "I want a single element, but will get partially ambiguous error that is tough to figure out the solution to":
imho Not desirable:
MyInterface # ( .DATA_WIDTH( 8 ), .ADDR_WIDTH( 8 ), .A1D( 3 ), .A2D( 1 ) ) my_signal () ;
assign my_signal.bus.data[0][0] = 8'h20 ;
assign my_signal.bus.data[1][0] = 8'h21 ;
assign my_signal.bus.data[2][0] = 8'h22 ;
My desire is to have the user write the code they need to accomplish the complexity of elements that they want. There are most uses for a single element, some uses for a 1D array of elements, and few uses for 2D array of the elements. Since I will want to have one interface defined, I will have to allow for all the uses. I don't want in-elegant code needed just because I want the interface to support 2D and a user only needs a single element for their particular instantiation and code.