From c8e1a3756076459a8c7f5658a47245a78dce9385 Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Thu, 30 Jun 2022 22:20:02 +0200 Subject: [PATCH] add new i2c for combined temperature and id chip tmp117 --- special/trb_net_i2cwire2.vhd | 385 +++++++++++++++++++++++++++++++++++ trb_net_std.vhd | 20 +- 2 files changed, 396 insertions(+), 9 deletions(-) create mode 100644 special/trb_net_i2cwire2.vhd 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; diff --git a/trb_net_std.vhd b/trb_net_std.vhd index b581d92..c442f05 100644 --- a/trb_net_std.vhd +++ b/trb_net_std.vhd @@ -18,16 +18,12 @@ package trb_net_std is --Trigger Info constant TRIG_SUPPRESS_BIT : integer range 0 to 15 := 0; - - -- some basic definitions for the whole network ----------------------------------------------- - constant c_DATA_WIDTH : integer := 16; constant c_NUM_WIDTH : integer := 3; constant c_MUX_WIDTH : integer := 3; --!!! - --assigning channel names constant c_TRG_LVL1_CHANNEL : integer := 0; constant c_DATA_CHANNEL : integer := 1; @@ -60,12 +56,18 @@ package trb_net_std is constant c_FIFO_INFTY : integer := 7; --simple logic - constant c_YES : integer := 1; - constant c_NO : integer := 0; + constant c_YES : integer := 1; + constant c_NO : integer := 0; constant c_MONITOR : integer := 2; - constant c_I2C : integer := 3; - constant c_XDNA : integer := 4; - + constant c_I2C : integer := 3; + constant c_XDNA : integer := 4; + constant c_I2C_TC : integer := 5; + +--media interface steering + constant c_IS_UNUSED : integer := 0; + constant c_IS_MASTER : integer := 1; + constant c_IS_SLAVE : integer := 8; + --standard values constant std_SBUF_VERSION : integer := c_SBUF_FULL; constant std_IBUF_SECURE_MODE : integer := c_SECURE_MODE; -- 2.43.0