This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
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;
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.
您好,
0X74地址对应的是A2 为高电平,A1 A0为低电平。
如果写入操作(8-6. Write to Control Register),第一个字节后PCA9548A没有ACK反馈,请检查芯片供电是否正常,
I2C时序是否正确(图 8-1. Definition of Start and Stop Conditions )。
支持复位的 PCA9548A 低电压 8 通道 I2C 开关 datasheet (Rev. G) (ti.com.cn)