如何在SystemVerilog中定义共享同一数据总线的多个模块

问题描述

我试图了解如何在SystemVerilog中定义引脚。

我有

  • 常见的dataBus
  • 一个ramController模块,可以在其ioData引脚上发送或接收数据。
  • 可以写入ramController(例如准备显示缓冲区)的顶级模块
  • 一个vgaController,主要从ramController接收数据,但也具有命令模式,该模式允许使用dataBus上的数据对其进行配置

ioData中的ramController引脚是双向的,但也必须是三态的,以便在ramControllerdataBus可以“脱离总线”用于向vgaController

发送命令
module RAMController(
    inout wire[15 : 0 ] ioData,..
);
..
    logic [15 : 0 ] ioDatacopy;
    assign ioData = ( chipSelect ) ? ioDatacopy : 16'hzzzzzzzzzzzzzzzz;

即使vgaController从未写入dataBus,它的引脚是否也需要inout才能被输入或HiZ?

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

dataBus仅仅是顶部模块中的一组导线值吗?

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

我可能会完全不对。有人可以帮我定义一个包含多个共享同一总线的模块的系统。

解决方法

如果没有可复制的示例,很难说您是对是错。但是,您的某些断言基本上是正确的。我假设您的dataBus与控制器级别的ioData相同。在这种情况下,如果两个控制器都在“ top”中实例化并正确连接,则应该全部设置好。您必须确保总线始终只有一个驱动程序,这样'chipSelect'可以阻止总线的多次驱动。

因此,这是一个演示上述内容的示例。

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

和结果:

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

更详细地说,您可以使用tri定义而不是wire。它们之间没有什么区别,但是使代码更具可读性,恕我直言。

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