library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity i2c_wrapper is generic ( prescale : std_logic_vector(15 downto 0) := x"00c8"); port ( wb_clk_i : in std_logic; wb_rst_i : in std_logic; wb_adr_i : in std_logic_vector(15 downto 0); wb_dat_i : in std_logic_vector(7 downto 0); wb_dat_o : out std_logic_vector(7 downto 0); wb_we_i : in std_logic; wb_stb_i : in std_logic; wb_ack_o : out std_logic; scl_i : in std_logic; scl_o : out std_logic; sda_i : in std_logic; sda_o : out std_logic; debug : out std_logic_vector(3 downto 0) ); end; architecture i2c_wrapper of i2c_wrapper is signal wb_adr : unsigned(2 downto 0); signal wb_dati : std_logic_vector(7 downto 0); signal wb_dato : std_logic_vector(7 downto 0); signal wb_we : std_logic; signal wb_stb : std_logic; signal wb_cyc : std_logic; signal wb_ack : std_logic; signal wb_inta : std_logic; signal wb_dat_oq : std_logic_vector(7 downto 0); signal cnt : unsigned(3 downto 0); signal wb_dowrite : std_logic; signal wb_doread : std_logic; signal end_cnt : integer range 0 to 11; type i2c_rec is record adr : unsigned(2 downto 0); dat : std_logic_vector(7 downto 0); int : std_logic; end record; type i2c_mem is ARRAY(0 to 11) of i2c_rec; signal dat : i2c_mem; type i2c_states is (IDLE, I2C_GO, I2C_WAIT_INT, I2C_GET_RXDAT, I2C_WB_ACK); signal i2c_sm : i2c_states; signal scl : std_logic; signal sda : std_logic; signal scl_oen : std_logic; signal sda_oen : std_logic; signal i2c_init_done : std_logic; begin scl_o <= scl when scl_oen = '0' else '1'; sda_o <= sda when sda_oen = '0' else '1'; wb_dat_o <= wb_dat_oq; i2c_master : entity work.i2c_master_top generic map( ARST_LVL => '1' ) port map ( -- wishbone signals wb_clk_i => wb_clk_i, wb_rst_i => wb_rst_i, arst_i => wb_rst_i, wb_adr_i => std_logic_vector(wb_adr), wb_dat_i => wb_dati, wb_dat_o => wb_dato, wb_we_i => wb_we, wb_stb_i => wb_stb, wb_cyc_i => wb_cyc, wb_ack_o => wb_ack, wb_inta_o => wb_inta, -- i2c lines scl_pad_i => scl_i, scl_pad_o => scl, scl_padoen_o => scl_oen, sda_pad_i => sda_i, sda_pad_o => sda, sda_padoen_o => sda_oen ); i2c_write: process (wb_clk_i, wb_rst_i) begin if rising_edge(wb_clk_i) then if wb_rst_i = '1' then wb_dat_oq <= (others => '0'); cnt <= (others => '0'); i2c_init_done <= '0'; wb_dowrite <= '0'; wb_doread <= '0'; end_cnt <= 0; else dat <= dat; if wb_ack = '1' and i2c_sm = I2C_GO then cnt <= cnt + "1"; elsif i2c_sm = IDLE and i2c_init_done = '1' then cnt <= "0011"; elsif i2c_sm = IDLE and i2c_init_done = '0' then cnt <= "0000"; end if; if i2c_sm = IDLE and wb_stb_i = '1' then if wb_we_i = '1' then -- PRESCALE Register enable core and interrupt dat <= (("000", prescale(7 downto 0),'0'), ("001", prescale(15 downto 8),'0'), ("010", x"c0",'0'), -- ADDRESS STA and WR bit DATA/REG STA and WR ("011", x"EC", '0'), ("100", x"90",'1'), ("011", x"ff", '0'), ("100", x"90",'1'), -- DATA STO and WR ("011", x"ff",'0'), ("100", x"50", '1')); dat(3).dat <= wb_adr_i(15 downto 0); dat(5).dat <= wb_adr_i( 7 downto 0); dat(8).dat <= wb_dat_i; end_cnt <= 9; else dat <= (("000", prescale(7 downto 0),'0'), ("001", prescale(15 downto 8),'0'), ("010", x"c0",'0'), -- ADDRESS STA and WR bit DATA/REG WR ("011", x"EC", '0'), ("100", x"91",'1'), ("011", x"ff", '0'), ("100", x"11", '1'), -- ADDRESS STA,WR STO, RD, NACK ("011", x"ED", '0'), ("100", x"91",'1'), ("100", x"69", '1'), ("111", x"00", '0'), ("111", x"00", '0')); dat(3).dat <= wb_adr_i(15 downto 9) & '0'; -- address write dat(5).dat <= wb_adr_i( 7 downto 0); -- memory location dat(7).dat <= wb_adr_i(15 downto 9) & '1'; -- address read end_cnt <= 10; end if; end if; i2c_init_done <= i2c_init_done; if i2c_sm = I2C_GO and cnt = "0010" then i2c_init_done <= '1'; end if; if i2c_sm = I2C_GET_RXDAT and wb_ack = '1' then wb_dat_oq <= wb_dato; end if; case i2c_sm is when IDLE => if (wb_stb_i = '1') then i2c_sm <= I2C_GO; end if; when I2C_GO => wb_dowrite <= '1'; if wb_ack = '1' and dat(to_integer(cnt)).int = '1' then i2c_sm <= I2C_WAIT_INT; wb_dowrite <= '0'; elsif wb_ack = '1' and dat(to_integer(cnt)).int = '0' then if to_integer(cnt) = end_cnt then i2c_sm <= I2C_GET_RXDAT; end if; wb_dowrite <= '0'; end if; when I2C_WAIT_INT => wb_doread <= '1'; if wb_ack = '1' and wb_dato(1) = '0' then wb_doread <= '0'; if to_integer(cnt) = end_cnt then i2c_sm <= I2C_GET_RXDAT; else i2c_sm <= I2C_GO; end if; end if; when I2C_GET_RXDAT => wb_doread <= '1'; if wb_ack = '1' then wb_doread <= '0'; i2c_sm <= I2C_WB_ACK; end if; when I2C_WB_ACK => i2c_sm <= IDLE; end case; end if; end if; end process; wb_ack_o <= '1' when i2c_sm = I2C_WB_ACK else '0'; wb_dati <= dat(to_integer(cnt)).dat; wb_adr <= dat(to_integer(cnt)).adr when wb_dowrite = '1' else "011" when i2c_sm = I2C_GET_RXDAT else "100"; wb_cyc <= wb_stb; wb_stb <= '1' when (wb_dowrite = '1' or wb_doread = '1') and wb_ack = '0' else '0'; wb_we <= wb_dowrite; debug(3 downto 0) <= std_logic_vector(cnt); end i2c_wrapper;