所以我听说无法通过双向数据端口而不知道协议(或没有控制线)。 (见tie two inout together vhdl)
但是,我真的很喜欢这样做,我真的不想知道协议。 SO ...
我想从SIM智能卡(从手机)传递DATA线。目前一切都有效,除了DATA线,这是双向的。
我还没有确认这一点,但我的范围暗示该线被拉高,任何一方都可以根据需要将其拉下来。我想利用从外部拉高的线路。
我想尝试以下注释代码中列出的两个选项:
architecture Behavioral of SIM_Select_Test_A is
begin
process(MOD_CLK, MOD_RST)
begin
SIM_RST <= MOD_RST;
SIM_CLK <= MOD_CLK;
end process;
-- OPTION ONE1
-- process(MOD_CLK, MOD_DATA, SIM_DATA)
-- begin
-- IF MOD_DATA = '0' THEN
-- SIM_DATA <= '0';
-- ELSE
-- IF SIM_DATA = '0' THEN
-- MOD_DATA <= '0';
-- ELSE
-- MOD_DATA <= MOD_DATA;
-- SIM_DATA <= SIM_DATA;
-- END IF;
-- END IF;
-- end process;
-- OPTION 2
-- process(MOD_CLK, MOD_DATA, SIM_DATA)
-- begin
-- IF MOD_DATA = '0' THEN
-- SIM_DATA <= '0';
-- ELSE
-- IF SIM_DATA = '0' THEN
-- MOD_DATA <= '0';
-- ELSE
-- MOD_DATA <= 'Z';
-- SIM_DATA <= 'Z';
-- END IF;
-- END IF;
-- end process;
end Behavioral;
有人可以确认,如果我将SIM_DATA驱动为低电平,我将不会进入第二个ELSE,因此将MOD_DATA驱动为低电平(即进入某个循环逻辑)
如果我应该追求这条道路,或者我绝对需要知道协议的任何评论。如果是这样,我想我会开始研究:(
提前致谢, 库尔特
编辑: 添加我的实体声明:
entity SIM_Select_Test_A is
Port ( SIM_VCC : OUT STD_LOGIC;
SIM_DATA : inout STD_LOGIC;
SIM_RST : out STD_LOGIC;
SIM_CLK : out STD_LOGIC;
MOD_VCC : in STD_LOGIC;
MOD_DATA : inout STD_LOGIC;
MOD_RST : in STD_LOGIC;
MOD_CLK : in STD_LOGIC);
attribute bufg : string;
attribute bufg of MOD_CLK : signal is "CLK";
attribute bufg of MOD_DATA : signal is "OE";
end SIM_Select_Test_A;
编辑2: 哇,谢谢你的详细回复。 是的,我可以看到你在说什么。我想我希望的是,我可以在代码中添加一些智能,以便在CPLD控制线路和优先考虑wire1时意识到这一点。所以你的评论让我正式化了我的想法,这就是我得到的。为伪代码道歉,但我希望它能使事情变得更清晰,当我把它编入脑中时,它总能很好地工作:)
IF (wire1 = '0' AND flag = '0') THEN
wire2 <= '0' <--here wire1 gets priority and wire2 is controlled based on wire1. My hope is that when it is at this point in the code then it does NOT fall into the else statement.
ELSE <-- IF (wire1 is NOT low OR there is a flag) THEN check if wire2 is low (which in my head seems slightly different than elsif
IF (wire2 = '0') THEN
wire1 <= '0';
flag <= '1'; <-- I think this is where there might be a problem. I am trying to use the flag to tell the outer IF that the CPLD holding wire1 low and to ignore it
ELSE <--neither are being held low externally
wire1 <= 'HIZ';
wire2 <= 'HIZ';
flag <= '0';
END IF
END IF;
我会看看今天是否可以模拟,但感谢您的任何评论。
答案 0 :(得分:0)
编辑此答案仅适用于,如果无法对截获的总线上的数据传输做出任何假设。请查看my other answer。
即使使用由电阻器上拉的漏极开路/集电极开路总线也无法做到这一点。实际上,电阻器可以集成到一个IC中,但它们总是放在焊盘和I / O驱动器之间,因此也可以放在总线上。
拦截看起来像这样:IC1 <--wire1--> FPGA <--wire2--> IC2
。
让我们假设在启动后截获的总线空闲,然后电阻将两条线拉高。如果IC1拉低wire1
,则FPGA也会下拉wire2
。但现在,FPGA还会读取wire2
被拉下来,因此也会降低wire1
。现在,两条线都被FPGA下拉。即使IC1禁用其输出驱动程序,也会保留此状态。
如果您不相信,请尝试使用此VHDL代码。
library ieee;
use ieee.std_logic_1164.all;
entity intercept_open_drain_bus is
port (
wire1 : inout std_logic;
wire2 : inout std_logic);
end entity intercept_open_drain_bus;
architecture rtl of intercept_open_drain_bus is
begin
-- Assume port is pulled-up externally.
wire1 <= '0' when wire2 = '0' else 'Z';
wire2 <= '0' when wire1 = '0' else 'Z';
end architecture rtl;
以下是运行上述场景的测试平台:
library ieee;
use ieee.std_logic_1164.all;
entity intercept_open_drain_bus_tb is
end entity intercept_open_drain_bus_tb;
architecture sim of intercept_open_drain_bus_tb is
signal wire1 : std_logic;
signal wire2 : std_logic;
begin
DUT: entity work.intercept_open_drain_bus
port map (
wire1 => wire1,
wire2 => wire2);
-- external PULLUP resistor
wire1 <= 'H';
wire2 <= 'H';
WaveGen_Proc: process
begin
-- both far-end ICs have their outputs disabled
wire1 <= 'Z';
wire2 <= 'Z';
wait for 1 ns;
assert (wire1 = 'H') and (wire2 = 'H') report "initial pullup failed." severity error;
-- IC 1 pulls down wire 1
wire1 <= '0';
wait for 1 ns;
assert (wire2 = '0') report "passing from wire1 failed." severity error;
-- IC 1 disables its output again
wire1 <= 'Z';
wait for 1 ns;
assert (wire1 = 'H') and (wire2 = 'H') report "pullup after transfer failed." severity error;
wait;
end process WaveGen_Proc;
end architecture sim;
这是模拟器输出显示最后一个测试用例失败(在黄色标记的右侧):
答案 1 :(得分:0)
如果可以对截获的双向总线的数据传输做出至少一些假设,则该答案适用。如果不能做出任何假设,那么my other answer仍然是正确的。
拦截看起来像这样:IC1 <--wire1--> FPGA <--wire2--> IC2
。
如果可以做出至少这些假设,那么解决方案是可能的:
总线在数据传输IC1 - > IC2和IC2 - > IC1之间空闲。
FPGA可以由一个时钟(来自外部振荡器)驱动,该时钟至少比总线的信号速率快10倍。
该解决方案需要一个有限状态机,其中状态跟踪哪一侧(IC1或IC2)实际上拉下线。如果一个IC拉下线,FPGA会拉低另一个IC。如果IC释放导线并且导线由电阻器上拉,则FPGA也会释放另一根导线。但是现在,我们必须等到另一根导线被自己的电阻上拉,然后再检查该导线以便向另一个方向传输数据。
以下是代码:
library ieee;
use ieee.std_logic_1164.all;
entity intercept_open_drain_bus2 is
port (
clock : in std_logic;
wire1 : inout std_logic;
wire2 : inout std_logic);
end entity intercept_open_drain_bus2;
architecture rtl of intercept_open_drain_bus2 is
type state_t is (IDLE, PULLDOWN1, WAIT1, PULLDOWN2, WAIT2);
signal state : state_t := IDLE;
begin
-- Moore outputs from finite state machine
wire1 <= '0' when state = PULLDOWN1 else 'Z';
wire2 <= '0' when state = PULLDOWN2 else 'Z';
-- finite state machine
process(clock)
begin
if rising_edge(clock) then
case state is
when IDLE =>
if wire2 = '0' then
state <= PULLDOWN1;
elsif wire1 = '0' then
state <= PULLDOWN2;
end if;
when PULLDOWN1 =>
if wire2 /= '0' then -- 'H' or '1'
state <= WAIT1;
end if;
when WAIT1 => -- wait until wire1 is pulled-up by the resistor
if wire1 /= '0' then
state <= IDLE;
end if;
when PULLDOWN2 =>
if wire1 /= '0' then -- 'H' or '1'
state <= WAIT2;
end if;
when WAIT2 => -- wait until wire2 is pulled-up by the resistor
if wire2 /= '0' then
state <= IDLE;
end if;
end case;
end if;
end process;
end architecture rtl;
这是测试平台:
library ieee;
use ieee.std_logic_1164.all;
entity intercept_open_drain_bus2_tb is
end entity intercept_open_drain_bus2_tb;
architecture sim of intercept_open_drain_bus2_tb is
signal clock : std_logic := '1';
signal wire1 : std_logic;
signal wire2 : std_logic;
signal STOPPED : boolean := false;
begin
DUT: entity work.intercept_open_drain_bus2
port map (
clock => clock,
wire1 => wire1,
wire2 => wire2);
-- 100 MHz FPGA clock from external oscillator
clock <= not clock after 5 ns when not STOPPED;
-- external PULLUP resistor
wire1 <= 'H';
wire2 <= 'H';
WaveGen_Proc: process
begin
-- both far-end ICs have their outputs disabled
wire1 <= 'Z';
wire2 <= 'Z';
wait until rising_edge(clock);
assert (wire1 = 'H') and (wire2 = 'H') report "initial pullup failed." severity error;
-- IC 1 pulls down wire 1 for at least 10 FPGA clock cycles
wire1 <= '0';
wait until rising_edge(clock);
-- wire2 is changing here in the real world
for i in 2 to 10 loop
wait until rising_edge(clock);
assert (wire2 = '0') report "passing from wire1 failed." severity error;
end loop;
-- IC 1 disables its output again for at least 10 FPGA clock cycles
wire1 <= 'Z';
wait until rising_edge(clock);
-- wire2 is changing here in the real world
for i in 2 to 10 loop
wait until rising_edge(clock);
assert (wire1 = 'H') and (wire2 = 'H') report "pullup after transfer failed." severity error;
end loop;
-- IC 2 pulls down wire 1 for at least 10 FPGA clock cycles
wire2 <= '0';
wait until rising_edge(clock);
-- wire1 is changing here in the real world
for i in 2 to 10 loop
wait until rising_edge(clock);
assert (wire1 = '0') report "passing from wire2 failed." severity error;
end loop;
-- IC 2 disables its output again for at least 10 FPGA clock cycles
wire2 <= 'Z';
wait until rising_edge(clock);
-- wire1 is changing here in the real world
for i in 2 to 10 loop
wait until rising_edge(clock);
assert (wire2 = 'H') and (wire1 = 'H') report "pullup after transfer failed." severity error;
end loop;
STOPPED <= true;
wait;
end process WaveGen_Proc;
end architecture sim;
现在,模拟器输出看起来不错: