--- /dev/null
+LIBRARY IEEE;\r
+USE IEEE.std_logic_1164.ALL;\r
+USE IEEE.std_logic_ARITH.ALL;\r
+USE IEEE.std_logic_UNSIGNED.ALL;\r
+\r
+library work;\r
+use work.trb_net_std.all;\r
+\r
+entity trb_net_i2cwire2 is\r
+ generic(\r
+ USE_TEMPERATURE_READOUT : integer range 0 to 1 := 1;\r
+ CLK_PERIOD : integer := 10 --clk period in ns\r
+ );\r
+ port(\r
+ CLK : in std_logic;\r
+ RESET : in std_logic;\r
+ READOUT_ENABLE_IN : in std_logic := '1';\r
+ --connection to I2C interface\r
+ SCL_INOUT : inout std_logic;\r
+ SDA_INOUT : inout std_logic;\r
+ --connection to id ram, according to memory map in TrbNetRegIO\r
+ DATA_OUT : out std_logic_vector(15 downto 0);\r
+ ADDR_OUT : out std_logic_vector(2 downto 0);\r
+ WRITE_OUT : out std_logic;\r
+ TEMP_OUT : out std_logic_vector(11 downto 0);\r
+ ID_OUT : out std_logic_vector(63 downto 0);\r
+ STAT : out std_logic_vector(31 downto 0)\r
+ );\r
+end entity trb_net_i2cwire2;\r
+\r
+architecture trb_net_i2cwire2_arch of trb_net_i2cwire2 is\r
+\r
+ -- States\r
+ type FSM_STATES is (SLEEP, IDLE, RD_ID0, ST_ID0, RD_ID1, ST_ID1, RD_ID2, ST_ID2,\r
+ RD_ID3, ST_ID3, WR_TMP, RD_TMP, ST_TMP, ID_DONE);\r
+ signal CURRENT_STATE, NEXT_STATE: FSM_STATES;\r
+\r
+ -- Signals\r
+ constant MAX_COUNTER : integer := 2**28-1; \r
+ signal timecounter : integer range 0 to MAX_COUNTER;\r
+ signal rst_tc_x : std_logic;\r
+ constant IDLE_PERIOD : integer := 1000; -- unit [ns]\r
+ constant READOUT_PERIOD : integer := 1000000000; -- unit [ns]\r
+ constant I2C_CYCLE : integer := 5000; -- unit [ns]\r
+ constant I2C_PERIOD : integer := (((I2C_CYCLE / CLK_PERIOD) - 2)/8);\r
+\r
+ signal ram_we_x : std_logic;\r
+ signal ram_we : std_logic;\r
+ signal temp_we_x : std_logic;\r
+ signal temp_we : std_logic;\r
+ \r
+ signal i2c_go_x : std_logic;\r
+ signal i2c_go : std_logic;\r
+\r
+ signal i2c_action_int : std_logic;\r
+ signal i2c_word_int : std_logic;\r
+ signal i2c_direct_int : std_logic;\r
+ signal i2c_addr_int : std_logic_vector(7 downto 0);\r
+ signal i2c_cmd_int : std_logic_vector(7 downto 0);\r
+ signal i2c_dw_int : std_logic_vector(15 downto 0);\r
+ signal i2c_dr_int : std_logic_vector(15 downto 0);\r
+ signal i2c_status_int : std_logic_vector(7 downto 0);\r
+ signal i2c_busy_int : std_logic;\r
+ signal i2c_done_int : std_logic;\r
+ signal i2c_bsm_int : std_logic_vector(3 downto 0);\r
+ signal valid_int : std_logic;\r
+\r
+ signal addr_int : std_logic_vector(2 downto 0);\r
+\r
+ signal id_int : std_logic_vector(63 downto 0);\r
+ signal temp_int : std_logic_vector(11 downto 0);\r
+\r
+ signal sda_drv : std_logic;\r
+ signal scl_drv : std_logic;\r
+ \r
+ -- Components\r
+ component i2c_slim2 is\r
+ port(\r
+ CLOCK : in std_logic;\r
+ RESET : in std_logic;\r
+ -- I2C command / setup\r
+ I2C_GO_IN : in std_logic; -- startbit to trigger I2C actions\r
+ ACTION_IN : in std_logic; -- '0' -> write, '1' -> read\r
+ WORD_IN : in std_logic; -- '0' -> byte, '1' -> word\r
+ DIRECT_IN : in std_logic; -- '0' -> normal access, '1' -> direct read\r
+ I2C_SPEED_IN : in std_logic_vector(5 downto 0); -- speed adjustment (to be defined)\r
+ I2C_ADDR_IN : in std_logic_vector(7 downto 0); -- I2C address byte (R/W bit is ignored)\r
+ I2C_CMD_IN : in std_logic_vector(7 downto 0); -- I2C command byte (sent after address byte)\r
+ I2C_DW_IN : in std_logic_vector(15 downto 0); -- data word for write command\r
+ I2C_DR_OUT : out std_logic_vector(15 downto 0); -- data word from read command\r
+ STATUS_OUT : out std_logic_vector(7 downto 0); -- status and error bits\r
+ VALID_OUT : out std_logic;\r
+ I2C_BUSY_OUT : out std_logic;\r
+ I2C_DONE_OUT : out std_logic;\r
+ -- I2C connections\r
+ SDA_IN : in std_logic;\r
+ SDA_OUT : out std_logic;\r
+ SCL_IN : in std_logic;\r
+ SCL_OUT : out std_logic;\r
+ -- Debug\r
+ BSM_OUT : out std_logic_vector(3 downto 0)\r
+ );\r
+ end component i2c_slim2;\r
+\r
+begin\r
+\r
+-- The main state machine\r
+-- State memory process\r
+STATE_MEM: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1' ) then\r
+ CURRENT_STATE <= SLEEP;\r
+ ram_we <= '0';\r
+ temp_we <= '0';\r
+ i2c_go <= '0';\r
+ else\r
+ CURRENT_STATE <= NEXT_STATE;\r
+ ram_we <= ram_we_x;\r
+ temp_we <= temp_we_x;\r
+ i2c_go <= i2c_go_x;\r
+ end if;\r
+ end if;\r
+end process STATE_MEM;\r
+\r
+-- Transition matrix\r
+TRANSFORM: process( CURRENT_STATE, READOUT_ENABLE_IN, timecounter, i2c_done_int )\r
+begin\r
+ NEXT_STATE <= CURRENT_STATE;\r
+ rst_tc_x <= '0';\r
+ ram_we_x <= '0';\r
+ temp_we_x <= '0';\r
+ addr_int <= b"011";\r
+ i2c_go_x <= '0';\r
+\r
+ i2c_action_int <= '1';\r
+ i2c_word_int <= '1';\r
+ i2c_direct_int <= '0';\r
+ i2c_addr_int <= x"90";\r
+ i2c_cmd_int <= x"ff";\r
+ i2c_dw_int <= x"ffff";\r
+\r
+ case CURRENT_STATE is\r
+ when SLEEP =>\r
+ if( READOUT_ENABLE_IN = '1' ) then\r
+ NEXT_STATE <= IDLE;\r
+ rst_tc_x <= '1';\r
+ ram_we_x <= '1';\r
+ end if;\r
+ when IDLE =>\r
+ if( is_time_reached(timecounter,IDLE_PERIOD,CLK_PERIOD) = '1' ) then\r
+ NEXT_STATE <= RD_ID0;\r
+ rst_tc_x <= '1';\r
+ i2c_go_x <= '1';\r
+ end if;\r
+ when RD_ID0 =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP117\r
+ i2c_cmd_int <= x"0f"; -- man/prod ID\r
+ i2c_dw_int <= x"ffff"; -- dont't care\r
+ addr_int <= b"011";\r
+ if( i2c_done_int = '1' ) then \r
+ NEXT_STATE <= ST_ID0;\r
+ ram_we_x <= '1';\r
+ end if; \r
+ when ST_ID0 =>\r
+ NEXT_STATE <= RD_ID1;\r
+ i2c_go_x <= '1';\r
+ addr_int <= b"011";\r
+ when RD_ID1 =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP117\r
+ i2c_cmd_int <= x"05"; -- serial #1\r
+ i2c_dw_int <= x"ffff"; -- dont't care \r
+ addr_int <= b"010";\r
+ if( i2c_done_int = '1' ) then \r
+ NEXT_STATE <= ST_ID1;\r
+ ram_we_x <= '1';\r
+ end if; \r
+ when ST_ID1 =>\r
+ NEXT_STATE <= RD_ID2;\r
+ i2c_go_x <= '1';\r
+ addr_int <= b"010";\r
+ when RD_ID2 =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP117\r
+ i2c_cmd_int <= x"06"; -- serial #2\r
+ i2c_dw_int <= x"ffff"; -- dont't care \r
+ addr_int <= b"001";\r
+ if( i2c_done_int = '1' ) then \r
+ NEXT_STATE <= ST_ID2;\r
+ ram_we_x <= '1';\r
+ end if; \r
+ when ST_ID2 =>\r
+ NEXT_STATE <= RD_ID3;\r
+ i2c_go_x <= '1';\r
+ addr_int <= b"001";\r
+ when RD_ID3 =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP117\r
+ i2c_cmd_int <= x"08"; -- serial #3\r
+ i2c_dw_int <= x"ffff"; -- dont't care\r
+ addr_int <= b"000";\r
+ if( i2c_done_int = '1' ) then \r
+ if( USE_TEMPERATURE_READOUT = 1 ) then\r
+ NEXT_STATE <= ST_ID3;\r
+ ram_we_x <= '1';\r
+ else \r
+ NEXT_STATE <= ID_DONE;\r
+ ram_we_x <= '1';\r
+ end if;\r
+ end if; \r
+ when ST_ID3 =>\r
+ NEXT_STATE <= WR_TMP;\r
+ i2c_go_x <= '1';\r
+ addr_int <= b"000";\r
+ when WR_TMP =>\r
+ i2c_action_int <= '0'; -- write\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP117\r
+ i2c_cmd_int <= x"01"; -- config reg\r
+ i2c_dw_int <= x"0220"; -- 1s conversion cycle\r
+ if( i2c_done_int = '1' ) then \r
+ NEXT_STATE <= RD_TMP;\r
+ rst_tc_x <= '1';\r
+ i2c_go_x <= '1';\r
+ end if; \r
+ when RD_TMP =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP1117\r
+ i2c_cmd_int <= x"00"; -- temp reg\r
+ i2c_dw_int <= x"ffff"; -- don't care\r
+ if( is_time_reached(timecounter,READOUT_PERIOD,CLK_PERIOD) = '1' ) then\r
+ NEXT_STATE <= ST_TMP;\r
+ rst_tc_x <= '1';\r
+ temp_we_x <= '1';\r
+ end if;\r
+ when ST_TMP =>\r
+ i2c_action_int <= '1'; -- read\r
+ i2c_word_int <= '1'; -- word\r
+ i2c_addr_int <= x"90"; -- TMP1117\r
+ i2c_cmd_int <= x"00"; -- temp reg\r
+ i2c_dw_int <= x"ffff"; -- don't care\r
+ NEXT_STATE <= RD_TMP;\r
+ i2c_go_x <= '1';\r
+ when ID_DONE =>\r
+ NEXT_STATE <= ID_DONE;\r
+ addr_int <= b"000";\r
+ \r
+ when others =>\r
+ NEXT_STATE <= SLEEP;\r
+ end case;\r
+end process TRANSFORM;\r
+\r
+\r
+-- ID register [15:0]\r
+THE_ID0_REG_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1') then\r
+ id_int(15 downto 0) <= x"00ff"; --(others => '0');\r
+ elsif( (addr_int = b"000") and (ram_we = '1') ) then\r
+ id_int(15 downto 0) <= i2c_dr_int;\r
+ end if;\r
+ end if;\r
+end process THE_ID0_REG_PROC;\r
+\r
+-- ID register [31:16]\r
+THE_ID1_REG_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1') then\r
+ id_int(31 downto 16) <= x"1dea"; --(others => '0');\r
+ elsif( (addr_int = b"001") and (ram_we = '1') ) then\r
+ id_int(31 downto 16) <= i2c_dr_int;\r
+ end if;\r
+ end if;\r
+end process THE_ID1_REG_PROC;\r
+\r
+-- ID register [47:32]\r
+THE_ID2_REG_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1') then\r
+ id_int(47 downto 32) <= x"abad"; --(others => '0');\r
+ elsif( (addr_int = b"010") and (ram_we = '1') ) then\r
+ id_int(47 downto 32) <= i2c_dr_int;\r
+ end if;\r
+ end if;\r
+end process THE_ID2_REG_PROC;\r
+\r
+-- ID register [63:48]\r
+THE_ID3_REG_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1') then\r
+ id_int(63 downto 48) <= x"ff00"; --(others => '0');\r
+ elsif( (addr_int = b"011") and (ram_we = '1') ) then\r
+ id_int(63 downto 48) <= i2c_dr_int;\r
+ end if;\r
+ end if;\r
+end process THE_ID3_REG_PROC;\r
+\r
+\r
+-- temperature register\r
+THE_TEMP_REG_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1') then\r
+ temp_int <= (others => '0');\r
+ elsif( (CURRENT_STATE = RD_TMP) and (valid_int = '1') ) then\r
+ temp_int <= i2c_dr_int(15 downto 4);\r
+ end if;\r
+ end if;\r
+end process THE_TEMP_REG_PROC;\r
+\r
+-- Time counter\r
+THE_TIME_COUNTER_PROC: process( CLK )\r
+begin\r
+ if( rising_edge(CLK) )then\r
+ if( rst_tc_x = '1' ) then\r
+ timecounter <= 0;\r
+ else\r
+ timecounter <= timecounter + 1;\r
+ end if;\r
+ end if;\r
+end process THE_TIME_COUNTER_PROC;\r
+\r
+THE_I2C_SLIM: i2c_slim2 \r
+port map(\r
+ CLOCK => CLK,\r
+ RESET => RESET,\r
+ -- I2C command / setup\r
+ I2C_GO_IN => i2c_go,\r
+ ACTION_IN => i2c_action_int,\r
+ WORD_IN => i2c_word_int,\r
+ DIRECT_IN => i2c_direct_int,\r
+ I2C_SPEED_IN => conv_std_logic_vector(I2C_PERIOD, 6), --b"000001", -- (value * 8 + 2) * CLK_PERIOD\r
+ I2C_ADDR_IN => i2c_addr_int,\r
+ I2C_CMD_IN => i2c_cmd_int,\r
+ I2C_DW_IN => i2c_dw_int,\r
+ I2C_DR_OUT => i2c_dr_int,\r
+ STATUS_OUT => i2c_status_int,\r
+ VALID_OUT => valid_int,\r
+ I2C_BUSY_OUT => i2c_busy_int,\r
+ I2C_DONE_OUT => i2c_done_int,\r
+ -- I2C connections\r
+ SDA_IN => SDA_INOUT,\r
+ SDA_OUT => sda_drv,\r
+ SCL_IN => SCL_INOUT,\r
+ SCL_OUT => scl_drv,\r
+ -- Debug\r
+ BSM_OUT => i2c_bsm_int\r
+);\r
+\r
+-- I2C signal open collector driver\r
+SDA_INOUT <= '0' when (sda_drv = '0') else 'Z';\r
+SCL_INOUT <= '0' when (scl_drv = '0') else 'Z';\r
+\r
+ADDR_OUT <= addr_int;\r
+DATA_OUT <= i2c_dr_int;\r
+WRITE_OUT <= ram_we;\r
+\r
+ID_OUT <= id_int;\r
+TEMP_OUT <= temp_int;\r
+\r
+STAT(31 downto 25) <= (others => '0');\r
+STAT(24) <= sda_drv;\r
+STAT(23 downto 21) <= (others => '0');\r
+STAT(20) <= scl_drv;\r
+STAT(19) <= '0';\r
+STAT(18) <= i2c_done_int;\r
+STAT(17) <= i2c_busy_int;\r
+STAT(16) <= i2c_go;\r
+STAT(15 downto 8) <= i2c_status_int;\r
+STAT(7 downto 5) <= (others => '0');\r
+STAT(4) <= '0';\r
+STAT(3 downto 0) <= i2c_bsm_int;\r
+\r
+end architecture;\r