This project implements an FPGA-based I2C communication system for reading temperature data from the ADT7420 and a display interface for real-time temperature visualization on a 7-segment display.
The clock_gen module generates a clock signal at a specified frequency by dividing a 100 MHz input clock. It outputs a signal that toggles at a 50% duty cycle, effectively producing a square wave at the desired frequency. This output is used as a timing signal (e.g., 400 kHz or 1 Hz) for other modules requiring a slower clock domain.
This block uses a synchronous counter to toggle the output clock enable signal, and it does not have an external reset.
This module works closely with I2C driver. Specific informations about temperature sensor ADT7420 including I2C address, register value and state-machine necessary for optaining desired information is stored in this module.
start
signal is used to progress fromWAIT_FOR_START_STATE
. Edges of both clock signal and start signal could be shifted from each other depending on frequency of start signal. For that very reasonlatch_start
signal is used to actually start the state-machine.- Module commands starts of the I2C transaction by passing necessary informations to underlying I2C driver.
- Module waits until I2C driver reports that commanded operation has ended either successfully (
done = '1'
) or not (bit_error = '1'
). After unsuccesful request state-machine falls back intoWAIT_FOR_START_STATE
state. - After successful request module converts returnted response into temperature. Programm does not implement FPU so the convertend temperature is stored as fixed point decimal number in 10E4 degrees Celsius. Simple check of converted temperature is performed to isolate ironious values. Before falling back into
WAIT_FOR_START_STATE
done_read <= '1'
is written for I2C driver to signal that response was read and it too can fall back into idle state.
I2C driver establishes communication between ADT7420 driver and the sensor itself. The code is separated into 3 processes which are sensitive to clock signal generated by clock_gen module:
- rising_process is sensitive to rising edge of the clock signal and responsible for switching between states (FSM), reading data from both slave and master, and increasing iterative signals such as counter or read_counter.
- falling_process on the other hand based on conditional statements and iterative signals changes SDA_drive and SCL_drive signals between '0' a 'Z' ('Z' stands for released bus).
- If a signal disable_auto_SCL is set to '0' p_SCL_driver updates the SCL_drive according to the signal from clock_gen, otherwise SCL is set to 'Z'.
- Collaterally to these processes inouts SDA and SCL are updated from signals SCL_drive and SDA_drive. The correct sequence of the FSM is stored in the array 'state_sequence'.
Reset
is set to be always the first state in the FSM. 'Reset' state generally lasts untill the push button on the Nexys_a7_50T is not being pushed anymore so therst
is low.- I2C_driver is in
Idle
state untill receiving any data from ADT7420_driver, which is tested by conditionnum_bytes /= '0'
. - 'Start_condition' is defined as high-to-low transition on 'SDA' while
SCL
remains high. Note that only in start/stop condition SDA doesnt change on falling edge. Send_address_w
is processed in both rising and falling processes. In rising_process on rising edges there is an internal signalcounter
that increases every clock period. On the other hand in falling_process we utilize the increasing 'counter' for indexing an appropriate bit in the 'address' 7-bit input vector. There is also a convertor for converting logic '1' to released busZ
.w
in the name of this state stands for write bit ('0') which is the last bit in the 8-bit frame.- After sending address there is a state
Check_ack
, which detects whether the sensor send acknowledge ('0') or not ('Z'). If the sensor didnt send the ack, signalerror_signal
is set to '1' and the next state isstop
, otherwise itsSend_register
. - Note that for
Send_register
is used the same logic as for theSend_address_w
state except the reg input vector is 8-bit and we dont deal with that last bit must be set to '0'. - Next follows
Check_ack
state again and thenStart
- no differences. Send_address_r
is the same as with thew
exceptr
as a read bit stands forZ
. LastCheck_ack
follows.- As
Check_ack
stateRead_data
is only in rising_process, because we need to read the data on rising_edge. At first theread_size
variable is set according to signalsnum_bytes
andread_counter
.read_size
represents the length of the response vector - 1 (at the beginning it should be 15 or 7). 'H' in the logic convertor means weak-pull-up.
The seg drive module is a synchronous module used to dislplay meassured temperature using 7 out of 8 availiable 7-segment display units with non floating decimal point. Module is able to display values in range +-99.9999.
Input value is represented by integer value that contains actual value multiplied by 10^4 (e.g., 256365 for 25.6365). Module mathematically separates digits of input number and displays them on individual units using upgraded 7-segment driver from classes with 400 kHz refresh rate.