⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c_master_byte_ctrl.vhd

📁 实现基于Avalon总线架构的I2C控制器!可实现OV7620等数字摄像头的配置功能!
💻 VHD
字号:
---------------------------------------------------------------------
----                                                             ----
----  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_UNSIGNED.ALL;

ENTITY i2c_master_byte_ctrl IS
	PORT(
		Clk        :    IN STD_LOGIC;
--		rst        :    IN STD_LOGIC; -- synchronous active high reset (WISHBONE compatible)
		Reset_n    :    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      :    IN STD_LOGIC;
		stop       :    IN STD_LOGIC;
		read_en    :    IN STD_LOGIC;
		write_en   :    IN STD_LOGIC;
		ack_in     :    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 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;
		Reset_n    :    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;
	SIGNAL dcnt : STD_LOGIC_VECTOR(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,
		Reset_n => Reset_n,
		ena     => ena,
		clk_cnt => clk_cnt,
		cmd     => core_cmd,
		cmd_ack => core_ack,
		busy    => i2c_busy,
--		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_en OR write_en OR stop) AND (NOT host_ack);

	-- assign Dout output to shift-register
	dout <= sr;--????

	-- generate shift register
	shift_register: PROCESS(Clk, Reset_n)
	BEGIN
	    IF (Reset_n = '0') THEN
	      sr <= (OTHERS => '0');
	    ELSIF (Clk'EVENT AND Clk = '1') THEN
	      IF (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, Reset_n)
	BEGIN
	    IF (Reset_n = '0') THEN
	      dcnt <= (OTHERS => '0');
	    ELSIF (Clk'EVENT AND Clk = '1') THEN
	      IF (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, Reset_n)
	    BEGIN
	        IF (Reset_n = '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 (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_en = '1') THEN
	                     c_state  <= st_read;
	                     core_cmd <= I2C_CMD_READ;
	                   ELSIF (write_en = '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_en = '1') THEN--start and read
	                     c_state  <= st_read;
	                     core_cmd <= I2C_CMD_READ;
	                   ELSE--else start and write
	                     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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -