SystemVerilog Array of Interfaces

A

Ari Ari

Guest
I need to receive data from an array of input interfaces and send the
output to an array of output interfaces. The receive (send) is
implemented by calling a task called Receive (Send).

interface test_I;
logic req;
logic ack;
logic data;

task Receive (output logic d);
wait (req == 1);
ack = 1;
d = data;
wait (req == 0);
ack = 0;
endtask
task Send (input logic d);
req = 1;
data = d;
wait (ack == 1);
req = 0;
wait (ack == 0);
endtask
endinterface

module Receiver_16(test_I inputs [15:0], test_I outputs [15:0]);
integer i = 0;
logic [15:0] rData, sData;
always
begin
for (i=0 ; i<=15 ; i++)
inputs.Receive(rData); //Can't do this: Nonconstant index
into instance array 'inputs'

//Consume received data and generate sData

for (i=0 ; i<=15 ; i++)
outputs.Send(sData); //Can't do this: Nonconstant index
into instance array 'outputs'
end
endmodule


----
According to this
http://objectmix.com/verilog/189492-systemverilog-interface-arrays.html

this can be done only by using multiple always blocks or virtual
interfaces. Can someone tell me if these are the only options although
the compiler is told that are interfaces are of the same type? How can
I do this with virtual interfaces?
 
In article <a86dbb7b-62c8-4d52-8c17-647e93b1b1f1@l14g2000pre.googlegroups.com>,
Ari Ari <onlyari@gmail.com> wrote:
I need to receive data from an array of input interfaces and send the
output to an array of output interfaces. The receive (send) is
implemented by calling a task called Receive (Send).

interface test_I;
logic req;
logic ack;
logic data;

task Receive (output logic d);
wait (req == 1);
ack = 1;
d = data;
wait (req == 0);
ack = 0;
endtask
task Send (input logic d);
req = 1;
data = d;
wait (ack == 1);
req = 0;
wait (ack == 0);
endtask
endinterface

module Receiver_16(test_I inputs [15:0], test_I outputs [15:0]);
integer i = 0;
logic [15:0] rData, sData;
always
begin
for (i=0 ; i<=15 ; i++)
inputs.Receive(rData); //Can't do this: Nonconstant index
into instance array 'inputs'

//Consume received data and generate sData

for (i=0 ; i<=15 ; i++)
outputs.Send(sData); //Can't do this: Nonconstant index
into instance array 'outputs'
end
endmodule

Try using a generate loop instead of a procedural loop. Maybe a little more
clumsy, but should get around this problem.

--Mark
 
On Mar 31, 2:13 pm, gtw...@sonic.net (Mark Curry) wrote:
In article <a86dbb7b-62c8-4d52-8c17-647e93b1b...@l14g2000pre.googlegroups..com>,
Ari Ari  <only...@gmail.com> wrote:









I need to receive data from an array of input interfaces and send the
output to an array of output interfaces. The receive (send) is
implemented by calling a task called Receive (Send).

interface test_I;
 logic req;
 logic ack;
 logic data;

 task Receive (output logic d);
   wait (req == 1);
   ack = 1;
   d = data;
   wait (req == 0);
   ack = 0;
 endtask
task Send (input logic d);
   req = 1;
   data = d;
   wait (ack == 1);
   req = 0;
   wait (ack == 0);
 endtask
endinterface

module Receiver_16(test_I inputs [15:0], test_I outputs [15:0]);
integer i = 0;
logic [15:0] rData, sData;
always
begin
 for (i=0 ; i<=15 ; i++)
   inputs.Receive(rData);  //Can't do this: Nonconstant index
into instance array 'inputs'

//Consume received data and generate sData

for (i=0 ; i<=15 ; i++)
   outputs.Send(sData);  //Can't do this: Nonconstant index
into instance array 'outputs'
end
endmodule

Try using a generate loop instead of a procedural loop.  Maybe a little more
clumsy, but should get around this problem.

--Mark

Thanks for the reply! I tried the generate loop with 16 always blocks
for Receive and 16 always blocks for Send. The problem is in a longer
code that Send and Receive calls are on multiple interfaces and the
sequence of Receive/Send matters, the code becomes very messy. I had
to synchronize my always blocks in the generate loop using the event
data structure:

genvar i;
for (i=0 ; i <=15 ; i++)
begin
always
begin
@ (receive_event);
L.Receive(x);
ReceiveCounter++ ;
end

always
begin
@ (send_event);
R.Send(s);
SendCounter++;
end
end

Moreover, I had to use a counter to detect that all 16 Receive tasks
are finished.

It's a bit disappointing that one cannot use interfaces in
SystemVerilog as easily as input and output ports...
 
On Apr 6, 3:06 pm, Ari Ari <only...@gmail.com> wrote:
It's a bit disappointing that one cannot use interfaces in
SystemVerilog as easily as input and output ports...
Unfortunately, "arrays" of instances aren't true arrays. That is the
fault of the Verilog defparam construct, which allows different
instances in the array to be parameterized differently, which allows
their contents to be entirely different from each other.

The practicality of true arrays being indexed with variables at
runtime
is dependent on their being homogeneous, with the internal structure
of each element being the same regardless of index.

One way to get around this is to declare an array of virtual
interfaces,
and use a generate loop to initialize it to the elements of the array
of instances. An array of virtual interfaces is a true array, and all
of the elements are guaranteed to have the same parameterization (and
if
you try to initialize it to an array of instances where some elements
have different parameterizations, you should get type mismatches).
Once
you have an array of virtual interfaces, you can use variable indexes
with that to access the interfaces procedurally.
 

Welcome to EDABoard.com

Sponsor

Back
Top