]> jspc29.x-matter.uni-frankfurt.de Git - vhdlbasics.git/commitdiff
merge i2c_slim2 from blackcat branch to master
authorJan Michel <michel@physik.uni-frankfurt.de>
Thu, 10 Nov 2022 15:57:29 +0000 (16:57 +0100)
committerJan Michel <michel@physik.uni-frankfurt.de>
Thu, 10 Nov 2022 15:57:29 +0000 (16:57 +0100)
interface/i2c_slim2.vhd

index 249c35170f26874a51d50eb27e464e08f031d409..568b1aa36fe1c99b646f84b5b0502954885ed2c1 100644 (file)
@@ -11,6 +11,7 @@ port(
   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
@@ -26,7 +27,7 @@ port(
   SCL_IN          : in  std_logic;\r
   SCL_OUT         : out std_logic;\r
   -- Debug\r
-  BSM_OUT         : out std_logic_vector(4 downto 0)\r
+  BSM_OUT         : out std_logic_vector(3 downto 0)\r
 );\r
 end entity i2c_slim2;\r
 \r
@@ -37,7 +38,7 @@ type STATES is (SLEEP, LOADA, GSTART, SENDA, LOADC, SENDC, LOADD, SENDD,
                 GSTOP, INC, DONE, FAILED, LOADD2, SENDD2);\r
 signal CURRENT_STATE, NEXT_STATE: STATES;\r
 \r
-signal bsm          : std_logic_vector( 4 downto 0 );\r
+signal bsm          : std_logic_vector(3 downto 0);\r
 signal phase        : std_logic; -- '0' => first phase, '1' => second phase of read cycle\r
 \r
 signal start_x      : std_logic;\r
@@ -57,6 +58,8 @@ signal load_dh_x    : std_logic;
 signal load_dh      : std_logic;\r
 signal load_dl_x    : std_logic;\r
 signal load_dl      : std_logic;\r
+signal clr_data_x   : std_logic;\r
+signal clr_data     : std_logic;\r
 \r
 signal sdone        : std_logic; -- acknowledge signal from GenStart module\r
 signal sok          : std_logic; -- status signal from GenStart module\r
@@ -140,7 +143,7 @@ begin
 end process THE_SYNC_PROC;\r
 \r
 -- lower limit of speed\r
-i2c_speed <= i2c_speed_in & "000";\r
+i2c_speed <= i2c_speed_in & b"010";\r
 \r
 -- Read phase indicator\r
 THE_PHASE_PROC: process( CLOCK )\r
@@ -148,7 +151,7 @@ begin
   if( rising_edge(CLOCK) ) then\r
     if( RESET = '1' ) then\r
       phase <= '0';\r
-    elsif( CURRENT_STATE = INC ) then\r
+    elsif( (CURRENT_STATE = INC) ) then\r
       phase <= '1';\r
     elsif( (CURRENT_STATE = DONE) or (CURRENT_STATE = SLEEP) ) then\r
       phase <= '0';\r
@@ -166,44 +169,48 @@ begin
       start         <= '0';\r
       dostart       <= '0';\r
       dobyte        <= '0';\r
-      i2c_done      <= '0';\r
       running       <= '0';\r
       load_dh       <= '0';\r
       load_dl       <= '0';\r
+      clr_data      <= '1';\r
       valid         <= '0';\r
+      i2c_done      <= '0';\r
     else\r
       CURRENT_STATE <= NEXT_STATE;\r
       start         <= start_x;\r
       dostart       <= dostart_x;\r
       dobyte        <= dobyte_x;\r
-      i2c_done      <= i2c_done_x;\r
       running       <= running_x;\r
       load_dh       <= load_dh_x;\r
       load_dl       <= load_dl_x;\r
+      clr_data      <= clr_data_x;\r
       valid         <= valid_x;\r
+      i2c_done      <= i2c_done_x;\r
     end if;\r
   end if;\r
 end process STATE_MEM;\r
 \r
 -- Transition matrix\r
-TRANSFORM: process(CURRENT_STATE, i2c_go_in, sdone, sok, phase, bdone, bok, action_in, word_in)\r
+TRANSFORM: process(CURRENT_STATE, I2C_GO_IN, sdone, sok, phase, bdone, bok, ACTION_IN, WORD_IN)\r
 begin\r
   NEXT_STATE <= SLEEP;\r
   start_x    <= '0';\r
   dostart_x  <= '0';\r
   dobyte_x   <= '0';\r
-  i2c_done_x <= '0';\r
   running_x  <= '1';\r
   load_dh_x  <= '0';\r
   load_dl_x  <= '0';\r
+  clr_data_x <= '0';\r
   valid_x    <= '0';\r
+  i2c_done_x <= '0';\r
   errors_x   <= x"00";\r
   save_x     <= '0';\r
   case CURRENT_STATE is\r
     when SLEEP      =>  \r
-      if( i2c_go_in = '1' ) then\r
+      if( I2C_GO_IN = '1' ) then\r
         NEXT_STATE <= LOADA;\r
         save_x     <= '1';\r
+        clr_data_x <= '1';\r
       else\r
         NEXT_STATE <= SLEEP;\r
         running_x  <= '0';\r
@@ -232,12 +239,22 @@ begin
         dostart_x  <= '1';\r
       end if;\r
     when SENDA      =>  \r
-      if   ( (bdone = '1') and (bok = '1') and (action_in = '0') ) then\r
-        NEXT_STATE <= LOADC; -- I2C write, send command\r
-      elsif( (bdone = '1') and (bok = '1') and (action_in = '1') and (phase = '0') ) then\r
-        NEXT_STATE <= LOADC; -- I2C read, send command\r
-      elsif( (bdone = '1') and (bok = '1') and (action_in = '1') and (phase = '1') ) then\r
-        NEXT_STATE <= LOADD; -- I2C read, send 0xff dummy byte\r
+      if   ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '0') ) then\r
+        NEXT_STATE <= LOADC; -- I2C normal write\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '0') and (phase = '0') ) then\r
+        NEXT_STATE <= LOADC; -- I2C normal read, address stage (same for byte and word)\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (phase = '1') and (WORD_IN = '0') ) then\r
+        NEXT_STATE <= LOADD2; -- I2C normal read (byte), data stage\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (phase = '1') and (WORD_IN = '1') ) then\r
+        NEXT_STATE <= LOADD; -- I2C normal read (word), data stage\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '1') and (WORD_IN = '0') ) then\r
+        NEXT_STATE <= LOADD2; -- I2C direct write (byte)\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (DIRECT_IN = '1') and (WORD_IN = '1') ) then\r
+        NEXT_STATE <= LOADD; -- I2C direct write (word)\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '1') and (WORD_IN = '0') ) then\r
+        NEXT_STATE <= LOADD2; -- I2C direct read (byte)\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') and (DIRECT_IN = '1') and (WORD_IN = '1') ) then\r
+        NEXT_STATE <= LOADD; -- I2C direct read (word)\r
       elsif( (bdone = '1') and (bok = '0') and (phase = '0') ) then\r
         NEXT_STATE <= FAILED; -- first address phase failed\r
         errors_x   <= x"20";\r
@@ -255,11 +272,11 @@ begin
     when LOADC      =>  \r
       NEXT_STATE <= SENDC;\r
     when SENDC      =>  \r
-      if   ( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '0') ) then\r
+      if   ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (WORD_IN = '0') ) then\r
         NEXT_STATE <= LOADD2; -- I2C byte write, prepare data\r
-      elsif( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '1') ) then\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') and (WORD_IN = '1') ) then\r
         NEXT_STATE <= LOADD; -- I2C word write, prepare data\r
-      elsif( (bdone = '1') and (bok = '1') and (action_in = '1') ) then\r
+      elsif( (bdone = '1') and (bok = '1') and (ACTION_IN = '1') ) then\r
         NEXT_STATE <= GSTOP; -- I2C read, first phase ends\r
         dostart_x  <= '1';\r
       elsif( (bdone = '1') and (bok = '0') ) then\r
@@ -274,19 +291,12 @@ begin
     when LOADD      =>  \r
       NEXT_STATE <= SENDD;\r
     when SENDD      =>  \r
-      if   ( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '0') ) then\r
-        NEXT_STATE <= GSTOP;    -- I2C write, byte access, done\r
-        dostart_x  <= '1';\r
-      elsif( (bdone = '1') and (bok = '1') and (action_in = '0') and (word_in = '1') ) then\r
-        NEXT_STATE <= LOADD2;    -- I2C write, word access, last byte to send\r
-      elsif( (bdone = '1') and                 (action_in = '1') and (word_in = '0') ) then\r
-        NEXT_STATE <= GSTOP; -- I2C read, byte access, data phase\r
-        dostart_x  <= '1';\r
-        load_dl_x  <= '1';\r
-      elsif( (bdone = '1') and                 (action_in = '1') and (word_in = '1') ) then\r
+      if   ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') ) then\r
+        NEXT_STATE <= LOADD2; -- I2C write, word access, last byte to send\r
+      elsif( (bdone = '1') and                 (ACTION_IN = '1') ) then\r
         NEXT_STATE <= LOADD2; -- I2C read, word access, last byte to receive\r
         load_dh_x  <= '1';\r
-      elsif( (bdone = '1') and (bok = '0') and (action_in = '0') ) then\r
+      elsif( (bdone = '1') and (bok = '0') and (ACTION_IN = '0') ) then\r
         NEXT_STATE <= FAILED; -- I2C write, first data phase failed\r
         errors_x   <= x"04";\r
         save_x     <= '1';\r
@@ -298,14 +308,14 @@ begin
     when LOADD2     =>  \r
       NEXT_STATE <= SENDD2;\r
     when SENDD2     =>  \r
-      if   ( (bdone = '1') and (bok = '1') and (action_in = '0') ) then\r
+      if   ( (bdone = '1') and (bok = '1') and (ACTION_IN = '0') ) then\r
         NEXT_STATE <= GSTOP; -- I2C write, done\r
         dostart_x  <= '1';\r
-      elsif( (bdone = '1') and                 (action_in = '1') ) then\r
+      elsif( (bdone = '1') and                 (ACTION_IN = '1') ) then\r
         NEXT_STATE <= GSTOP; -- I2C read, data phase\r
         dostart_x  <= '1';\r
         load_dl_x  <= '1';\r
-      elsif( (bdone = '1') and (bok = '0') and (action_in = '0') ) then\r
+      elsif( (bdone = '1') and (bok = '0') and (ACTION_IN = '0') ) then\r
         NEXT_STATE <= FAILED; -- I2C write, data phase failed\r
         errors_x   <= x"02";\r
         save_x     <= '1';\r
@@ -315,16 +325,20 @@ begin
         dobyte_x   <= '1';\r
       end if;\r
     when GSTOP      =>  \r
-      if   ( (sdone = '1') and (action_in = '0') ) then\r
+      if   ( (sdone = '1') and (ACTION_IN = '0') ) then\r
         NEXT_STATE <= DONE;\r
         i2c_done_x <= '1';\r
         valid_x    <= '1';\r
-      elsif( (sdone = '1') and (action_in = '1') and (phase = '1') ) then\r
+      elsif( (sdone = '1') and (ACTION_IN = '1') and (phase = '1') ) then\r
         NEXT_STATE <= DONE;\r
         i2c_done_x <= '1';\r
         valid_x    <= '1';\r
-      elsif( (sdone = '1') and (action_in = '1') and (phase = '0') ) then\r
+      elsif( (sdone = '1') and (ACTION_IN = '1') and (phase = '0') and (DIRECT_IN = '0') ) then\r
         NEXT_STATE <= INC;\r
+      elsif( (sdone = '1') and (ACTION_IN = '1') and                   (DIRECT_IN = '1') ) then\r
+        NEXT_STATE <= DONE;\r
+        i2c_done_x <= '1';\r
+        valid_x    <= '1';\r
       else\r
         NEXT_STATE <= GSTOP;\r
         dostart_x  <= '1';\r
@@ -332,6 +346,7 @@ begin
     when INC        =>  \r
       NEXT_STATE <= LOADA;\r
     when FAILED     =>  \r
+      -- emergency STOP condition to correctly free the bus\r
       if( sdone = '1' ) then\r
         NEXT_STATE <= DONE;\r
         i2c_done_x <= '1';\r
@@ -365,50 +380,65 @@ begin
   end if;\r
 end process THE_ERROR_PROC;\r
 \r
+---- DONE bit: set by FSM completion, cleared by start of FSM\r
+--THE_DONE_PROC: process( CLOCK )\r
+--begin\r
+--  if( rising_edge(CLOCK) ) then\r
+--    if   ( RESET = '1' ) then\r
+--      i2c_done <= '0';\r
+--    elsif( CURRENT_STATE = LOADA ) then\r
+--      i2c_done <= '0';\r
+--    elsif( CURRENT_STATE = DONE ) then\r
+--      i2c_done <= '1';\r
+--    end if;\r
+--  end if;\r
+--end process THE_DONE_PROC;\r
+\r
 -- Output decoding\r
 DECODE: process(CURRENT_STATE)\r
 begin\r
   case CURRENT_STATE is\r
-    when SLEEP      =>  bsm <= b"00000"; -- 00\r
-    when LOADA      =>  bsm <= b"00001"; -- 01\r
-    when GSTART     =>  bsm <= b"00010"; -- 02\r
-    when SENDA      =>  bsm <= b"00011"; -- 03\r
-    when LOADC      =>  bsm <= b"00100"; -- 04\r
-    when SENDC      =>  bsm <= b"00101"; -- 05\r
-    when LOADD      =>  bsm <= b"00110"; -- 06\r
-    when SENDD      =>  bsm <= b"00111"; -- 07\r
-    when GSTOP      =>  bsm <= b"01000"; -- 08\r
-    when INC        =>  bsm <= b"01001"; -- 09\r
-    when FAILED     =>  bsm <= b"01010"; -- 0a\r
-    when DONE       =>  bsm <= b"01011"; -- 0b\r
-    when LOADD2                        =>      bsm <= b"01100"; -- 0c\r
-    when SENDD2                        =>      bsm <= b"01101"; -- 0d\r
-    when others     =>  bsm <= b"11111"; -- 1f\r
+    when SLEEP      =>  bsm <= b"0000"; -- 0\r
+    when LOADA      =>  bsm <= b"0001"; -- 1\r
+    when GSTART     =>  bsm <= b"0010"; -- 2\r
+    when SENDA      =>  bsm <= b"0011"; -- 3\r
+    when LOADC      =>  bsm <= b"0100"; -- 4\r
+    when SENDC      =>  bsm <= b"0101"; -- 5\r
+    when LOADD      =>  bsm <= b"0110"; -- 6\r
+    when SENDD      =>  bsm <= b"0111"; -- 7\r
+    when GSTOP      =>  bsm <= b"1000"; -- 8\r
+    when INC        =>  bsm <= b"1001"; -- 9\r
+    when FAILED     =>  bsm <= b"1010"; -- a\r
+    when DONE       =>  bsm <= b"1011"; -- b\r
+    when LOADD2                        =>      bsm <= b"1100"; -- c\r
+    when SENDD2                        =>      bsm <= b"1101"; -- d\r
+    when others     =>  bsm <= b"1111"; -- f\r
   end case;\r
 end process DECODE;\r
 \r
 -- We need to load different data sets\r
---LOAD_DATA_PROC: process( CLOCK, RESET, CURRENT_STATE, action_in, phase)\r
 LOAD_DATA_PROC: process( CLOCK )\r
 begin\r
   if( rising_edge(CLOCK) ) then\r
     if   ( RESET = '1' ) then\r
       i2c_byte <= (others => '1');\r
-    elsif( (CURRENT_STATE = LOADA) and (phase = '0') ) then\r
+    elsif( (CURRENT_STATE = LOADA) and (phase = '0') and (DIRECT_IN = '0') ) then\r
       i2c_byte <= i2c_addr_in(7 downto 1) & '0' & '1'; -- send write address, receive ACK\r
+    elsif( (CURRENT_STATE = LOADA) and (phase = '0') and (DIRECT_IN = '1') and (ACTION_IN = '0') ) then\r
+      i2c_byte <= i2c_addr_in(7 downto 1) & '0' & '1'; -- send write address, receive ACK\r
+    elsif( (CURRENT_STATE = LOADA) and (phase = '0') and (DIRECT_IN = '1') and (ACTION_IN = '1') ) then\r
+      i2c_byte <= i2c_addr_in(7 downto 1) & '1' & '1'; -- send read address, receive ACK\r
     elsif( (CURRENT_STATE = LOADA) and (phase = '1') ) then\r
       i2c_byte <= i2c_addr_in(7 downto 1) & '1' & '1'; -- send read address, receive ACK\r
-    elsif( (CURRENT_STATE = LOADC) and (action_in = '0') ) then\r
-      i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (WRITE), receive ACK\r
-    elsif( (CURRENT_STATE = LOADC) and (action_in = '1') ) then\r
-      i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (READ), receive ACK\r
-    elsif( (CURRENT_STATE = LOADD) and (action_in = '0') ) then\r
+    elsif( (CURRENT_STATE = LOADC) ) then\r
+      i2c_byte <= i2c_cmd_in(7 downto 0) & '1'; -- send command byte (read/write), receive ACK\r
+    elsif( (CURRENT_STATE = LOADD) and (ACTION_IN = '0') ) then\r
       i2c_byte <= i2c_dw_in(15 downto 8) & '1'; -- send data byte, receive ACK\r
-    elsif( (CURRENT_STATE = LOADD2) and (action_in = '0') ) then\r
+    elsif( (CURRENT_STATE = LOADD2) and (ACTION_IN = '0') ) then\r
       i2c_byte <= i2c_dw_in(7 downto 0) & '1'; -- send data byte, receive ACK\r
-    elsif( (CURRENT_STATE = LOADD) and (action_in = '1') ) then\r
+    elsif( (CURRENT_STATE = LOADD) and (ACTION_IN = '1') ) then\r
       i2c_byte <= x"ff" & '0'; -- send 0xff byte, send ACK\r
-    elsif( (CURRENT_STATE = LOADD2) and (action_in = '1') ) then\r
+    elsif( (CURRENT_STATE = LOADD2) and (ACTION_IN = '1') ) then\r
       i2c_byte <= x"ff" & '1'; -- send 0xff byte, send NACK\r
     end if;\r
   end if;\r
@@ -490,8 +520,8 @@ end process THE_SDA_PROC;
 THE_STORE_READ_H_PROC: process( CLOCK ) \r
 begin\r
   if( rising_edge(CLOCK) ) then\r
-    if   ( RESET = '1' ) then\r
-      i2c_drw(15 downto 8) <= (others => '0');\r
+    if   ( clr_data = '1' ) then\r
+      i2c_drw(15 downto 8) <= (others => '1');\r
     elsif( rising_edge(CLOCK) ) then\r
       if( load_dh = '1' ) then\r
         i2c_drw(15 downto 8) <= i2c_dr(8 downto 1);\r
@@ -504,8 +534,8 @@ end process THE_STORE_READ_H_PROC;
 THE_STORE_READ_L_PROC: process( CLOCK ) \r
 begin\r
   if( rising_edge(CLOCK) ) then\r
-    if   ( RESET = '1' ) then\r
-      i2c_drw(7 downto 0) <= (others => '0');\r
+    if   ( clr_data = '1' ) then\r
+      i2c_drw(7 downto 0) <= (others => '1');\r
     elsif( rising_edge(CLOCK) ) then\r
       if( load_dl = '1' ) then\r
         i2c_drw(7 downto 0) <= i2c_dr(8 downto 1);\r