[1766] | 1 | -- |
---|
| 2 | -- Simple I2C controller |
---|
| 3 | -- |
---|
| 4 | -- 1) No multimaster |
---|
| 5 | -- 2) No slave mode |
---|
| 6 | -- 3) No fifo's |
---|
| 7 | -- |
---|
| 8 | -- notes: |
---|
| 9 | -- Every command is acknowledged. Do not set a new command before previous is acknowledged. |
---|
| 10 | -- Dout is available 1 clock cycle later as cmd_ack |
---|
| 11 | -- |
---|
| 12 | |
---|
| 13 | library ieee; |
---|
| 14 | use ieee.std_logic_1164.all; |
---|
| 15 | use ieee.std_logic_arith.all; |
---|
| 16 | |
---|
| 17 | package I2C is |
---|
| 18 | component simple_i2c is |
---|
| 19 | port ( |
---|
| 20 | clk : in std_logic; |
---|
| 21 | ena : in std_logic; |
---|
| 22 | nReset : in std_logic; |
---|
| 23 | |
---|
| 24 | clk_cnt : in unsigned(7 downto 0); -- 4x SCL |
---|
| 25 | |
---|
| 26 | -- input signals |
---|
| 27 | start, |
---|
| 28 | stop, |
---|
| 29 | read, |
---|
| 30 | write, |
---|
| 31 | ack_in : std_logic; |
---|
| 32 | Din : in std_logic_vector(7 downto 0); |
---|
| 33 | |
---|
| 34 | -- output signals |
---|
| 35 | cmd_ack : out std_logic; |
---|
| 36 | ack_out : out std_logic; |
---|
| 37 | Dout : out std_logic_vector(7 downto 0); |
---|
| 38 | |
---|
| 39 | -- i2c signals |
---|
| 40 | SCL : inout std_logic; |
---|
| 41 | SDA : inout std_logic |
---|
| 42 | ); |
---|
| 43 | end component simple_i2c; |
---|
| 44 | end package I2C; |
---|
| 45 | |
---|
| 46 | |
---|
| 47 | library ieee; |
---|
| 48 | use ieee.std_logic_1164.all; |
---|
| 49 | use ieee.std_logic_arith.all; |
---|
| 50 | |
---|
| 51 | entity simple_i2c is |
---|
| 52 | port ( |
---|
| 53 | clk : in std_logic; |
---|
| 54 | ena : in std_logic; |
---|
| 55 | nReset : in std_logic; |
---|
| 56 | |
---|
| 57 | clk_cnt : in unsigned(7 downto 0); -- 4x SCL |
---|
| 58 | |
---|
| 59 | -- input signals |
---|
| 60 | start, |
---|
| 61 | stop, |
---|
| 62 | read, |
---|
| 63 | write, |
---|
| 64 | ack_in : std_logic; |
---|
| 65 | Din : in std_logic_vector(7 downto 0); |
---|
| 66 | |
---|
| 67 | -- output signals |
---|
| 68 | cmd_ack : out std_logic; |
---|
| 69 | ack_out : out std_logic; |
---|
| 70 | Dout : out std_logic_vector(7 downto 0); |
---|
| 71 | |
---|
| 72 | -- i2c signals |
---|
| 73 | SCL : inout std_logic; |
---|
| 74 | SDA : inout std_logic |
---|
| 75 | ); |
---|
| 76 | end entity simple_i2c; |
---|
| 77 | |
---|
| 78 | architecture structural of simple_i2c is |
---|
| 79 | component i2c_core is |
---|
| 80 | port ( |
---|
| 81 | clk : in std_logic; |
---|
| 82 | nReset : in std_logic; |
---|
| 83 | |
---|
| 84 | clk_cnt : in unsigned(7 downto 0); |
---|
| 85 | |
---|
| 86 | cmd : in std_logic_vector(2 downto 0); |
---|
| 87 | cmd_ack : out std_logic; |
---|
| 88 | busy : out std_logic; |
---|
| 89 | |
---|
| 90 | Din : in std_logic; |
---|
| 91 | Dout : out std_logic; |
---|
| 92 | |
---|
| 93 | SCL : inout std_logic; |
---|
| 94 | SDA : inout std_logic |
---|
| 95 | ); |
---|
| 96 | end component i2c_core; |
---|
| 97 | |
---|
| 98 | -- commands for i2c_core |
---|
| 99 | constant CMD_NOP : std_logic_vector(2 downto 0) := "000"; |
---|
| 100 | constant CMD_START : std_logic_vector(2 downto 0) := "010"; |
---|
| 101 | constant CMD_STOP : std_logic_vector(2 downto 0) := "011"; |
---|
| 102 | constant CMD_READ : std_logic_vector(2 downto 0) := "100"; |
---|
| 103 | constant CMD_WRITE : std_logic_vector(2 downto 0) := "101"; |
---|
| 104 | |
---|
| 105 | -- signals for i2c_core |
---|
| 106 | signal core_cmd : std_logic_vector(2 downto 0); |
---|
| 107 | signal core_ack, core_busy, core_txd, core_rxd : std_logic; |
---|
| 108 | |
---|
| 109 | -- signals for shift register |
---|
| 110 | signal sr : std_logic_vector(7 downto 0); -- 8bit shift register |
---|
| 111 | signal shift, ld : std_logic; |
---|
| 112 | |
---|
| 113 | -- signals for state machine |
---|
| 114 | signal go, host_ack : std_logic; |
---|
| 115 | begin |
---|
| 116 | -- hookup i2c core |
---|
| 117 | u1: i2c_core port map (clk, nReset, clk_cnt, core_cmd, core_ack, core_busy, core_txd, core_rxd, SCL, SDA); |
---|
| 118 | |
---|
| 119 | -- generate host-command-acknowledge |
---|
| 120 | cmd_ack <= host_ack; |
---|
| 121 | |
---|
| 122 | -- generate go-signal |
---|
| 123 | go <= (read or write) and not host_ack; |
---|
| 124 | |
---|
| 125 | -- assign Dout output to shift-register |
---|
| 126 | Dout <= sr; |
---|
| 127 | |
---|
| 128 | -- assign ack_out output to core_rxd (contains last received bit) |
---|
| 129 | ack_out <= core_rxd; |
---|
| 130 | |
---|
| 131 | -- generate shift register |
---|
| 132 | shift_register: process(clk) |
---|
| 133 | begin |
---|
| 134 | if (clk'event and clk = '1') then |
---|
| 135 | if (ld = '1') then |
---|
| 136 | sr <= din; |
---|
| 137 | elsif (shift = '1') then |
---|
| 138 | sr <= (sr(6 downto 0) & core_rxd); |
---|
| 139 | end if; |
---|
| 140 | end if; |
---|
| 141 | end process shift_register; |
---|
| 142 | |
---|
| 143 | -- |
---|
| 144 | -- state machine |
---|
| 145 | -- |
---|
| 146 | statemachine : block |
---|
| 147 | type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); |
---|
| 148 | signal state : states; |
---|
| 149 | signal dcnt : unsigned(2 downto 0); |
---|
| 150 | begin |
---|
| 151 | -- |
---|
| 152 | -- command interpreter, translate complex commands into simpler I2C commands |
---|
| 153 | -- |
---|
| 154 | nxt_state_decoder: process(clk, nReset, state) |
---|
| 155 | variable nxt_state : states; |
---|
| 156 | variable idcnt : unsigned(2 downto 0); |
---|
| 157 | variable ihost_ack : std_logic; |
---|
| 158 | variable icore_cmd : std_logic_vector(2 downto 0); |
---|
| 159 | variable icore_txd : std_logic; |
---|
| 160 | variable ishift, iload : std_logic; |
---|
| 161 | begin |
---|
| 162 | -- 8 databits (1byte) of data to shift-in/out |
---|
| 163 | idcnt := dcnt; |
---|
| 164 | |
---|
| 165 | -- no acknowledge (until command complete) |
---|
| 166 | ihost_ack := '0'; |
---|
| 167 | |
---|
| 168 | icore_txd := core_txd; |
---|
| 169 | |
---|
| 170 | -- keep current command to i2c_core |
---|
| 171 | icore_cmd := core_cmd; |
---|
| 172 | |
---|
| 173 | -- no shifting or loading of shift-register |
---|
| 174 | ishift := '0'; |
---|
| 175 | iload := '0'; |
---|
| 176 | |
---|
| 177 | -- keep current state; |
---|
| 178 | nxt_state := state; |
---|
| 179 | case state is |
---|
| 180 | when st_idle => |
---|
| 181 | if (go = '1') then |
---|
| 182 | if (start = '1') then |
---|
| 183 | nxt_state := st_start; |
---|
| 184 | icore_cmd := CMD_START; |
---|
| 185 | elsif (read = '1') then |
---|
| 186 | nxt_state := st_read; |
---|
| 187 | icore_cmd := CMD_READ; |
---|
| 188 | idcnt := "111"; |
---|
| 189 | else |
---|
| 190 | nxt_state := st_write; |
---|
| 191 | icore_cmd := CMD_WRITE; |
---|
| 192 | idcnt := "111"; |
---|
| 193 | iload := '1'; |
---|
| 194 | end if; |
---|
| 195 | end if; |
---|
| 196 | |
---|
| 197 | when st_start => |
---|
| 198 | if (core_ack = '1') then |
---|
| 199 | if (read = '1') then |
---|
| 200 | nxt_state := st_read; |
---|
| 201 | icore_cmd := CMD_READ; |
---|
| 202 | idcnt := "111"; |
---|
| 203 | else |
---|
| 204 | nxt_state := st_write; |
---|
| 205 | icore_cmd := CMD_WRITE; |
---|
| 206 | idcnt := "111"; |
---|
| 207 | iload := '1'; |
---|
| 208 | end if; |
---|
| 209 | end if; |
---|
| 210 | |
---|
| 211 | when st_write => |
---|
| 212 | if (core_ack = '1') then |
---|
| 213 | idcnt := dcnt -1; -- count down Data_counter |
---|
| 214 | icore_txd := sr(7); |
---|
| 215 | if (dcnt = 0) then |
---|
| 216 | nxt_state := st_ack; |
---|
| 217 | icore_cmd := CMD_READ; |
---|
| 218 | else |
---|
| 219 | ishift := '1'; |
---|
| 220 | -- icore_txd := sr(7); |
---|
| 221 | end if; |
---|
| 222 | end if; |
---|
| 223 | |
---|
| 224 | when st_read => |
---|
| 225 | if (core_ack = '1') then |
---|
| 226 | idcnt := dcnt -1; -- count down Data_counter |
---|
| 227 | ishift := '1'; |
---|
| 228 | if (dcnt = 0) then |
---|
| 229 | nxt_state := st_ack; |
---|
| 230 | icore_cmd := CMD_WRITE; |
---|
| 231 | icore_txd := ack_in; |
---|
| 232 | end if; |
---|
| 233 | end if; |
---|
| 234 | |
---|
| 235 | when st_ack => |
---|
| 236 | if (core_ack = '1') then |
---|
| 237 | -- generate command acknowledge signal |
---|
| 238 | ihost_ack := '1'; |
---|
| 239 | |
---|
| 240 | -- Perform an additional shift, needed for 'read' (store last received bit in shift register) |
---|
| 241 | ishift := '1'; |
---|
| 242 | |
---|
| 243 | -- check for stop; Should a STOP command be generated ? |
---|
| 244 | if (stop = '1') then |
---|
| 245 | nxt_state := st_stop; |
---|
| 246 | icore_cmd := CMD_STOP; |
---|
| 247 | else |
---|
| 248 | nxt_state := st_idle; |
---|
| 249 | icore_cmd := CMD_NOP; |
---|
| 250 | end if; |
---|
| 251 | end if; |
---|
| 252 | |
---|
| 253 | when st_stop => |
---|
| 254 | if (core_ack = '1') then |
---|
| 255 | nxt_state := st_idle; |
---|
| 256 | icore_cmd := CMD_NOP; |
---|
| 257 | end if; |
---|
| 258 | |
---|
| 259 | when others => -- illegal states |
---|
| 260 | nxt_state := st_idle; |
---|
| 261 | icore_cmd := CMD_NOP; |
---|
| 262 | end case; |
---|
| 263 | |
---|
| 264 | -- generate registers |
---|
| 265 | if (nReset = '0') then |
---|
| 266 | core_cmd <= CMD_NOP; |
---|
| 267 | core_txd <= '0'; |
---|
| 268 | |
---|
| 269 | shift <= '0'; |
---|
| 270 | ld <= '0'; |
---|
| 271 | |
---|
| 272 | dcnt <= "111"; |
---|
| 273 | host_ack <= '0'; |
---|
| 274 | |
---|
| 275 | state <= st_idle; |
---|
| 276 | elsif (clk'event and clk = '1') then |
---|
| 277 | if (ena = '1') then |
---|
| 278 | state <= nxt_state; |
---|
| 279 | |
---|
| 280 | dcnt <= idcnt; |
---|
| 281 | shift <= ishift; |
---|
| 282 | ld <= iload; |
---|
| 283 | |
---|
| 284 | core_cmd <= icore_cmd; |
---|
| 285 | core_txd <= icore_txd; |
---|
| 286 | |
---|
| 287 | host_ack <= ihost_ack; |
---|
| 288 | end if; |
---|
| 289 | end if; |
---|
| 290 | end process nxt_state_decoder; |
---|
| 291 | |
---|
| 292 | end block statemachine; |
---|
| 293 | |
---|
| 294 | end architecture structural; |
---|
| 295 | |
---|
| 296 | |
---|
| 297 | -- |
---|
| 298 | -- |
---|
| 299 | -- I2C Core |
---|
| 300 | -- |
---|
| 301 | -- Translate simple commands into SCL/SDA transitions |
---|
| 302 | -- Each command has 5 states, A/B/C/D/idle |
---|
| 303 | -- |
---|
| 304 | -- start: SCL ~~~~~~~~~~\____ |
---|
| 305 | -- SDA ~~~~~~~~\______ |
---|
| 306 | -- x | A | B | C | D | i |
---|
| 307 | -- |
---|
| 308 | -- repstart SCL ____/~~~~\___ |
---|
| 309 | -- SDA __/~~~\______ |
---|
| 310 | -- x | A | B | C | D | i |
---|
| 311 | -- |
---|
| 312 | -- stop SCL ____/~~~~~~~~ |
---|
| 313 | -- SDA ==\____/~~~~~ |
---|
| 314 | -- x | A | B | C | D | i |
---|
| 315 | -- |
---|
| 316 | --- write SCL ____/~~~~\____ |
---|
| 317 | -- SDA ==X=========X= |
---|
| 318 | -- x | A | B | C | D | i |
---|
| 319 | -- |
---|
| 320 | --- read SCL ____/~~~~\____ |
---|
| 321 | -- SDA XXXX=====XXXX |
---|
| 322 | -- x | A | B | C | D | i |
---|
| 323 | -- |
---|
| 324 | |
---|
| 325 | -- Timing: Normal mode Fast mode |
---|
| 326 | ----------------------------------------------------------------- |
---|
| 327 | -- Fscl 100KHz 400KHz |
---|
| 328 | -- Th_scl 4.0us 0.6us High period of SCL |
---|
| 329 | -- Tl_scl 4.7us 1.3us Low period of SCL |
---|
| 330 | -- Tsu:sta 4.7us 0.6us setup time for a repeated start condition |
---|
| 331 | -- Tsu:sto 4.0us 0.6us setup time for a stop conditon |
---|
| 332 | -- Tbuf 4.7us 1.3us Bus free time between a stop and start condition |
---|
| 333 | -- |
---|
| 334 | |
---|
| 335 | library ieee; |
---|
| 336 | use ieee.std_logic_1164.all; |
---|
| 337 | use ieee.std_logic_arith.all; |
---|
| 338 | |
---|
| 339 | entity i2c_core is |
---|
| 340 | port ( |
---|
| 341 | clk : in std_logic; |
---|
| 342 | nReset : in std_logic; |
---|
| 343 | |
---|
| 344 | clk_cnt : in unsigned(7 downto 0); |
---|
| 345 | |
---|
| 346 | cmd : in std_logic_vector(2 downto 0); |
---|
| 347 | cmd_ack : out std_logic; |
---|
| 348 | busy : out std_logic; |
---|
| 349 | |
---|
| 350 | Din : in std_logic; |
---|
| 351 | Dout : out std_logic; |
---|
| 352 | |
---|
| 353 | SCL : inout std_logic; |
---|
| 354 | SDA : inout std_logic |
---|
| 355 | ); |
---|
| 356 | end entity i2c_core; |
---|
| 357 | |
---|
| 358 | architecture structural of i2c_core is |
---|
| 359 | constant CMD_NOP : std_logic_vector(2 downto 0) := "000"; |
---|
| 360 | constant CMD_START : std_logic_vector(2 downto 0) := "010"; |
---|
| 361 | constant CMD_STOP : std_logic_vector(2 downto 0) := "011"; |
---|
| 362 | constant CMD_READ : std_logic_vector(2 downto 0) := "100"; |
---|
| 363 | constant CMD_WRITE : std_logic_vector(2 downto 0) := "101"; |
---|
| 364 | |
---|
| 365 | type cmds is (idle, start_a, start_b, start_c, start_d, stop_a, stop_b, stop_c, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); |
---|
| 366 | signal state : cmds; |
---|
| 367 | signal SDAo, SCLo : std_logic; |
---|
| 368 | signal txd : std_logic; |
---|
| 369 | signal clk_en, slave_wait :std_logic; |
---|
| 370 | signal cnt : unsigned(7 downto 0) := clk_cnt; |
---|
| 371 | begin |
---|
| 372 | -- whenever the slave is not ready it can delay the cycle by pulling SCL low |
---|
| 373 | slave_wait <= '1' when ((SCLo = '1') and (SCL = '0')) else '0'; |
---|
| 374 | |
---|
| 375 | -- generate clk enable signal |
---|
| 376 | gen_clken: process(clk, nReset) |
---|
| 377 | begin |
---|
| 378 | if (nReset = '0') then |
---|
| 379 | cnt <= (others => '0'); |
---|
| 380 | clk_en <= '1'; --'0'; |
---|
| 381 | elsif (clk'event and clk = '1') then |
---|
| 382 | if (cnt = 0) then |
---|
| 383 | clk_en <= '1'; |
---|
| 384 | cnt <= clk_cnt; |
---|
| 385 | else |
---|
| 386 | if (slave_wait = '0') then |
---|
| 387 | cnt <= cnt -1; |
---|
| 388 | end if; |
---|
| 389 | clk_en <= '0'; |
---|
| 390 | end if; |
---|
| 391 | end if; |
---|
| 392 | end process gen_clken; |
---|
| 393 | |
---|
| 394 | -- generate statemachine |
---|
| 395 | nxt_state_decoder : process (clk, nReset, state, cmd, SDA) |
---|
| 396 | variable nxt_state : cmds; |
---|
| 397 | variable icmd_ack, ibusy, store_sda : std_logic; |
---|
| 398 | variable itxd : std_logic; |
---|
| 399 | begin |
---|
| 400 | |
---|
| 401 | nxt_state := state; |
---|
| 402 | |
---|
| 403 | icmd_ack := '0'; -- default no acknowledge |
---|
| 404 | ibusy := '1'; -- default busy |
---|
| 405 | |
---|
| 406 | store_sda := '0'; |
---|
| 407 | |
---|
| 408 | itxd := txd; |
---|
| 409 | |
---|
| 410 | case (state) is |
---|
| 411 | -- idle |
---|
| 412 | when idle => |
---|
| 413 | case cmd is |
---|
| 414 | when CMD_START => |
---|
| 415 | nxt_state := start_a; |
---|
| 416 | icmd_ack := '1'; -- command completed |
---|
| 417 | |
---|
| 418 | when CMD_STOP => |
---|
| 419 | nxt_state := stop_a; |
---|
| 420 | icmd_ack := '1'; -- command completed |
---|
| 421 | |
---|
| 422 | when CMD_WRITE => |
---|
| 423 | nxt_state := wr_a; |
---|
| 424 | icmd_ack := '1'; -- command completed |
---|
| 425 | itxd := Din; |
---|
| 426 | |
---|
| 427 | when CMD_READ => |
---|
| 428 | nxt_state := rd_a; |
---|
| 429 | icmd_ack := '1'; -- command completed |
---|
| 430 | |
---|
| 431 | when others => |
---|
| 432 | nxt_state := idle; |
---|
| 433 | -- don't acknowledge NOP command icmd_ack := '1'; -- command completed |
---|
| 434 | ibusy := '0'; |
---|
| 435 | end case; |
---|
| 436 | |
---|
| 437 | -- start |
---|
| 438 | when start_a => |
---|
| 439 | nxt_state := start_b; |
---|
| 440 | |
---|
| 441 | when start_b => |
---|
| 442 | nxt_state := start_c; |
---|
| 443 | |
---|
| 444 | when start_c => |
---|
| 445 | nxt_state := start_d; |
---|
| 446 | |
---|
| 447 | when start_d => |
---|
| 448 | nxt_state := idle; |
---|
| 449 | ibusy := '0'; -- not busy when idle |
---|
| 450 | |
---|
| 451 | |
---|
| 452 | -- stop |
---|
| 453 | when stop_a => |
---|
| 454 | nxt_state := stop_b; |
---|
| 455 | |
---|
| 456 | when stop_b => |
---|
| 457 | nxt_state := stop_c; |
---|
| 458 | |
---|
| 459 | when stop_c => |
---|
| 460 | -- nxt_state := stop_d; |
---|
| 461 | |
---|
| 462 | -- when stop_d => |
---|
| 463 | nxt_state := idle; |
---|
| 464 | ibusy := '0'; -- not busy when idle |
---|
| 465 | |
---|
| 466 | -- read |
---|
| 467 | when rd_a => |
---|
| 468 | nxt_state := rd_b; |
---|
| 469 | |
---|
| 470 | when rd_b => |
---|
| 471 | nxt_state := rd_c; |
---|
| 472 | |
---|
| 473 | when rd_c => |
---|
| 474 | nxt_state := rd_d; |
---|
| 475 | store_sda := '1'; |
---|
| 476 | |
---|
| 477 | when rd_d => |
---|
| 478 | nxt_state := idle; |
---|
| 479 | ibusy := '0'; -- not busy when idle |
---|
| 480 | |
---|
| 481 | -- write |
---|
| 482 | when wr_a => |
---|
| 483 | nxt_state := wr_b; |
---|
| 484 | |
---|
| 485 | when wr_b => |
---|
| 486 | nxt_state := wr_c; |
---|
| 487 | |
---|
| 488 | when wr_c => |
---|
| 489 | nxt_state := wr_d; |
---|
| 490 | |
---|
| 491 | when wr_d => |
---|
| 492 | nxt_state := idle; |
---|
| 493 | ibusy := '0'; -- not busy when idle |
---|
| 494 | |
---|
| 495 | end case; |
---|
| 496 | |
---|
| 497 | -- generate regs |
---|
| 498 | if (nReset = '0') then |
---|
| 499 | state <= idle; |
---|
| 500 | cmd_ack <= '0'; |
---|
| 501 | busy <= '0'; |
---|
| 502 | txd <= '0'; |
---|
| 503 | Dout <= '0'; |
---|
| 504 | elsif (clk'event and clk = '1') then |
---|
| 505 | if (clk_en = '1') then |
---|
| 506 | state <= nxt_state; |
---|
| 507 | busy <= ibusy; |
---|
| 508 | |
---|
| 509 | txd <= itxd; |
---|
| 510 | if (store_sda = '1') then |
---|
| 511 | Dout <= SDA; |
---|
| 512 | end if; |
---|
| 513 | end if; |
---|
| 514 | |
---|
| 515 | cmd_ack <= icmd_ack and clk_en; |
---|
| 516 | end if; |
---|
| 517 | end process nxt_state_decoder; |
---|
| 518 | |
---|
| 519 | -- |
---|
| 520 | -- convert states to SCL and SDA signals |
---|
| 521 | -- |
---|
| 522 | output_decoder: process (clk, nReset, state) |
---|
| 523 | variable iscl, isda : std_logic; |
---|
| 524 | begin |
---|
| 525 | case (state) is |
---|
| 526 | when idle => |
---|
| 527 | iscl := SCLo; -- keep SCL in same state |
---|
| 528 | isda := SDA; -- keep SDA in same state |
---|
| 529 | |
---|
| 530 | -- start |
---|
| 531 | when start_a => |
---|
| 532 | iscl := SCLo; -- keep SCL in same state (for repeated start) |
---|
| 533 | isda := '1'; -- set SDA high |
---|
| 534 | |
---|
| 535 | when start_b => |
---|
| 536 | iscl := '1'; -- set SCL high |
---|
| 537 | isda := '1'; -- keep SDA high |
---|
| 538 | |
---|
| 539 | when start_c => |
---|
| 540 | iscl := '1'; -- keep SCL high |
---|
| 541 | isda := '0'; -- sel SDA low |
---|
| 542 | |
---|
| 543 | when start_d => |
---|
| 544 | iscl := '0'; -- set SCL low |
---|
| 545 | isda := '0'; -- keep SDA low |
---|
| 546 | |
---|
| 547 | -- stop |
---|
| 548 | when stop_a => |
---|
| 549 | iscl := '0'; -- keep SCL disabled |
---|
| 550 | isda := '0'; -- set SDA low |
---|
| 551 | |
---|
| 552 | when stop_b => |
---|
| 553 | iscl := '1'; -- set SCL high |
---|
| 554 | isda := '0'; -- keep SDA low |
---|
| 555 | |
---|
| 556 | when stop_c => |
---|
| 557 | iscl := '1'; -- keep SCL high |
---|
| 558 | isda := '1'; -- set SDA high |
---|
| 559 | |
---|
| 560 | -- write |
---|
| 561 | when wr_a => |
---|
| 562 | iscl := '0'; -- keep SCL low |
---|
| 563 | -- isda := txd; -- set SDA |
---|
| 564 | isda := Din; |
---|
| 565 | |
---|
| 566 | when wr_b => |
---|
| 567 | iscl := '1'; -- set SCL high |
---|
| 568 | -- isda := txd; -- set SDA |
---|
| 569 | isda := Din; |
---|
| 570 | |
---|
| 571 | when wr_c => |
---|
| 572 | iscl := '1'; -- keep SCL high |
---|
| 573 | -- isda := txd; -- set SDA |
---|
| 574 | isda := Din; |
---|
| 575 | |
---|
| 576 | when wr_d => |
---|
| 577 | iscl := '0'; -- set SCL low |
---|
| 578 | -- isda := txd; -- set SDA |
---|
| 579 | isda := Din; |
---|
| 580 | |
---|
| 581 | -- read |
---|
| 582 | when rd_a => |
---|
| 583 | iscl := '0'; -- keep SCL low |
---|
| 584 | isda := '1'; -- tri-state SDA |
---|
| 585 | |
---|
| 586 | when rd_b => |
---|
| 587 | iscl := '1'; -- set SCL high |
---|
| 588 | isda := '1'; -- tri-state SDA |
---|
| 589 | |
---|
| 590 | when rd_c => |
---|
| 591 | iscl := '1'; -- keep SCL high |
---|
| 592 | isda := '1'; -- tri-state SDA |
---|
| 593 | |
---|
| 594 | when rd_d => |
---|
| 595 | iscl := '0'; -- set SCL low |
---|
| 596 | isda := '1'; -- tri-state SDA |
---|
| 597 | end case; |
---|
| 598 | |
---|
| 599 | -- generate registers |
---|
| 600 | if (nReset = '0') then |
---|
| 601 | SCLo <= '1'; |
---|
| 602 | SDAo <= '1'; |
---|
| 603 | elsif (clk'event and clk = '1') then |
---|
| 604 | if (clk_en = '1') then |
---|
| 605 | SCLo <= iscl; |
---|
| 606 | SDAo <= isda; |
---|
| 607 | end if; |
---|
| 608 | end if; |
---|
| 609 | end process output_decoder; |
---|
| 610 | |
---|
| 611 | SCL <= '0' when (SCLo = '0') else 'Z'; -- since SCL is externally pulled-up convert a '1' to a 'Z'(tri-state) |
---|
| 612 | SDA <= '0' when (SDAo = '0') else 'Z'; -- since SDA is externally pulled-up convert a '1' to a 'Z'(tri-state) |
---|
| 613 | -- SCL <= SCLo; |
---|
| 614 | -- SDA <= SDAo; |
---|
| 615 | |
---|
| 616 | end architecture structural; |
---|
| 617 | |
---|
| 618 | |
---|
| 619 | |
---|
| 620 | |
---|