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