输出 IOBUF 上的多个驱动网。

huangapple go评论93阅读模式
英文:

Multiple Driver Nets on output of IOBUF

问题

我编写了以下模块,它将充当标准4线SPI和AD9637 ADC的3线SPI之间的开关。

因此,我实例化了一个IOBUF,在第16个时钟周期之后,计算时钟边缘的数量,并将IOBUF从输出切换到输入,ADC开始在共享线上输出数据的地方。

然而,我在尝试在Vivado 2019.1中实现设计时遇到了“多个驱动器网络”错误,我无法理解为什么会发生这种情况,因为在我的描述中,受影响的信号io_SDIO只受到实例化的IOBUF的IO引脚的驱动。

完整的错误如下:

[DRC MDRV-1] 多个驱动器网络:网络zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO有多个驱动器:zsys_i/SPI_3wire_adapter_AD_0/U0/IOBUF_inst/IBUF/O和zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO_reg/Q。

完整的设计如下:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

entity SPI_3wire_adapter_AD9637 is
    port (
        o_count : out std_logic_vector(4 downto 0);
        o_enable : out std_logic;
    
        i_SCLK :    in STD_LOGIC;           --PS side clock on which the module operates syncronously
        i_MOSI :    in STD_LOGIC;           --MOSI PS side (input)
        o_MISO :    out STD_LOGIC;          --MISO PS side (output)
        i_CS :      in STD_LOGIC;           --CS PS side (input)
    
        o_SCLK :    out std_logic;          --SPI clock (output)
        o_CS :      out std_logic;          --SPI CS (output)
        io_SDIO :   inout STD_LOGIC         --SPI SDIO - shared MOSI/MISO for 3-wire SPI (output/input)
    );
end SPI_3wire_adapter_AD9637;

architecture behavioral of SPI_3wire_adapter_AD9637 is

    signal s_CLK_count: integer range 0 to 23 := 0;
    signal s_N_enable_output : STD_LOGIC := '0';

begin

IOBUF_inst : IOBUF
generic map (
   DRIVE => 12,
   IOSTANDARD => "DEFAULT",
   SLEW => "SLOW")
port map (
   O => o_MISO,             -- Buffer output
   IO => io_SDIO,           -- Buffer inout port (connect directly to top-level port)
   I => i_MOSI,             -- Buffer input
   T => s_N_enable_output   -- 3-state enable input, high=input, low=output
);

o_CS <= i_CS;
o_SCLK <= i_SCLK;

o_count <= std_logic_vector(to_unsigned(s_CLK_count, 5));
o_enable <= s_N_enable_output;

    process(i_SCLK, i_CS)
    begin
        if falling_edge(i_CS) then
            -- 重置CLK_count并将IOBUF切换到输出模式
            s_CLK_count <= 0;
            s_N_enable_output <= '0'; -- 将IOBUF设置为输出模式
        end if;
        
        if falling_edge(i_SCLK) then
            if s_CLK_count = 16 then
                -- 在第16个时钟边沿上切换到输入模式
                s_N_enable_output <= '1'; -- 将IOBUF设置为输入模式
            end if;
            
            -- 在所有下降的时钟边沿上,如果处于活动状态,则增加CLK_count
            if i_CS = '0' then
                s_CLK_count <= s_CLK_count + 1;
            end if;
            
            if i_CS = '1' then
                -- 使用下降的时钟边沿重置系统,如果处于非活动状态,即CS == 1
                s_N_enable_output <= '1'; -- 将IOBUF设置为输入模式
            end if;
        end if;
        
    end process;

end behavioral;

我对设计的方法是创建一个信号s_N_enable_output,表示IOBUF的期望输入/输出模式,并仅使用这个信号驱动IOBUF的T引脚。通过仅将共享数据线映射到inout端口,而不在进程中直接驱动它,我希望避免出现这种“多个驱动器网络”的错误。

编辑:我忽略了o_MISO引脚上的另一个“多个驱动器网络”错误:

[DRC MDRV-1] 多个驱动器网络:网络zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO有多个驱动器:zsys_i/SPI_3wire_adapter_AD_0/U0/IOBUF_inst/IBUF/O和zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO_reg/Q。
英文:

I wrote the following module which shall act as a switch between a standard 4-wire SPI and the 3-wire SPI of an AD9637 ADC.
Therefore I instantiated an IOBUF, count clock edges and switch the IOBUF from output to input after the 16th clock cycle, where the ADC starts to put out data on the shared line.
However, I get e Multiple Driver Nets error, trying to implement the design in Vivado 2019.1 and I cannot wrap my head around why this happens, as in my description, the affected signal io_SDIO is only driven by the IO pin of the instantiated IOBUF.
The full error is

[DRC MDRV-1] Multiple Driver Nets: Net zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO has multiple drivers: zsys_i/SPI_3wire_adapter_AD_0/U0/IOBUF_inst/IBUF/O, and zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO_reg/Q.

The full design is

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity SPI_3wire_adapter_AD9637 is
port (
o_count : out std_logic_vector(4 downto 0);
o_enable : out std_logic;
i_SCLK :    in STD_LOGIC;           --PS side clock on which the module operates syncronously
i_MOSI :    in STD_LOGIC;           --MOSI PS side (input)
o_MISO :    out STD_LOGIC;          --MISO PS side (output)
i_CS :      in STD_LOGIC;           --CS PS side (input)
o_SCLK :    out STD_LOGIC;          --SPI clock (output)
o_CS :      out STD_LOGIC;          --SPI CS (output)
io_SDIO :   inout STD_LOGIC         --SPI SDIO - shared MOSI/MISO for 3-wire SPI (output/input)
);
end SPI_3wire_adapter_AD9637;
architecture behavioral of SPI_3wire_adapter_AD9637 is
signal s_CLK_count: integer range 0 to 23 := 0;
signal s_N_enable_output : STD_LOGIC := &#39;0&#39;;
begin
IOBUF_inst : IOBUF
generic map (
DRIVE =&gt; 12,
IOSTANDARD =&gt; &quot;DEFAULT&quot;,
SLEW =&gt; &quot;SLOW&quot;)
port map (
O =&gt; o_MISO,             -- Buffer output
IO =&gt; io_SDIO,           -- Buffer inout port (connect directly to top-level port)
I =&gt; i_MOSI,             -- Buffer input
T =&gt; s_N_enable_output   -- 3-state enable input, high=input, low=output
);
o_CS &lt;= i_CS;
o_SCLK &lt;= i_SCLK;
o_count &lt;= std_logic_vector(to_unsigned(s_CLK_count, 5));
o_enable &lt;= s_N_enable_output;
process(i_SCLK, i_CS)
begin
if falling_edge(i_CS) then
-- Reset CLK_count and turn IOBUF into output mode
s_CLK_count &lt;= 0;
s_N_enable_output &lt;= &#39;0&#39;; -- set IOBUF to output mode
end if;
if falling_edge(i_SCLK) then
if s_CLK_count = 16 then
-- on the 16th clk edge switch to input mode
s_N_enable_output &lt;= &#39;1&#39;; -- set IOBUF to input mode
end if;
-- on all falling clk edges increment the CLK_count if active
if i_CS = &#39;0&#39; then
s_CLK_count &lt;= s_CLK_count + 1;
end if;
if i_CS = &#39;1&#39; then
-- use the falling clk edges to reset the system if inactive, i.e., CS == 1
s_N_enable_output &lt;= &#39;1&#39;; -- set IOBUF to input modde
end if;
end if;
end process;
end behavioral;

My approach to the design was to create a signal s_N_enable_output which represents the desired input/output mode of the IOBUF and drive the T pin of the IOBUF with this signal only. By onyl mapping the shared data line to the inout port and not driving it directly in the process I was hoping to avoid such Multiple Driver Nets errors.

EDIT: I have overlooked that there is another Multiple Driver Nets error on the o_MISO pin:

[DRC MDRV-1] Multiple Driver Nets: Net zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO has multiple drivers: zsys_i/SPI_3wire_adapter_AD_0/U0/IOBUF_inst/IBUF/O, and zsys_i/SPI_3wire_adapter_AD_0/U0/o_MISO_reg/Q.

答案1

得分: 0

我通过引入中间信号 s_CLK_count_greater_15 并在一个进程中处理所有的 "状态变化",使设计适用于综合和实现:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

Library UNISIM;
use UNISIM.vcomponents.all;

entity SPI_3wire_adapter_AD9637 is
    port (
        o_count : out std_logic_vector(4 downto 0);
        o_enable : out std_logic;
    
        i_SCLK :    in STD_LOGIC;           --PS side clock on which the module operates synchronously
        i_MOSI :    in STD_LOGIC;           --MOSI PS side (input)
        o_MISO :    out STD_LOGIC;          --MISO PS side (output)
        i_CS :      in STD_LOGIC;           --CS PS side (input)
    
        o_SCLK :    out STD_LOGIC;          --SPI clock (output)
        o_CS :      out std_logic;          --SPI CS (output)
        io_SDIO :   inout STD_LOGIC         --SPI SDIO - shared MOSI/MISO for 3-wire SPI (output/input)
    );
end SPI_3wire_adapter_AD9637;

architecture behavioral of SPI_3wire_adapter_AD9637 is

    signal s_CLK_count: integer range 0 to 23 := 0;
    signal s_IN_notOUT : STD_LOGIC;
    signal s_CLK_count_greater_15 : STD_LOGIC;

begin

IOBUF_inst : IOBUF
generic map (
   DRIVE => 12,
   IOSTANDARD => "DEFAULT",
   SLEW => "SLOW")
port map (
   O => o_MISO,             -- Buffer output
   IO => io_SDIO,           -- Buffer inout port (connect directly to top-level port)
   I => i_MOSI,             -- Buffer input
   T => s_IN_notOUT         -- 3-state enable input, high=input, low=output
);

o_CS <= i_CS;
o_SCLK <= i_SCLK;

o_count <= std_logic_vector(to_unsigned(s_CLK_count, 5));
s_IN_notOUT <= not i_CS and s_CLK_count_greater_15;
o_enable <= s_IN_notOUT;

process(i_SCLK)
begin
    if falling_edge(i_SCLK) then
        
        if i_CS = '1' then
            s_CLK_count <= 0;          
        else
            s_CLK_count <= s_CLK_count + 1; -- on all falling clk edges increment the CLK_count if CS is low
        end if;
        
        if s_CLK_count > 15 then
            s_CLK_count_greater_15 <= '1';
        else
            s_CLK_count_greater_15 <= '0';
        end if;
        
    end if;
end process;

end behavioral;
英文:

I made the design suitable for synthesis and implementation by introducing an intermidiate signal s_CLK_count_greater_15 and handling all the "state changes" in one process:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
Library UNISIM;
use UNISIM.vcomponents.all;
entity SPI_3wire_adapter_AD9637 is
port (
o_count : out std_logic_vector(4 downto 0);
o_enable : out std_logic;
i_SCLK :    in STD_LOGIC;           --PS side clock on which the module operates syncronously
i_MOSI :    in STD_LOGIC;           --MOSI PS side (input)
o_MISO :    out STD_LOGIC;          --MISO PS side (output)
i_CS :      in STD_LOGIC;           --CS PS side (input)
o_SCLK :    out STD_LOGIC;          --SPI clock (output)
o_CS :      out STD_LOGIC;          --SPI CS (output)
io_SDIO :   inout STD_LOGIC         --SPI SDIO - shared MOSI/MISO for 3-wire SPI (output/input)
);
end SPI_3wire_adapter_AD9637;
architecture behavioral of SPI_3wire_adapter_AD9637 is
signal s_CLK_count: integer range 0 to 23 := 0;
signal s_IN_notOUT : STD_LOGIC;
signal s_CLK_count_greater_15 : STD_LOGIC;
begin
IOBUF_inst : IOBUF
generic map (
DRIVE =&gt; 12,
IOSTANDARD =&gt; &quot;DEFAULT&quot;,
SLEW =&gt; &quot;SLOW&quot;)
port map (
O =&gt; o_MISO,             -- Buffer output
IO =&gt; io_SDIO,           -- Buffer inout port (connect directly to top-level port)
I =&gt; i_MOSI,             -- Buffer input
T =&gt; s_IN_notOUT         -- 3-state enable input, high=input, low=output
);
o_CS &lt;= i_CS;
o_SCLK &lt;= i_SCLK;
o_count &lt;= std_logic_vector(to_unsigned(s_CLK_count, 5));
s_IN_notOUT &lt;= not i_CS and s_CLK_count_greater_15;
o_enable &lt;= s_IN_notOUT;
process(i_SCLK)
begin
if falling_edge(i_SCLK) then
if i_CS = &#39;1&#39; then
s_CLK_count &lt;= 0;          
else
s_CLK_count &lt;= s_CLK_count + 1; -- on all falling clk edges increment the CLK_count if CS is low
end if;
if s_CLK_count &gt; 15 then
s_CLK_count_greater_15 &lt;= &#39;1&#39;;
else
s_CLK_count_greater_15 &lt;= &#39;0&#39;;
end if;
end if;
end process;
end behavioral;

huangapple
  • 本文由 发表于 2023年6月14日 23:55:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76475452.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定