📄 altera_avalon_i2c_slave.vhd
字号:
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 + -