I am experiencing an issue while configuring the IIC with AXI-IIC. After I set the RESET pin high, only one 9-bit piece of information is transmitted on the SCL and SDA lines. The last bit of this transmission is a NACK signal. Despite multiple attempts, I am unable to successfully configure the IIC.
Here are the codes and cores I've used:
-- Title : IIC Controller for KC705 clock setup -- Project : cpri_v6_1 ----------------------------------------------------------------------- -- File : iic_controller.vhd -- Author : Xilinx ----------------------------------------------------------------------- -- Description: -- This module generates IIC commands to set up the Si570 and Si5326 -- Clock generation on the KC705 board to provide CPRI GT reference -- clock -- ----------------------------------------------------------------------- -- (c) Copyright 2004 - 2012 Xilinx, Inc. All rights reserved. -- -- This file contains confidential and proprietary information -- of Xilinx, Inc. and is protected under U.S. and -- international copyright and other intellectual property -- laws. -- -- DISCLAIMER -- This disclaimer is not a license and does not grant any -- rights to the materials distributed herewith. Except as -- otherwise provided in a valid license issued to you by -- Xilinx, and to the maximum extent permitted by applicable -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and -- (2) Xilinx shall not be liable (whether in contract or tort, -- including negligence, or under any other theory of -- liability) for any loss or damage of any kind or nature -- related to, arising under or in connection with these -- materials, including for any direct, or any indirect, -- special, incidental, or consequential loss or damage -- (including loss of data, profits, goodwill, or any type of -- loss or damage suffered as a result of any action brought -- by a third party) even if such damage or loss was -- reasonably foreseeable or Xilinx had been advised of the -- possibility of the same. -- -- CRITICAL APPLICATIONS -- Xilinx products are not designed or intended to be fail- -- safe, or for use in any application requiring fail-safe -- performance, such as life-support or safety devices or -- systems, Class III medical devices, nuclear facilities, -- applications related to the deployment of airbags, or any -- other applications that could lead to death, personal -- injury, or severe property or environmental damage -- (individually and collectively, "Critical -- Applications"). Customer assumes the sole risk and -- liability of any use of Xilinx products in Critical -- Applications, subject only to applicable laws and -- regulations governing limitations on product liability. -- -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS -- PART OF THIS FILE AT ALL TIMES. ----------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity iic_controller is port ( reset : in std_logic; clk100 : in std_logic; -- 100 MHz system clock iic_sda : inout std_logic; iic_scl : inout std_logic; done : out std_logic ); end iic_controller; architecture rtl of iic_controller is -- AXI IIC controller component (from EDK) component axi_iic_control port ( S_AXI_ACLK : in std_logic; S_AXI_ARESETN : in std_logic; IIC2INTC_Irpt : out std_logic; S_AXI_AWADDR : in std_logic_vector(31 downto 0); S_AXI_AWVALID : in std_logic; S_AXI_AWREADY : out std_logic; S_AXI_WDATA : in std_logic_vector(31 downto 0); S_AXI_WSTRB : in std_logic_vector(3 downto 0); S_AXI_WVALID : in std_logic; S_AXI_WREADY : out std_logic; S_AXI_BRESP : out std_logic_vector(1 downto 0); S_AXI_BVALID : out std_logic; S_AXI_BREADY : in std_logic; S_AXI_ARADDR : in std_logic_vector(31 downto 0); S_AXI_ARVALID : in std_logic; S_AXI_ARREADY : out std_logic; S_AXI_RDATA : out std_logic_vector(31 downto 0); S_AXI_RRESP : out std_logic_vector(1 downto 0); S_AXI_RVALID : out std_logic; S_AXI_RREADY : in std_logic; tx_fifo_empty : out std_logic; bus_busy : out std_logic; Sda_I : in std_logic; Sda_O : out std_logic; Sda_T : out std_logic; Scl_I : in std_logic; Scl_O : out std_logic; Scl_T : out std_logic; Gpo : out std_logic_vector(0 downto 0) ); end component; ------------------------------------------------------------------------------- -- Command look up table format ------------------------------------------------------------------------------- -- -- The total number of IIC commands is indicated in the first entry. -- Each subsequent entry indicates the AXI IIC core target address and target data. -- -- Refer to AXI IIC core DS756 for addresses and tx_fifo format. -- -- for example, -- - entry 1 writes 0x0001 to address 0x100 -- - entry 2 writes 0x01e8 to address 0x108 -- -- AXI IIC controller registers : -- x0100 - Control Register -- x0108 - Tx FIFO bit 8 = Start, Bit 9 = Stop, 7:0 = Data signal cmd_rom : t_cmd_rom := ( 0 => X"0000_0039", -- Total IIC commands in table -- 1 => X"0100_0001", -- enable AXI IIC core ----------------------------------------------- -- PCA9548 IIC switch Addr = 74 ----------------------------------------------- 2 => X"0108_01e8", -- addr = 74 (shifted up 1 bit - bit 0 = rw) 3 => X"0108_0281", -- channel 7 enabled (Si5324/Si5326) -- channel 0 enabled (Si570) ----------------------------------------------- -- Si5326 Jitter Attenuator Addr = 68 ----------------------------------------------- 4 => X"0108_01d0", -- Register 0 5 => X"0108_0000", -- setup Si5326 for 6 => X"0108_0254", -- free run mode -- Set N1_HS output divider 7 => X"0108_01d0", 8 => X"0108_0019", -- Register 25 9 => X"0108_0280", -- N1_HS = 8 (0b101) -- Transceiver is clocked from CLKOUT1 from Si5324/5326. -- Set the CLKOUT1 divider here. 10 => X"0108_01d0", 11 => X"0108_001f", -- Register 31 12 => X"0108_0200", -- NC1_LS[19:16] = 4 (0x00) 13 => X"0108_01d0", 14 => X"0108_0020", -- Register 32 15 => X"0108_0200", -- NC1_LS[15:8] = 4 (0x00) 16 => X"0108_01d0", 17 => X"0108_0021", -- Register 33 18 => X"0108_0203", -- NC1_LS[7:0] = 4 (0x03) -- Set the PLL divider to 8 * 312 19 => X"0108_01d0", 20 => X"0108_0028", -- Register 40 21 => X"0108_0280", -- N2_HS = 8, N2_LS[19:16] = 336 (0x00) 22 => X"0108_01d0", 23 => X"0108_0029", -- Register 41 24 => X"0108_0201", -- N2_LS[15:8] = 336 (0x51) 25 => X"0108_01d0", 26 => X"0108_002A", -- Register 42 27 => X"0108_024F", -- N2_LS[7:0] = 336 (0x4F) -- The recovered clock from the FPGA to the CLKIN1 input of the Si5324/5326 -- is set at 30.72MHz. Divide this by 1301 to get the correct input -- to the PLL. 28 => X"0108_01d0", 29 => X"0108_002B", -- Register 43 30 => X"0108_0200", -- N31[18:16] = 84 (0x00) 31 => X"0108_01d0", 32 => X"0108_002C", -- Register 44 33 => X"0108_0200", -- N31[15:8] = 84 (0x05) 34 => X"0108_01d0", 35 => X"0108_002D", -- Register 45 36 => X"0108_0253", -- N31[7:0] = 84 (0x14) -- The free running oscillator runs at 114.285MHz. Divide this by -- 4840 to get the correct input to the PLL 37 => X"0108_01d0", 38 => X"0108_002E", -- Register 46 39 => X"0108_0200", -- N32[18:16] = 60 (0x00) 40 => X"0108_01d0", 41 => X"0108_002F", -- Register 47 42 => X"0108_0200", -- N32[18:16] = 60 (0x12) 43 => X"0108_01d0", 44 => X"0108_0030", -- Register 48 45 => X"0108_023B", -- N32[7:0] = 60 (0xE7) -- Set the auto-select mode to "Automatic Revertive" and -- program LOCK settings 46 => X"0108_01d0", 47 => X"0108_0004", -- Register 4 48 => X"0108_0292", -- AUTOSEL_REG[1:0] = 0b10 49 => X"0108_01d0", 50 => X"0108_0013", -- Register 19 51 => X"0108_0229", -- LOCKT[2:0] = 0b001 52 => X"0108_01d0", 53 => X"0108_0089", -- Register 137 54 => X"0108_0201", -- FASTLOCK = 1 -- Perform an internal calibration 55 => X"0108_01d0", 56 => X"0108_0088", -- Register 136 57 => X"0108_0240", -- ICAL = 1 others => (others => '0') ); type state_type is (START, IDLE, AXI_WRITE, AXI_RESP, FINISH); signal axi_state : state_type := START; signal lut_address : unsigned(LUT_AWIDTH-1 downto 0); signal lut_commands : unsigned(LUT_AWIDTH-1 downto 0); signal lut_data : std_logic_vector(31 downto 0); signal axi_areset_n : std_logic; signal iic2intc_irpt : std_logic; signal s_axi_awaddr : std_logic_vector(31 downto 0); signal s_axi_awvalid : std_logic; signal s_axi_awready : std_logic; signal s_axi_wdata : std_logic_vector(31 downto 0); signal s_axi_wstrb : std_logic_vector( 3 downto 0); signal s_axi_wvalid : std_logic; signal s_axi_wready : std_logic; signal s_axi_bresp : std_logic_vector( 1 downto 0); signal s_axi_bvalid : std_logic; signal s_axi_bready : std_logic; signal s_axi_araddr : std_logic_vector(31 downto 0); signal s_axi_arvalid : std_logic; signal s_axi_arready : std_logic; signal s_axi_rdata : std_logic_vector(31 downto 0); signal s_axi_rresp : std_logic_vector( 1 downto 0); signal s_axi_rvalid : std_logic; signal s_axi_rready : std_logic; signal tx_fifo_empty : std_logic; signal bus_busy : std_logic; signal sda_buf : std_logic; signal scl_buf : std_logic; signal sda_o : std_logic; signal scl_o : std_logic; signal sda_t : std_logic; signal scl_t : std_logic; signal sda_i : std_logic; signal scl_i : std_logic; begin -- Synchronous read on rom to improve timing process(clk100) begin if rising_edge(clk100) then -- register rom data output lut_data <= cmd_rom(to_integer(lut_address)); end if; end process; ------------------------------------------------------------------------------- -- State machine for controlling writes to the AXI IIC core p_mgmnt_states : process(clk100, reset) begin if (reset = '1') then axi_state <= START; s_axi_awaddr <= (others => '0'); s_axi_awvalid <= '0'; s_axi_wstrb <= (others => '0'); s_axi_wvalid <= '0'; s_axi_bready <= '0'; s_axi_araddr <= (others => '0'); s_axi_arvalid <= '0'; s_axi_rready <= '0'; lut_address <= (others => '0'); done <= '0'; elsif rising_edge(clk100) then case axi_state is when START => -- Read the command count from location 0 in the LUT if (lut_address = 1) then axi_state <= IDLE; end if; lut_commands <= unsigned(lut_data(LUT_AWIDTH-1 downto 0)); lut_address <= to_unsigned(1, lut_address'length); done <= '0'; when IDLE => -- write s_axi_awaddr <= (others => '0'); s_axi_awvalid <= '0'; s_axi_wstrb <= (others => '0'); s_axi_wvalid <= '0'; s_axi_bready <= '0'; -- read s_axi_araddr <= (others => '0'); s_axi_arvalid <= '0'; s_axi_rready <= '0'; done <= '0'; if (lut_commands = 0) then axi_state <= FINISH; else -- bit 8 from LUT is 'START' bit indicating a new IIC command -- so we ensure the bus is not busy and the Tx FIFO is empty -- otherwise, just write data to the Tx FIFO if ( (lut_data(8) = '1') and (tx_fifo_empty = '1') and (bus_busy = '0') ) or ( (lut_data(8) = '0') ) then -- Write operation, post address and data axi_state <= AXI_WRITE; s_axi_awaddr(15 downto 0) <= lut_data(31 downto 16); s_axi_awvalid <= '1'; s_axi_wdata(15 downto 0) <= lut_data(15 downto 00); s_axi_wstrb <= (others => '1'); s_axi_wvalid <= '1'; end if; end if; when AXI_WRITE => if (s_axi_wready = '1') and (s_axi_awready = '1') then axi_state <= AXI_RESP; s_axi_wstrb <= (others => '0'); s_axi_awvalid <= '0'; s_axi_wvalid <= '0'; s_axi_bready <= '1'; lut_commands <= lut_commands - 1; lut_address <= lut_address + 1; end if; when AXI_RESP => if (s_axi_bvalid = '1') then axi_state <= IDLE; s_axi_bready <= '0'; end if; when FINISH => -- all commands executed, flag complete and hibernate done <= '1'; end case; end if; end process; ------------------------------------------------------------------------------- -- IIC control - uses AXI IIC controller axi_areset_n <= not reset; iic_ctrl : axi_iic_control port map ( S_AXI_ACLK => clk100, S_AXI_ARESETN => axi_areset_n, IIC2INTC_Irpt => iic2intc_irpt, -- write port S_AXI_AWADDR => s_axi_awaddr, S_AXI_AWVALID => s_axi_awvalid, S_AXI_AWREADY => s_axi_awready, S_AXI_WDATA => s_axi_wdata, S_AXI_WSTRB => s_axi_wstrb, S_AXI_WVALID => s_axi_wvalid, S_AXI_WREADY => s_axi_wready, S_AXI_BRESP => s_axi_bresp, S_AXI_BVALID => s_axi_bvalid, S_AXI_BREADY => s_axi_bready, -- read port S_AXI_ARADDR => s_axi_araddr, S_AXI_ARVALID => s_axi_arvalid, S_AXI_ARREADY => s_axi_arready, S_AXI_RDATA => s_axi_rdata, S_AXI_RRESP => s_axi_rresp, S_AXI_RVALID => s_axi_rvalid, S_AXI_RREADY => s_axi_rready, -- extra status signals tx_fifo_empty => tx_fifo_empty, bus_busy => bus_busy, Sda_I => sda_i, Sda_O => sda_o, Sda_T => sda_t, Scl_I => scl_i, Scl_O => scl_o, Scl_T => scl_t, Gpo => open ); -- tristate buffers for IIC interface sda_i <= iic_sda; scl_i <= iic_scl; sda_buf <= sda_o when (sda_t = '0') else 'Z'; scl_buf <= scl_o when (scl_t = '0') else 'Z'; iic_sda <= sda_buf; iic_scl <= scl_buf; end rtl;within which I invoke the file AXI-IIC.
Here are the steps I've taken:
- I have set up the hardware as per the manufacturer's guidelines.
- For configuration, I followed the steps outlined in the datasheet, including setting specific registers and initialization sequences. The IIC slave bus address I use is 74(hexadecimal).
- I observed the SCL and SDA lines using an oscilloscope, which confirmed the single 9-bit transmission with the final bit as a NACK.
I am unsure what might be causing this problem and would appreciate any insights or suggestions on how to resolve it.
Thank you in advance for your help! Best regards.