OpenCores
URL https://opencores.org/ocsvn/i2c/i2c/trunk

Subversion Repositories i2c

[/] [i2c/] [trunk/] [rtl/] [vhdl/] [I2C.VHD] - Diff between revs 10 and 68

Only display areas with differences | Details | Blame | View Log

Rev 10 Rev 68
--
--
-- Simple I2C controller
-- Simple I2C controller
--
--
-- 1) No multimaster
-- 1) No multimaster
-- 2) No slave mode
-- 2) No slave mode
-- 3) No fifo's
-- 3) No fifo's
--
--
-- notes:
-- notes:
-- Every command is acknowledged. Do not set a new command before previous is acknowledged.
-- Every command is acknowledged. Do not set a new command before previous is acknowledged.
-- Dout is available 1 clock cycle later as cmd_ack
-- Dout is available 1 clock cycle later as cmd_ack
--
--
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_arith.all;
package I2C is
package I2C is
        component simple_i2c is
        component simple_i2c is
        port (
        port (
                clk : in std_logic;
                clk : in std_logic;
                ena : in std_logic;
                ena : in std_logic;
                nReset : in std_logic;
                nReset : in std_logic;
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
                -- input signals
                -- input signals
                start,
                start,
                stop,
                stop,
                read,
                read,
                write,
                write,
                ack_in : std_logic;
                ack_in : std_logic;
                Din : in std_logic_vector(7 downto 0);
                Din : in std_logic_vector(7 downto 0);
                -- output signals
                -- output signals
                cmd_ack : out std_logic;
                cmd_ack : out std_logic;
                ack_out : out std_logic;
                ack_out : out std_logic;
                Dout : out std_logic_vector(7 downto 0);
                Dout : out std_logic_vector(7 downto 0);
                -- i2c signals
                -- i2c signals
                SCL : inout std_logic;
                SCL : inout std_logic;
                SDA : inout std_logic
                SDA : inout std_logic
        );
        );
        end component simple_i2c;
        end component simple_i2c;
end package I2C;
end package I2C;
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_arith.all;
entity simple_i2c is
entity simple_i2c is
        port (
        port (
                clk : in std_logic;
                clk : in std_logic;
                ena : in std_logic;
                ena : in std_logic;
                nReset : in std_logic;
                nReset : in std_logic;
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
                clk_cnt : in unsigned(7 downto 0);      -- 4x SCL
                -- input signals
                -- input signals
                start,
                start,
                stop,
                stop,
                read,
                read,
                write,
                write,
                ack_in : std_logic;
                ack_in : std_logic;
                Din : in std_logic_vector(7 downto 0);
                Din : in std_logic_vector(7 downto 0);
                -- output signals
                -- output signals
                cmd_ack : out std_logic;
                cmd_ack : out std_logic;
                ack_out : out std_logic;
                ack_out : out std_logic;
                Dout : out std_logic_vector(7 downto 0);
                Dout : out std_logic_vector(7 downto 0);
                -- i2c signals
                -- i2c signals
                SCL : inout std_logic;
                SCL : inout std_logic;
                SDA : inout std_logic
                SDA : inout std_logic
        );
        );
end entity simple_i2c;
end entity simple_i2c;
architecture structural of simple_i2c is
architecture structural of simple_i2c is
        component i2c_core is
        component i2c_core is
        port (
        port (
                clk : in std_logic;
                clk : in std_logic;
                nReset : in std_logic;
                nReset : in std_logic;
                clk_cnt : in unsigned(7 downto 0);
                clk_cnt : in unsigned(7 downto 0);
                cmd : in std_logic_vector(2 downto 0);
                cmd : in std_logic_vector(2 downto 0);
                cmd_ack : out std_logic;
                cmd_ack : out std_logic;
                busy : out std_logic;
                busy : out std_logic;
                Din : in std_logic;
                Din : in std_logic;
                Dout : out std_logic;
                Dout : out std_logic;
                SCL : inout std_logic;
                SCL : inout std_logic;
                SDA : inout std_logic
                SDA : inout std_logic
        );
        );
        end component i2c_core;
        end component i2c_core;
        -- commands for i2c_core
        -- commands for i2c_core
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
        -- signals for i2c_core
        -- signals for i2c_core
        signal core_cmd : std_logic_vector(2 downto 0);
        signal core_cmd : std_logic_vector(2 downto 0);
        signal core_ack, core_busy, core_txd, core_rxd : std_logic;
        signal core_ack, core_busy, core_txd, core_rxd : std_logic;
        -- signals for shift register
        -- signals for shift register
        signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
        signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
        signal shift, ld : std_logic;
        signal shift, ld : std_logic;
        -- signals for state machine
        -- signals for state machine
        signal go, host_ack : std_logic;
        signal go, host_ack : std_logic;
begin
begin
        -- hookup i2c core
        -- hookup i2c core
        u1: i2c_core port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_busy, core_txd, core_rxd, SCL, SDA);
        u1: i2c_core port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_busy, core_txd, core_rxd, SCL, SDA);
        -- generate host-command-acknowledge
        -- generate host-command-acknowledge
        cmd_ack <= host_ack;
        cmd_ack <= host_ack;
        -- generate go-signal
        -- generate go-signal
        go <= (read or write) and not host_ack;
        go <= (read or write) and not host_ack;
        -- assign Dout output to shift-register
        -- assign Dout output to shift-register
        Dout <= sr;
        Dout <= sr;
        -- assign ack_out output to core_rxd (contains last received bit)
        -- assign ack_out output to core_rxd (contains last received bit)
        ack_out <= core_rxd;
        ack_out <= core_rxd;
        -- generate shift register
        -- generate shift register
        shift_register: process(clk)
        shift_register: process(clk)
        begin
        begin
                if (clk'event and clk = '1') then
                if (clk'event and clk = '1') then
                        if (ld = '1') then
                        if (ld = '1') then
                                sr <= din;
                                sr <= din;
                        elsif (shift = '1') then
                        elsif (shift = '1') then
                                sr <= (sr(6 downto 0) & core_rxd);
                                sr <= (sr(6 downto 0) & core_rxd);
                        end if;
                        end if;
                end if;
                end if;
        end process shift_register;
        end process shift_register;
        --
        --
        -- state machine
        -- state machine
        --
        --
        statemachine : block
        statemachine : block
                type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
                type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
                signal state : states;
                signal state : states;
                signal dcnt : unsigned(2 downto 0);
                signal dcnt : unsigned(2 downto 0);
        begin
        begin
                --
                --
                -- command interpreter, translate complex commands into simpler I2C commands
                -- command interpreter, translate complex commands into simpler I2C commands
                --
                --
                nxt_state_decoder: process(clk, nReset, state)
                nxt_state_decoder: process(clk, nReset, state)
                        variable nxt_state : states;
                        variable nxt_state : states;
                        variable idcnt : unsigned(2 downto 0);
                        variable idcnt : unsigned(2 downto 0);
                        variable ihost_ack : std_logic;
                        variable ihost_ack : std_logic;
                        variable icore_cmd : std_logic_vector(2 downto 0);
                        variable icore_cmd : std_logic_vector(2 downto 0);
                        variable icore_txd : std_logic;
                        variable icore_txd : std_logic;
                        variable ishift, iload : std_logic;
                        variable ishift, iload : std_logic;
                begin
                begin
                        -- 8 databits (1byte) of data to shift-in/out
                        -- 8 databits (1byte) of data to shift-in/out
                        idcnt := dcnt;
                        idcnt := dcnt;
                        -- no acknowledge (until command complete)
                        -- no acknowledge (until command complete)
                        ihost_ack := '0';
                        ihost_ack := '0';
                        icore_txd := core_txd;
                        icore_txd := core_txd;
                        -- keep current command to i2c_core
                        -- keep current command to i2c_core
                        icore_cmd := core_cmd;
                        icore_cmd := core_cmd;
                        -- no shifting or loading of shift-register
                        -- no shifting or loading of shift-register
                        ishift := '0';
                        ishift := '0';
                        iload := '0';
                        iload := '0';
                        -- keep current state;
                        -- keep current state;
                        nxt_state := state;
                        nxt_state := state;
                        case state is
                        case state is
                                when st_idle =>
                                when st_idle =>
                                        if (go = '1') then
                                        if (go = '1') then
                                                if (start = '1') then
                                                if (start = '1') then
                                                        nxt_state := st_start;
                                                        nxt_state := st_start;
                                                        icore_cmd := CMD_START;
                                                        icore_cmd := CMD_START;
                                                elsif (read = '1') then
                                                elsif (read = '1') then
                                                        nxt_state := st_read;
                                                        nxt_state := st_read;
                                                        icore_cmd := CMD_READ;
                                                        icore_cmd := CMD_READ;
                                                        idcnt := "111";
                                                        idcnt := "111";
                                                else
                                                else
                                                        nxt_state := st_write;
                                                        nxt_state := st_write;
                                                        icore_cmd := CMD_WRITE;
                                                        icore_cmd := CMD_WRITE;
                                                        idcnt := "111";
                                                        idcnt := "111";
                                                        iload := '1';
                                                        iload := '1';
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when st_start =>
                                when st_start =>
                                        if (core_ack = '1') then
                                        if (core_ack = '1') then
                                                if (read = '1') then
                                                if (read = '1') then
                                                        nxt_state := st_read;
                                                        nxt_state := st_read;
                                                        icore_cmd := CMD_READ;
                                                        icore_cmd := CMD_READ;
                                                        idcnt := "111";
                                                        idcnt := "111";
                                                else
                                                else
                                                        nxt_state := st_write;
                                                        nxt_state := st_write;
                                                        icore_cmd := CMD_WRITE;
                                                        icore_cmd := CMD_WRITE;
                                                        idcnt := "111";
                                                        idcnt := "111";
                                                        iload := '1';
                                                        iload := '1';
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when st_write =>
                                when st_write =>
                                        if (core_ack = '1') then
                                        if (core_ack = '1') then
                                                idcnt := dcnt -1;       -- count down Data_counter
                                                idcnt := dcnt -1;       -- count down Data_counter
                                                icore_txd := sr(7);
                                                icore_txd := sr(7);
                                                if (dcnt = 0) then
                                                if (dcnt = 0) then
                                                        nxt_state := st_ack;
                                                        nxt_state := st_ack;
                                                        icore_cmd := CMD_READ;
                                                        icore_cmd := CMD_READ;
                                                else
                                                else
                                                        ishift := '1';
                                                        ishift := '1';
--                                                      icore_txd := sr(7);
--                                                      icore_txd := sr(7);
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when st_read =>
                                when st_read =>
                                        if (core_ack = '1') then
                                        if (core_ack = '1') then
                                                idcnt := dcnt -1;       -- count down Data_counter
                                                idcnt := dcnt -1;       -- count down Data_counter
                                                ishift := '1';
                                                ishift := '1';
                                                if (dcnt = 0) then
                                                if (dcnt = 0) then
                                                        nxt_state := st_ack;
                                                        nxt_state := st_ack;
                                                        icore_cmd := CMD_WRITE;
                                                        icore_cmd := CMD_WRITE;
                                                        icore_txd := ack_in;
                                                        icore_txd := ack_in;
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when st_ack =>
                                when st_ack =>
                                        if (core_ack = '1') then
                                        if (core_ack = '1') then
                                                -- generate command acknowledge signal
                                                -- generate command acknowledge signal
                                                ihost_ack := '1';
                                                ihost_ack := '1';
                                                -- Perform an additional shift, needed for 'read' (store last received bit in shift register)
                                                -- Perform an additional shift, needed for 'read' (store last received bit in shift register)
                                                ishift := '1';
                                                ishift := '1';
                                                -- check for stop; Should a STOP command be generated ?
                                                -- check for stop; Should a STOP command be generated ?
                                                if (stop = '1') then
                                                if (stop = '1') then
                                                        nxt_state := st_stop;
                                                        nxt_state := st_stop;
                                                        icore_cmd := CMD_STOP;
                                                        icore_cmd := CMD_STOP;
                                                else
                                                else
                                                        nxt_state := st_idle;
                                                        nxt_state := st_idle;
                                                        icore_cmd := CMD_NOP;
                                                        icore_cmd := CMD_NOP;
                                                end if;
                                                end if;
                                        end if;
                                        end if;
                                when st_stop =>
                                when st_stop =>
                                        if (core_ack = '1') then
                                        if (core_ack = '1') then
                                                nxt_state := st_idle;
                                                nxt_state := st_idle;
                                                icore_cmd := CMD_NOP;
                                                icore_cmd := CMD_NOP;
                                        end if;
                                        end if;
                                when others => -- illegal states
                                when others => -- illegal states
                                        nxt_state := st_idle;
                                        nxt_state := st_idle;
                                        icore_cmd := CMD_NOP;
                                        icore_cmd := CMD_NOP;
                        end case;
                        end case;
                        -- generate registers
                        -- generate registers
                        if (nReset = '0') then
                        if (nReset = '0') then
                                core_cmd <= CMD_NOP;
                                core_cmd <= CMD_NOP;
                                core_txd <= '0';
                                core_txd <= '0';
                                shift <= '0';
                                shift <= '0';
                                ld <= '0';
                                ld <= '0';
                                dcnt <= "111";
                                dcnt <= "111";
                                host_ack <= '0';
                                host_ack <= '0';
                                state <= st_idle;
                                state <= st_idle;
                        elsif (clk'event and clk = '1') then
                        elsif (clk'event and clk = '1') then
                                if (ena = '1') then
                                if (ena = '1') then
                                        state <= nxt_state;
                                        state <= nxt_state;
                                        dcnt <= idcnt;
                                        dcnt <= idcnt;
                                        shift <= ishift;
                                        shift <= ishift;
                                        ld <= iload;
                                        ld <= iload;
                                        core_cmd <= icore_cmd;
                                        core_cmd <= icore_cmd;
                                        core_txd <= icore_txd;
                                        core_txd <= icore_txd;
                                        host_ack <= ihost_ack;
                                        host_ack <= ihost_ack;
                                end if;
                                end if;
                        end if;
                        end if;
                end process nxt_state_decoder;
                end process nxt_state_decoder;
        end block statemachine;
        end block statemachine;
end architecture structural;
end architecture structural;
--
--
--
--
-- I2C Core
-- I2C Core
--
--
-- Translate simple commands into SCL/SDA transitions
-- Translate simple commands into SCL/SDA transitions
-- Each command has 5 states, A/B/C/D/idle
-- Each command has 5 states, A/B/C/D/idle
--
--
-- start:       SCL     ~~~~~~~~~~\____
-- start:       SCL     ~~~~~~~~~~\____
--      SDA     ~~~~~~~~\______
--      SDA     ~~~~~~~~\______
--               x | A | B | C | D | i
--               x | A | B | C | D | i
--
--
-- repstart     SCL     ____/~~~~\___
-- repstart     SCL     ____/~~~~\___
--      SDA     __/~~~\______
--      SDA     __/~~~\______
--               x | A | B | C | D | i
--               x | A | B | C | D | i
--
--
-- stop SCL     ____/~~~~~~~~
-- stop SCL     ____/~~~~~~~~
--      SDA     ==\____/~~~~~
--      SDA     ==\____/~~~~~
--               x | A | B | C | D | i
--               x | A | B | C | D | i
--
--
--- write       SCL     ____/~~~~\____
--- write       SCL     ____/~~~~\____
--      SDA     ==X=========X=
--      SDA     ==X=========X=
--               x | A | B | C | D | i
--               x | A | B | C | D | i
--
--
--- read        SCL     ____/~~~~\____
--- read        SCL     ____/~~~~\____
--      SDA     XXXX=====XXXX
--      SDA     XXXX=====XXXX
--               x | A | B | C | D | i
--               x | A | B | C | D | i
--
--
-- Timing:              Normal mode     Fast mode
-- Timing:              Normal mode     Fast mode
-----------------------------------------------------------------
-----------------------------------------------------------------
-- Fscl         100KHz          400KHz
-- Fscl         100KHz          400KHz
-- Th_scl               4.0us           0.6us   High period of SCL
-- Th_scl               4.0us           0.6us   High period of SCL
-- Tl_scl               4.7us           1.3us   Low period of SCL
-- Tl_scl               4.7us           1.3us   Low period of SCL
-- Tsu:sta              4.7us           0.6us   setup time for a repeated start condition
-- Tsu:sta              4.7us           0.6us   setup time for a repeated start condition
-- Tsu:sto              4.0us           0.6us   setup time for a stop conditon
-- Tsu:sto              4.0us           0.6us   setup time for a stop conditon
-- Tbuf         4.7us           1.3us   Bus free time between a stop and start condition
-- Tbuf         4.7us           1.3us   Bus free time between a stop and start condition
--
--
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_arith.all;
entity i2c_core is
entity i2c_core is
        port (
        port (
                clk : in std_logic;
                clk : in std_logic;
                nReset : in std_logic;
                nReset : in std_logic;
                clk_cnt : in unsigned(7 downto 0);
                clk_cnt : in unsigned(7 downto 0);
                cmd : in std_logic_vector(2 downto 0);
                cmd : in std_logic_vector(2 downto 0);
                cmd_ack : out std_logic;
                cmd_ack : out std_logic;
                busy : out std_logic;
                busy : out std_logic;
                Din : in std_logic;
                Din : in std_logic;
                Dout : out std_logic;
                Dout : out std_logic;
                SCL : inout std_logic;
                SCL : inout std_logic;
                SDA : inout std_logic
                SDA : inout std_logic
        );
        );
end entity i2c_core;
end entity i2c_core;
architecture structural of i2c_core is
architecture structural of i2c_core is
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
        constant CMD_NOP        : std_logic_vector(2 downto 0) := "000";
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
        constant CMD_START      : std_logic_vector(2 downto 0) := "010";
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
        constant CMD_STOP       : std_logic_vector(2 downto 0) := "011";
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
        constant CMD_READ       : std_logic_vector(2 downto 0) := "100";
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
        constant CMD_WRITE      : std_logic_vector(2 downto 0) := "101";
        type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
        type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
        signal state : cmds;
        signal state : cmds;
        signal SDAo, SCLo : std_logic;
        signal SDAo, SCLo : std_logic;
        signal txd : std_logic;
        signal txd : std_logic;
        signal clk_en, slave_wait :std_logic;
        signal clk_en, slave_wait :std_logic;
        signal cnt : unsigned(7 downto 0) := clk_cnt;
        signal cnt : unsigned(7 downto 0) := clk_cnt;
begin
begin
        -- whenever the slave is not ready it can delay the cycle by pulling SCL low
        -- whenever the slave is not ready it can delay the cycle by pulling SCL low
        slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
        slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0';
        -- generate clk enable signal
        -- generate clk enable signal
        gen_clken: process(clk, nReset)
        gen_clken: process(clk, nReset)
        begin
        begin
                if (nReset = '0') then
                if (nReset = '0') then
                        cnt <= (others => '0');
                        cnt <= (others => '0');
                        clk_en <= '1'; --'0';
                        clk_en <= '1'; --'0';
                elsif (clk'event and clk = '1') then
                elsif (clk'event and clk = '1') then
                        if (cnt = 0) then
                        if (cnt = 0) then
                                clk_en <= '1';
                                clk_en <= '1';
                                cnt <= clk_cnt;
                                cnt <= clk_cnt;
                        else
                        else
                                if (slave_wait = '0') then
                                if (slave_wait = '0') then
                                        cnt <= cnt -1;
                                        cnt <= cnt -1;
                                end if;
                                end if;
                                clk_en <= '0';
                                clk_en <= '0';
                        end if;
                        end if;
                end if;
                end if;
        end process gen_clken;
        end process gen_clken;
        -- generate statemachine
        -- generate statemachine
        nxt_state_decoder : process (clk, nReset, state, cmd, SDA)
        nxt_state_decoder : process (clk, nReset, state, cmd, SDA)
                variable nxt_state : cmds;
                variable nxt_state : cmds;
                variable icmd_ack, ibusy, store_sda : std_logic;
                variable icmd_ack, ibusy, store_sda : std_logic;
                variable itxd : std_logic;
                variable itxd : std_logic;
        begin
        begin
                nxt_state := state;
                nxt_state := state;
                icmd_ack := '0'; -- default no acknowledge
                icmd_ack := '0'; -- default no acknowledge
                ibusy := '1'; -- default busy
                ibusy := '1'; -- default busy
                store_sda := '0';
                store_sda := '0';
                itxd := txd;
                itxd := txd;
                case (state) is
                case (state) is
                        -- idle
                        -- idle
                        when idle =>
                        when idle =>
                                case cmd is
                                case cmd is
                                        when CMD_START =>
                                        when CMD_START =>
                                                nxt_state := start_a;
                                                nxt_state := start_a;
                                                icmd_ack := '1'; -- command completed
                                                icmd_ack := '1'; -- command completed
                                        when CMD_STOP =>
                                        when CMD_STOP =>
                                                nxt_state := stop_a;
                                                nxt_state := stop_a;
                                                icmd_ack := '1'; -- command completed
                                                icmd_ack := '1'; -- command completed
                                        when CMD_WRITE =>
                                        when CMD_WRITE =>
                                                nxt_state := wr_a;
                                                nxt_state := wr_a;
                                                icmd_ack := '1'; -- command completed
                                                icmd_ack := '1'; -- command completed
                                                itxd := Din;
                                                itxd := Din;
                                        when CMD_READ =>
                                        when CMD_READ =>
                                                nxt_state := rd_a;
                                                nxt_state := rd_a;
                                                icmd_ack := '1'; -- command completed
                                                icmd_ack := '1'; -- command completed
                                        when others =>
                                        when others =>
                                                nxt_state := idle;
                                                nxt_state := idle;
-- don't acknowledge NOP command                                                icmd_ack := '1'; -- command completed
-- don't acknowledge NOP command                                                icmd_ack := '1'; -- command completed
                                                ibusy := '0';
                                                ibusy := '0';
                                end case;
                                end case;
                        -- start
                        -- start
                        when start_a =>
                        when start_a =>
                                nxt_state := start_b;
                                nxt_state := start_b;
                        when start_b =>
                        when start_b =>
                                nxt_state := start_c;
                                nxt_state := start_c;
                        when start_c =>
                        when start_c =>
                                nxt_state := start_d;
                                nxt_state := start_d;
                        when start_d =>
                        when start_d =>
                                nxt_state := idle;
                                nxt_state := idle;
                                ibusy := '0'; -- not busy when idle
                                ibusy := '0'; -- not busy when idle
                        -- stop
                        -- stop
                        when stop_a =>
                        when stop_a =>
                                nxt_state := stop_b;
                                nxt_state := stop_b;
                        when stop_b =>
                        when stop_b =>
                                nxt_state := stop_c;
                                nxt_state := stop_c;
                        when stop_c =>
                        when stop_c =>
--                              nxt_state := stop_d;
--                              nxt_state := stop_d;
--                      when stop_d =>
--                      when stop_d =>
                                nxt_state := idle;
                                nxt_state := idle;
                                ibusy := '0'; -- not busy when idle
                                ibusy := '0'; -- not busy when idle
                        -- read
                        -- read
                        when rd_a =>
                        when rd_a =>
                                nxt_state := rd_b;
                                nxt_state := rd_b;
                        when rd_b =>
                        when rd_b =>
                                nxt_state := rd_c;
                                nxt_state := rd_c;
                        when rd_c =>
                        when rd_c =>
                                nxt_state := rd_d;
                                nxt_state := rd_d;
                                store_sda := '1';
                                store_sda := '1';
                        when rd_d =>
                        when rd_d =>
                                nxt_state := idle;
                                nxt_state := idle;
                                ibusy := '0'; -- not busy when idle
                                ibusy := '0'; -- not busy when idle
                        -- write
                        -- write
                        when wr_a =>
                        when wr_a =>
                                nxt_state := wr_b;
                                nxt_state := wr_b;
                        when wr_b =>
                        when wr_b =>
                                nxt_state := wr_c;
                                nxt_state := wr_c;
                        when wr_c =>
                        when wr_c =>
                                nxt_state := wr_d;
                                nxt_state := wr_d;
                        when wr_d =>
                        when wr_d =>
                                nxt_state := idle;
                                nxt_state := idle;
                                ibusy := '0'; -- not busy when idle
                                ibusy := '0'; -- not busy when idle
                end case;
                end case;
                -- generate regs
                -- generate regs
                if (nReset = '0') then
                if (nReset = '0') then
                        state <= idle;
                        state <= idle;
                        cmd_ack <= '0';
                        cmd_ack <= '0';
                        busy <= '0';
                        busy <= '0';
                        txd <= '0';
                        txd <= '0';
                        Dout <= '0';
                        Dout <= '0';
                elsif (clk'event and clk = '1') then
                elsif (clk'event and clk = '1') then
                        if (clk_en = '1') then
                        if (clk_en = '1') then
                                state <= nxt_state;
                                state <= nxt_state;
                                busy <= ibusy;
                                busy <= ibusy;
                                txd <= itxd;
                                txd <= itxd;
                                if (store_sda = '1') then
                                if (store_sda = '1') then
                                        Dout <= SDA;
                                        Dout <= SDA;
                                end if;
                                end if;
                        end if;
                        end if;
                        cmd_ack <= icmd_ack and clk_en;
                        cmd_ack <= icmd_ack and clk_en;
                end if;
                end if;
        end process nxt_state_decoder;
        end process nxt_state_decoder;
        --
        --
        -- convert states to SCL and SDA signals
        -- convert states to SCL and SDA signals
        --
        --
        output_decoder: process (clk, nReset, state)
        output_decoder: process (clk, nReset, state)
                variable iscl, isda : std_logic;
                variable iscl, isda : std_logic;
        begin
        begin
                case (state) is
                case (state) is
                        when idle =>
                        when idle =>
                                iscl := SCLo; -- keep SCL in same state
                                iscl := SCLo; -- keep SCL in same state
                                isda := SDA; -- keep SDA in same state
                                isda := SDA; -- keep SDA in same state
                        -- start
                        -- start
                        when start_a =>
                        when start_a =>
                                iscl := SCLo; -- keep SCL in same state (for repeated start)
                                iscl := SCLo; -- keep SCL in same state (for repeated start)
                                isda := '1'; -- set SDA high
                                isda := '1'; -- set SDA high
                        when start_b =>
                        when start_b =>
                                iscl := '1';    -- set SCL high
                                iscl := '1';    -- set SCL high
                                isda := '1'; -- keep SDA high
                                isda := '1'; -- keep SDA high
                        when start_c =>
                        when start_c =>
                                iscl := '1';    -- keep SCL high
                                iscl := '1';    -- keep SCL high
                                isda := '0'; -- sel SDA low
                                isda := '0'; -- sel SDA low
                        when start_d =>
                        when start_d =>
                                iscl := '0'; -- set SCL low
                                iscl := '0'; -- set SCL low
                                isda := '0'; -- keep SDA low
                                isda := '0'; -- keep SDA low
                        -- stop
                        -- stop
                        when stop_a =>
                        when stop_a =>
                                iscl := '0'; -- keep SCL disabled
                                iscl := '0'; -- keep SCL disabled
                                isda := '0'; -- set SDA low
                                isda := '0'; -- set SDA low
                        when stop_b =>
                        when stop_b =>
                                iscl := '1'; -- set SCL high
                                iscl := '1'; -- set SCL high
                                isda := '0'; -- keep SDA low
                                isda := '0'; -- keep SDA low
                        when stop_c =>
                        when stop_c =>
                                iscl := '1'; -- keep SCL high
                                iscl := '1'; -- keep SCL high
                                isda := '1'; -- set SDA high
                                isda := '1'; -- set SDA high
                        -- write
                        -- write
                        when wr_a =>
                        when wr_a =>
                                iscl := '0';    -- keep SCL low
                                iscl := '0';    -- keep SCL low
--                              isda := txd; -- set SDA
--                              isda := txd; -- set SDA
                                isda := Din;
                                isda := Din;
                        when wr_b =>
                        when wr_b =>
                                iscl := '1';    -- set SCL high
                                iscl := '1';    -- set SCL high
--                              isda := txd; -- set SDA
--                              isda := txd; -- set SDA
                                isda := Din;
                                isda := Din;
                        when wr_c =>
                        when wr_c =>
                                iscl := '1';    -- keep SCL high
                                iscl := '1';    -- keep SCL high
--                              isda := txd; -- set SDA
--                              isda := txd; -- set SDA
                                isda := Din;
                                isda := Din;
                        when wr_d =>
                        when wr_d =>
                                iscl := '0'; -- set SCL low
                                iscl := '0'; -- set SCL low
--                              isda := txd; -- set SDA
--                              isda := txd; -- set SDA
                                isda := Din;
                                isda := Din;
                        -- read
                        -- read
                        when rd_a =>
                        when rd_a =>
                                iscl := '0'; -- keep SCL low
                                iscl := '0'; -- keep SCL low
                                isda := '1'; -- tri-state SDA
                                isda := '1'; -- tri-state SDA
                        when rd_b =>
                        when rd_b =>
                                iscl := '1'; -- set SCL high
                                iscl := '1'; -- set SCL high
                                isda := '1'; -- tri-state SDA
                                isda := '1'; -- tri-state SDA
                        when rd_c =>
                        when rd_c =>
                                iscl := '1'; -- keep SCL high
                                iscl := '1'; -- keep SCL high
                                isda := '1'; -- tri-state SDA
                                isda := '1'; -- tri-state SDA
                        when rd_d =>
                        when rd_d =>
                                iscl := '0'; -- set SCL low
                                iscl := '0'; -- set SCL low
                                isda := '1'; -- tri-state SDA
                                isda := '1'; -- tri-state SDA
                end case;
                end case;
                -- generate registers
                -- generate registers
                if (nReset = '0') then
                if (nReset = '0') then
                        SCLo <= '1';
                        SCLo <= '1';
                        SDAo <= '1';
                        SDAo <= '1';
                elsif (clk'event and clk = '1') then
                elsif (clk'event and clk = '1') then
                        if (clk_en = '1') then
                        if (clk_en = '1') then
                                SCLo <= iscl;
                                SCLo <= iscl;
                                SDAo <= isda;
                                SDAo <= isda;
                        end if;
                        end if;
                end if;
                end if;
        end process output_decoder;
        end process output_decoder;
        SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state)
        SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state)
        SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state)
        SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state)
--      SCL <= SCLo;
--      SCL <= SCLo;
--      SDA <= SDAo;
--      SDA <= SDAo;
end architecture structural;
end architecture structural;
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.