FPGA proven, AISC proven, I2C controller core from OpenCores
http://opencores.org/project,i2c
Bit-controller
-- Translate simple commands into SCL/SDA transitions
-- Each command has 5 states, A/B/C/D/idle
--
-- start: SCL ~~~~~~~~~~~~~~\____
-- SDA XX/~~~~~~~\______
-- x | A | B | C | D | i
--
-- repstart SCL ______/~~~~~~~\___
-- SDA __/~~~~~~~\______
-- x | A | B | C | D | i
--
-- stop SCL _______/~~~~~~~~~~~
-- SDA ==\___________/~~~~~
-- x | A | B | C | D | i
--
--- write SCL ______/~~~~~~~\____
-- SDA XXX===============XX
-- x | A | B | C | D | i
--
--- read SCL ______/~~~~~~~\____
-- SDA XXXXXXX=XXXXXXXXXXX
-- x | A | B | C | D | i
--
1 ports declaration
1 library ieee; 2 use ieee.std_logic_1164.all; 3 use ieee.numeric_std.all; 4 5 entity i2c_master_bit_ctrl is 6 port ( 7 clk : in std_logic; 8 rst : in std_logic; 9 nRst : in std_logic; 10 ena : in std_logic; -- core enable signal 11 12 clk_cnt : in unsigned(15 downto 0); -- clock prescale value
--! type unsigned is array (natural range <>) of std_logic 13 14 cmd : in std_logic_vector(3 downto 0); 15 cmd_ack : out std_logic; -- command completed 16 busy : out std_logic; -- i2c bus busy 17 al : out std_logic; -- arbitration lost 18 19 din : in std_logic; 20 dout : out std_logic; 21 22 -- i2c lines 23 scl_i : in std_logic; -- i2c clock line input 24 scl_o : out std_logic; -- i2c clock line output 25 scl_oen : out std_logic; -- i2c clock line output enable, active low 26 sda_i : in std_logic; -- i2c data line input 27 sda_o : out std_logic; -- i2c data line output 28 sda_oen : out std_logic -- i2c data line output enable, active low 29 ); 30 end entity i2c_master_bit_ctrl;
2 signals declaration
1 -- architecture 2 constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; 3 constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; 4 constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; 5 constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; 6 constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; 7 8 type states is (idle, start_a, start_b, start_c, start_d, start_e,stop_a,stop_b, 9 stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); 10 signal c_state : states; 11 12 signal iscl_oen, isda_oen : std_logic; -- internal I2C lines 13 signal sda_chk : std_logic; -- check SDA status (multi-master arbitration) 14 signal dscl_oen : std_logic; -- delayed scl_oen signals 15 signal sSCL, sSDA : std_logic; -- synchronized SCL and SDA inputs 16 signal dSCL, dSDA : std_logic; -- delayed versions of sSCL and sSDA 17 signal clk_en : std_logic; -- statemachine clock enable 18 signal scl_sync, slave_wait : std_logic; -- clock generation signals 19 signal ial : std_logic; -- internal arbitration lost signal 20 signal cnt : unsigned(15 downto 0); -- clock divider counter (synthesis) 21 22 -- block 23 signal cSCL, cSDA : std_logic_vector(1 downto 0); -- capture SDA and SCL 24 signal fSCL, fSDA : std_logic_vector(2 downto 0); -- filter inputs for SCL and SDA 25 signal filter_cnt : unsigned(13 downto 0); -- clock divider for filter 26 signal sta_condition : std_logic; -- start detected 27 signal sto_condition : std_logic; -- stop detected 28 signal cmd_stop : std_logic; -- STOP command 29 signal ibusy : std_logic; -- internal busy signal
3 assign outputs
1 -- assign outputs 2 scl_o <= '0'; 3 scl_oen <= iscl_oen; 4 sda_o <= '0'; 5 sda_oen <= isda_oen;