+++ /dev/null
----------------------------------------------------------------------
----- ----
----- WISHBONE revB2 compl. I2C Master Core; byte-controller ----
----- ----
----- ----
----- Author: Richard Herveille ----
----- richard@asics.ws ----
----- www.asics.ws ----
----- ----
----- Downloaded from: http://www.opencores.org/projects/i2c/ ----
----- ----
----------------------------------------------------------------------
----- ----
----- Copyright (C) 2000 Richard Herveille ----
----- richard@asics.ws ----
----- ----
----- This source file may be used and distributed without ----
----- restriction provided that this copyright statement is not ----
----- removed from the file and that any derivative work contains ----
----- the original copyright notice and the associated disclaimer.----
----- ----
----- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
----- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
----- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
----- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
----- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
----- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
----- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
----- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
----- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
----- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
----- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
----- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
----- POSSIBILITY OF SUCH DAMAGE. ----
----- ----
----------------------------------------------------------------------
-
--- CVS Log
---
--- $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004/02/18 11:41:48 rherveille Exp $
---
--- $Date: 2004/02/18 11:41:48 $
--- $Revision: 1.5 $
--- $Author: rherveille $
--- $Locker: $
--- $State: Exp $
---
--- Change History:
--- $Log: i2c_master_byte_ctrl.vhd,v $
--- Revision 1.5 2004/02/18 11:41:48 rherveille
--- Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
---
--- Revision 1.4 2003/08/09 07:01:13 rherveille
--- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
--- Fixed a potential bug in the byte controller's host-acknowledge generation.
---
--- Revision 1.3 2002/12/26 16:05:47 rherveille
--- Core is now a Multimaster I2C controller.
---
--- Revision 1.2 2002/11/30 22:24:37 rherveille
--- Cleaned up code
---
--- Revision 1.1 2001/11/05 12:02:33 rherveille
--- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
--- Code updated, is now up-to-date to doc. rev.0.4.
--- Added headers.
---
-
-
-
-
---
-------------------------------------------
--- Byte controller section
-------------------------------------------
---
-library ieee;
-use ieee.std_logic_1164.all;
-use ieee.std_logic_arith.all;
-
-entity i2c_master_byte_ctrl is
- port (
- clk : in std_logic;
- rst : in std_logic; -- synchronous active high reset (WISHBONE compatible)
- nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
- ena : in std_logic; -- core enable signal
-
- clk_cnt : in unsigned(15 downto 0); -- 4x SCL
-
- -- input signals
- start,
- stop,
- read,
- write,
- ack_in : std_logic;
- din : in std_logic_vector(7 downto 0);
-
- -- output signals
- cmd_ack : out std_logic; -- command done
- ack_out : out std_logic;
- i2c_busy : out std_logic; -- arbitration lost
- i2c_al : out std_logic; -- i2c bus busy
- dout : out std_logic_vector(7 downto 0);
-
- -- i2c lines
- scl_i : in std_logic; -- i2c clock line input
- scl_o : out std_logic; -- i2c clock line output
- scl_oen : out std_logic; -- i2c clock line output enable, active low
- sda_i : in std_logic; -- i2c data line input
- sda_o : out std_logic; -- i2c data line output
- sda_oen : out std_logic -- i2c data line output enable, active low
- );
-end entity i2c_master_byte_ctrl;
-
-architecture structural of i2c_master_byte_ctrl is
- component i2c_master_bit_ctrl is
- port (
- clk : in std_logic;
- rst : in std_logic;
- nReset : in std_logic;
- ena : in std_logic; -- core enable signal
-
- clk_cnt : in unsigned(15 downto 0); -- clock prescale value
-
- cmd : in std_logic_vector(3 downto 0);
- cmd_ack : out std_logic; -- command done
- busy : out std_logic; -- i2c bus busy
- al : out std_logic; -- arbitration lost
-
- din : in std_logic;
- dout : out std_logic;
-
- -- i2c lines
- scl_i : in std_logic; -- i2c clock line input
- scl_o : out std_logic; -- i2c clock line output
- scl_oen : out std_logic; -- i2c clock line output enable, active low
- sda_i : in std_logic; -- i2c data line input
- sda_o : out std_logic; -- i2c data line output
- sda_oen : out std_logic -- i2c data line output enable, active low
- );
- end component i2c_master_bit_ctrl;
-
- -- commands for bit_controller block
- constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000";
- constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001";
- constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010";
- constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100";
- constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000";
-
- -- signals for bit_controller
- signal core_cmd : std_logic_vector(3 downto 0);
- signal core_ack, core_txd, core_rxd : std_logic;
- signal al : std_logic;
-
- -- signals for shift register
- signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
- signal shift, ld : std_logic;
-
- -- signals for state machine
- signal go, host_ack : std_logic;
- signal dcnt : unsigned(2 downto 0); -- data counter
- signal cnt_done : std_logic;
-
-begin
- -- hookup bit_controller
- bit_ctrl: i2c_master_bit_ctrl port map(
- clk => clk,
- rst => rst,
- nReset => nReset,
- ena => ena,
- clk_cnt => clk_cnt,
- cmd => core_cmd,
- cmd_ack => core_ack,
- busy => i2c_busy,
- al => al,
- din => core_txd,
- dout => core_rxd,
- scl_i => scl_i,
- scl_o => scl_o,
- scl_oen => scl_oen,
- sda_i => sda_i,
- sda_o => sda_o,
- sda_oen => sda_oen
- );
- i2c_al <= al;
-
- -- generate host-command-acknowledge
- cmd_ack <= host_ack;
-
- -- generate go-signal
- go <= (read or write or stop) and not host_ack;
-
- -- assign Dout output to shift-register
- dout <= sr;
-
- -- generate shift register
- shift_register: process(clk, nReset)
- begin
- if (nReset = '0') then
- sr <= (others => '0');
- elsif (clk'event and clk = '1') then
- if (rst = '1') then
- sr <= (others => '0');
- elsif (ld = '1') then
- sr <= din;
- elsif (shift = '1') then
- sr <= (sr(6 downto 0) & core_rxd);
- end if;
- end if;
- end process shift_register;
-
- -- generate data-counter
- data_cnt: process(clk, nReset)
- begin
- if (nReset = '0') then
- dcnt <= (others => '0');
- elsif (clk'event and clk = '1') then
- if (rst = '1') then
- dcnt <= (others => '0');
- elsif (ld = '1') then
- dcnt <= (others => '1'); -- load counter with 7
- elsif (shift = '1') then
- dcnt <= dcnt -1;
- end if;
- end if;
- end process data_cnt;
-
- cnt_done <= '1' when (dcnt = 0) else '0';
-
- --
- -- state machine
- --
- statemachine : block
- type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
- signal c_state : states;
- begin
- --
- -- command interpreter, translate complex commands into simpler I2C commands
- --
- nxt_state_decoder: process(clk, nReset)
- begin
- if (nReset = '0') then
- core_cmd <= I2C_CMD_NOP;
- core_txd <= '0';
- shift <= '0';
- ld <= '0';
- host_ack <= '0';
- c_state <= st_idle;
- ack_out <= '0';
- elsif (clk'event and clk = '1') then
- if (rst = '1' or al = '1') then
- core_cmd <= I2C_CMD_NOP;
- core_txd <= '0';
- shift <= '0';
- ld <= '0';
- host_ack <= '0';
- c_state <= st_idle;
- ack_out <= '0';
- else
- -- initialy reset all signal
- core_txd <= sr(7);
- shift <= '0';
- ld <= '0';
- host_ack <= '0';
-
- case c_state is
- when st_idle =>
- if (go = '1') then
- if (start = '1') then
- c_state <= st_start;
- core_cmd <= I2C_CMD_START;
- elsif (read = '1') then
- c_state <= st_read;
- core_cmd <= I2C_CMD_READ;
- elsif (write = '1') then
- c_state <= st_write;
- core_cmd <= I2C_CMD_WRITE;
- else -- stop
- c_state <= st_stop;
- core_cmd <= I2C_CMD_STOP;
- end if;
-
- ld <= '1';
- end if;
-
- when st_start =>
- if (core_ack = '1') then
- if (read = '1') then
- c_state <= st_read;
- core_cmd <= I2C_CMD_READ;
- else
- c_state <= st_write;
- core_cmd <= I2C_CMD_WRITE;
- end if;
-
- ld <= '1';
- end if;
-
- when st_write =>
- if (core_ack = '1') then
- if (cnt_done = '1') then
- c_state <= st_ack;
- core_cmd <= I2C_CMD_READ;
- else
- c_state <= st_write; -- stay in same state
- core_cmd <= I2C_CMD_WRITE; -- write next bit
- shift <= '1';
- end if;
- end if;
-
- when st_read =>
- if (core_ack = '1') then
- if (cnt_done = '1') then
- c_state <= st_ack;
- core_cmd <= I2C_CMD_WRITE;
- else
- c_state <= st_read; -- stay in same state
- core_cmd <= I2C_CMD_READ; -- read next bit
- end if;
-
- shift <= '1';
- core_txd <= ack_in;
- end if;
-
- when st_ack =>
- if (core_ack = '1') then
- -- check for stop; Should a STOP command be generated ?
- if (stop = '1') then
- c_state <= st_stop;
- core_cmd <= I2C_CMD_STOP;
- else
- c_state <= st_idle;
- core_cmd <= I2C_CMD_NOP;
-
- -- generate command acknowledge signal
- host_ack <= '1';
- end if;
-
- -- assign ack_out output to core_rxd (contains last received bit)
- ack_out <= core_rxd;
-
- core_txd <= '1';
- else
- core_txd <= ack_in;
- end if;
-
- when st_stop =>
- if (core_ack = '1') then
- c_state <= st_idle;
- core_cmd <= I2C_CMD_NOP;
-
- -- generate command acknowledge signal
- host_ack <= '1';
- end if;
-
- when others => -- illegal states
- c_state <= st_idle;
- core_cmd <= I2C_CMD_NOP;
- report ("Byte controller entered illegal state.");
-
- end case;
-
- end if;
- end if;
- end process nxt_state_decoder;
-
- end block statemachine;
-
-end architecture structural;
-