问题描述
我试图了解如何在SystemVerilog中定义引脚。
我有:
- 常见的
dataBus
- 一个
ramController
模块,可以在其ioData
引脚上发送或接收数据。 - 可以写入
ramController
(例如准备显示缓冲区)的顶级模块 - 一个
vgaController
,主要从ramController
接收数据,但也具有命令模式,该模式允许使用dataBus
上的数据对其进行配置
ioData
中的ramController
引脚是双向的,但也必须是三态的,以便在ramController
时dataBus
可以“脱离总线”用于向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;