summaryrefslogtreecommitdiffstats
path: root/opencores
diff options
context:
space:
mode:
authorBert Lange <b.lange@fzd.de>2011-05-03 08:36:26 +0200
committerBert Lange <b.lange@fzd.de>2011-05-03 08:36:26 +0200
commit0007e67e3f10fc8a7a6bd2d2689a43165313e877 (patch)
treec7fb38605239b91083ca87bc8fd8863abcac9be1 /opencores
parent404c108ca26989f47a27e79e6d4afab252b5d6f7 (diff)
downloadzpu-0007e67e3f10fc8a7a6bd2d2689a43165313e877.zip
zpu-0007e67e3f10fc8a7a6bd2d2689a43165313e877.tar.gz
add: I2C stuff from opencores
Diffstat (limited to 'opencores')
-rw-r--r--opencores/rtl/i2c_master_bit_ctrl.vhd545
-rw-r--r--opencores/rtl/i2c_master_byte_ctrl.vhd373
-rw-r--r--opencores/rtl/i2coc.vhd68
-rw-r--r--opencores/sim/Makefile35
-rw-r--r--opencores/sim/modelsim.ini54
5 files changed, 1075 insertions, 0 deletions
diff --git a/opencores/rtl/i2c_master_bit_ctrl.vhd b/opencores/rtl/i2c_master_bit_ctrl.vhd
new file mode 100644
index 0000000..c944086
--- /dev/null
+++ b/opencores/rtl/i2c_master_bit_ctrl.vhd
@@ -0,0 +1,545 @@
+---------------------------------------------------------------------
+---- ----
+---- WISHBONE revB2 I2C Master Core; bit-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_bit_ctrl.vhd,v 1.14 2006/10/11 12:10:13 rherveille Exp $
+--
+-- $Date: 2006/10/11 12:10:13 $
+-- $Revision: 1.14 $
+-- $Author: rherveille $
+-- $Locker: $
+-- $State: Exp $
+--
+-- Change History:
+-- $Log: i2c_master_bit_ctrl.vhd,v $
+-- Revision 1.14 2006/10/11 12:10:13 rherveille
+-- Added missing semicolons ';' on endif
+--
+-- Revision 1.13 2006/10/06 10:48:24 rherveille
+-- fixed short scl high pulse after clock stretch
+--
+-- Revision 1.12 2004/05/07 11:53:31 rherveille
+-- Fixed previous fix :) Made a variable vs signal mistake.
+--
+-- Revision 1.11 2004/05/07 11:04:00 rherveille
+-- Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit.
+--
+-- Revision 1.10 2004/02/27 07:49:43 rherveille
+-- Fixed a bug in the arbitration-lost signal generation. VHDL version only.
+--
+-- Revision 1.9 2003/08/12 14:48:37 rherveille
+-- Forgot an 'end if' :-/
+--
+-- Revision 1.8 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.7 2003/02/05 00:06:02 rherveille
+-- Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles.
+--
+-- Revision 1.6 2003/02/01 02:03:06 rherveille
+-- Fixed a few 'arbitration lost' bugs. VHDL version only.
+--
+-- Revision 1.5 2002/12/26 16:05:47 rherveille
+-- Core is now a Multimaster I2C controller.
+--
+-- Revision 1.4 2002/11/30 22:24:37 rherveille
+-- Cleaned up code
+--
+-- Revision 1.3 2002/10/30 18:09:53 rherveille
+-- Fixed some reported minor start/stop generation timing issuess.
+--
+-- Revision 1.2 2002/06/15 07:37:04 rherveille
+-- Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment.
+--
+-- 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.
+--
+-- Modified by Jan Andersson (jan@gaisler.com):
+-- * Added two start states to fulfill Set-up time for
+-- repeated START condition.
+-- * Modified synchronization of SCL and SDA. START and STOP detection
+-- is now performed after a two stage synchronizer and is also
+-- filtered.
+-- * Changed evaluation order of 'slave_wait', 'en' and 'cnt' in
+-- generation of clk_en signal to prevent clk_en assertion when
+-- slave_wait is asserted.
+-- * Needed to differentiate between slave clock stretching and master
+-- clock synchronization.
+-- * Added register s_state which contains the next state in case
+-- of clock synchronization
+--
+-------------------------------------
+-- Bit controller section
+------------------------------------
+--
+-- 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
+--
+
+-- Timing: Normal mode Fast mode
+-----------------------------------------------------------------
+-- Fscl 100KHz 400KHz
+-- Th_scl 4.0us 0.6us High 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: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
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+library grlib;
+use grlib.stdlib.all;
+
+entity 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 std_logic_vector(15 downto 0); -- clock prescale value
+
+ cmd : in std_logic_vector(3 downto 0);
+ cmd_ack : out std_logic; -- command completed
+ 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 entity i2c_master_bit_ctrl;
+
+architecture structural of i2c_master_bit_ctrl is
+ 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";
+
+ type states is (idle, start_a, start_b, start_c, start_d, start_e, start_f, start_g,
+ stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d);
+ signal c_state, s_state : states;
+
+ signal iscl_oen, isda_oen : std_logic; -- internal I2C lines
+ signal disda_oen : std_logic; -- delayed isda_oen
+ signal sda_chk : std_logic; -- check SDA status (multi-master arbitration)
+ signal dscl_oen : std_logic_vector(1 downto 0); -- delayed scl_oen signal
+ signal sSCL, sSDA : std_logic_vector(5 downto 0); -- synchronized SCL and SDA inputs
+ signal clk_en, slave_wait : std_logic; -- clock generation signals
+ signal ial : std_logic; -- internal arbitration lost signal
+ signal cnt : std_logic_vector(15 downto 0); -- clock divider counter (synthesis)
+ signal csync : std_logic; -- Need to synchronize clock with other master
+ signal slvw_dis : std_logic; -- Slave wait disable;
+
+begin
+ -- whenever the slave is not ready it can delay the cycle by pulling SCL low
+ -- delay scl_oen
+ process (clk)
+ begin
+ if (clk'event and clk = '1') then
+ -- Keep SCL output enable values
+ dscl_oen <= dscl_oen(0) & iscl_oen;
+ -- Disable slave stretch detection when other device drives SCL
+ -- H->L (only a master should to this).
+ slvw_dis <= (slvw_dis or csync) and dscl_oen(0);
+ end if;
+ end process;
+ -- SCL forced low after master tried to assert, slave is stretching clock
+ slave_wait <= dscl_oen(1) and not sSCL(1) and not (slvw_dis or sSCL(4));
+ -- SCL HIGH time cut short, master clock synchronization
+ csync <= dscl_oen(1) and not sSCL(1) and andv(sSCL(4 downto 2));
+
+ -- generate clk enable signal
+ gen_clken: process(clk, nReset)
+ begin
+ if (nReset = '0') then
+ cnt <= (others => '0');
+ clk_en <= '1';
+ elsif (clk'event and clk = '1') then
+ if (rst = '1') then
+ cnt <= (others => '0');
+ clk_en <= '1';
+ elsif (ena = '0' or csync = '1') then
+ cnt <= clk_cnt;
+ clk_en <= '1';
+ elsif (slave_wait = '1') then
+ cnt <= cnt;
+ clk_en <= '0';
+ elsif (cnt = X"0000") then
+ cnt <= clk_cnt;
+ clk_en <= '1';
+ else
+ cnt <= cnt -1;
+ clk_en <= '0';
+ end if;
+ end if;
+ end process gen_clken;
+
+
+ -- generate bus status controller
+ bus_status_ctrl: block
+ --signal dSCL, dSDA : std_logic; -- delayes sSCL and sSDA
+ signal sta_condition : std_logic; -- start detected
+ signal sto_condition : std_logic; -- stop detected
+ signal cmd_stop : std_logic; -- STOP command
+ signal ibusy : std_logic; -- internal busy signal
+ begin
+ -- synchronize SCL and SDA inputs
+ synch_scl_sda: process(clk, nReset)
+ begin
+ if (nReset = '0') then
+ sSCL <= (others => '1');
+ sSDA <= (others => '1');
+ elsif (clk'event and clk = '1') then
+ if (rst = '1') then
+ sSCL <= (others => '1');
+ sSDA <= (others => '1');
+ else
+ sSCL <= sSCL(4 downto 0) & scl_i;
+ sSDA <= sSDA(4 downto 0) & sda_i;
+ end if;
+ end if;
+ end process synch_SCL_SDA;
+
+ -- detect start condition => detect falling edge on SDA while SCL is high
+ -- detect stop condition => detect rising edge on SDA while SCL is high
+ detect_sta_sto: process(clk, nReset)
+ begin
+ if (nReset = '0') then
+ sta_condition <= '0';
+ sto_condition <= '0';
+ elsif (clk'event and clk = '1') then
+ if (rst = '1') then
+ sta_condition <= '0';
+ sto_condition <= '0';
+ else
+ if sSCL(5 downto 2) = "1111" and sSDA(5 downto 2) = "1100" then
+ sta_condition <= '1';
+ else
+ sta_condition <= '0';
+ end if;
+ if sSCL(5 downto 2) = "1111" and sSDA(5 downto 2) = "0011" then
+ sto_condition <= '1';
+ else
+ sto_condition <= '0';
+ end if;
+ end if;
+ end if;
+ end process detect_sta_sto;
+
+ -- generate i2c-bus busy signal
+ gen_busy: process(clk, nReset)
+ begin
+ if (nReset = '0') then
+ ibusy <= '0';
+ elsif (clk'event and clk = '1') then
+ if (rst = '1') then
+ ibusy <= '0';
+ else
+ ibusy <= (sta_condition or ibusy) and not sto_condition;
+ end if;
+ end if;
+ end process gen_busy;
+ busy <= ibusy;
+
+
+ -- generate arbitration lost signal
+ -- aribitration lost when:
+ -- 1) master drives SDA high, but the i2c bus is low
+ -- 2) stop detected while not requested (detect during 'idle' state)
+ gen_al: process(clk, nReset)
+ begin
+ if (nReset = '0') then
+ cmd_stop <= '0';
+ ial <= '0';
+ disda_oen <= '1';
+ elsif (clk'event and clk = '1') then
+ if (rst = '1') then
+ cmd_stop <= '0';
+ ial <= '0';
+ disda_oen <= '1';
+ else
+ if (clk_en = '1') then
+ if (cmd = I2C_CMD_STOP) then
+ cmd_stop <= '1';
+ else
+ cmd_stop <= '0';
+ end if;
+ end if;
+
+ if (c_state = idle) then
+ ial <= (sda_chk and not sSDA(1) and disda_oen);
+ else
+ ial <= (sda_chk and not sSDA(1) and disda_oen) or
+ (sto_condition and not cmd_stop);
+ end if;
+ disda_oen <= isda_oen;
+ end if;
+ end if;
+ end process gen_al;
+ al <= ial;
+
+ -- generate dout signal, store dout on rising edge of SCL
+ gen_dout: process(clk)
+ begin
+ if (clk'event and clk = '1') then
+ if sSCL(3 downto 2) = "01" then
+ dout <= sSDA(2);
+ end if;
+ end if;
+ end process gen_dout;
+ end block bus_status_ctrl;
+
+
+ -- generate statemachine
+ nxt_state_decoder : process (clk, nReset, c_state, cmd)
+ begin
+ if (nReset = '0') then
+ c_state <= idle;
+ s_state <= idle;
+ cmd_ack <= '0';
+ iscl_oen <= '1';
+ isda_oen <= '1';
+ sda_chk <= '0';
+ elsif (clk'event and clk = '1') then
+ if (rst = '1' or ial = '1') then
+ c_state <= idle;
+ cmd_ack <= '0';
+ iscl_oen <= '1';
+ isda_oen <= '1';
+ sda_chk <= '0';
+ elsif csync = '1' then
+ c_state <= s_state;
+ else
+
+ cmd_ack <= '0'; -- default no acknowledge
+
+ -- csync is always '0' here, but including it in the expression
+ -- appears to let some compilers optimize the design more...
+ if (clk_en or csync) = '1' then
+
+ case (c_state) is
+ -- idle
+ when idle =>
+ case cmd is
+ when I2C_CMD_START => c_state <= start_a;
+ s_state <= start_g;
+ when I2C_CMD_STOP => c_state <= stop_a;
+ s_state <= stop_d;
+ when I2C_CMD_WRITE => c_state <= wr_a;
+ s_state <= wr_d;
+ when I2C_CMD_READ => c_state <= rd_a;
+ s_state <= rd_d;
+ when others => c_state <= idle; -- NOP command
+ s_state <= idle;
+ end case;
+
+ iscl_oen <= iscl_oen; -- keep SCL in same state
+ isda_oen <= isda_oen; -- keep SDA in same state
+ sda_chk <= '0'; -- don't check SDA
+
+ -- start
+ when start_a =>
+ c_state <= start_b;
+ iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start)
+ isda_oen <= '1'; -- set SDA high
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_b =>
+ c_state <= start_c;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= '1'; -- keep SDA high
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_c =>
+ c_state <= start_d;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= '1'; -- keep SDA high
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_d =>
+ c_state <= start_e;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= '1'; -- keep SDA high
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_e =>
+ c_state <= start_f;
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= '0'; -- set SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_f =>
+ c_state <= start_g;
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= '0'; -- keep SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ when start_g =>
+ c_state <= idle;
+ cmd_ack <= '1'; -- command completed
+ iscl_oen <= '0'; -- set SCL low
+ isda_oen <= '0'; -- keep SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ -- stop
+ when stop_a =>
+ c_state <= stop_b;
+ iscl_oen <= '0'; -- keep SCL low
+ isda_oen <= '0'; -- set SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ when stop_b =>
+ c_state <= stop_c;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= '0'; -- keep SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ when stop_c =>
+ c_state <= stop_d;
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= '0'; -- keep SDA low
+ sda_chk <= '0'; -- don't check SDA
+
+ when stop_d =>
+ c_state <= idle;
+ cmd_ack <= '1'; -- command completed
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= '1'; -- set SDA high
+ sda_chk <= '0'; -- don't check SDA
+
+ -- read
+ when rd_a =>
+ c_state <= rd_b;
+ iscl_oen <= '0'; -- keep SCL low
+ isda_oen <= '1'; -- tri-state SDA
+ sda_chk <= '0'; -- don't check SDA
+
+ when rd_b =>
+ c_state <= rd_c;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= '1'; -- tri-state SDA
+ sda_chk <= '0'; -- don't check SDA
+
+ when rd_c =>
+ c_state <= rd_d;
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= '1'; -- tri-state SDA
+ sda_chk <= '0'; -- don't check SDA
+
+ when rd_d =>
+ c_state <= idle;
+ cmd_ack <= '1'; -- command completed
+ iscl_oen <= '0'; -- set SCL low
+ isda_oen <= '1'; -- tri-state SDA
+ sda_chk <= '0'; -- don't check SDA
+
+ -- write
+ when wr_a =>
+ c_state <= wr_b;
+ iscl_oen <= '0'; -- keep SCL low
+ isda_oen <= din; -- set SDA
+ sda_chk <= '0'; -- don't check SDA (SCL low)
+
+ when wr_b =>
+ c_state <= wr_c;
+ iscl_oen <= '1'; -- set SCL high
+ isda_oen <= din; -- keep SDA
+ sda_chk <= '1'; -- check SDA
+
+ when wr_c =>
+ c_state <= wr_d;
+ iscl_oen <= '1'; -- keep SCL high
+ isda_oen <= din; -- keep SDA
+ sda_chk <= '1'; -- check SDA
+
+ when wr_d =>
+ c_state <= idle;
+ cmd_ack <= '1'; -- command completed
+ iscl_oen <= '0'; -- set SCL low
+ isda_oen <= din; -- keep SDA
+ sda_chk <= '0'; -- don't check SDA (SCL low)
+
+ when others =>
+
+ end case;
+ end if;
+ end if;
+ end if;
+ end process nxt_state_decoder;
+
+
+ -- assign outputs
+ scl_o <= '0';
+ scl_oen <= iscl_oen;
+ sda_o <= '0';
+ sda_oen <= isda_oen;
+end architecture structural;
+
diff --git a/opencores/rtl/i2c_master_byte_ctrl.vhd b/opencores/rtl/i2c_master_byte_ctrl.vhd
new file mode 100644
index 0000000..f2da57b
--- /dev/null
+++ b/opencores/rtl/i2c_master_byte_ctrl.vhd
@@ -0,0 +1,373 @@
+---------------------------------------------------------------------
+---- ----
+---- 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.
+--
+
+-- Modified by Jan Andersson (jan@gaisler.com). Changed std_logic_arith to numeric_std.
+
+
+--
+------------------------------------------
+-- Byte controller section
+------------------------------------------
+--
+library ieee;
+use ieee.std_logic_1164.all;
+library grlib;
+use grlib.stdlib.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 std_logic_vector(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 std_logic_vector(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;
+ -- Added init value to dcnt to prevent simulation meta-value
+ -- - jan@gaisler.com
+ signal dcnt : std_logic_vector(2 downto 0) := (others => '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 = "000") 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;
+
diff --git a/opencores/rtl/i2coc.vhd b/opencores/rtl/i2coc.vhd
new file mode 100644
index 0000000..44f4098
--- /dev/null
+++ b/opencores/rtl/i2coc.vhd
@@ -0,0 +1,68 @@
+---------------------------------------------------------------------
+---- ----
+---- 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. ----
+---- ----
+---------------------------------------------------------------------
+-- Package containing i2c master byte controller component. Component
+-- declaration separated into this file by jan@gaisler.com.
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package i2coc is
+ component i2c_master_byte_ctrl is
+ port (
+ clk : in std_logic;
+ rst : in std_logic; -- active high reset
+ nReset : in std_logic; -- asynchornous active low reset
+ -- (not used in GRLIB)
+ ena : in std_logic; -- core enable signal
+
+ clk_cnt : in std_logic_vector(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;
+ ack_out : out std_logic;
+ i2c_busy : out std_logic;
+ i2c_al : out std_logic;
+ 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 component i2c_master_byte_ctrl;
+end;
diff --git a/opencores/sim/Makefile b/opencores/sim/Makefile
new file mode 100644
index 0000000..fb5a9c1
--- /dev/null
+++ b/opencores/sim/Makefile
@@ -0,0 +1,35 @@
+library = opencores
+
+rtl_files = ../rtl/i2c_master_bit_ctrl.vhd \
+ ../rtl/i2c_master_byte_ctrl.vhd \
+ ../rtl/i2coc.vhd \
+
+vhdlfiles = $(rtl_files)
+vhdltargets := $(foreach n, $(vhdlfiles), ./$(library)/$(basename $(notdir $n))/_primary.dat)
+
+
+all: compile
+
+compile: lib deplibs $(vhdltargets)
+
+deplibs:
+ make compile --directory ../../grlib/sim
+
+$(vhdltargets): $(vhdlfiles)
+ vcom -quiet -2008 -work $(library) $(vhdlfiles)
+
+
+clean:
+ rm -f transcript
+ rm -f *.wlf
+ rm -f wlf*
+ rm -rf $(library)
+ rm -f Makefile.$(library)
+
+
+# default patterns
+
+lib: $(library)
+
+$(library):
+ vlib $(library)
diff --git a/opencores/sim/modelsim.ini b/opencores/sim/modelsim.ini
new file mode 100644
index 0000000..f417f5f
--- /dev/null
+++ b/opencores/sim/modelsim.ini
@@ -0,0 +1,54 @@
+
+[Library]
+others = $MODEL_TECH/../modelsim.ini
+grlib = ../../grlib/sim/grlib/
+
+[vcom]
+VHDL93 = 2002
+
+; Show source line containing error. Default is off.
+Show_source = 1
+
+; Turn on resolving of ambiguous function overloading in favor of the
+; "explicit" function declaration (not the one automatically created by
+; the compiler for each type declaration). Default is off.
+; The .ini file has Explicit enabled so that std_logic_signed/unsigned
+; will match the behavior of synthesis tools.
+Explicit = 1
+
+; Keep silent about case statement static warnings.
+; Default is to give a warning.
+; NoCaseStaticError = 1
+
+; Keep silent about warnings caused by aggregates that are not locally static.
+; Default is to give a warning.
+; NoOthersStaticError = 1
+
+; Turn on some limited synthesis rule compliance checking. Checks only:
+; -- signals used (read) by a process must be in the sensitivity list
+CheckSynthesis = 1
+
+[vsim]
+Resolution = ps
+UserTimeUnit = default
+
+; Assertion Message Format
+; %S - Severity Level
+; %R - Report Message
+; %T - Time of assertion
+; %D - Delta
+; %I - Instance or Region pathname (if available)
+; %% - print '%' character
+; AssertionFormat = "** %S: %R\n Time: %T Iteration: %D%I\n"
+
+; Assertion File - alternate file for storing VHDL/Verilog assertion messages
+; AssertFile = assert.log
+
+; Default radix for all windows and commands...
+; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned
+DefaultRadix = symbolic
+
+[lmc]
+
+[msg_system]
+
OpenPOWER on IntegriCloud