Vivado中非顶层模块双向INOUT信号无法正常转发问题咨询
本人近期开展双向数据传输相关工作,编写了如下简单Verilog模块:
module my_main_module( input sys_clock, inout [7:0] data_io ); reg data_dir = 0; // 0: input, 1: output reg [7:0] data_reg; assign data_io = (data_dir) ? data_reg : 8'bz; reg [1:0] state = 0; always @(posedge sys_clock) begin case(state) 0: begin // read data state <= 1; data_reg <= data_io + 1; end 1: begin // bus turnaround state <= 2; end 2: begin // write result state <= 3; data_dir <= 1; // set output end 3: begin // bus turnaround state <= 0; data_dir <= 0; // tri-state, ready for next input end endcase end endmodule
该模块在一个时钟周期内接收输入,经过总线周转后返回加1处理的结果。当将其作为顶层模块时,功能正常,综合结果符合预期;但使用Block Design编辑器时,双向INOUT引脚无法正确转发,三态标志未被传递,且所有数据引脚均出现HPDR #1警告:
HPDR #1 Warning Hierarchical port(pin) data_io[0] direction INOUT is not consistent with the directions of the cell pins/ports found at that level of the netlist hierarchy. Please review the design and consider changing the port(pin) direction. Both drivers and loads were expected for the net (data_io[0]) connected to this Port, but both were not found.
经查询得知Utility Buffer IP可提供显式IOBUF实现并能正常工作,请问为何该IP可正常工作而我的模块不行?
问题原因分析
Block Design层次化综合的规则限制:当模块作为Block Design的子模块时,工具会对层次化端口做更严格的属性检查。你用
assign条件赋值实现的隐式三态逻辑,在层次化分析阶段,工具可能无法实时识别出该端口同时具备输入和输出能力——它只会看到某一时刻端口要么是驱动状态要么是高阻状态,无法确认其同时存在驱动和负载属性,从而触发HPDR警告。IOBUF是FPGA专用硬宏单元:Utility Buffer IP本质是封装了FPGA底层的IOBUF(输入输出缓冲器)硬宏。这种硬宏是厂商专门为双向IO设计的物理单元,有明确的输入、输出、方向控制引脚,Block Design工具可以直接识别其标准双向属性,不会做层次化端口方向的误判。而你的代码是行为级描述的三态逻辑,工具需要将其映射到IOBUF,但在Block Design的层次化流程中,这个映射过程可能被提前的端口检查打断,导致无法生成正确的硬件结构。
顶层与子模块的综合逻辑差异:当模块作为顶层时,工具直接将
data_io映射到FPGA的IO引脚,会自动推断出需要IOBUF来实现双向功能;但作为Block Design子模块时,工具会先分析模块内部的端口驱动情况,由于代码没有显式调用IOBUF,工具无法确定这个inout端口是要连接外部IO引脚,还是仅作为内部双向总线,因此无法正确处理三态逻辑的传递。
内容的提问来源于stack exchange,提问作者0BLU

