diff --git a/i2c_master.vhd b/i2c_master.vhd new file mode 100644 index 0000000..20403a4 --- /dev/null +++ b/i2c_master.vhd @@ -0,0 +1,253 @@ +-------------------------------------------------------------------------------- +-- +-- FileName: i2c_master.vhd +-- Dependencies: none +-- Design Software: Quartus II 64-bit Version 13.1 Build 162 SJ Full Version +-- +-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY +-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY +-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL +-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF +-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS +-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), +-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. +-- +-- Version History +-- Version 1.0 11/01/2012 Scott Larson +-- Initial Public Release +-- Version 2.0 06/20/2014 Scott Larson +-- Added ability to interface with different slaves in the same transaction +-- Corrected ack_error bug where ack_error went 'Z' instead of '1' on error +-- Corrected timing of when ack_error signal clears +-- Version 2.1 10/21/2014 Scott Larson +-- Replaced gated clock with clock enable +-- Adjusted timing of SCL during start and stop conditions +-- Version 2.2 02/05/2015 Scott Larson +-- Corrected small SDA glitch introduced in version 2.1 +-- +-------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +use ieee.numeric_std.all; +--USE ieee.std_logic_unsigned.all; + +ENTITY i2c_master IS + GENERIC( + input_clk : INTEGER := 50_000_000; --input clock speed from user logic in Hz + bus_clk : INTEGER := 400_000); --speed the i2c bus (scl) will run at in Hz + PORT( + clk : IN STD_LOGIC; --system clock + reset_n : IN STD_LOGIC; --active low reset + ena : IN STD_LOGIC; --latch in command + addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave + rw : IN STD_LOGIC; --'0' is write, '1' is read + data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave + busy : OUT STD_LOGIC; --indicates transaction in progress + data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data read from slave + ack_error : BUFFER STD_LOGIC; --flag if improper acknowledge from slave + sda : INOUT STD_LOGIC; --serial data output of i2c bus + scl : INOUT STD_LOGIC; --serial clock output of i2c bus + scl_invert: IN STD_LOGIC --true if need to invert output SCL signal + ); +END i2c_master; + +ARCHITECTURE logic OF i2c_master IS + CONSTANT divider : INTEGER := (input_clk/bus_clk)/4; --number of clocks in 1/4 cycle of scl + TYPE machine IS(ready, start, command, slv_ack1, wr, rd, slv_ack2, mstr_ack, stop); --needed states + SIGNAL state : machine; --state machine + SIGNAL data_clk : STD_LOGIC; --data clock for sda + SIGNAL data_clk_prev : STD_LOGIC; --data clock during previous system clock + SIGNAL scl_clk : STD_LOGIC; --constantly running internal scl + SIGNAL scl_ena : STD_LOGIC := '0'; --enables internal scl to output + SIGNAL sda_int : STD_LOGIC := '1'; --internal sda + SIGNAL sda_ena_n : STD_LOGIC; --enables internal sda to output + SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write + SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave + SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave + SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction + SIGNAL stretch : STD_LOGIC := '0'; --identifies if slave is stretching scl +BEGIN + + --generate the timing for the bus clock (scl_clk) and the data clock (data_clk) + PROCESS(clk, reset_n) + VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock generation + BEGIN + IF(reset_n = '0') THEN --reset asserted + stretch <= '0'; + count := 0; + ELSIF(clk'EVENT AND clk = '1') THEN + data_clk_prev <= data_clk; --store previous value of data clock + IF(count = divider*4-1) THEN --end of timing cycle + count := 0; --reset timer + ELSIF(stretch = '0') THEN --clock stretching from slave not detected + count := count + 1; --continue clock generation timing + END IF; + CASE count IS + WHEN 0 TO divider-1 => --first 1/4 cycle of clocking + scl_clk <= '0'; + data_clk <= '0'; + WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking + scl_clk <= '0'; + data_clk <= '1'; + WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking + scl_clk <= '1'; --release scl + IF(scl = '0') THEN --detect if slave is stretching clock + stretch <= '1'; + ELSE + stretch <= '0'; + END IF; + data_clk <= '1'; + WHEN OTHERS => --last 1/4 cycle of clocking + scl_clk <= '1'; + data_clk <= '0'; + END CASE; + END IF; + END PROCESS; + + --state machine and writing to sda during scl low (data_clk rising edge) + PROCESS(clk, reset_n) + BEGIN + IF(reset_n = '0') THEN --reset asserted + state <= ready; --return to initial state + busy <= '1'; --indicate not available + scl_ena <= '0'; --sets scl high impedance + sda_int <= '1'; --sets sda high impedance + ack_error <= '0'; --clear acknowledge error flag + bit_cnt <= 7; --restarts data bit counter + data_rd <= "00000000"; --clear data read port + ELSIF(clk'EVENT AND clk = '1') THEN + IF(data_clk = '1' AND data_clk_prev = '0') THEN --data clock rising edge + CASE state IS + WHEN ready => --idle state + IF(ena = '1') THEN --transaction requested + busy <= '1'; --flag busy + addr_rw <= addr & rw; --collect requested slave address and command + data_tx <= data_wr; --collect requested data to write + state <= start; --go to start bit + ELSE --remain idle + busy <= '0'; --unflag busy + state <= ready; --remain idle + END IF; + WHEN start => --start bit of transaction + busy <= '1'; --resume busy if continuous mode + sda_int <= addr_rw(bit_cnt); --set first address bit to bus + state <= command; --go to command + WHEN command => --address and command byte of transaction + IF(bit_cnt = 0) THEN --command transmit finished + sda_int <= '1'; --release sda for slave acknowledge + bit_cnt <= 7; --reset bit counter for "byte" states + state <= slv_ack1; --go to slave acknowledge (command) + ELSE --next clock cycle of command state + bit_cnt <= bit_cnt - 1; --keep track of transaction bits + sda_int <= addr_rw(bit_cnt-1); --write address/command bit to bus + state <= command; --continue with command + END IF; + WHEN slv_ack1 => --slave acknowledge bit (command) + IF(addr_rw(0) = '0') THEN --write command + sda_int <= data_tx(bit_cnt); --write first bit of data + state <= wr; --go to write byte + ELSE --read command + sda_int <= '1'; --release sda from incoming data + state <= rd; --go to read byte + END IF; + WHEN wr => --write byte of transaction + busy <= '1'; --resume busy if continuous mode + IF(bit_cnt = 0) THEN --write byte transmit finished + sda_int <= '1'; --release sda for slave acknowledge + bit_cnt <= 7; --reset bit counter for "byte" states + state <= slv_ack2; --go to slave acknowledge (write) + ELSE --next clock cycle of write state + bit_cnt <= bit_cnt - 1; --keep track of transaction bits + sda_int <= data_tx(bit_cnt-1); --write next bit to bus + state <= wr; --continue writing + END IF; + WHEN rd => --read byte of transaction + busy <= '1'; --resume busy if continuous mode + IF(bit_cnt = 0) THEN --read byte receive finished + IF(ena = '1' AND addr_rw = addr & rw) THEN --continuing with another read at same address + sda_int <= '0'; --acknowledge the byte has been received + ELSE --stopping or continuing with a write + sda_int <= '1'; --send a no-acknowledge (before stop or repeated start) + END IF; + bit_cnt <= 7; --reset bit counter for "byte" states + data_rd <= data_rx; --output received data + state <= mstr_ack; --go to master acknowledge + ELSE --next clock cycle of read state + bit_cnt <= bit_cnt - 1; --keep track of transaction bits + state <= rd; --continue reading + END IF; + WHEN slv_ack2 => --slave acknowledge bit (write) + IF(ena = '1') THEN --continue transaction + busy <= '0'; --continue is accepted + addr_rw <= addr & rw; --collect requested slave address and command + data_tx <= data_wr; --collect requested data to write + IF(addr_rw = addr & rw) THEN --continue transaction with another write + sda_int <= data_wr(bit_cnt); --write first bit of data + state <= wr; --go to write byte + ELSE --continue transaction with a read or new slave + state <= start; --go to repeated start + END IF; + ELSE --complete transaction + state <= stop; --go to stop bit + END IF; + WHEN mstr_ack => --master acknowledge bit after a read + IF(ena = '1') THEN --continue transaction + busy <= '0'; --continue is accepted and data received is available on bus + addr_rw <= addr & rw; --collect requested slave address and command + data_tx <= data_wr; --collect requested data to write + IF(addr_rw = addr & rw) THEN --continue transaction with another read + sda_int <= '1'; --release sda from incoming data + state <= rd; --go to read byte + ELSE --continue transaction with a write or new slave + state <= start; --repeated start + END IF; + ELSE --complete transaction + state <= stop; --go to stop bit + END IF; + WHEN stop => --stop bit of transaction + busy <= '0'; --unflag busy + state <= ready; --go to idle state + END CASE; + ELSIF(data_clk = '0' AND data_clk_prev = '1') THEN --data clock falling edge + CASE state IS + WHEN start => + IF(scl_ena = '0') THEN --starting new transaction + scl_ena <= '1'; --enable scl output + ack_error <= '0'; --reset acknowledge error output + END IF; + WHEN slv_ack1 => --receiving slave acknowledge (command) + IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge + ack_error <= '1'; --set error output if no-acknowledge + END IF; + WHEN rd => --receiving slave data + data_rx(bit_cnt) <= sda; --receive current slave data bit + WHEN slv_ack2 => --receiving slave acknowledge (write) + IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge + ack_error <= '1'; --set error output if no-acknowledge + END IF; + WHEN stop => + scl_ena <= '0'; --disable scl + WHEN OTHERS => + NULL; + END CASE; + END IF; + END IF; + END PROCESS; + + --set sda output + WITH state SELECT + sda_ena_n <= data_clk_prev WHEN start, --generate start condition + NOT data_clk_prev WHEN stop, --generate stop condition + sda_int WHEN OTHERS; --set to internal sda signal + + --set scl and sda outputs + --scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0') ELSE 'Z'; + scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0' AND scl_invert = '0') ELSE + '1' WHEN (scl_ena = '1' AND scl_clk = '0' AND scl_invert = '1') ELSE + 'Z'; + sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z'; + +END logic; diff --git a/odio_repeater.vhd b/odio_repeater.vhd deleted file mode 100644 index fd791d1..0000000 --- a/odio_repeater.vhd +++ /dev/null @@ -1,105 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; - ------------------------------------------------------------- -entity odio_repeater is - generic ( - WAIT_CYCLES : integer := 3 - ); - port ( - clk : in std_logic; - rstn : in std_logic; - signal_n1 : inout std_logic; - signal_n2 : inout std_logic - ); -end entity odio_repeater; ------------------------------------------------------------- -architecture arch of odio_repeater is - - component debounce is - generic ( - WAIT_CYCLES : integer := 5 - ); - port ( - signal_in : in std_logic; - signal_out : out std_logic; - clk : in std_logic - ); - end component; - - type state_t is (idle, n1_to_n2, n2_to_n1); - signal state : state_t := idle; - - signal s_n1_i_raw, s_n1_i, s_n1_o, s_n1_prev : std_logic; - signal s_n2_i_raw, s_n2_i, s_n2_o, s_n2_prev : std_logic; - -begin - - -- Tri-state IO handling - s_n1_i_raw <= signal_n1; - s_n2_i_raw <= signal_n2; - signal_n1 <= '0' when s_n1_o = '0' else 'Z'; - signal_n2 <= '0' when s_n2_o = '0' else 'Z'; - - -- Debounce input lines - n1_debounce : debounce - generic map ( - WAIT_CYCLES => WAIT_CYCLES - ) - port map ( - clk => clk, - signal_in => s_n1_i_raw, - signal_out => s_n1_i - ); - - n2_debounce : debounce - generic map ( - WAIT_CYCLES => WAIT_CYCLES - ) - port map ( - clk => clk, - signal_in => s_n2_i_raw, - signal_out => s_n2_i - ); - - -- Main open-drain IO repeater process - rptr_proc: process(clk, rstn, s_n1_i, s_n2_i) is - begin - if rstn = '0' then - s_n1_o <= '1'; - s_n2_o <= '1'; - s_n1_prev <= s_n1_i; - s_n2_prev <= s_n2_i; - state <= idle; - - elsif (rising_edge(clk)) then - s_n1_prev <= s_n1_i; - s_n2_prev <= s_n2_i; - - case state is - when idle => - if (s_n1_prev = '1' and s_n1_i = '0') then - s_n2_o <= '0'; - state <= n1_to_n2; - elsif (s_n2_prev = '1' and s_n2_i = '0') then - s_n1_o <= '0'; - state <= n2_to_n1; - end if; - - when n1_to_n2 => - if (s_n1_prev = '0' and s_n1_i = '1') then - s_n2_o <= '1'; - state <= idle; - end if; - - when n2_to_n1 => - if (s_n2_prev = '0' and s_n2_i = '1') then - s_n1_o <= '1'; - state <= idle; - end if; - end case; - - end if; - end process; - -end architecture arch; diff --git a/sim_switcher_top.vhd b/sim_switcher_top.vhd index 72cac6b..40f4bd0 100644 --- a/sim_switcher_top.vhd +++ b/sim_switcher_top.vhd @@ -225,7 +225,7 @@ architecture rtl of sim_switcher_top is type arr_regs_t is array (natural range <>) of std_logic_vector(7 downto 0); signal pse_regs_to_read, pse_regs_value: arr_regs_t(0 to PSE_REG_NUM-1); - type i2c_pse_fsm_t is (ready, i2c_trn_start, i2c_trn_main, i2c_wr_wait, i2c_rd_wait, wait_ack); + type i2c_pse_fsm_t is (ready, i2c_trn_start, i2c_trn_main, i2c_trn_final_word_wait, i2c_wr_wait, i2c_rd_wait, wait_ack); signal i2c_state : i2c_pse_fsm_t := ready; signal s_i2c_data_wr : std_logic_vector(7 downto 0); @@ -239,6 +239,11 @@ architecture rtl of sim_switcher_top is signal i2c_wr_done : std_logic; signal reg_i2c_trn_dir : std_logic; signal wait_i2c_start : std_logic; + signal pse_i2c_write_reg : std_logic; + signal pse_i2c_write_ack : std_logic; + signal pse_i2c_addr_wrtn : std_logic; + signal pse_i2c_wr_reg_num : std_logic_vector(7 downto 0); + signal pse_i2c_wr_reg_val : std_logic_vector(7 downto 0); begin @@ -294,7 +299,7 @@ begin scl_invert => '0' ); - -- SIM attach reset assigment: default is 1-to-1 SIM to MODEM connection + -- PSE register addresses pse_regs_to_read <= ( 0 => x"0C", -- RO 1 => x"0D", -- RO @@ -309,23 +314,40 @@ begin ------------------------------ -- PSE read trigger process -- ------------------------------ - pse_readtrig_proc: process(clk25_i, s_rstn_i, wait_i2c_start, i2c_core_busy) is + pse_readtrig_proc: process(clk25_i, s_rstn_i, wait_i2c_start, i2c_core_busy, pse_i2c_write_reg) is variable wait_cnt : natural := 0; begin if (s_rstn_i = '0') then - wait_i2c_start <= '0'; + i2c_core_start <= '0'; + wait_i2c_start <= '0'; + reg_i2c_trn_dir <= '1'; + pse_i2c_write_ack <= '0'; + elsif (rising_edge(clk25_i)) then - if (wait_i2c_start = '1') then + -- Clear write ack flag if pse_i2c_write_reg has been cleared + if (pse_i2c_write_reg = '0') then + pse_i2c_write_ack <= '0'; + end if; + + -- Main PSE I2C core control process + if (wait_i2c_start = '1') then -- Wait until PSE I2C core goes to busy state if wait_i2c_start is set if (i2c_core_busy = '1') then wait_i2c_start <= '0'; end if; - else - if (i2c_core_start = '1' and i2c_core_busy = '0') then + elsif (i2c_core_busy = '0') then -- If PSE I2C core is not busy - check for required operation and proceed + if (i2c_core_start = '1') then i2c_core_start <= '0'; + elsif (pse_i2c_write_reg = '1') then + wait_cnt := 0; + wait_i2c_start <= '1'; + pse_i2c_write_ack <= '1'; + reg_i2c_trn_dir <= '0'; -- I2C write op + i2c_core_start <= '1'; elsif (wait_cnt > PSE_POLL_INTERVAL) then - wait_cnt := 0; - wait_i2c_start <= '1'; - i2c_core_start <= '1'; + wait_cnt := 0; + wait_i2c_start <= '1'; + reg_i2c_trn_dir <= '1'; -- I2C read op + i2c_core_start <= '1'; end if; wait_cnt := wait_cnt + 1; end if; @@ -361,37 +383,43 @@ begin i2c_core_busy <= '1'; reg_num_rd := 0; i2c_busy_prev <= '0'; - reg_i2c_trn_dir <= '1'; end if; when i2c_trn_start => - s_i2c_txn_start <= '1'; -- Initiate the transaction - s_i2c_rw_flag <= '0'; -- First byte is always write - s_i2c_data_wr <= pse_regs_to_read(reg_num_rd); -- Place reg number to I2C master core + s_i2c_txn_start <= '1'; -- Initiate the transaction + s_i2c_rw_flag <= '0'; -- First byte is always write + case reg_i2c_trn_dir is + when '0' => -- write + s_i2c_data_wr <= pse_i2c_wr_reg_num; -- Place reg number to I2C master core + pse_i2c_addr_wrtn <= '0'; + when '1' => -- read + s_i2c_data_wr <= pse_regs_to_read(reg_num_rd); -- Place reg number to I2C master core + end case; i2c_busy_prev <= s_i2c_busy_flag; i2c_wr_done <= '0'; i2c_state <= i2c_trn_main; when i2c_trn_main => - i2c_busy_prev <= s_i2c_busy_flag; -- Capture the value of the previous i2c busy signal - if (i2c_busy_prev = '0' and s_i2c_busy_flag = '1') then -- I2C busy just went high - case reg_i2c_trn_dir is -- Switches to the needed transaction direction - -- when '0' => -- When write - continue to write - -- data_wr_cnt := data_wr_cnt + 1; - -- if (data_wr_cnt > 0 and data_wr_cnt < spi_command_len) then -- Keep writing if there's still data in the RAM - -- spi_ram_raddr <= data_wr_cnt; - -- i2c_state <= wait_ram; - -- else -- Else - finish the transaction - -- i2c_state <= i2c_trn_final_word_wait; - -- s_i2c_txn_start <= (others => '0'); - -- end if; - when '1' => -- When read - if (i2c_wr_done = '0') then -- Change the transaction from Write to Read after writing the first byte - s_i2c_rw_flag <= '1'; -- Switch to read + i2c_busy_prev <= s_i2c_busy_flag; -- Capture the value of the previous i2c busy signal + + if (i2c_busy_prev = '0' and s_i2c_busy_flag = '1') then -- I2C busy just went high + case reg_i2c_trn_dir is -- Switches to the needed transaction direction + when '0' => -- When write - continue to write + if (pse_i2c_addr_wrtn = '0') then -- Keep writing if there's still data in the RAM + pse_i2c_addr_wrtn <= '1'; + s_i2c_data_wr <= pse_i2c_wr_reg_val; -- Prepare register value to write + else -- Else - finish the transaction + i2c_state <= i2c_trn_final_word_wait; + s_i2c_txn_start <= '0'; + end if; + + when '1' => -- When read + if (i2c_wr_done = '0') then -- Change the transaction from Write to Read after writing the first byte + s_i2c_rw_flag <= '1'; -- Switch to read i2c_state <= i2c_wr_wait; else i2c_wr_done <= '0'; - s_i2c_txn_start <= '0'; -- Stop core after reading 1 byte + s_i2c_txn_start <= '0'; -- Stop core after reading 1 byte i2c_state <= i2c_rd_wait; end if; @@ -401,14 +429,14 @@ begin end if; - -- when i2c_trn_final_word_wait => - -- if (i2c_busy_prev = '1' and s_i2c_busy_flag = '0') then -- I2C became free - -- i2c_state <= wait_ack; - -- end if; + when i2c_trn_final_word_wait => + if (i2c_busy_prev = '1' and s_i2c_busy_flag = '0') then -- I2C became free + i2c_state <= wait_ack; + end if; when i2c_wr_wait => - if (s_i2c_busy_flag = '0') then -- Indicates data read in last command is ready - i2c_state <= i2c_trn_main; -- Transaction complete, go to next state in design + if (s_i2c_busy_flag = '0') then -- Indicates data read in last command is ready + i2c_state <= i2c_trn_main; -- Transaction complete, go to next state in design i2c_wr_done <= '1'; i2c_busy_prev <= s_i2c_busy_flag; end if; @@ -735,6 +763,7 @@ begin reg_expio_dir <= (others => '0'); -- All Expansion card IOs direction is IN reg_expio_intdirh2l <= (others => '0'); -- Expansion card GPIO default line interrupt generation for High-to-Low transition is off reg_expio_intdirl2h <= (others => '0'); -- Expansion card GPIO default line interrupt generation for Low-to-High transition is off + pse_i2c_write_reg <= '0'; elsif (rising_edge(clk25_i)) then if (s_int_expio_reset_ack = '1') then @@ -748,6 +777,10 @@ begin case i2c_slv_state is when ready => wait_cnt := 0; + -- Reset pse_i2c_write_reg trigger if PSE I2C core has ACKed the write operation + if (pse_i2c_write_ack = '1') then + pse_i2c_write_reg <= '0'; + end if; i2c_data_to_master <= (others => '0'); if (i2c_data_valid = '1') then -- master sent a register addr byte -- Save register address for later use in write procedure @@ -904,7 +937,7 @@ begin i2c_data_to_master <= pse_regs_value(4); i2c_slv_state <= wait_while_sent; - when x"65" => -- Read PSE register "Operating Mode" 0x12 + when x"65" => -- Read PSE register "Operating Mode" 0x12, 00 Off, 01 Manual, 10 Semi-Auto, 11 Auto i2c_data_to_master <= pse_regs_value(5); i2c_slv_state <= wait_while_sent; @@ -976,6 +1009,15 @@ begin when x"D5" => -- Write POE IN control register i2c_slv_state <= receive_byte; + when x"E5" => -- Write PSE register "Operating Mode" 0x12 + i2c_slv_state <= receive_byte; + + when x"E6" => -- Write PSE register "Disconnect Enable" 0x13 + i2c_slv_state <= receive_byte; + + when x"E7" => -- Write PSE register "Detect/Class Enable" 0x14 + i2c_slv_state <= receive_byte; + when others => i2c_slv_state <= ready; end case; @@ -1044,6 +1086,21 @@ begin when x"D5" => -- Write POE IN control register reg_poepd_ctl <= i2c_data_from_master(0); + when x"E5" => -- Write PSE register "Operating Mode" 0x12 + pse_i2c_wr_reg_val <= i2c_data_from_master(7 downto 0); + pse_i2c_wr_reg_num <= x"12"; + pse_i2c_write_reg <= '1'; + + when x"E6" => -- Write PSE register "Disconnect Enable" 0x13 + pse_i2c_wr_reg_val <= i2c_data_from_master(7 downto 0); + pse_i2c_wr_reg_num <= x"13"; + pse_i2c_write_reg <= '1'; + + when x"E7" => -- Write PSE register "Detect/Class Enable" 0x14 + pse_i2c_wr_reg_val <= i2c_data_from_master(7 downto 0); + pse_i2c_wr_reg_num <= x"14"; + pse_i2c_write_reg <= '1'; + when others => null; end case;