I'm trying to understand how pins should be defined in SystemVerilog.
I have:
dataBusramController module which can send or receive data on its ioData pins.ramController (e.g. prepare a display buffer)vgaController which mostly receives data from the ramController but also has a command mode which allows it to be configured using data on the dataBusThe 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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With