SparkyNZ
SparkyNZ

Reputation: 6676

How to define multiple modules sharing same data bus in SystemVerilog

I'm trying to understand how pins should be defined in SystemVerilog.

I have:

The ioData pins in the ramController are bi-directional but also need to be tri-state so that the ramController can be "off the bus" when dataBus is being used to send commands to the vgaController

module RAMController(
    inout wire[15 : 0 ] ioData,
    ..
);
..
    logic [15 : 0 ] ioDataCopy;
    assign ioData = ( chipSelect ) ? ioDataCopy : 16'hzzzzzzzzzzzzzzzz;

Even if vgaController never writes to the dataBus, does it's pins need to be inout in order to be input or HiZ?

module VGAController(
    inout  wire  [15 : 0 ] iData;
);
..
logic [15 : 0 ] iDataCopy    = 0;
assign iData = ( chipSelect ) ? iDataCopy : 16'bzzzzzzzzzzzzzzzz;

Is dataBus simply a set of wire values in the top module?

module Top(
..
);
..
wire   [15 : 0 ] dataBus;

I may be going about this completely wrong. Can someone please help me in defining a system containing multiple modules that share the same bus.

Upvotes: 3

Views: 1380

Answers (1)

Serge
Serge

Reputation: 12344

It is difficult to say if you did it right or wrong without a reproducible example. However, some of your assertions are basically correct. I assume that your dataBus is same as your ioData at the controller level. In this case if both controllers are instantiated in 'top' and are connected correctly, you should be all set. You have to make sure that there is always only a single driver for the bus, so that 'chipSelect' prevents from multiple driving of the bus.

So, here is an example that demonstrates the above.

module Top();
  wire   [15 : 0 ] dataBus;
  logic[1:0] select;
  
  RAMController rc(.ioData(dataBus), .chipSelect(select == 1 ? 1 : 0));
  VGAController vc(.ioData(dataBus), .chipSelect(select == 2 ? 1 : 0));
  
  always @*
    $display("%0t select: %b, data: %b", $time, select, dataBus);
  
  initial begin
    select = 0;
    #1 select = 1;
    #1 select = 0;
    #1 select = 2;
    #1 select = 0;
    #1 $finish;
  end
  
endmodule

module RAMController(
    inout wire[15 : 0 ] ioData,
    input logic chipSelect 
    //...
);
  logic [15 : 0 ] ioDataCopy = 1;
  assign ioData = ( chipSelect ) ? ioDataCopy : 'z;
endmodule

module VGAController(
    inout wire[15 : 0 ] ioData,
    input logic chipSelect 
    //...
);
  logic [15 : 0 ] ioDataCopy = 2;
  assign ioData = ( chipSelect ) ? ioDataCopy : 'z;
endmodule

and the result:

0 select: 00, data: xxxxxxxxxxxxxxxx
0 select: 00, data: zzzzzzzzzzzzzzzz
1 select: 01, data: zzzzzzzzzzzzzzzz
1 select: 01, data: 0000000000000001
2 select: 00, data: 0000000000000001
2 select: 00, data: zzzzzzzzzzzzzzzz
3 select: 10, data: zzzzzzzzzzzzzzzz
3 select: 10, data: 0000000000000010
4 select: 00, data: 0000000000000010
4 select: 00, data: zzzzzzzzzzzzzzzz

To be more verbose you could use tri definition instead of wire. There is no difference between them, but makes the code more readable, IMHO.

tri [15:0] dataBus;
...
tri [15:0] ioData;

Upvotes: 2

Related Questions