library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; ENTITY i2c_controller_top IS PORT ( clk : in std_logic; dataIn: in std_logic_vector(7 DOWNTO 0); dataOut: out std_logic_vector(7 DOWNTO 0); rst : in std_logic; rw : in std_logic; --Set to write or read data ready : out std_logic; -- Is set when ready for new data tip : out std_logic; -- Transfer is in progress last : in std_logic; -- Set when sending the last byte scl : inout std_logic; -- i2c clock line sda : inout std_logic -- i2c data line ); END ENTITY i2c_controller_top; USE WORK.ALL; ARCHITECTURE behave OF i2c_controller_top IS COMPONENT i2c_master_top IS PORT ( -- wishbone signals wb_clk_i : in std_logic; -- master clock input wb_rst_i : in std_logic := '0'; -- synchronous active high reset arst_i : in std_logic; --:= not ARST_LVL; -- asynchronous reset wb_adr_i : in unsigned(2 downto 0); -- lower address bits wb_dat_i : in std_logic_vector(7 downto 0); -- Databus input wb_dat_o : out std_logic_vector(7 downto 0); -- Databus output wb_we_i : in std_logic; -- Write enable input wb_stb_i : in std_logic; -- Strobe signals / core select signal wb_cyc_i : in std_logic; -- Valid bus cycle input wb_ack_o : out std_logic; -- Bus cycle acknowledge output -- i2c lines scl_pad_i : in std_logic; -- i2c clock line input scl_pad_o : out std_logic; -- i2c clock line output scl_padoen_o : out std_logic; -- i2c clock line output enable, active low sda_pad_i : in std_logic; -- i2c data line input sda_pad_o : out std_logic; -- i2c data line output sda_padoen_o : out std_logic -- i2c data line output enable, active low ); END COMPONENT i2c_master_top; -- Zustandsautomat TYPE TSTATE IS(IDLE0, INITcore, INITpreLow, INITpreHigh, SetAddr, WriteStart, WaitTIP0, ReadAck0, IDLE1, SetData0, SetData1, WriteData, WriteStop, WaitTIP1, ReadAck1); SIGNAL state: TSTATE := INITcore; -- Temporare Signale SIGNAL adr_iTemp : unsigned(2 downto 0); -- lower address bits SIGNAL dat_iTemp : std_logic_vector(7 downto 0); -- Databus input SIGNAL dat_oTemp : std_logic_vector(7 downto 0); -- Databus output SIGNAL we_iTemp : std_logic; -- Write enable input SIGNAL stb_iTemp : std_logic; -- Strobe signals / core select signal SIGNAL cyc_iTemp : std_logic; -- Valid bus cycle input SIGNAL ack_oTemp : std_logic; -- Bus cycle acknowledge output SIGNAL scl_i : std_logic; -- i2c clock line input SIGNAL scl_o : std_logic; -- i2c clock line output SIGNAL sclEn_o : std_logic; -- i2c clock line output enable, active low SIGNAL sda_i : std_logic; -- i2c data line input SIGNAL sda_o : std_logic; -- i2c data line output SIGNAL sdaEn_o : std_logic; BEGIN i2cM: i2c_master_top PORT MAP( wb_clk_i => clk, wb_rst_i => '0', arst_i => rst, wb_adr_i => adr_iTemp, wb_dat_i => dat_iTemp, wb_dat_o => dat_oTemp, wb_we_i => we_iTemp, wb_stb_i => stb_iTemp, wb_cyc_i => cyc_iTemp, wb_ack_o => ack_oTemp, scl_pad_i => scl_i, scl_pad_o => scl_o, scl_padoen_o => sclEn_o, sda_pad_i => sda_i, sda_pad_o => sda_o, sda_padoen_o => sdaEn_o ); PROCESS(clk, rst) BEGIN IF rst = '1' THEN state <= INITcore; ELSIF rising_edge(clk) THEN CASE state IS WHEN INITcore => state <= INITpreLow; WHEN INITpreLow => state <= INITpreHigh; WHEN INITpreHigh => state <= IDLE0; WHEN IDLE0 => IF rw = '1' AND dataIn(0) = '0' THEN -- Writing state <= SetAddr; END IF; WHEN SetAddr => state <= WriteStart; WHEN WriteStart => state <= WaitTIP0; WHEN WaitTIP0 => IF dat_oTemp(1) = '0' THEN -- 0: Transfer completed, 1: Transferring Data state <= ReadAck0; END IF; WHEN ReadAck0 => IF dat_oTemp(7) = '0' THEN state <= IdlE1; END IF; WHEN IDLE1 => IF rw = '1' and last = '0' THEN state <= SetData0; ELSIF rw = '1' and last = '1' THEN state <= SetData1; END IF; WHEN SetData1 => state <= WriteStop; WHEN SetData0 => state <= WriteData; WHEN WriteData => state <= WaitTIP0; WHEN WriteStop => state <= WaitTIP1; WHEN WaitTIP1 => state <= ReadAck1; WHEN ReadAck1 => IF dat_oTemp(7) = '0' THEN state <= IDLE0; END IF; END CASE; END IF; END PROCESS; PROCESS(state) BEGIN CASE state IS WHEN INITcore => -- Enable interrupt and core dat_iTemp <= "11000000"; adr_iTemp <= "010"; -- Set wb_we_i, wb_stb_i and wb_cyc_i to '1' to get write access for registers we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '0'; WHEN INITpreLow => -- PrescalerLOW register initialisieren: dat_iTemp <= "01100011"; adr_iTemp <= "000"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '0'; WHEN INITpreHigh => -- PrescalerHigh register initialisieren: dat_iTemp <= "00000000"; adr_iTemp <= "001"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '0'; WHEN IDLE0 => --Waiting we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '1'; tip <= '0'; WHEN IDLE1 => --Waiting we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '1'; tip <= '1'; WHEN SetAddr => --Write Addr to transmitregister dat_iTemp <= dataIn; adr_iTemp <= "011"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN WriteStart => -- Set start and write bit in command register dat_iTemp <= "10010000"; adr_iTemp <= "100"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN WaitTIP0 => -- Read status register to poll TIP flag adr_iTemp <= "100"; we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '0'; tip <= '1'; WHEN ReadAck0 => -- Read RxAck from statusregister adr_iTemp <= "100"; we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '0'; tip <= '1'; WHEN SetData0 => -- Write data to transmitregister dat_iTemp <= dataIn; adr_iTemp <= "011"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN SetData1 => -- Write data to transmitregister dat_iTemp <= dataIn; adr_iTemp <= "011"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN WriteData => -- Set write bit in command register dat_iTemp <= "00010000"; adr_iTemp <= "100"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN WriteStop => -- Set write and stop Bit in command register dat_iTemp <= "01010000"; adr_iTemp <= "100"; we_iTemp <= '1'; stb_iTemp <= '1'; cyc_iTemp <= '1'; ready <= '0'; tip <= '1'; WHEN WaitTIP1 => -- Read status register to poll TIP flag adr_iTemp <= "100"; we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '0'; tip <= '1'; WHEN ReadAck1 => -- Read RxAck from statusregister adr_iTemp <= "100"; we_iTemp <= '0'; stb_iTemp <= '0'; cyc_iTemp <= '0'; ready <= '0'; tip <= '1'; END CASE; END PROCESS; -- Tri State Buffer scl <= scl_o when (sclEn_o = '0') else 'Z'; sda <= sda_o when (sdaEn_o = '0') else 'Z'; scl_i <= scl; sda_i <= sda; END ARCHITECTURE behave;