6 generate statemachine
1 -- port 2 cmd_ack : out std_logic; -- command completed 3 4 -- architecture 5 type states is (idle, start_a, start_b, start_c, start_d, start_e, stop_a, stop_b, 6 stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); 7 signal c_state : states; 8 signal iscl_oen, isda_oen : std_logic; -- internal I2C lines 9 signal sda_chk : std_logic; -- check SDA status (multi-master arbitration) 10 11 -- statemachine 12 nxt_state_decoder : process (clk, nRst) 13 begin 14 if (nRst = '0') then 15 c_state <= idle; 16 cmd_ack <= '0'; 17 iscl_oen <= '1'; 18 isda_oen <= '1'; 19 sda_chk <= '0'; 20 elsif (clk'event and clk = '1') then 21 if (rst = '1' or ial = '1') then 22 c_state <= idle; 23 cmd_ack <= '0'; 24 iscl_oen <= '1'; 25 isda_oen <= '1'; 26 sda_chk <= '0'; 27 else 28 cmd_ack <= '0'; -- default no acknowledge 29 30 if (clk_en = '1') then 31 case (c_state) is 32 -- idle 33 when idle => 34 case cmd is 35 when I2C_CMD_START => c_state <= start_a; 36 when I2C_CMD_STOP => c_state <= stop_a; 37 when I2C_CMD_WRITE => c_state <= wr_a; 38 when I2C_CMD_READ => c_state <= rd_a; 39 when others => c_state <= idle; -- NOP command 40 end case; 41 42 iscl_oen <= iscl_oen; -- keep SCL in same state 43 isda_oen <= isda_oen; -- keep SDA in same state 44 sda_chk <= '0'; -- don't check SDA 45 46 -- start 47 when start_a => 48 c_state <= start_b; 49 iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start) 50 isda_oen <= '1'; -- set SDA high 51 sda_chk <= '0'; -- don't check SDA 52 53 when start_b => 54 c_state <= start_c; 55 iscl_oen <= '1'; -- set SCL high 56 isda_oen <= '1'; -- keep SDA high 57 sda_chk <= '0'; -- don't check SDA 58 59 when start_c => 60 c_state <= start_d; 61 iscl_oen <= '1'; -- keep SCL high 62 isda_oen <= '0'; -- set SDA low 63 sda_chk <= '0'; -- don't check SDA 64 65 when start_d => 66 c_state <= start_e; 67 iscl_oen <= '1'; -- keep SCL high 68 isda_oen <= '0'; -- keep SDA low 69 sda_chk <= '0'; -- don't check SDA 70 71 when start_e => 72 c_state <= idle; 73 cmd_ack <= '1'; -- command completed 74 iscl_oen <= '0'; -- set SCL low 75 isda_oen <= '0'; -- keep SDA low 76 sda_chk <= '0'; -- don't check SDA 77 78 -- stop 79 when stop_a => 80 c_state <= stop_b; 81 iscl_oen <= '0'; -- keep SCL low 82 isda_oen <= '0'; -- set SDA low 83 sda_chk <= '0'; -- don't check SDA 84 85 when stop_b => 86 c_state <= stop_c; 87 iscl_oen <= '1'; -- set SCL high 88 isda_oen <= '0'; -- keep SDA low 89 sda_chk <= '0'; -- don't check SDA 90 91 when stop_c => 92 c_state <= stop_d; 93 iscl_oen <= '1'; -- keep SCL high 94 isda_oen <= '0'; -- keep SDA low 95 sda_chk <= '0'; -- don't check SDA 96 97 when stop_d => 98 c_state <= idle; 99 cmd_ack <= '1'; -- command completed 100 iscl_oen <= '1'; -- keep SCL high 101 isda_oen <= '1'; -- set SDA high 102 sda_chk <= '0'; -- don't check SDA 103 104 -- read 105 when rd_a => 106 c_state <= rd_b; 107 iscl_oen <= '0'; -- keep SCL low 108 isda_oen <= '1'; -- tri-state SDA 109 sda_chk <= '0'; -- don't check SDA 110 111 when rd_b => 112 c_state <= rd_c; 113 iscl_oen <= '1'; -- set SCL high 114 isda_oen <= '1'; -- tri-state SDA 115 sda_chk <= '0'; -- don't check SDA 116 117 when rd_c => 118 c_state <= rd_d; 119 iscl_oen <= '1'; -- keep SCL high 120 isda_oen <= '1'; -- tri-state SDA 121 sda_chk <= '0'; -- don't check SDA 122 123 when rd_d => 124 c_state <= idle; 125 cmd_ack <= '1'; -- command completed 126 iscl_oen <= '0'; -- set SCL low 127 isda_oen <= '1'; -- tri-state SDA 128 sda_chk <= '0'; -- don't check SDA 129 130 -- write 131 when wr_a => 132 c_state <= wr_b; 133 iscl_oen <= '0'; -- keep SCL low 134 isda_oen <= din; -- set SDA 135 sda_chk <= '0'; -- don't check SDA (SCL low) 136 137 when wr_b => 138 c_state <= wr_c; 139 iscl_oen <= '1'; -- set SCL high 140 isda_oen <= din; -- keep SDA 141 sda_chk <= '0'; -- don't check SDA yet 142 -- Allow some more time for SDA and SCL to settle 143 144 when wr_c => 145 c_state <= wr_d; 146 iscl_oen <= '1'; -- keep SCL high 147 isda_oen <= din; -- keep SDA 148 sda_chk <= '1'; -- check SDA 149 150 when wr_d => 151 c_state <= idle; 152 cmd_ack <= '1'; -- command completed 153 iscl_oen <= '0'; -- set SCL low 154 isda_oen <= din; -- keep SDA 155 sda_chk <= '0'; -- don't check SDA (SCL low) 156 157 when others => 158 159 end case; 160 end if; 161 end if; 162 end if; 163 end process nxt_state_decoder;