From 3d1fcb871b8d115b1a2db1449ae06e9840891a6e Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Wed, 10 Jul 2013 19:19:53 +0200 Subject: [PATCH] reworked SFP I2C interface. Automatic reading, not yet working --- sfp_interface.vhd | 96 +++++++++------------ special/sfp_i2c_readout.vhd | 165 ++++++++++++++++++++++++++++++++++++ trb_net_components.vhd | 42 +++++++++ 3 files changed, 245 insertions(+), 58 deletions(-) create mode 100644 special/sfp_i2c_readout.vhd diff --git a/sfp_interface.vhd b/sfp_interface.vhd index e7a2705..3577341 100644 --- a/sfp_interface.vhd +++ b/sfp_interface.vhd @@ -22,7 +22,7 @@ entity Sfp_Interface is RST_IN : in std_logic; -- System reset -- host side START_PULSE : in std_logic; -- System start pulse - DEVICE_ADDRESS : in std_logic_vector(7 downto 0); -- Device address input: x"06" for SFP_Interface + DEVICE_ADDRESS : in std_logic_vector(7 downto 0) :=x"06"; -- Device address input: x"06" for SFP_Interface DATA_OUT : out std_logic_vector(15 downto 0); -- Data output from optical transmitter READ_DONE : out std_logic; -- Reading process done SFP_ADDRESS : in std_logic_vector(7 downto 0); -- SFP address @@ -34,8 +34,8 @@ entity Sfp_Interface is -- x"68" => Measured RX optical input power | --------------------------------------------------------------- -- optical transceiver side - SCL : inout std_logic; -- I2C Serial clock I/O - SDA : inout std_logic; -- I2C Serial data I/O + SCL : out std_logic_vector(15 downto 0); -- I2C Serial clock I/O + SDA : inout std_logic_vector(15 downto 0); -- I2C Serial data I/O DEBUG : out std_logic_vector(31 downto 0) ); @@ -77,10 +77,11 @@ architecture behavioral of Sfp_Interface is signal en_shift_reg : std_logic := '0'; signal en_FSM : std_logic := '0'; signal sfp_address_i : std_logic_vector(7 downto 0) := x"00"; - signal device_address_i : std_logic_vector(7 downto 0) := x"00"; + signal device_address_i : std_logic_vector(7 downto 0) := x"06"; signal start_pulse_i : std_logic := '0'; -- signal debug_signal : std_logic_vector(31 downto 0) := x"00000000"; + signal select_line : integer range 0 to 15; ------------------------------------------------------------------------------- type STATES is (IDLE, RESET_A, RESET_B, RESET_C, RESET_D, START_A, START_B, START_C, START_D, STOP_A, STOP_B, STOP_C, STOP_D, SEND_BYTE_A, @@ -91,58 +92,37 @@ architecture behavioral of Sfp_Interface is signal STATE_NEXT : STATES; ------------------------------------------------------------------------------- -------------------------------------------------------------------------------- - component up_down_counter - generic ( - NUMBER_OF_BITS : positive - ); - port ( - CLK : in std_logic; - RESET : in std_logic; - COUNT_OUT : out std_logic_vector(NUMBER_OF_BITS-1 downto 0); - UP_IN : in std_logic; - DOWN_IN : in std_logic - ); - end component; -------------------------------------------------------------------------------- ------------------------------------------------------------------------------- begin stop_reset_cnt <= rst_in or rst_reset_cnt; stop_bit_cnt <= rst_in or rst_bit_cnt; stop_fre_cnt <= rst_in or rst_fre_cnt; -------------------------------------------------------------------------------- - Reset_Counter : up_down_counter - generic map ( - NUMBER_OF_BITS => 4) - port map ( - CLK => CLK_IN, - RESET => stop_reset_cnt, - COUNT_OUT => reset_cnt, - UP_IN => en_reset_cnt, - DOWN_IN => '0'); -------------------------------------------------------------------------------- - Bit_Counter : up_down_counter - generic map ( - NUMBER_OF_BITS => 6) - port map ( - CLK => CLK_IN, - RESET => stop_bit_cnt, - COUNT_OUT => bit_cnt, - UP_IN => en_bit_cnt, - DOWN_IN => '0'); -------------------------------------------------------------------------------- - Frequency_Counter : up_down_counter - generic map ( - NUMBER_OF_BITS => 16) - port map ( - CLK => CLK_IN, - RESET => stop_fre_cnt, - COUNT_OUT => fre_cnt, - UP_IN => '1', - DOWN_IN => '0'); -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- + select_line <= to_integer(unsigned(DEVICE_ADDRESS(3 downto 0))); + + proc_counters : process begin + wait until rising_edge(CLK_IN); + if stop_fre_cnt = '1' then + fre_cnt <= x"0000"; + else + fre_cnt <= std_logic_vector(unsigned(fre_cnt)+1); + end if; + + if stop_bit_cnt = '1' then + bit_cnt <= "000000"; + elsif en_bit_cnt = '1' then + bit_cnt <= std_logic_vector(unsigned(bit_cnt)+1); + end if; + + if stop_reset_cnt = '1' then + reset_cnt <= "0000"; + elsif en_reset_cnt = '1' then + reset_cnt <= std_logic_vector(unsigned(reset_cnt)+1); + end if; + + + end process; + Frequency_Division : process (CLK_IN, RST_IN, fre_cnt) begin if rising_edge(CLK_IN) then @@ -187,8 +167,8 @@ begin byte_2_send_mem <= x"00"; reset_done_mem <= '0'; bit_read_mem <= '0'; - SCL <= 'Z'; - SDA <= 'Z'; + SCL <= (others => 'Z'); + SDA <= (others => 'Z'); sda_int_mem <= '1'; DEBUG <= x"00000000"; else @@ -200,8 +180,8 @@ begin reset_done_mem <= reset_done; sda_int_mem <= sda_int; bit_read_mem <= bit_read; - SCL <= scl_int; - SDA <= sda_int; + SCL <= (others => scl_int); + SDA <= (others => sda_int); DEBUG <= debug_signal; end if; end if; @@ -244,9 +224,9 @@ begin case (STATE_CURRENT) is --IDLE when IDLE => - if device_address_i = x"06" and start_pulse_i = '1' and reset_done = '0' then + if start_pulse_i = '1' and reset_done = '0' then STATE_NEXT <= RESET_C; - elsif device_address_i = x"06" and start_pulse_i = '1' and reset_done = '1' then + elsif start_pulse_i = '1' and reset_done = '1' then STATE_NEXT <= START_A; else STATE_NEXT <= IDLE; @@ -424,7 +404,7 @@ begin -- when READ_BYTE_C => scl_int <= '1'; - bit_read <= SDA; + bit_read <= SDA(select_line); if en_FSM = '1' then STATE_NEXT <= READ_BYTE_D; end if; @@ -522,7 +502,7 @@ begin -- when READ_ACK_C => scl_int <= '1'; - bit_read <= SDA; + bit_read <= SDA(select_line); if en_FSM = '1' then STATE_NEXT <= READ_ACK_D; end if; diff --git a/special/sfp_i2c_readout.vhd b/special/sfp_i2c_readout.vhd new file mode 100644 index 0000000..767b6e7 --- /dev/null +++ b/special/sfp_i2c_readout.vhd @@ -0,0 +1,165 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.trb_net_std.all; +use work.trb_net_components.all; + + +entity sfp_i2c_readout is + generic( + SFP_NUMBER : integer := 6 + ); + port( + CLOCK : in std_logic; + RESET : in std_logic; + + BUS_DATA_IN : in std_logic_vector(31 downto 0); + BUS_DATA_OUT : out std_logic_vector(31 downto 0); + BUS_ADDR_IN : in std_logic_vector(7 downto 0); + BUS_WRITE_IN : in std_logic; + BUS_READ_IN : in std_logic; + BUS_ACK_OUT : out std_logic; + BUS_NACK_OUT : out std_logic; + + SDA : inout std_logic_vector(SFP_NUMBER-1 downto 0); + SCL : out std_logic_vector(SFP_NUMBER-1 downto 0) + ); +end entity; + +architecture sfp_i2c_readout_arch of sfp_i2c_readout is + +--------------------------------------------------------------- +-- SFP_ADDRESS values: | +--------------------------------------------------------------| +-- x"60" => Internally measured module temperature | +-- x"62" => Voltage | +-- x"64" => TX current | +-- x"66" => Measured TX optical output power | +-- x"68" => Measured RX optical input power | +--------------------------------------------------------------- + + +signal start_i : std_logic; +signal data_i : std_logic_vector(15 downto 0); +signal done_i : std_logic; +signal address_i : std_logic_vector(7 downto 0); + +signal sfp_i : integer range 0 to 15; +signal reg_i : std_logic_vector(7 downto 0); +signal override_i: std_logic; +signal override_addr : std_logic_vector(7 downto 0); +signal debug_i : std_logic_vector(31 downto 0); +signal devaddress_i : std_logic_vector(7 downto 0); + +type ram_t is array(0 to 255) of std_logic_vector(15 downto 0); +signal ram : ram_t; + +type state_t is (IDLE, START_SFP, START_REG, GET_DATA,NEXT_REG); +signal state : state_t; + +begin + + debug_i(15 downto 12) <= std_logic_vector(to_unsigned(sfp_i,4)); + debug_i(23 downto 16) <= reg_i; + debug_i(31 downto 24) <= data_i(7 downto 0); + + THE_I2C_CONTROLLER : Sfp_Interface + port map( + CLK_IN => CLOCK, + RST_IN => RESET, + START_PULSE => start_i, + DATA_OUT => data_i, + DEVICE_ADDRESS => devaddress_i, + READ_DONE => done_i, + SFP_ADDRESS => address_i, + SCL(SFP_NUMBER-1 downto 0) => SCL, + SDA(SFP_NUMBER-1 downto 0) => SDA, + DEBUG(7 downto 0) => debug_i(7 downto 0) + ); + + + + devaddress_i(7 downto 4) <= x"0"; + devaddress_i(3 downto 0) <= std_logic_vector(to_unsigned(sfp_i,4)); + + proc_i2c_ctrl : process begin + wait until rising_edge(CLOCK); + address_i <= reg_i; + start_i <= '0'; + case state is + when IDLE => + reg_i <= x"60"; + sfp_i <= 0; + state <= START_REG; + debug_i(11 downto 8) <= x"1"; + + when START_REG => + debug_i(11 downto 8) <= x"2"; + if debug_i(7 downto 0) = x"01" then + state <= GET_DATA; + start_i <= '1'; + end if; + + when GET_DATA => + debug_i(11 downto 8) <= x"3"; + if done_i = '1' then + state <= NEXT_REG; + if override_i = '0' then + ram(sfp_i*16+to_integer(unsigned(reg_i(3 downto 1)))) <= data_i; + else + ram(sfp_i*16+15) <= data_i; + end if; + end if; + + when NEXT_REG => + debug_i(11 downto 8) <= x"4"; + if override_i = '1' then + reg_i <= override_addr; + elsif reg_i >= x"68" then + reg_i <= x"60"; + else + reg_i <= std_logic_vector(unsigned(reg_i) + 2); + end if; + if override_i = '1' or reg_i = x"68" then + if sfp_i = SFP_NUMBER -1 then + sfp_i <= 0; + else + sfp_i <= sfp_i + 1; + end if; + end if; + state <= START_REG; + end case; + if RESET = '1' then + state <= IDLE; + end if; + end process; + + + proc_sctrl : process begin + wait until rising_edge(CLOCK); + BUS_ACK_OUT <= '0'; + BUS_NACK_OUT <= '0'; + BUS_DATA_OUT <= x"EE000000"; + if BUS_READ_IN = '1' then + if BUS_ADDR_IN = x"FF" then + BUS_ACK_OUT <= '1'; + BUS_DATA_OUT <= debug_i; + else + BUS_ACK_OUT <= '1'; + BUS_DATA_OUT(31 downto 16) <= x"0000"; + BUS_DATA_OUT(15 downto 0) <= ram(to_integer(unsigned(BUS_ADDR_IN))); + end if; + elsif BUS_WRITE_IN = '1' then + if BUS_ADDR_IN = x"FF" then + BUS_ACK_OUT <= '1'; + override_i <= BUS_DATA_IN(8); + override_addr <= BUS_DATA_IN(7 downto 0); + else + BUS_NACK_OUT <= '1'; + end if; + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/trb_net_components.vhd b/trb_net_components.vhd index 74add9d..95b433e 100644 --- a/trb_net_components.vhd +++ b/trb_net_components.vhd @@ -12,7 +12,49 @@ package trb_net_components is --This list of components is sorted alphabetically, ignoring the trb_net or trb_net16 prefix of some component names + component Sfp_Interface is + generic ( + I2C_SPEED : std_logic_vector(15 downto 0) := x"0200" + ); + port( + CLK_IN : in std_logic; -- System clock + RST_IN : in std_logic; -- System reset + -- host side + START_PULSE : in std_logic; -- System start pulse + DEVICE_ADDRESS : in std_logic_vector(7 downto 0); -- Device address input: x"06" for SFP_Interface + DATA_OUT : out std_logic_vector(15 downto 0); -- Data output from optical transmitter + READ_DONE : out std_logic; -- Reading process done + SFP_ADDRESS : in std_logic_vector(7 downto 0); -- SFP address + -- optical transceiver side + SCL : out std_logic_vector(15 downto 0); -- I2C Serial clock I/O + SDA : inout std_logic_vector(15 downto 0); -- I2C Serial data I/O + DEBUG : out std_logic_vector(31 downto 0) + ); + end component; + + component sfp_i2c_readout is + generic( + SFP_NUMBER : integer := 6 + ); + port( + CLOCK : in std_logic; + RESET : in std_logic; + + BUS_DATA_IN : in std_logic_vector(31 downto 0); + BUS_DATA_OUT : out std_logic_vector(31 downto 0); + BUS_ADDR_IN : in std_logic_vector(7 downto 0); + BUS_WRITE_IN : in std_logic; + BUS_READ_IN : in std_logic; + BUS_ACK_OUT : out std_logic; + BUS_NACK_OUT : out std_logic; + + SDA : out std_logic_vector(SFP_NUMBER-1 downto 0); + SDA_IN : in std_logic_vector(SFP_NUMBER-1 downto 0); + SCL : out std_logic_vector(SFP_NUMBER-1 downto 0) + ); + end component; + component trb_net16_med_scm_sfp_gbe is generic( SERDES_NUM : integer range 0 to 3 := 0; -- DO NOT CHANGE -- 2.43.0