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

📄 altera_avalon_i2c_slave.vhd

📁 i2c从设备的源码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
				i2c_set_data <= '0';
				i2c_rx_data  <= i2c_rx_data;

				i2c_set_interrupt <= '0';
				i2c_counter <= (others => '0');
				i2c_shift_reg <= (others => '0');
				i2c_read_writen <= '0';

				sda_pad_o <= '1';

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					i2c_slave_state <= I2C_SLAVE_STATE_RX_ADDR; -- begin clocking in address after the clock input goes low
				else
					i2c_slave_state <= I2C_SLAVE_STATE_START;
				end if;

			--------------------------------------------------------------------------
			elsif i2c_slave_state = I2C_SLAVE_STATE_RX_ADDR then
			--------------------------------------------------------------------------
				
				i2c_set_data <= '0';
				i2c_rx_data  <= i2c_rx_data;

				i2c_set_interrupt <= '0';

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					if i2c_counter = "0111" then

						if i2c_shift_reg(6 downto 0) = i2c_address then

							sda_pad_o <= '0'; -- send the ack
							i2c_slave_state <= I2C_SLAVE_STATE_ADDR_ACK;
						else
							sda_pad_o <= '1';
							i2c_slave_state <= I2C_SLAVE_STATE_IDLE;
						end if;

						i2c_read_writen <= sda_pad_i; -- record the read/writen bit
					else
						sda_pad_o <= '1';
						i2c_read_writen <= i2c_read_writen;
					end if;

					i2c_counter <= i2c_counter + 1;

					if i2c_counter < "0111" then

						i2c_shift_reg(0) <= sda_pad_i;
						i2c_shift_reg(7 downto 1) <= i2c_shift_reg(6 downto 0);

					else
						i2c_shift_reg <= i2c_shift_reg;
					end if;

				else
					i2c_counter <= i2c_counter;
					i2c_shift_reg <= i2c_shift_reg;
					i2c_read_writen <= i2c_read_writen;

					sda_pad_o <= '1';

					i2c_slave_state <= I2C_SLAVE_STATE_RX_ADDR;
				end if;

			--------------------------------------------------------------------------
			elsif i2c_slave_state = I2C_SLAVE_STATE_ADDR_ACK then
			--------------------------------------------------------------------------

				i2c_set_data <= '0';
				i2c_rx_data  <= i2c_rx_data;

				i2c_set_interrupt <= '0';

				i2c_counter <= (others => '0');
				i2c_read_writen <= i2c_read_writen;

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					if i2c_read_writen = '1' then

						i2c_slave_state <= I2C_SLAVE_STATE_READ;
						i2c_shift_reg <= i2c_data(6 downto 0) & '0';
						sda_pad_o <= i2c_data(7);
					else
						i2c_slave_state <= I2C_SLAVE_STATE_WRITE;
						i2c_shift_reg <= (others => '0');
						sda_pad_o <= '1';
					end if;
				else
					i2c_slave_state <= I2C_SLAVE_STATE_ADDR_ACK;
					i2c_shift_reg <= i2c_shift_reg;
					sda_pad_o <= '0';
				end if;

			--------------------------------------------------------------------------
			elsif i2c_slave_state = I2C_SLAVE_STATE_READ then
			--------------------------------------------------------------------------

				i2c_set_data <= '0';
				i2c_rx_data  <= i2c_rx_data;

				i2c_set_interrupt <= '0';

				i2c_read_writen <= i2c_read_writen;

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					if i2c_counter = "0111" then

						sda_pad_o <= '1';

						i2c_shift_reg <= i2c_shift_reg;

						i2c_slave_state <= I2C_SLAVE_STATE_STOP;
					else
						sda_pad_o <= i2c_shift_reg(7);

						i2c_shift_reg(7 downto 1) <= i2c_shift_reg(6 downto 0);
						i2c_shift_reg(0) <= '1';

						i2c_slave_state <= I2C_SLAVE_STATE_READ;
					end if;

					i2c_counter <= i2c_counter + 1;

				else
					i2c_counter <= i2c_counter;
					i2c_shift_reg <= i2c_shift_reg;

					sda_pad_o <= sda_pad_o;

					i2c_slave_state <= I2C_SLAVE_STATE_READ;
				end if;

			--------------------------------------------------------------------------
			elsif i2c_slave_state = I2C_SLAVE_STATE_WRITE then
			--------------------------------------------------------------------------
				i2c_read_writen <= i2c_read_writen;

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					if i2c_counter = "0111" then

						sda_pad_o <= '0'; -- send the ack

						i2c_set_interrupt <= '1';
						i2c_set_data <= '1';
						i2c_slave_state <= I2C_SLAVE_STATE_STOP;

						i2c_rx_data <= i2c_shift_reg(6 downto 0) & sda_pad_i;
					else
						sda_pad_o <= '1';

						i2c_set_interrupt <= '0';
						i2c_set_data <= '0';
						i2c_rx_data <= i2c_rx_data;
						i2c_slave_state <= I2C_SLAVE_STATE_WRITE;
					end if;

					i2c_shift_reg(0) <= sda_pad_i;
					i2c_shift_reg(7 downto 1) <= i2c_shift_reg(6 downto 0);

					i2c_counter <= i2c_counter + 1;
				else
					i2c_set_interrupt <= '0';
					i2c_set_data <= i2c_set_data;
					i2c_counter <= i2c_counter;
					i2c_shift_reg <= i2c_shift_reg;

					sda_pad_o <= '1';

					i2c_slave_state <= I2C_SLAVE_STATE_WRITE;
				end if;
			--------------------------------------------------------------------------
			elsif i2c_slave_state = I2C_SLAVE_STATE_STOP then
			--------------------------------------------------------------------------

				i2c_set_data <= '0';
				i2c_rx_data  <= i2c_rx_data;

				i2c_set_interrupt <= '0';
				i2c_counter <= (others => '0');
				i2c_shift_reg <= (others => '0');
				i2c_read_writen <= '0';

				if last_scl_pad_i = '1' and scl_pad_i = '0' then

					sda_pad_o <= '1'; -- only master can issue stop

					i2c_slave_state <= I2C_SLAVE_STATE_IDLE;
				else
					sda_pad_o <= sda_pad_o;

					i2c_slave_state <= I2C_SLAVE_STATE_STOP;
				end if;

			--------------------------------------------------------------------------
			else -- bad state - reset to IDLE
			--------------------------------------------------------------------------
				i2c_slave_state <= I2C_SLAVE_STATE_IDLE;
			end if;

			--------------------------------------------------------------------------
			-- i2c receiver filtering and edge detection
			--------------------------------------------------------------------------

			-- I2C clock

			scl_metafilt(3 downto 1) <= scl_metafilt(2 downto 0);
			scl_metafilt(0) <= scl;

			if scl_pad_i = '1' then
				if scl_metafilt = "0000" then
					scl_pad_i <= '0';
				else
					scl_pad_i <= scl_pad_i;
				end if;
			else
				if scl_metafilt = "1111" then
					scl_pad_i <= '1';
				else
					scl_pad_i <= scl_pad_i;
				end if;
			end if;

			last_scl_pad_i <= scl_pad_i; -- for transition detection

			-- I2C data

			sda_metafilt(3 downto 1) <= sda_metafilt(2 downto 0);
			sda_metafilt(0) <= sda;

			if sda_pad_i = '1' then
				if sda_metafilt = "0000" then
					sda_pad_i <= '0';
				else
					sda_pad_i <= sda_pad_i;
				end if;
			else
				if sda_metafilt = "1111" then
					sda_pad_i <= '1';
				else
					sda_pad_i <= sda_pad_i;
				end if;
			end if;

			last_sda_pad_i <= sda_pad_i; -- for transition detection

		end if;
	end process i2c_slave;

end rtl;


⌨️ 快捷键说明

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