SystemVerilog: Collapsing and & on an array of interface ... Collapsing or | on an array of interface

661 views Asked by At

I am trying to change some of my code pretty drastically. Everywhere where I am using a widely used struct in a module port signature, I would like to replace with a interface (if appropriate).

One logical operation that I have not figured out is a collapsing & or and collapsing or.

This is very easy to do with a regular vector of bits: Somewhere in a module I can very easily perform collapsing & and |

logic [31:0] vect ;
logic my_sig_and ;
logic my_sig_or ;

always_comb begin
  my_sig_and = &vect ;
  my_sig_or = |vect ;
end

But, my question is, how to perform this on a single bit field across an array of interface

My attempts are below (even the silly ones):

interface myInterface () () ;
    logic valid
    logic[31:0] data
endinterface

Attempt #1:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = my_intfs[0].ready ;
    for( genvar ii = 1; ii < PORTS; ii++ ) begin
        temp_signal = temp_signal && my_intfs[ii].ready ; // error line
    end
end

always_comb begin
    my_sig_and = temp_signal;
end

Error: near "genvar": syntax error, unexpected genvar, expecting ';'.

Attempt #2:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = my_intfs[0].ready ;
    for( int ii = 1; ii < PORTS; ii++ ) begin
        temp_signal = temp_signal && my_intfs[ii].ready ; // error line
    end
end

always_comb begin
    my_sig_and = temp_signal;
end

Error: Nonconstant index into instance array 'my_intfs'

Attempt #3:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = my_intfs[0].ready ;
    for( int ii = 1; ii < PORTS; ii++ ) begin
        temp_signal = temp_signal && my_intfs[ii+:0].ready ; // error line
    end
end

always_comb begin
    my_sig_and = temp_signal;
end

(vlog-13172) Selected name after a part-select may only be a modport on an interface port.

Attempt #4:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = my_intfs[0].ready ;
end

for( genvar ii = 1; ii < PORTS; ii++ ) begin
    always_comb begin
        temp_signal = temp_signal && my_intfs[ii].ready ; // error line
    end
end

always_comb begin
    my_sig_and = temp_signal;
end

(vopt-7033) Variable 'temp_signal' driven in a combinational block, may not be driven by any other process

Attempt #5:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

for( genvar ii = 0; ii < PORTS; ii++ ) begin
    always_comb begin
        temp_signal = temp_signal && my_intfs[ii].ready ; // error line
    end
end

always_comb begin
    my_sig_and = temp_signal;
end

(vopt-7033) Variable 'temp_signal' driven in a combinational block, may not be driven by any other process.

Attempt #6:

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = &my_intfs.ready ; // error line
end

always_comb begin
    my_sig_and = temp_signal;
end

(vopt-2990) Illegal operation on unpacked type.

Attempt #7 (silly but desired haha):

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = my_intfs.&ready ; // error line
end

always_comb begin
    my_sig_and = temp_signal;
end

near "&": syntax error, unexpected '&'

Attempt #8 some syntax from bash/sh with @ to ref whole array (silly but desired haha):

My attempt somewhere in a module:

myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

always_comb begin
    temp_signal = &my_intfs[@].ready ; // error line
end

always_comb begin
    my_sig_and = temp_signal;
end

near "@": syntax error, unexpected '@'.

2

There are 2 answers

0
ik631 On BEST ANSWER

Using a macro that assigns all interface array elements to a placeholder logic vector worked. Simply collapse the logic vector after all of the assignments are complete.:

somewhere in a module:
myInterface () my_intfs [PORTS-1:0] () ; // assume this is assigned to
logic temp_signal ;
logic my_sig_and ;

`INTF_FIELD_COLLAPSE_AND( blah, my_intfs, valid, PORTS, 1, my_sig_and )


`ifndef INTF_FIELD_COLLAPSE_AND
    `define INTF_FIELD_COLLAPSE_AND( unique, intf, field, size, field_size, output_sig ) \
        logic [size-1:0] [field_size-1:0] my_sig_unique ; \
        for( genvar ii_unique = 0; ii_unique < PORTS; ii_unique++ ) begin \
            always_comb begin \
                my_sig_unique[ii_unique] = intf[ii_unique].field ; \
            end \
        end \
        output_sig = &my_sig_unique ;
`endif
1
dave_59 On

You cannot access an array of (interface or module) instances like a normal array of bits. Because of potential parameter overriding interface port connections, each instance must be accessed independently with a constant.

What you should do is create a local packed array from the array of interfaces signals separately, and then you can perform the operation on the local array.

myInterface my_intfs [PORTS-1:0] () ; 

logic [PORTS-1:0] local_ready;

for(genvar i=0;i<PORTS;i++)
   assign local_ready[i] = my_intfs[i].ready;

assign my_sig_and = &local_ready;