T0l3d0R0bs0n
T0l3d0R0bs0n

Reputation: 33

Interconnecting modules in combinational circuit, Verilog or SystemVerilog

I want to connect multiple instances of a module up in a grid with column and row connections (like in the scheme). Can i do that using nested generate blocks? I need the code to be scalable because the design is large. grid

Output1 of a module is driven to input1 of the module on its left. Outputs2,3 of a module are driven to inputs2,3 of the module beneath that.

Edit of my question after Morgan's answer: I try to give as input a slice of each array using the following code:

module top(
//Inputs to system:
input out1[0][1:3],
input out2[1:3][0], 
input out3[1:3][0]
);

wire out1[0:3][1:3];
wire out2[1:3][0:3];
wire out3[1:3][0:3];

I can't compile it though. What is my mistake? I tried to find out myself, but I couldn't.

Upvotes: 3

Views: 1121

Answers (1)

Morgan
Morgan

Reputation: 20534

A new answer based on the edited question. The answer will work through my process, understanding the problem and refining, otherwise the generates used will be pretty difficult to understand. Skip to the end to see the generate syntax.

First an example of the desired connectivity from the given diagram.

Base module:

module m (
  input  in1,
  input  in2,
  input  in3,
  output out1,
  output out2,
  output out3
);
endmodule

The example connectivity:

//row 1 to drive row 2 (in2/3)
//column 1 to drive column 2 (in1)

//port _ col(x) _ row(y) 

wire out1_1_1, out2_1_1, out3_1_1;
wire out1_1_2, out2_1_2, out3_1_2;
wire out1_1_3, out2_1_3, out3_1_3;

wire out1_2_1, out2_2_1, out3_2_1;
wire out1_2_2, out2_2_2, out3_2_2;
wire out1_2_3, out2_2_3, out3_2_3;

wire out1_3_1, out2_3_1, out3_3_1;
wire out1_3_2, out2_3_2, out3_3_2;
wire out1_3_3, out2_3_3, out3_3_3;


//First column  
m m_1_1( .in1(    ?    ), .in2(   ?     ), .in3(   ?     ),   
         .out1(out1_1_1), .out2(out2_1_1), .out3(out3_1_1)  );
m m_1_2( .in1(    ?    ), .in2( out2_1_1), .in3( out3_1_1),
         .out1(out1_1_2), .out2(out2_1_2), .out3(out3_1_2)  ); //in2/3 driven from 0_0 (Above)
m m_1_3( .in1(    ?    ), .in2( out2_1_2), .in3( out3_1_2),
         .out1(out1_1_3), .out2(out2_1_3), .out3(out3_1_3)  ); //in2/3 driven from 0_1 (above)

//Second Vertical column, in1's driven from previous column.
m m_2_1( .in1( out1_1_1), .in2(   ?    ),  .in3(   ?     ),
         .out1(out1_2_1), .out2(out2_2_1), .out3(out3_2_1)  ); 
m m_2_2( .in1( out1_1_2), .in2( out2_2_1), .in3( out3_2_1),
         .out1(out1_2_2), .out2(out2_2_2), .out3(out3_2_2)  );
m m_2_3( .in1( out1_1_3), .in2( out2_2_2), .in3( out3_2_2),
         .out1(out1_2_3), .out2(out2_2_3), .out3(out3_2_3)  );

m m_3_1( .in1( out1_2_1), .in2(   ?    ), .in3(   ?    ).
         .out1(out1_3_1), .out2(out2_3_1), .out3(out3_3_1) );
m m_3_2( .in1( out1_2_2), .in2( out2_3_1), .in3( out3_3_1),
         .out1(out1_3_2), .out2(out2_3_2), .out3(out3_3_2) );
m m_3_3( .in1( out1_2_3), .in2( out2_3_2), .in3( out3_3_2),
         .out1(out1_3_3), .out2(out2_3_3), .out3(out3_3_3) );

The x y numbers encoded into the wires can become index for an array, which can be used with generate statements, the main issue to overcome is connecting the primary inputs marked above with ?

Filling in these gaps with to match the pattern we end up with a few index '0', hence why I started at 1 for the first example. The then adds :

//Inputs to system:
wire out1_0_1, out1_0_2, out1_0_3;
wire out2_1_0, out3_1_0;
wire out2_2_0, out3_2_0;
wire out2_3_0, out3_3_0;

//First column  
m m_1_1( .in1( out1_0_1), .in2( out2_1_0), .in3( out3_1_0),   
         .out1(out1_1_1), .out2(out2_1_1), .out3(out3_1_1)  );
m m_1_2( .in1( out1_0_2), .in2( out2_1_1), .in3( out3_1_1),
         .out1(out1_1_2), .out2(out2_1_2), .out3(out3_1_2)  ); //in2/3 driven from 0_0 (Above)
m m_1_3( .in1( out1_0_3), .in2( out2_1_2), .in3( out3_1_2),
         .out1(out1_1_3), .out2(out2_1_3), .out3(out3_1_3)  ); //in2/3 driven from 0_1 (above)

//Second Vertical column, in1's driven from previous column.
m m_2_1( .in1( out1_1_1), .in2( out2_2_0), .in3( out3_2_0),
         .out1(out1_2_1), .out2(out2_2_1), .out3(out3_2_1)  ); 
m m_2_2( .in1( out1_1_2), .in2( out2_2_1), .in3( out3_2_1),
         .out1(out1_2_2), .out2(out2_2_2), .out3(out3_2_2)  );
m m_2_3( .in1( out1_1_3), .in2( out2_2_2), .in3( out3_2_2),
         .out1(out1_2_3), .out2(out2_2_3), .out3(out3_2_3)  );

m m_3_1( .in1( out1_2_1), .in2( out2_3_0), .in3( out3_3_0).
         .out1(out1_3_1), .out2(out2_3_1), .out3(out3_3_1) );
m m_3_2( .in1( out1_2_2), .in2( out2_3_1), .in3( out3_3_1),
         .out1(out1_3_2), .out2(out2_3_2), .out3(out3_3_2) );
m m_3_3( .in1( out1_2_3), .in2( out2_3_2), .in3( out3_3_2),
         .out1(out1_3_3), .out2(out2_3_3), .out3(out3_3_3) );

Now vectorising the wires for use in a generate we end up with:

wire out1[0:3][1:3];
wire out2[1:3][0:3];
wire out3[1:3][0:3];

//First column  
m m_1_1( .in1( out1[0][1]), .in2( out2[1][0]), .in3( out3[1][0]),   
         .out1(out1[1][1]), .out2(out2[1][1]), .out3(out3[1][1])  );
m m_1_2( .in1( out1[0][2]), .in2( out2[1][1]), .in3( out3[1][1]),
         .out1(out1[1][2]), .out2(out2[1][2]), .out3(out3[1][2])  ); //in2/3 driven from 0_0 (Above)
m m_1_3( .in1( out1[0][3]), .in2( out2[1][2]), .in3( out3[1][2]),
         .out1(out1[1][3]), .out2(out2[1][3]), .out3(out3[1][3])  ); //in2/3 driven from 0_1 (above)

//Second Vertical column, in1's driven from previous column.
m m_2_1( .in1( out1[1][1]), .in2( out2[2][0]), .in3( out3[2][0]),
         .out1(out1[2][1]), .out2(out2[2][1]), .out3(out3[2][1])  ); 
m m_2_2( .in1( out1[1][2]), .in2( out2[2][1]), .in3( out3[2][1]),
         .out1(out1[2][2]), .out2(out2[2][2]), .out3(out3[2][2])  );
m m_2_3( .in1( out1[1][3]), .in2( out2[2][2]), .in3( out3[2][2]),
         .out1(out1[2][3]), .out2(out2[2][3]), .out3(out3[2][3])  );

m m_3_1( .in1( out1[2][1]), .in2( out2[3][0]), .in3( out3[3][0]).
         .out1(out1[3][1]), .out2(out2[3][1]), .out3(out3[3][1]) );
m m_3_2( .in1( out1[2][2]), .in2( out2[3][1]), .in3( out3[3][1]),
         .out1(out1[3][2]), .out2(out2[3][2]), .out3(out3[3][2]) );
m m_3_3( .in1( out1[2][3]), .in2( out2[3][2]), .in3( out3[3][2]),
         .out1(out1[3][3]), .out2(out2[3][3]), .out3(out3[3][3]) );

Now just need to spot the pattern and equations for the indices.

m m_x_y( .in1( out1[x-1][y]), .in2( out2[x][y-1]), .in3( out3[x][y-1]),   
         .out1(out1[x  ][y]), .out2(out2[x][y  ]), .out3(out3[x][y  ])  );

TL;DR

Wrapped up in generates this becomes :

//Inputs to system:
//out1[0][1], out1[0][2], out1[0][3]
//out2[1][0], out3[1][0]
//out2[2][0], out3[2][0]
//out2[3][0], out3[3][0]

parameter WIDTH = 3; 
parameter DEPTH = 3;

wire out1[0:WIDTH][1:DEPTH];
wire out2[1:WIDTH][0:DEPTH];
wire out3[1:WIDTH][0:DEPTH];

genvar x;
genvar y;
generate 
  for(y=1; y<=DEPTH; y++) begin
    for (x=1; x<=WIDTH; x++) begin
      m m_x_y( .in1( out1[x-1][y]), .in2( out2[x][y-1]), .in3( out3[x][y-1]),   
               .out1(out1[x  ][y]), .out2(out2[x][y  ]), .out3(out3[x][y  ])  );
    end
  end
endgenerate

Inputs

The inputs could be connected via assigns:

module xor (
  input in1,
  input in2,
  //...
);

parameter WIDTH = 3; 
parameter DEPTH = 3;

wire out1[0:WIDTH][1:DEPTH];
wire out2[1:WIDTH][0:DEPTH];
wire out3[1:WIDTH][0:DEPTH];

assign out1[0][1] = in1;
assign out1[0][2] = in2;
// etc

Upvotes: 3

Related Questions