]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
I2C UID works now with TMP117
authorMichael Boehmer <mboehmer@ph.tum.de>
Sun, 29 May 2022 21:27:42 +0000 (23:27 +0200)
committerMichael Boehmer <mboehmer@ph.tum.de>
Sun, 29 May 2022 21:27:42 +0000 (23:27 +0200)
special/trb_net_i2cwire2.vhd [new file with mode: 0644]

diff --git a/special/trb_net_i2cwire2.vhd b/special/trb_net_i2cwire2.vhd
new file mode 100644 (file)
index 0000000..b3b2090
--- /dev/null
@@ -0,0 +1,385 @@
+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