VHDL代码在合成后表现异常(I2C)
首先,由于公司披露协议,我不允许发布我的代码,因此我将描述这种行为的症状,希望这样就足够了 我使用的是由提供的I2C主机IP,我使用的方式与页面上提供的示例相同。区别在于我有几个示例中描述的过程VHDL代码在合成后表现异常(I2C),vhdl,i2c,Vhdl,I2c,首先,由于公司披露协议,我不允许发布我的代码,因此我将描述这种行为的症状,希望这样就足够了 我使用的是由提供的I2C主机IP,我使用的方式与页面上提供的示例相同。区别在于我有几个示例中描述的过程 WHEN get_data => --state for conducting this transaction busy_prev <= i2c_busy; --capture the
WHEN get_data => --state for conducting this transaction
busy_prev <= i2c_busy; --capture the value of the previous i2c busy signal
IF(busy_prev = '0' AND i2c_busy = '1') THEN --i2c busy just went high
busy_cnt := busy_cnt + 1; --counts the times busy has gone from low to high during transaction
END IF;
CASE busy_cnt IS --busy_cnt keeps track of which command we are on
WHEN 0 => --no command latched in yet
i2c_ena <= '1'; --initiate the transaction
i2c_addr <= slave_addr; --set the address of the slave
i2c_rw <= '0'; --command 1 is a write
i2c_data_wr <= data_to_write; --data to be written
WHEN 1 => --1st busy high: command 1 latched, okay to issue command 2
i2c_rw <= '1'; --command 2 is a read (addr stays the same)
WHEN 2 => --2nd busy high: command 2 latched, okay to issue command 3
i2c_rw <= '0'; --command 3 is a write
i2c_data_wr <= new_data_to_write; --data to be written
IF(i2c_busy = '0') THEN --indicates data read in command 2 is ready
data(15 DOWNTO 8) <= i2c_data_rd; --retrieve data from command 2
END IF;
WHEN 3 => --3rd busy high: command 3 latched, okay to issue command 4
i2c_rw <= '1'; --command 4 is read (addr stays the same)
WHEN 4 => --4th busy high: command 4 latched, ready to stop
i2c_ena <= '0'; --deassert enable to stop transaction after command 4
IF(i2c_busy = '0') THEN --indicates data read in command 4 is ready
data(7 DOWNTO 0) <= i2c_data_rd; --retrieve data from command 4
busy_cnt := 0; --reset busy_cnt for next transaction
state <= home; --transaction complete, go to next state in design
END IF;
WHEN OTHERS => NULL;
END CASE;
WHEN get_data=>--执行此事务的状态
busy_prev--尚未锁定任何命令
i2c_ena根据评论,如果发布的代码片段不再是计时过程的一部分,那么它会出现严重问题:
Me:发布的代码仍然是计时过程的一部分吗
mmahdich:@Martin在我的代码中不是这样的,如果您将原来的单进程SM转换为更复杂的2进程SM,那么时钟进程只会更新当前状态,从而提供几种引入失败的方法。仔细检查已注册但不再注册的敏感度列表和输出。“时钟信号路由[奇怪]”警告可能是这种情况的症状-您可以确定其原因。我强烈推荐单进程形式:是什么驱使您重写为2进程?根据警告“时钟信号是使用通用路由资源路由的,可能会出现过度延迟和/或扭曲”,这意味着您生成了一些本地时钟,这些时钟不是有意的,就是您必须通过时钟缓冲区对其进行缓冲。但是,在发布的代码中,这似乎不是一个问题。再次阅读代码后,busy\u cnt
看起来可疑,但需要更多的上下文。@Brian除了习惯和清晰之外,没有特别的理由在两个过程中编写它。我会尝试你的解决方案并回复@Martin我并不是有意生成这些内容的,我怀疑这与这个片段无关。busy\u cnt
仅仅是示例中设计师提供的相同设计(假设他最了解)。发布的代码仍然是计时过程的一部分吗?我明白了,谢谢Martin这实际上是一个很好的解释。我将尝试尽快将解决方案作为一个计时过程来实施。不幸的是,这将需要一段时间,因为我休假到明年。感谢您抽出时间回答。这是一种新的生活方式!我检查了一下,问题似乎是我把过程分成了两部分。当我回到单进程方法时,甚至警告也消失了。非常感谢你的帮助,非常感谢。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_test is
port (
clk : in std_logic;
i2c_busy : in std_logic;
slave_addr : in std_logic;
data_to_write : in std_logic_vector(7 downto 0);
new_data_to_write : in std_logic_vector(7 downto 0);
i2c_data_rd : in std_logic_vector(7 downto 0);
i2c_ena : out std_logic;
i2c_addr : out std_logic;
i2c_rw : out std_logic;
i2c_data_wr : out std_logic_vector(7 downto 0);
data : out std_logic_vector(15 downto 0));
end i2c_test;
architecture rtl of i2c_test is
type state_t is (get_data, home);
signal curr_state : state_t := home;
signal state : state_t; -- next state is named "state" in OP code
signal busy_prev : std_logic;
begin -- rtl
process (clk)
begin -- process
if rising_edge(clk) then
curr_state <= state;
end if;
end process;
process(curr_state, busy_prev, i2c_busy, slave_addr, data_to_write, new_data_to_write, i2c_data_rd)
variable busy_cnt : integer range 0 to 4 := 0;
begin
state <= curr_state; -- next state is named "state" in OP code
i2c_ena <= '0';
i2c_addr <= '-';
i2c_rw <= '-';
i2c_data_wr <= (others => '-');
-- no default assignments for busy_prev and data here, because the usage
-- below indicates that a register was intended
case curr_state is
when home => state <= get_data;
---------------------------------------------------------------
-- Add code from question here
---------------------------------------------------------------
end case;
end process;
end rtl;
busy_prev <= i2c_busy; --capture the value of the previous i2c busy signal
data(15 DOWNTO 8) <= i2c_data_rd; --retrieve data from command 2
data(7 DOWNTO 0) <= i2c_data_rd; --retrieve data from command 4
WHEN get_data => --state for conducting this transaction
IF(busy_prev = '0' AND i2c_busy = '1') THEN --i2c busy just went high
busy_cnt := busy_cnt + 1; --counts the times busy has gone from low to high during transaction
END IF;