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

📄 i2c_master.vhd

📁 MP3 for XPLA3 XILINX.CPLD,必须在XILINX的FPGA芯片下使用,因为IP核是xilinx
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- **************************************************************
-- File:  		i2c_master.vhd
--
-- Purpose: 	This file implements the I2C Master for configuring
--			the DAC3550A. It is a single transmit-only master.
--			A rising edge on the START signal indicates that 
--			a START condition should be generated and that 
--			data in the I2C Data Register is ready to be 
--			transmitted. Once the byte transmission has been 
--			completed, this code sets the EOT bit. At this point, 
--			the controller writes a new word into the I2C Data
--			Register. The controller is running much faster
--			than the I2C Master, therefore there are many clock
--			cycles to update the data register. Negation of the 
--			START signal causes the I2C Master to generate a STOP
--			condition.
--	
-- Created:		10/11/99	ALS
-- Revised:		10/14/99 	ALS
-- Revised:		11-28-99 ALS
-- Revised:		12-6-99 ALS
-- Revised:		2-17-00 ALS
-- **************************************************************

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity i2c_master is
  
  port(
	-- I2C bus signals
	sda : inout std_logic;
        scl : inout std_logic;
	
	-- interface signals from MPEG_CHIP_CONTROL
	i2cd		: in		std_logic_vector(7 downto 0);	-- I2C Data from MPEG Chip Control
	start		: in		std_logic;	-- start/stop indicator
	eot		: out		std_logic;	-- End of Byte Transfer
	i2c_err	: out		std_logic; 	-- error signal
	detect_stop	: inout	std_logic;	-- stop has been generated

      clock		: in		std_logic;	-- 2 MHz system clock
	reset 	: in 		std_logic	-- system reset
);

end i2c_master;

library IEEE;
use IEEE.std_logic_1164.all;

architecture behave of i2c_master is

-- ******************** CONSTANT DECLARATIONS ***********************

constant	CNT_400KHZ	:	std_logic_vector(2 downto 0) := "101";	-- number of 2MHz clocks in 400KHz
constant	HIGH_CNT	: 	std_logic_vector(1 downto 0) := "10"; 	-- CNT_400KHz/2 -1
constant	LOW_CNT		: 	std_logic_vector(1 downto 0) := "10";	-- CNT_400KHz/2 -1
constant	HIGH_CNT_2	:	std_logic_vector(1 downto 0) := "01";	-- HIGH_CNT/2
constant	DATA_HOLD	:	std_logic_vector(1 downto 0) := "01";	-- number of 2MHz clocks in 300ns(actually 500nS)
constant	START_HOLD	:	std_logic_vector(1 downto 0) := "10";
constant	START_CNT   : 	std_logic_vector(3 downto 0) := "0000";
constant	CNT_DONE    : 	std_logic_vector(3 downto 0) := "0111"; -- data bit count

constant	ZERO_CNT	: 	std_logic_vector(1 downto 0) := "00";  
constant 	RESET_ACTIVE :	std_logic := '1';

-- ********************* COMPONENT DECLARATIONS ************************

-- 8-bit serial load/parallel shift register
component SHIFT8
	port(
	     clock          : in std_logic;                        -- Clock
	     reset        : in std_logic;                        -- Active low clear
	     data_ld      : in std_logic;                        -- Data load enable
	     data_in      : in std_logic_vector (7 downto 0);     -- 8-bit data to load
	     shift_in     : in std_logic;                        -- Serial data in
	     shift_en     : in std_logic;                        -- Shift enable
	     shift_out    : out std_logic;                       -- Bit to shift out
	     data_out     : out std_logic_vector (7 downto 0));  -- 8-bit parallel out
		
end component;

-- Up counter - 2 bit
-- used to divide system clock to count SCL time
component UPCNT2
	port(
	     data         : in std_logic_vector (1 downto 0);    -- Serial data in
	     cnt_en       : in std_logic;                        -- Count enable
	     load         : in std_logic;                        -- Load line enable
 	     reset        : in std_logic;                        -- Active low clear
	     clock          : in std_logic;                        -- Clock
	     qout         : out std_logic_vector (1 downto 0));
		
end component;

-- Up counter - 4 bit
component UPCNT4
	port(
	     data         : in std_logic_vector (3 downto 0);    -- Serial data in
	     cnt_en       : in std_logic;                        -- Count enable
	     load         : in std_logic;                        -- Load line enable
 	     reset        : in std_logic;                        -- Active low clear
	     clock        : in std_logic;                        -- Clock
	     qout         : out std_logic_vector (3 downto 0));
		
end component;

-- ********************* SIGNAL DECLARATIONS ************************
type state_type is (IDLE, HEADER, ACK_HEADER, XMIT_DATA, GET_ACK_DATA, ERR);
signal state,next_state 		: state_type;

type scl_state_type is (SCL_IDLE, START_ST, SCL_LOW_EDGE, SCL_LOW, SCL_HIGH_EDGE, 
				SCL_HIGH);
signal scl_state, next_scl_state 		: scl_state_type;

signal scl_in		: std_logic;	-- sampled version of scl
signal scl_out		: std_logic;	-- combinatorial scl output from scl generator state machine
signal scl_not		: std_logic;	-- inverted SCL for use as clock
signal sda_in		: std_logic;	-- sampled version of sda
signal sda_out		: std_logic;	-- combinatorial sda output from scl generator state machine
signal sda_out_reg	: std_logic;	-- registered SDA_OUT signal
signal master_sda		: std_logic;	-- sda value when master

signal sda_oe		: std_logic;


-- Shift Register and the controls	
signal shift_reg		: std_logic_vector(7 downto 0);	-- shift register that holds I2C data				
signal shift_out		: std_logic;
signal shift_reg_en, shift_reg_ld   : std_logic;


signal start_d1		: std_logic;	-- registered version of START for edge detect
signal detect_start	: std_logic;	-- indicates that a START condition has been detected
signal sm_stop		: std_logic;	
							-- from state machine
signal sm_stop_com	: std_logic;	-- combinatorial sm_stop
signal eot_com		: std_logic;	-- combinatorial EOT signal from state machine
signal gen_start		: std_logic;	-- indicates MPEG_CHIP_CTRL wants to generate a START
signal gen_stop		: std_logic;	-- indicates MPEG_CHIP_CTRL wants to generate a STOP
signal stop_scl		: std_logic;	-- signal in SCL state machine indicating a STOP
signal stop_scl_reg	: std_logic;	-- registered STOP_SCL signal

-- Bit counter 0 to 7
signal bit_cnt		: std_logic_vector(3 downto 0);
signal bit_cnt_ld, bit_cnt_en : std_logic; 

-- Clock Counter
signal clk_cnt		: std_logic_vector (1 downto 0);
signal clk_cnt_rst	: std_logic;
signal clk_cnt_en 	: std_logic;      


-- the following signals are only here because Viewlogic's VHDL compiler won't allow a constant
-- to be used in a component instantiation	
signal cnt_zero		: std_logic_vector(1 downto 0);
signal cnt_start	: std_logic_vector(3 downto 0);



begin

  -- set SDA and SCL
	sda <= '0' when sda_oe = '1' else 'Z';
	scl <= '0' when scl_out = '0' else 'Z';

  -- negate SCL for use as clock
	scl_not <= not(scl);

  -- sda_oe is set when  data to be output = 0 

	sda_oe <= '1' when ((sda_out = '0')or stop_scl = '1') else '0';
	

-- the following signals are only here because Viewlogic's VHDL compiler won't allow a constant
-- to be used in a component instantiation

cnt_zero <= ZERO_CNT;
cnt_start <= START_CNT;


-- ************************  SCL_Generator Process ************************
-- This process generates SCL and SDA when in Master mode. It generates the START
-- and STOP conditions.

scl_generator_comb: process (scl_state,  sm_stop, gen_stop, 
					 gen_start,  stop_scl_reg, stop_scl,
					clk_cnt, bit_cnt, scl_in, 
					sda_out_reg, state, master_sda)

begin

-- state machine defaults
	scl_out <= '1';
	sda_out <= sda_out_reg;
	stop_scl <= stop_scl_reg;
	clk_cnt_en <= '0';
	clk_cnt_rst <= '1';
	next_scl_state <= scl_state;

		case scl_state is 
	
			when SCL_IDLE =>
				sda_out <= '1';
				stop_scl <= '0';
				-- leave IDLE state when gen_start
				if gen_start = '1' then
					next_scl_state <= START_ST;
				end if;

			when START_ST =>
				-- generate start condition
				clk_cnt_en <= '1';
				clk_cnt_rst <= '0';
				sda_out <= '0';
				stop_scl <= '0';
				if clk_cnt = START_HOLD then
					next_scl_state <= SCL_LOW_EDGE;
				else
					next_scl_state <= START_ST;
				end if;
			
			when SCL_LOW_EDGE =>
				clk_cnt_rst <= '1';
				scl_out <= '0';
				next_scl_state <= SCL_LOW;
				stop_scl <= '0';


			when SCL_LOW =>
				clk_cnt_en <= '1';
				clk_cnt_rst <= '0';
				scl_out <= '0';
				
				-- set SDA_OUT based on control signals
				if  ((sm_stop = '1' or gen_stop = '1') and
					(state /= GET_ACK_DATA and state /= ACK_HEADER )) then
					sda_out <= '0';
					stop_scl <= '1';
				elsif clk_cnt = DATA_HOLD then
					sda_out <= master_sda;
					stop_scl <= '0';
				else
					stop_scl <= '0';
				end if;
			
				-- determine next state
				if clk_cnt = LOW_CNT then
					next_scl_state <= SCL_HIGH_EDGE;
				else
					next_scl_state <= SCL_LOW;
				end if;
				
			when SCL_HIGH_EDGE =>
				clk_cnt_rst <= '1';
				scl_out <= '1';
				if ((sm_stop = '1' or gen_stop = '1') and
				   (state /= GET_ACK_DATA and state /= ACK_HEADER )) then
					stop_scl <= '1';
				else
					stop_scl <= '0';
				end if;

				
				-- this state sets SCL high
				-- stay in this state until SCL_IN = 1
				-- this will hold the counter in reset until all SCL drivers
				-- have released SCL to 1
				if scl_in = '0' then
					next_scl_state <= SCL_HIGH_EDGE;
				else
					next_scl_state <= SCL_HIGH;
				end if;

			when SCL_HIGH =>
				-- now all SCL drivers have set SCL to '1'
				-- begin count for high time
				clk_cnt_en <= '1';

⌨️ 快捷键说明

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