英文:
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 := '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
-- Reset CLK_count and turn IOBUF into output mode
s_CLK_count <= 0;
s_N_enable_output <= '0'; -- 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 <= '1'; -- set IOBUF to input mode
end if;
-- on all falling clk edges increment the CLK_count if active
if i_CS = '0' then
s_CLK_count <= s_CLK_count + 1;
end if;
if i_CS = '1' then
-- use the falling clk edges to reset the system if inactive, i.e., CS == 1
s_N_enable_output <= '1'; -- 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 => 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;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论