2017-08-10 44 views
1

我試圖實現I²C從機與寫入和讀取操作(8位數據),並在我的代碼寫入部分工作正常,並在讀取端的數據需要被閱讀不正確,我的意思是它的全部「11111111」的。i2c從機寫入和從內存位置讀取vhdl

在閱讀部分它獲取從地址,然後,而不是寫我需要從中讀取的寄存器號碼,它顯示所有「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; 

I²C寫:
I2C write
(點擊放大)

I²C閱讀:
I2C Read
(點擊放大)

回答

0

護理,以顯示你的測試平臺?

SDA線路連接出現問題。如果這個內核不如您的設計,您應該使用不同的SDA_IN和SDA_OUT信號,並將它們複用到頂層的單向雙向線路中。如果這個文件本身是頂層的,那麼當傳輸處於非活動狀態時,應該將SDA設置爲'Z',而不是'0',以便在該時間內使該引腳輸入。

至於註冊連接,有多種方式可以這樣做。例如,您可以製作i2c控制的狀態機,並將第一個操作碼用作寄存器編號,將第二個操作碼用作讀取和寫入的數據。

而你使用data_clk無緩衝信號作爲時鐘。這被認爲是FPGA的一個不好的做法。您應該使用單個高速時鐘來提供所有寄存器/進程,並使用啓用信號以較低的速度執行。或者將data_clk作爲時鐘饋入,但首先通過全局時鐘緩衝區路由。