EE 5315 System on Chip Design Design of a I2C IP Core and Linux Device Drivers Ganesh Reddy Tamatam 1001983860 Overview The objective of this project is to construct an I2C IP module on a Cyclone V FPGA that can be controlled and configured via an Avalon memory-mapped interface from the hard processor subsystem. Verilog Modules I2C Module: This is the main module which communicates with the HPS. All the sub modules are instantiated in this module. The prsimary functions of this module include reading from and writing to the HPS and the bus expander. FIFO Module: This module implements hardware fifo. It is instantiated in the I2C module as TX_FIFO and RX_FIFO. FSM Module: It generates the control signals for driving the data to the SDA line and reading from it. It goes through different states depending on what step of transmission/reception is the I2C at. Serializer Module: It takes the control signals from the FSM and drives the data to the SDA line accordingly. Sampler Module: It takes the control signals from the FSM and reads the data from the SDA line accordingly. Synchronizer Module: This module generates the SCL clock and timing reference signals for the FSM, Serializer and Sampler. FSM States for write cycle IDLE: In this state, all the control signals are disabled. The FSM remains in this state if there is no read command or write command. When there is a write command, it goes to START_W state. When there is a read command, it goes to START_1R state. START_W: The FSM asserts ‘start_enb’ to the serializer with which the serializer implements the start condition. The next state is DRIVE_ADDRESS_W state. DRIVE_ADDRESS_W: The FSM asserts ‘add_enb’ signal. This signal makes the serializer to drive the address of the slave on to the SDA line. ACK_WAIT_ADD_W: As long as the serializer drives the address, the FSM keeps waiting for the acknowledgement from the slave. It asserts ‘samp_ack_enb’ signal to the sampler. Then the sampler starts counting the bits that are being driven. After driving 8 bits, the sampler samples the SDA line data. If a 0 is received on the SDA, ‘ack_received’ signal is sent to the FSM. If a 1 is sampled, ‘ack_error’ signal is sent. If acknowledgement is received and ‘use_register’ is set, the next state is DRV_REG_W. If acknowledgement is received and ‘use_register’ is not set, the next state is DRV_DATA_W. If acknowledgement is not received, the next state is STOP_W. DRIVE_REG_W: The signal ‘reg_enb’ is asserted which tells the serializer to drive the register value. The FSM goes to the state ‘ACK_WAIT_W’ unconditionally. ACK_WAIT_W: The FSM waits for ‘ack_received’ signal from the sampler. If acknowledgement is received, the next state is DRIVE_DATA_W, else the next state is STOP_W. DRIVE_DATA_W: The signal ‘data_enb’ is asserted which tells the serializer to drive the data in the TX_FIFO. The remaining byte count is decremented in this state. The next state is ACK_WAIT_W unconditionally. The FSM moves between the states DRIVE_DATA_W and ACK_WAIT_W as long as the remaining byte count is not equal to 0. STOP_W: The signal ‘stop_enb’ is asserted which tells the serializer to drive a stop condition. The next state is IDLE unconditionally. FSM States for read cycle START_1R: The FSM comes to this state when the previous state is IDLE and read command is asserted. If ‘use_register’ is set, the next state is DRIVE_ADDRESS_1R, else it is DRIVE_ADDRESS_2R. DRIVE_ADDRESS_1R: Here, we set the ‘rw’ bit and assert the add_enb signals which tells the serializer to drive the address followed by write bit. The next state is ACK_WAIT_ADD_1R. ACK_WAIT_ADD_1R: The FSM remains in this state till it receives ‘ack_received’ signal or ‘ack_error’ signal. If acknowledgement is received, the next state is DRIVE_REG_1R, else it is STOP_2R. DRIVE_REG_1R: The signal ‘reg_enb’ is asserted which tells the serializer to drive the register address. The next state is ACK_WAIT_REG_1R. ACK_WAIT_REG_1R: The FSM waits for acknowledgement. If acknowledgement is received and ‘use repeated start’ is set, the next state is START_2R. If acknowledgement is received and ‘use repeated start’ is not set, the next state is STOP_1R. If acknowledgement is not received, the next state is STOP_2R. STOP_1R: A stop condition is driven. The next state is START_2R. START_2R: A start condition is driven. The next state is DRIVE_ADDRESS_2R. DRIVE_ADDRESS_2R: The slave address is driven. The next state is ACK_WAIT_2R. ACK_WAIT_2R: Waits for acknowledgement. If ack is received, the next state is DATA_WAIT_2R, else it is STOP_2R. DATA_WAIT_2R: Waits for the data to be received. After receiving the data, byte count is decremented. The next state is SEND_ACK_2R. SEND_ACK_2R: Acknowledgement is sent to the slave. If the byte count is not 0, the next state is DATA_WAIT_2R, else it is STOP_2R. STOP_2R: A stop condition is driven. The next state is IDLE. Kernel Objects Mode: Used to set/reset the Control Register bit 0. ‘Write’ is written for write operation. ‘Read’ is written for read operation. Byte_Count: Writes to and reads from the Control Register bits [6:1]. Its value is in the range 0 – 63. Register: Writes to and reads from the Control Register bits [15:8]. Its value is in the range 0 – 255. Address: Writes to and reads from the Address Register. Its value is in the range 0 – 127. Use_Repeated_Start: Used to set/reset the Control Register bit 16. ‘True’ is written to set. ‘False’ is written to reset. Use_Register: Used to set/reset the Control Register bit 7. ‘True’ is written to set. ‘False’ is written to reset. Start: Used to set/reset the Control Register bit 17. Any value can be written to set. TX_Data: Writes to the Data Register. Its value is in the range 0 – 255. RX_Data: Reads from the Data Register. Its value is in the range 0 – 255. Circuit Fig1. Connection between DE1 and MCP 23008 Waveforms Fig2. Write Cycle Fig3. Read Cycle (without Use Repeated Start) Fig4. Read Cycle (with Use Repeated Start) Fig5. ‘Re-Start’ in ‘use repeated start’ condition Output Fig6. Transmission/Reception of Data