我正在尝试使用写入和读取操作(8位数据)实现I²C从器件,并且在我的代码写入部分工作正常,在读取端需要读取的数据不正确,我的意思是它所有“11111111”的。
在读取部分中,它获取从属地址,然后在此之后,而不是写入我需要读取的寄存器号,它显示所有“11111111”。我需要帮助。写入和读取都应该发生在256个寄存器位置。如何在寄存器上写入和读取数据?
在我的代码中,我只是尝试实现一些寄存器,而不是使用全部256个,我只使用了10个寄存器。我需要一些建议。
我正在使用Artix-7 Digilent Basys 3板和Vivado 2016.4。这是我的代码和模拟结果。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity I2C is
Port (clk : in std_logic;
rst : in std_logic;
ena : in std_logic;
rw : in std_logic;
state_cnt : out std_logic_vector(3 downto 0);
data_read : out std_logic_vector(7 downto 0);
sda : inout std_logic;
scl : out std_logic );
end I2C;
architecture Behavioral of I2C is
type machine is (ready,start,slave_addr,slv_ack1,reg_num,act_data,read_data,slv_ack2,mas_ack,stop,slv_ack3);
signal pre_state,next_state : machine;
signal data_clk : std_logic;
signal scl_clk : std_logic;
signal scl_ena : std_logic := '0';
signal sda_int : std_logic := '1';
signal sda_ena : std_logic;
signal addr_rw : std_logic_vector(7 downto 0);
signal data_tx : std_logic_vector(7 downto 0);
signal data_rx : std_logic_vector(7 downto 0);
signal bit_count : integer range 0 to 7 := 7;
signal addr : std_logic_vector(6 downto 0) := "1010000";
signal data_wr : std_logic_vector(7 downto 0) := "01010110";--"11110000";
--signal data_rd : std_logic_vector(7 downto 0) := "01010110";
signal wr_addr : std_logic_vector(7 downto 0) := "00000001";
signal count : integer range 0 to 250;
type slv_array is array (0 to 9) of std_logic_vector (7 downto 0);
signal reg_array : slv_array;
begin
reg_array(0) <= "00000000";
reg_array(1) <= "00000001";
reg_array(2) <= "00000010";
reg_array(3) <= "00000011";
reg_array(4) <= "00000100";
reg_array(5) <= "00000101";
reg_array(6) <= "00000110";
reg_array(7) <= "00000111";
reg_array(8) <= "00001000";
reg_array(9) <= "00001001";
process (clk, rst)
begin
if (rst = '1') then
count <= 0;
elsif (rising_edge(clk))then
if (count = 249) then
-- temp <= not temp;
count <= 0;
else
count <= count + 1;
end if;
end if;
end process;
--scl_clk <= temp;
process (clk,rst,count)
begin
if (rst = '1') then
scl_clk <= '0';
data_clk <= '0';
elsif (rising_edge(clk)) then
case count is
when 0 to 62 =>
scl_clk <= '0';
data_clk <= '0';
when 63 to 124 =>
scl_clk <= '0';
data_clk <= '1';
when 125 to 187 =>
scl_clk <= '1';
data_clk <= '1';
when 188 to 249 =>
scl_clk <= '1';
data_clk <= '0';
when others => null;
end case;
end if;
end process;
process (clk,rst)
begin
if (rst = '1') then
pre_state <= ready;
elsif (rising_edge(clk))then
pre_state <= next_state;
end if;
end process;
process(data_clk,rst)
begin
if (rst = '1') then
next_state <= ready;
scl_ena <= '0';
sda_int <= '1';
bit_count <= 7;
data_read <= "00000000";
state_cnt <= "1111";
elsif (rising_edge(data_clk)) then
case pre_state is
when ready =>
state_cnt <= "0001";
if (ena ='1') then
addr_rw <= addr & rw;
data_tx <= wr_addr;
next_state <= start;
else
next_state <= ready;
end if;
when start =>
state_cnt <= "0010";
scl_ena <= '1';
sda_int <= addr_rw(bit_count);
next_state <= slave_addr;
when slave_addr =>
state_cnt <= "0011";
if (bit_count = 0) then
sda_int <= '1';
bit_count <= 7;
next_state <= slv_ack1;
else
bit_count <= bit_count - 1;
sda_int <= addr_rw(bit_count -1);
next_state <= slave_addr;
end if;
when slv_ack1 =>
state_cnt <= "0100";
if (addr_rw(0) = '0') then
sda_int <= data_tx(bit_count);
next_state <= reg_num;
else
sda_int <= '1';
next_state <= read_data;
end if;
when reg_num =>
state_cnt <= "0101";
if (bit_count = 0) then
sda_int <= '1';
bit_count <= 7;
next_state <= slv_ack2;
else
bit_count <= bit_count - 1;
sda_int <= data_tx(bit_count -1);
next_state <= reg_num;
end if;
when slv_ack2 =>
state_cnt <= "0110";
if (ena ='1') then
data_tx <= data_wr;
sda_int <= data_wr(bit_count);
next_state <= act_data;
else
scl_ena <= '0';
next_state <= stop;
end if;
when act_data =>
state_cnt <= "0111";
if (bit_count =0) then
sda_int <= '1';
bit_count <= 7;
next_state <= slv_ack3;
else
bit_count <= bit_count - 1;
sda_int <= data_tx(bit_count-1);
next_state <= act_data;
end if;
when slv_ack3 =>
state_cnt <= "1000";
scl_ena <= '0';
next_state <= stop;
when stop =>
state_cnt <= "1001";
if (rw = '1') then
next_state <= ready;
else
next_state <= stop;
end if;
when read_data =>
state_cnt <= "1010";
if (bit_count = 0) then
if (ena ='1' and rw ='1') then
sda_int <= '0';
else
sda_int <= '1';
end if;
data_read(0) <= sda;
data_read(7 downto 1) <= data_rx(7 downto 1);
bit_count <= 7;
next_state <= stop;
else
data_rx(bit_count) <= sda;
bit_count <= bit_count - 1;
next_state <= read_data;
end if;
when mas_ack =>
state_cnt <= "1011";
if (ena = '1') then
addr_rw <= addr & rw;
data_tx <= data_wr;
if (rw = '0') then
next_state <= start;
else
sda_int <= '1';
next_state <= read_data;
end if;
else
scl_ena <='0';
next_state <= stop;
end if;
when others => null;
end case;
end if;
end process;
WITH pre_state select
sda_ena <= data_clk when start,
not data_clk when stop,
sda_int when others;
scl <= scl_clk;
sda <= '0' when sda_ena = '0' else sda_ena;
end Behavioral;
答案 0 :(得分:0)
小心展示你的测试平台?
您遇到SDA线路连接问题。如果这个内核不如你的设计,你应该使用差分SDA_IN和SDA_OUT信号,并将它们复用到顶层的单个双向线。如果此文件本身是顶层文件,则应将SDA设置为&#39; Z&#39;而不是设置为&#39; 0&#39;当传输无效时,在此期间输入该引脚。
对于寄存器连接,有多种方法可以实现。例如,您可以创建i2c控制的状态机,并使用第一个操作码作为寄存器编号,第二个作为读取和写入的数据。
您正在使用data_clk无缓冲信号作为时钟。这被认为是FPGA的不良做法。您应该使用单个高速时钟为所有寄存器/进程提供信号,并使用启用信号以较低的速度执行。或者将data_clk作为时钟提供,但首先通过全局时钟缓冲器进行路由。