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

📄 i2c_master.vhd

📁 MP3 for XPLA3 XILINX.CPLD,必须在XILINX的FPGA芯片下使用,因为IP核是xilinx
💻 VHD
📖 第 1 页 / 共 2 页
字号:
				clk_cnt_rst <= '0';
				scl_out <= '1';	
				-- check to see if a repeated start or a stop needs to be 
				-- generated. If so, only hold SCL high for half of the high time
				if clk_cnt = HIGH_CNT_2 then
					if stop_scl = '1' then
						next_scl_state <= SCL_IDLE;
					end if;
				elsif clk_cnt = HIGH_CNT then 
					next_scl_state <= SCL_LOW_EDGE;
				else
					next_scl_state <= SCL_HIGH;
				end if;
		
			when others =>
					next_scl_state <= SCL_IDLE;
		end case;
end process;

scl_generator_regs: process (clock, reset)
begin
	if reset = RESET_ACTIVE then
		scl_state <= SCL_IDLE;
		sda_out_reg <= '1';
		stop_scl_reg <= '0';
	elsif clock'event and clock='1' then
		scl_state <= next_scl_state;
		sda_out_reg <= sda_out;
		stop_scl_reg <= stop_scl;
	end if;
end process;

-- ************************  Clock Counter Implementation ************************
-- The following code implements the counter that divides the sys_clock for 
-- creation of SCL. Control lines for this counter are set in SCL state machine

	CLKCNT : UPCNT2
	  port map( data      => cnt_zero,
		      cnt_en    => clk_cnt_en,
		      load      => clk_cnt_rst,
		      reset     => reset,  
		      clock     => clock, 
		      qout      => clk_cnt );
		




-- ************************  SDA/SCL Sample Registers Process ************************
-- This process samples the incoming SDA and SCL with the system clock
sda_in <= '0' when sda = '0' 
		else '1';
scl_in <= '0' when scl = '0' 
		else '1';

start_regs: process(clock,reset)
begin
	if reset = RESET_ACTIVE then
		start_d1 <= '0';	
	elsif clock'event and clock = '1' then
		start_d1 <= start;
	end if;
end process;

-- ************************  START/STOP Detect Process ************************
-- This process detects the start and stop conditions.
-- by using SDA as a clock.
start_det: process(sda, reset, state)
begin
	if reset = RESET_ACTIVE or state = HEADER then
		detect_start <= '0';
	elsif sda'event and sda = '0' then
		if scl /= '0' then 
			detect_start <= '1';
		else
			detect_start <= '0';
		end if;
	end if;
end process;

stop_det: process(sda, reset, detect_start)
begin
	if reset = RESET_ACTIVE or detect_start = '1' then
		detect_stop <= '0';
	elsif sda'event and sda /= '0' then
		if scl /= '0' then
			detect_stop <= '1';
		else
			detect_stop <= '0';
		end if;
	end if;
end process;


-- ************************   Generate START/STOP Process ************************
-- This process detects the rising and falling edges of START and sets signals to
-- control generation of start and stop conditions

gen_start_stop: process (clock,reset)
begin
	if reset = RESET_ACTIVE then
		gen_start <= '0';
		gen_stop <= '0';
	elsif clock'event and clock = '1' then
		if start_d1 = '0' and start = '1' then
			-- rising edge of START - generate start condition
			gen_start <= '1';
		elsif detect_start = '1' then
			gen_start <= '0';
		end if;
		if start_d1 = '1' and start = '0' then
			-- falling edge of START - generate stop condition 
			gen_stop <= '1';
		elsif detect_stop = '1' then
			gen_stop <= '0';
		end if;
	end if;
end process;



-- ************************  Main State Machine Process ************************
-- The following processes contain the main I2C state machine.
-- This state machine is clocked on the falling edge of SCL. DETECT_STOP must stay as
-- an asynchronous reset because once STOP has been generated, SCL clock stops.
state_machine_regs: process (scl, reset, detect_stop)

begin

	if reset = RESET_ACTIVE or detect_stop = '1' then
		state <= IDLE;
		sm_stop <= '0';
	elsif scl'event and scl = '0'  then
		state <= next_state;
		sm_stop <= sm_stop_com;
	end if;

end process;

eot <= eot_com;

state_machine_comb: process (state, detect_start, bit_cnt, sda_in, sda)

begin

-- list defaults
sm_stop_com <= '0';
i2c_err <= '0';
eot_com <= '0';
next_state <= state;

		case state is
	
			------------- IDLE STATE -------------
			when IDLE => 
				if detect_start = '1' then
					next_state <= HEADER;
				end if;

			------------- HEADER STATE -------------	
			when HEADER =>
				if bit_cnt = CNT_DONE then
					next_state <= ACK_HEADER;
				end if;

			------------- ACK_HEADER STATE -------------
			when ACK_HEADER =>
				-- set EOT bit
				eot_com <= '1';

				if sda_in = '0' then
					-- ack has been received, transmit data
					next_state <= XMIT_DATA;

				else
					-- no ack received, stop and set error bit
					next_state <= ERR;
					sm_stop_com <= '1';
				end if;

		    ------------ XMIT_DATA State --------------
	            when XMIT_DATA =>

		      if bit_cnt = CNT_DONE then

			   -- Wait for acknowledge
			   next_state <= GET_ACK_DATA;

		      end if;
		
                    ------------- GET_ACK_DATA State --------------
		    when GET_ACK_DATA =>
			-- set EOT bit
			eot_com <= '1';

			if (sda_in = '0') then
			      next_state <= XMIT_DATA;
			 else
				-- no ack received, generate a stop and go
				-- to error state
				sm_stop_com <= '1';
			      next_state <= ERR;
			 end if;

		        ------------- ERR State --------------
		    when ERR =>
			-- set the error flag and return to IDLE state
			i2c_err <= '1';
			next_state <= IDLE;
			sm_stop_com <= '1';


		  end case;
	
		
	end process;
	
master_sda <= shift_out when (state=HEADER or state=XMIT_DATA) 
			else	'1';


-- ************************  I2C Data Shift Register ************************
	I2CSHIFT_REG: SHIFT8
	  port map (  		      
		      clock       => scl_not,
		      reset       => reset, 
		      data_ld   => shift_reg_ld,
		      data_in   => i2cd,
		      shift_in  => sda_in,
		      shift_en  => shift_reg_en,
		      shift_out => shift_out,
		      data_out  => shift_reg );

i2cdata_reg_ctrl: process(clock, reset)

begin
	if reset = RESET_ACTIVE then
		shift_reg_en <= '0';
		shift_reg_ld <= '0';
	elsif clock'event and clock = '1' then

		if ((state = HEADER) or (state = XMIT_DATA)) then		
			shift_reg_en <= '1';
		else 
			shift_reg_en <= '0';
		end if;

		if ((state = IDLE) or (state = GET_ACK_DATA) or (state = ACK_HEADER)) then
				shift_reg_ld <= '1';
		else 
				shift_reg_ld <= '0';
		end if;
	end if;
end process;
	

	
-- ************************  Bit Counter  ************************
	BITCNT : UPCNT4
	  port map(  data      => cnt_start,
		      cnt_en    => bit_cnt_en,
		      load      => bit_cnt_ld,
		      reset       => reset,  
		      clock       => scl_not, 
		      qout      => bit_cnt );

	-- Counter control lines
	bit_cnt_en <= '1' when (state = HEADER) or (state = XMIT_DATA) 
				else '0';

	bit_cnt_ld <= '1' when (state = IDLE) or (state = ACK_HEADER) 
		            or (state = GET_ACK_DATA)
				else '0';

		

end behave;

⌨️ 快捷键说明

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