1

I'm trying to create a simple crossbar style interconnect between N masters and M slaves.

Say if I have 2 Masters and 2 Slaves, the crossbar connects them as follows:

// Master - to - Slave  
assign s[0].addr = (gnt[0] == 1) ? m[0].addr : ( (gnt[1] == 1) ? m[1].addr : 'b0; )
assign s[0].data = (gnt[0] == 1) ? m[0].data : ( (gnt[1] == 1) ? m[1].data : 'b0; )

// Slave - to - Master  
assign m[0].resp = (sel[0] == 1) ? s[0].resp : ( (sel[1] == 1) ? s[1].resp : 'b0; )

Is there a way to generate the above assign statements if number of master and slaves are parameters? Or is there any other way to accomplish what I'm trying to do? Any help would be appreciated.

Greg
  • 18,111
  • 5
  • 46
  • 68
sundar
  • 456
  • 2
  • 7
  • 19
  • Are `gnt` and `sel` onehot-zero or priority? Please show that the assignments to `s[1]` and `m[1]` would look like – Greg Nov 07 '14 at 16:47

2 Answers2

1

You can use generate blocks in this case:

typedef struct {
  integer addr;
  integer data;
  integer resp;
} sigs;

module crossbar;
  parameter int num_masters = 3;
  parameter int num_slaves = 3;

  sigs s[num_slaves];
  sigs m[num_masters];
  bit gnt[num_masters];


  genvar i, j;

  // master to slave loop
  for (i = 0; i < num_slaves; i++) begin
    wire[31:0] addr;
    for (j = 0; j < num_masters; j++) begin
      assign addr = gnt[j] == 1'b1 ? m[j].addr : 'z;
    end
    assign addr = gnt == '0 ? '0 : 'z;
    assign s[i].addr = addr;
  end
endmodule

What I illustrated here are only the assigns for addr. You'd had to have data and any other master to slave signals to this loop and create another loop where you loop over masters first and then slaves to assign resp and any other slave to master signals.

I've used an intermediate wire for addr to be able to have an assign statement per master. This way, when a master is granted it will drive the wire, otherwise it will drive high impedance. It's therefore vital to not grant two or more masters at the same time.

It isn't exactly what you have, but you can replace the multiple assigns with a priority encoding scheme if you want to allow multiple masters at the same time.

Greg
  • 18,111
  • 5
  • 46
  • 68
Tudor Timi
  • 7,453
  • 1
  • 24
  • 53
  • Functionally this concept should work. However, many synthesizers will attempt to use tri-state drivers when they see anything matching `assign io = en ? in : 'z;` format and this can be a limitation with design constraints. This style also requires `gnt` and `sel` to be onehot coded – Greg Nov 07 '14 at 17:24
1

The muxing logic can be scaled withing a combinational block. The example below defaults in assignments to zero then updates the assignments with LSB priority.

parameter NUM_MASTERS=5, NUM_SLAVES=3;
/* 
 * ...
 */

for ( genvar s_idx = 0; s_idx < NUM_SLAVES; s_idx++ ) begin
  alwasy_comb begin
    // default value
    s[s_idx].addr = '0;
    s[s_idx].data = '0;
    // update with lsb priority
    for ( int idx = NUM_MASTERS-1; idx >= 0; idx-- ) begin
      if (gnt[idx]) begin
        s[s_idx].addr = m[idx].addr;
        s[s_idx].data = m[idx].data;
      end
    end
  end
end

for ( genvar m_idx = 0; m_idx < NUM_MASTERS; m_idx++ ) begin
  alwasy_comb begin
    // default value
    m[m_idx].resp = '0;
    // update with lsb priority
    for ( int idx = NUM_SLAVES-1; idx >= 0; idx-- ) begin
      if (sel[idx]) begin
        m[m_idx].resp = s[idx].resp;
      end
    end
  end
end
Greg
  • 18,111
  • 5
  • 46
  • 68
  • gnt and sel are one-hot encoded. Thanks a lot!! Your method works too but I'm able accept only one answer here.. – sundar Nov 11 '14 at 11:23