Logo Studenta

TFG-4177 RamÃ_rez Pons

¡Este material tiene más páginas!

Vista previa del material en texto

,, Equation Chapter 1 Section 1 
Proyecto Fin de Grado 
Ingeniería Eléctronica, Robótica y Mecatrónica 
 
Diseño VHDL de un driver I3C 
Autor: Pablo Ramírez Pons 
Tutores: Fernando Muñoz Chavero, Jóse María Hinojo Montero 
Dpto. Electrónica 
Escuela Técnica Superior de Ingeniería 
Universidad de Sevilla 
 Sevilla, 2022 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
iii 
 
Proyecto Fin de Grado 
Ingeniería Electrónica, Robótica y Mecatrónica 
 
 
 
 
 
Diseño VHDL de un driver I3C 
 
 
Autor: 
Pablo Ramírez Pons 
 
 
Tutores: 
Fernando Muñoz Chavero 
Catedrático de Universidad 
Jóse María Hinojo 
Investigador Postdoctoral Talento 
 
 
Dpto. de Ingeniería Electrónica 
Escuela Técnica Superior de Ingeniería 
Universidad de Sevilla 
Sevilla, 2022 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
v 
 
 
 
Proyecto Fin de Grado: Diseño VHDL de un driver I3C 
 
 
 
 
 
Autor: Pablo Ramírez Pons 
Tutores: Fernando Muñoz Chavero, José María Hinojo Montero 
 
 
El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros: 
Presidente: 
 
 
 
Vocales: 
 
 
 
 
Secretario: 
 
 
 
 
Acuerdan otorgarle la calificación de: 
 
Sevilla, 2022 
 
 
 
 
 
 
El Secretario del Tribunal 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
vii 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Página intencionalmente en blanco. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ix 
 
Agradecimientos 
Este proyecto ha sido desarrollado como un proyecto colaborativo entre Jóse María Hinojo, Fernando Muñoz 
y servidor. Agradezco toda la ayuda aportada por ambos profesores y los nuevos conocimientos obtenidos en 
el desarrollo de este. 
También agradezco a mi ordenador que no se haya estropeado durante el desarrollo del proceso. 
 
Pablo Ramírez Pons 
Estudiante de la Escuela Técnica Superior de Ingeniería 
Sevilla, 2022 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xi 
 
Resumen 
 
 
Desde la creación de los circuitos eléctricos, ha sido imprescindible seguir una serie de reglas para evitar 
problemas por la naturaleza de la electricidad. Con el posterior desarrollo de estos circuitos, ha surgido la 
necesidad de crear comunicaciones entre ellos que deben de seguir una serie de pautas para lograr la mayor 
complejidad en la comunicación utilizando la menor cantidad de material posible. Es así como surge la 
necesidad de crear los protocolos de comunicación. 
En este proyecto se va a implementar un protocolo de comunicación cuyo desarrollo empezó hace bastante 
poco en la historia de la electrónica (2015) llamado I3C y se va a probar su funcionamiento implementándolo 
en una FPGA. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xiii 
 
Abstract 
 
Since the creation of electrical circuit boards, it has been essential to follow a set of rules to avoid the 
consequences of the nature of electricity. As circuits grew in complexity, it rised the necessity to create 
intercommunication between diverse components trying to use the less quantity of materials in order to 
achieve higher complexity. This is the reason behind the creation of the communication protocols. 
In this project we are going to implement a pretty new communication protocol in the history of electronics 
(2015) known as I3C and we will implement it using a FPGA. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Índice 
Agradecimientos ix 
Resumen xi 
Abstract xiii 
Índice xiv 
Índice de Códigos xvi 
Índice de Figuras xviii 
1 Introducción 1 
1.1 Objetivos 1 
1.2 Herramientas Utilizadas 2 
2 Protocolo I2C VS I3C 5 
2.1. Protocolo I2C 5 
2.1.1 ¿Qué es el I2C? 5 
2.1.2 Implementación física del I2C 5 
2.1.3 Funcionamiento del protocolo I2C 6 
2.1.4 Ventajas del bus I2C 7 
2.2. Necesidad de actualizar el protocolo 8 
2.3. Protocolo I3C 8 
2.3.1 Objetivos y propósito del I3C 8 
2.3.2 Resumen técnico 10 
2.3.3 Principios fundamentales del bus 10 
2.3.4 I3C Maestro 13 
2.3.5 I3C esclavo 13 
2.3.6 Modo SDR 14 
3 Aplicación y hardware 17 
3.1 Aplicación 17 
3.2 Hardware 18 
3.2.1 Sensor de temperature TMP139 18 
3.3 Placa de adaptación 21 
3.3.1 PCB de ajuste 21 
3.3.2 PCB de voltajes 21 
3.4 Cableado 23 
4 Implementación en VHDL 25 
4.1 Máquinas de estado y esquemas de funcionamiento 25 
4.1.1 Maestro I3C 25 
4.1.2 Sensor initializer 27 
4.1.3 Top level registers 30 
xv 
 
4.1.4 Serial transmiter 31 
4.2 Código VHDL 32 
4.2.1 I3C_master.vhd 32 
4.2.2 SENSOR_INITIALIZER.vhd 42 
4.2.3 SERIAL_TRANSMITER.vhd 43 
4.2.4 Top_level.vhd 47 
5 Resultados y Conclusión 55 
5.1. Resultados finales 55 
5.1.1 Simulaciones 55 
5.1.2 Resultados de la implementación física 60 
6 Líneas futuras y conclusión 63 
6.1 Líneas Futuras 63 
6.2 Conclusión 64 
Referencias 65 
Glosario 67 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ÍNDICE DE CÓDIGOS 
 
 
Código 4-1 Generación de señales de reloj SDA y SCL. 33 
Código 4-2 Divider. 34 
Código 4-3 Máquina de estados general maestro I3C. 41 
Código 4-4 Puertos y generics maestro I3C. 42 
Código 4-5 Gestor de maestro I3C. 43 
Código 4-6 Señales y parte concurrente Serial Transmiter. 44 
Código 4-7 Puertos y generics Serial Transmiter. 44 
Código 4-8 Proceso síncrono Serial Transmiter 45 
Código 4-9 Máquina de estados general Serial Transmiter. 46 
Código 4-10 Proceso síncrono registros nivel superior. 47 
Código 4-11 Proceso combinacional del registro 1 de nivel superior. 48 
Código 4-12 Proceso combinacional del registro 2 de nivel superior. 49 
Código 4-13 Port map Top level. 50 
Código 4-14 Descripción concurrente nivel superior. 51 
Código 4-15 Conexionado de instancia SERIAL_TRANSMITER nivel superior. 52 
Código 4-16 Conexionado de instancia I3C_master nivel superior. 52 
Código 4-17 Conexionado de instancia sensor_initializer nivel superior. 53 
Código 4-18 Declaración de componente IOBUF. 53 
Código 4-19 Instancia de componente IOBUF. 54 
 
 
 
 
 
xvii 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ÍNDICE DE FIGURAS 
 
 
Figura 2-1 Condiciones de START y STOP del protocolo I2C. 6 
Figura 2-2 Traza I2C. 7 
Figura 2-3 Características del bus I3C. 9 
Figura 2-4 Consumo eléctrico I3C vs I2C. 10 
Figura 2-5 Traza I3C con múltiples tipos de mensaje. 11 
Figura 2-6 Máquina de estados general I3C. 12 
Figura 2-7 Roles dispositivos I3C. 13 
Figura 2-8 Configuración general del bus. 14 
Figura 2-9 Mensajes SDR I3C. 15 
Figura 2-10 Ejemplo traza I3C SDR. 16 
Figura 3-1 Esquema de aplicación del proyecto. 17 
Figura 3-2 Esquema pines externos TMP139. 18 
Figura 3-3 Esquema módulos internos TMP139. 19 
Figura 3-4 Registros internos de temperatura del TMP139. 19 
Figura 3-5 Dirección variable TMP139. 20 
Figura 3-6 Traza de lectura de registro sensor TMP139 usando I3C. 20 
Figura 3-7 Traza de envio de SETAASA. 21 
Figura 3-8 PCB del adaptador del sensor. 21 
Figura 3-9 Esquemático placa de voltajes. 22 
Figura 3-10 PCB placa de voltajes, vista superior. 22 
Figura 3-11 PCB placa de voltajes, vista inferior. 23 
Figura 4-1 Máquinade estados I3C maestro. 26 
Figura 4-2 Máquina de estados Sensor Initalizer. 28 
Figura 4-3 Esquema de montaje Sensor Initializer. 29 
Figura 4-4 Esquema general registros del nivel superior. 30 
Figura 4-5 Máquinas de estado de registros de nivel superior. 31 
xix 
 
Figura 4-6 Máquina de estados de Serial Transmiter. 32 
Figura 4-7 Diagrama de timings de SDA y SCL. 34 
Figura 5-1 Waveform SERIAL_TRANSMITER.vhd. 55 
Figura 5-2 Waveform INITIALIZER.vhd. 56 
Figura 5-3 Waveform i3c_master.vhd Modo escritura. 56 
Figura 5-4 Waveform i3c_master.vhd Modo Lectura. 57 
Figura 5-5 Waveform Registro intermedio Serial Transmitter y comparación. 58 
Figura 5-6 Waveform Registro intermedio Master_I3C. 58 
Figura 5-7 Waveform Sensor Initializer nivel superior. 58 
Figura 5-8 Waveform Master I3C nivel superior - Parte 1. 59 
Figura 5-9 Waveform Master I3C nivel superior - Parte 2. 59 
Figura 5-10 Waveform Top Level. 60 
Figura 5-11 Placa de voltajes física. 60 
Figura 5-12 Placa de adaptación física. 61 
Figura 5-13 Captura de Osciloscopio Broadcast I3C. 61 
Figura 5-14 Captura de Osciloscopio cambio de Initializer a Master I3C. 62 
Figura 5-15 Captura de Osciloscopio Envío de dirección de chip y ACK. 62 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 
 
 
1 INTRODUCCIÓN 
 
 
 
 
 
 
A RAE describe un sensor como “Dispositivo que detecta una determinada acción externa, temperatura, 
presión, etc., y la transmite adecuadamente”. En la actualidad vivimos en un mundo gobernado por 
sensores dado que esta es la principal forma que tiene un dispositivo digital de percibir el mundo 
exterior, y cada vez más y más sensores se van implementando para aumentar las funcionalidades de los 
instrumentos que utilizamos en nuestro día a día. 
Los sensores también son los encargados de transformar la información que perciben en señales eléctricas con 
las que podamos trabajar y esto conlleva una serie de problemas por la naturaleza de la electricidad. Dado que 
la información que recibimos de estos está codificada en ceros y unos correspondientes a niveles altos y bajos 
de tensión, si tenemos varios sensores conectados a un mismo dispositivo mediante un mismo bus, no 
podemos dejar que estos escriban y lean información a su antojo ya que esto puede provocar cortocircuitos en 
los integrados dañándolos severemante. Por tanto, es importante que los sensores se comuniquen de una 
manera ordenada para evitar este tipo de problemas. Es así como surgen los protocolos de comunicación, 
siendo estos no más que una conveción para tratar la información que se quiere transmitir o recibir de estos 
sensores. 
Un protocolo maestro-esclavo (master-slave en inglés) se define como un modelo asimétrico de comunicación 
o control donde un dispositivo llamado maestro controla a otros dispositivos o procesos llamados esclavos y 
hace el papel principal en el proceso. Tanto los protocolos I2C como I3C siguen este tipo de protocolo y el 
principal objetivo del proyecto es el de la implementación de un dispositivo maestro que se comunique con un 
esclavo en I3C. 
1.1 Objetivos 
El principal objetivo del presente trabajo es crear un controlador I3C funcional que permite establecer una 
comunicación básica (lecturas y escrituras) con un sensor (dispositivo esclavo). Este controlador será 
implementado en una FPGA. 
Dado que el protocolo I3C es una versión mejorada de su predecesor I2C, el estándar incorpora multitud de 
modos nuevos. Por tanto, para limitar el alcance del proyecto, debido a que la implementación de un 
controlador que soporte el estándar completo excedería el alcance de un Trabajo Fin de Grado, se ha optado 
por desarrollar una versión limitada pero funcional del protocolo. Esta versión da soporte a los accesos en 
modo lectura y escritura, así como los principales comandos definidos por el estándar. 
 
L 
 
“Ser autodidacta es, estoy convencido, el único tipo de 
educación que existe.” 
- Isaac Asimov - 
 
 
 Introducción 
 
 
2 
Los principales objetivos del trabajo han sido los siguientes: 
• Determinar el funcionamiento del protocolo de comunicación I3C y los diferentes modos de 
operación. 
• Describir las operaciones esenciales para un correcto funcionamiento del controlador. 
• Implementar en una FPGA un maestro que sea capaz de comunicarse por I3C. 
• Comprobar el funcionamiento del protocolo leyendo datos de un sensor de temperatura que soporte 
una comunicación I3C. 
1.2 Herramientas Utilizadas 
Para ello, vamos a precisar de varios programas y elementos hardware que se listan a continuación: 
• FPGA. En este caso utilizaremos la Basys 3 Xilinx Artix-7 (XC7A35-1CPG236C). 
• Sensor I3C. Sensor de temperatura TMP139 de Texas Instruments. 
• Vivado. Programa provisto por Xilinx para sintetizar e implementar un leguaje HDL en FPGAs 
(Version 2020.2). 
• Altium Designer. Programa empleado para la creación de esquemáticos y PCBs (Versión 19.1.5). 
• Docklight. Herramienta software usada para la lectura de datos por el puerto serie del ordenador. 
 
FPGA fue elegida por la gran cantidad de recursos hardware disponibles, así como por el número de interfaces 
de entrada y salida puestas a disposición del usuario. Además, este kit de desarrollo es compatible con el 
programa de diseño VHDL Vivado. 
El sensor de temperatura fue elegido ya que soporta el protocolo I3C en su mayoría. Además, el sensor 
permite hacer uso del protocolo I2C en un primer momento, ideal para familiarizarse con su funcionamiento. 
Se eligió un sensor en vez de un micrcontrolador ya que en el inicio del presente Trabajo Fin de Grado no 
había ninguna opción disponible en el mercado. Por tanto, se optó por buscar un dispositivo esclavo. La falta 
de dispositivos compatibles en el mercado se debe a que el protocolo I3C es de reciente diseño y aún no está 
muy extendido de manera comercial (Junio - 2021). 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3 
 
3 Diseño VHDL de un driver I3C 
 
 
 
 
 
 
 
 
5 
 
 
2 PROTOCOLO I2C VS I3C 
 
 
 
 
 
 
 
L protocolo I3C es parte de una evolución de otro protocolo de comunicación creado en los años 80 
llamado I2C [1]. Dado que se trata de una versión mejorada y actualizada del mismo, ambos comparten 
bastantes similitudes y, por lo tanto, lo más natural para desarrollar un proyecto I3C es partir de una 
implementación I2C para ver cómo se maneja el mismo. 
En este capítulo se va a describir las principales características del protocolo I2C. A continuación, se indicará 
la necesidad de actualizar dicho protocolo para resolver los problemas del presente. Finalmente, se detallará el 
protocolo I3C. 
2.1. Protocolo I2C 
2.1.1 ¿Qué es el I2C? 
El protocolo para bus I2C fue diseñado por Philips para permitir una comunicación fácil y sencilla entre 
componentes electrónicos que se encuentren en una misma PCB. 
Su sigla proviene del inglés Inter-Integrated Circuit y es conocido también como I2C o IIC [1]. 
En su origen, I2C estaba pensado para transmitir datos a una velocidad estandar de 100kbit/s (Slow Mode, 
SM) y un modo de transmisión rápida de 400kbit/s (Fast Mode, FM). Más adelante, se implementaron modos 
de comunicación que incrementaban las tasas de transmisión hasta 1Mbit/s (FM+), 3.4Mbit/s (HS-Mode) y 
5Mbit/s (UFM) [2]. Este último roza los límites del bus y es, por tanto, el único modo que es unidireccional. 
El protocolo I2C sigue un modelo maestro-esclavo el cual es definido de una forma asimétrica de 
comunicación en la que un dispositivo maestro controla a uno o más dispositivos denominados esclavos[3]. 
2.1.2 Implementación física del I2C 
El bus solamente necesita de dos líneas para funcionar, la línea SCL, que es la que define el reloj de las 
transacciones, y la línea SDA, que es por donde se transmiten los datos que queramos leer o escribir. Estas doslíneas son de tipo colector o drenador abierto. Por tanto, requieren de una resistencia de pull-up, dejando así un 
valor de 1 lógico débil, para su correcto funcionamiento. De esta forma, cuando se libera el bus, quedando este 
en un estado de alta impedancia, el estado lógico del mismo queda correctamente definido. Estas dos líneas 
E 
 
Proyecto planteado y elaborado por Pablo Ramírez 
Pons, estudiante de la Escuela Técnica Superior de 
Ingeniería de la Universidad de Sevilla 
 
 
Protocolo I2C VS I3C 
 
 
 
6 
son bidireccionales. 
2.1.3 Funcionamiento del protocolo I2C 
Cada dispositivo que quiera comunicarse bajo este protocolo tiene una dirección asignada de 7 bits y tiene uno 
de los roles maestro o esclavo. En la notación mas reciente, debido a controversia por la naturaleza del nombre 
los dos roles, son también conocidos como controlador y objetivo (controller y target en inglés). Sin embargo, 
para este proyecto vamos a utilizar la notación original [2]. 
Cabe destacar que aparte de los bits de información, el bus I2C introduce dos condiciones adicionales a la hora 
de intercambiar información que son las condiciones de START y STOP. Estas trabajan como delimitadores 
del mensaje o trama I2C. De esta manera se puede saber cuándo empieza y cuándo. 
La comunicación se inicia cuando el dispositivo maestro manda la condición de START para que los 
dispositivos esclavos estén a la escucha. La condición de START se define como una transición de nivel alto a 
bajo en la línea SDA cuando SCL se encuentra aún a nivel alto. La condición de STOP se define de la manera 
opuesta, siendo la transición de bajo nivel a lato nivel mientras SCL se encuentra a nivel bajo. La ¡Error! No 
se encuentra el origen de la referencia. muestra un ejemplo de estos valores. 
 
 
Figura 2-1 Condiciones de START y STOP del protocolo I2C[4]. 
 
Cualquier traspase de información distinto a estas dos condiciones se lee cuando SCL se encuentra a nivel alto, 
por lo tanto, el dato que queramos leer tiene que transmitirse por el bus con un poco de antelación para que el 
dato se estabilice. 
Acto seguido el maestro manda una traza de 8 bits que consiste en la dirección de 7 bits del dispositivo esclavo 
con el que nos queremos comunicar y el último bit que refleja el modo de funcionamiento en el que va a 
transcurrir la información pudiendo ser modo escritura o modo lectura. En I2C los bits se transmiten desde el 
MSB al LSB. 
Una vez se ha enviado la traza de 8 bits, el esclavo debe responder con un ACK, dando así a entender que está 
preparado para leer o enviar datos. Para esto, el maestro deja el bus libre, y comprueba su valor. Si el 
dispositivo esclavo pone a nivel bajo el bus, condición de ACK, se considera que está listo para recibir o 
transmitir información y la comunicación puede continuar. Por el contrario, si el esclavo pone la línea a nivel 
alto durante esta fase, se considera que no está preparado para continuar la comunicación y el maestro debe 
abortarla mediante la generación de la condición de STOP. Esto se conoce como condición NACK. Un 
ejemplo se puede ver en la ¡Error! No se encuentra el origen de la referencia.. 
El maestro o el esclavo empieza a mandar datos por el bus hasta completar los 8 bits de la traza. Una vez 
acabada la transacción en función de quien hubiera mandado los datos, debe dejar libre el bus para que su 
análogo mande el ACK (o NACK en su defecto en caso de haber habido un problema con la transacción). 
 
7 
 
7 Diseño VHDL de un driver I3C 
 
Finalmente, el maestro genera la condición de STOP dando fin a la comunicación. 
Esto funciona así, salvo algunas excepciones, ya que es posible que el maestro o esclavo quiera seguir 
recibiendo o mandando datos y, por tanto, la condición de STOP no tiene por qué generarse al enviarse una 
única trama de 8 bits. De esta manera, se podría llegar a un estado de START nuevo que se conoce como 
REPEATED START, volviendo a reiniciar todo el proceso anterior. Esta condición tiene una funcionalidad 
idéntica al START. 
 
 
Figura 2-2 Traza I2C. 
 
Adicionalmente, el protocolo I2C posee características adicionales que aportan mayor flexibilidad. Por lo 
general, la única forma que tiene un esclavo de transmitir su estado es mediante los ACKs. Sin embargo, esto 
no es del todo cierto ya que existe un concepto conocido como clock stretching. 
Cuando el esclavo determina que el reloj del maestro es superior al que puede manejar, el esclavo puede 
mantener la línea SCL a bajo nivel cuando el maestro está intentando forzarlo a alto nivel siguiendo su reloj 
interno. De esta manera, cuando el maestro lee que el reloj se encuentra en un estado que no debería (nivel 
bajo en vez de nivel alto), el maestro detiene la transacción y la maquina de estado se queda en estado de 
suspensión hasta que el esclavo deje libre la línea. De este modo, el esclavo puede modificar ligeramente el 
ritmo de la transacción. Cabe decir que el clock stretching es una característica opcional que muchos 
dispositivos no incluyen en los controladores que implementan [2]. 
 
2.1.4 Ventajas del bus I2C 
La forma de implementación del bus y su funcionamiento hace que sea tanto atractivo a niveles de diseño 
como de fabricación y creación de periféricos para circuitos integrados. 
A nivel de diseño tiene las siguientes ventajas: 
• Debido a la sencillez de la integración física del bus, es sencillo su integración en PCBs. 
• No hay necesidad de diseñar interfaces del bus ya que se encuentran integrados en el propio IC. 
• Tiene un modo de direccionamiento y protocolo de transferencia de datos integrado lo que permite 
simplificar la gestión y manejo de los dispositivos. 
• Permite flexibilidad en sus aplicaciones. 
• Permite que los IC se acoplen o desacoplen sin afectar al resto de los IC. 
• Los fallos son fácilmente localizables. 
• Debido a sus características, las implementaciones resultantes pueden ser de muy bajo consumo, 
haciéndolo ideal para dispositivos alimentados a baterías, donde la potencia estática disipada es un 
factor crítico. Además, su gran tolerancia al ruido, su gran rango de tensiones de funcionamiento 
 
Protocolo I2C VS I3C 
 
 
 
8 
(dependiente de la tecnología CMOS seleccionada) y su amplio rango de velocidades de 
funcionamiento, hace muy versátil el protocolo I2C. 
 
Desde el punto de vista de la fabricación, podemos observar las siguientes ventajas: 
• Al poseer únicamente dos líneas se reducen las interconexiones y el tamaño de las pistas, así como la 
cantidad de los pines. Esto hace que se puedan usar PCBs más pequeñas y, en consecuencia, mas 
baratas. 
• No requiere del uso de decodificadores de dirección ni otro tipo de lógica de adaptación. 
Finalmente, desde el punto de vista del desarrollo de ICs, su principal atractivo es que el protocolo está 
bastante extendido en el mercado en la actualidad y por tanto es mas sencillo buscar otros ICs compatibles 
para comunicarse [5] 
2.2. Necesidad de actualizar el protocolo 
En los últimos años, la proliferación de los dispositivos móviles, así como su complejidad. Esto lleva consigo 
un aumento del número de sensores del que dispone cada móvil para ejecutar diversas tareas. Se necesitan 
cada vez más pines y líneas para gestionar la comunicación y el control. Uno de los principales problemas que 
se encuentra con el I2C es que en el protocolo no está definido en ningún momento cómo se gestionan las 
interrupciones ni señales de sleep de los distintos dispositivos conectados al bus, por lo que se necesitan unas 
líneas auxiliares. Además, los smartphones más recientes ya incluyen del orden de diez o más sensores 
incorporados en un mismo bus, lo cual da lugar a que los límites físicos del mismo rocen su límite (el número 
máximo de dispositivos conectados a un mismo bus I2C se estima en 20 sensores). Otro problema deriva de la 
propia sencillez del protocolo I2C. Como ya se ha mencionado anteriormente,el bus I2C sólo precisa de dos 
líneas de comunicación, esto viene con algunos costes como la inahibilitación de los esclavos del bus para 
iniciar la comunicación. El uso de una resistencia de pull-up también provoca problemas tanto en la tasa de 
transmisión como en el consumo que, aunque siendo considerado bajo en los años de su creación (década de 
los 80), en la actualidad no resulta competitivo. Finalmente, los dispositivos I2C disponen de un filtro de ruido 
llamado spike filter que trabaja a 50 ns, lo que también limita la velocidad máxima a la que se puede transmitir 
en el bus sin considerar la información como un glitch. 
Una alternativa para cambiar de protocolo de comunicación es utilizar la interfaz SPI. Este protocolo requiere 
de cuatro líneas de comunicación y es, principalmente, utilizado cuando queremos transmitir grandes 
cantidades de datos en un intervalo pequeño como, por ejemplo, borrar memorias de almacenamiento estático 
o leer grandes volúmenes de datos de sensores. Aunque puede presentar mayores tasas de transmisión que el 
bus 2C, requiere de un mayor número de líneas de control, incrementando el área ocupada, así como los costes 
de fabricación. 
Como se puede ver, ambos protocolos tienen ventajas y desventajas que ni uno de los dos puede realmente 
solucionar. De esta manera surge un nuevo tipo de protocolo que sea escalable, sencillo y se uso como nuevo 
estándar para la comunicación de sensores añadiendo las funcionalidades de ambos métodos. Surge así un 
nuevo protocolo de comunicación centrado en la comunicación entre sensores y que fuera compatible con los 
antiguos sensores I2C y con los nuevos. Este es el conocido como I3C [6] 
2.3. Protocolo I3C 
2.3.1 Objetivos y propósito del I3C 
La interfaz I3C es una evolución del estándar que mejora las características de del I2C manteniendo 
compatibilidad hacia atrás. Esta gestionada por la organización MIPI[7]. 
La finalidad del bus I3C cumple con los siguientes requisitos: 
• Estandarizar la comunicación entre sensores 
 
9 
 
9 Diseño VHDL de un driver I3C 
 
• Reducir el número de pines utilizado en la integración de sistemas de sensores 
• Soportar modos de bajo consumo, altas velocidades y otras características críticas que están 
actualmente cubiertos por I2C y SPI 
Originalmente, el protocolo I3C estaba pensado para crear una única interfaz entre aplicaciones móviles que 
requiriesen de sensores, permitiendo ubicar varios en un mismo bus para minimizar la lógica adicional que 
gestionaba las interrupciones o los modos de sleep. Sin embargo, dicha utilidad no quedó reducida 
exclusivamente al uso de móviles ya que ofrecía altas velocidades de transmisión con un consumo energético 
reducido. Esta característica es fundamental para cualquier tipo de comunicación en un circuito integrado [6]. 
 
 
Figura 2-3 Características del bus I3C. 
 
Además, podemos comprobar en la Figura 2-4 que los modos de funcionamiento del I3C consumen menos 
energía a la vez que logran una mayor tasa de transmisión de datos [6]. 
 
 
Protocolo I2C VS I3C 
 
 
 
10 
 
Figura 2-4 Consumo eléctrico I3C vs I2C. 
2.3.2 Resumen técnico 
I3C es un bus de comunicación serie bidireccional optimizado para trabajar con múltiples dispositivos objetivo 
(generalmente sensores) y controlados mediante un único controlador I3C. Este protocolo es retrocompatible 
con una gran variedad de dispositivos I2C, pero también soporta velocidades significativamente mayores, 
nuevos modos de comunicación y nuevos roles para los dispositivos. Además, los roles pueden cambiar a lo 
largo del tiempo; por ejemplo, si el dispositivo maestro quiere ceder su rol de manera cooperativa para que el 
nuevo dispositivo trabaje como un maestro secundario, se puede efectuar. 
En cuanto a los modos de comunicación disponibles se encuentran lo siguientes. 
• Modo Compatibilidad (Legacy Mode): Soporte para dispositivos de legado I2C y mensajes. 
• I3C Single Data Rate (SDR) Mode: Versión mejorada del protocolo I2C que soporta el envío de 
mensajes privados. En este modo se añaden dos tipos de mensaje distintos. 
• Broadcast Messages: Mensajes que se envían a todos los dispositivos que se encuentran 
conectados al bus. 
• Direct Messages: Mensajes dirigidos a un solo dispositivo. 
• I3C High Data Rate (HDR) Modes: Modos de funcionamiento opcionales que añaden 
funcionalidades significativas. 
• Dual Data Rate (HDR - DDR) Mode: Funciona igual que el SDR pero al doble de 
velocidad. 
• Bulk Transport (HDR - BT) Mode: Consigue la máxima tasa de transmisión de datos 
aprovechándose del DDR y de los relojes de SDA y SCL. 
Para este proyecto, se va a desarrollar un maestro que pueda trabajar exclusivamente en modo SDR. De 
cualquier manera, es importante conocer los distintos modos de los que dispone el protocolo [7]. 
 
2.3.3 Principios fundamentales del bus 
Al igual que en I2C el protocolo I3C utiliza dos líneas de comunicación. Estas líneas comparten el mismo 
 
11 
 
11 Diseño VHDL de un driver I3C 
 
nombre que sus predecesoras siendo SCL y SDA. 
• SDA: Linea bidireccional de información. 
• SCL: Puede ser tanto línea de reloj como línea de datos bidireccional en algunos modos de HDR. 
Un bus I3C soporta además el uso de distintos tipos de mensajes en una solo línea de comunicación 
cambiando entre diversos modos mientras se transmiten datos de un tipo o de otro. Un ejemplo del tráfico del 
bus es muestra en la Figura 2-5. 
 
Figura 2-5 Traza I3C con múltiples tipos de mensaje. 
 
De igual forma que ocurría en I2C, las comunicaciones en I3C ocurren dentro de un intervalo delimitado entre 
las condiones de START (o REPEATED START) y STOP. Los paquetes de datos se transmiten entre las dos 
condiciones y se pueden transferir diversas tramas de datos antes de terminar la comunicación [7]. 
 
 
Protocolo I2C VS I3C 
 
 
 
12 
 
Figura 2-6 Máquina de estados general I3C. 
 
Las trazas en I3C difieren con respecto a las de su antecesor I2C, y dependen además del modo de 
comunicación en el que se trabaja. 
En cualquier momento, el bus de comunicación siempre tendremos un sólo dispositivo que funciona como 
maestro y uno o más dispositivos que funcionan como esclavos. Lo cual significa que, aunque dispongamos de 
dispositivos que puedan funcionar en ambos roles en ningún momento se puede tener una configuración que 
disponga de más de un maestro o menos de un esclavo. Aún así, a lo largo del ciclo de comunicación los roles 
pueden ir cambiando. Se define así el rol de maestro activo, siendo el dispositivo que está trabajando como 
maestro en un momento dado. La variabilidad de los roles da como resultado un espectro de posibles 
funciones que puede tener cada dispositivo, siendo todas unas variaciones de las denominaciones clásicas de 
maestro y esclavo. En la siguiente figura se pueden ver los siguientes roles compatibles con I3C [7]. 
 
 
13 
 
13 Diseño VHDL de un driver I3C 
 
 
Figura 2-7 Roles dispositivos I3C. 
 
2.3.4 I3C Maestro 
El dispositivo maestro activo es el principal encargado de mandar la mayoría de los comandos I3C (CCC) que 
pueden ser dirigidos a todos los dispositivos conectados del bus (Broadcast CCC) o a un dispositivo en 
particular (Directed CCC). El maestro es también el único dispositivo que permite mandar mensajes I2C en 
Legacy Mode. 
Adicionalmente, el maestro I3C debe encargarse de las siguientes tareas: 
• Generar la señal de reloj cuando se encuentra se encuentra en los modos SDR y los HDR que lo 
precisen (Para algunos modos de HDR no se utiliza un reloj convencional). 
• Gestionar las estructuras de pull-up del bus. 
• Gestionar los modos de asignación dinámica de direcciones. 
• Gestionar las solicitudes de START del bus y las solicitudes de arbitraje de direcciones como pueden 
ser: 
• Generar IBIs. 
• Eventos Hot-Join. 
• Solicitudes de transferencia del rol de maestro activo. 
• Obviamente debe también soportary gestionar los modos de funcionamiento tanto de Legacy I2C 
como los modos SDR y cualquiera de los HDR. 
 
2.3.5 I3C esclavo 
Dado la naturaleza de los protocolos maestro-esclavo, un esclavo debe simplemente encargarse de la otra parte 
de la comunicación en lo mencionado anteriormente. Por lo tanto, un esclavo I3C generalmente se encarga de 
lo siguiente. 
• Escuchar y actuar correctamente a cada CCC que se recibe. 
• Debe soportar siempre el modo de operación SDR del protocolo. 
• Debe seguir la señal de reloj generada por el maestro. 
 
Protocolo I2C VS I3C 
 
 
 
14 
• Leer o escribir en los modos HDR (HDR-BT es opcional). 
• Soportar alguno de los tipos de asignación dinámica de direcciones. 
• Opcionalmente el dispositivo puede: 
• Solicitar IBIs. 
• Generar eventos Hot-Join. 
• Solicitar la transferencia de rol a maestro activo. 
 
2.3.6 Modo SDR 
Como ya se ha mencionado previamente, para este proyecto vamos a crear un maestro simple que trate de 
comunicarse con el nuevo protocolo I3C. Para ello se ha implementado un maestro con las funcionalidades 
más simples del protocolo, trabajando exclusivamente en modo SDR. 
SDR es el modo principal de comunicación del I3C, siendo también el principal nexo para trabajar en otros 
modos, submodos o estados del bus; y para para características propias del mismo como los CCCs, IBIs o 
transiciones de modo Legacy I2C a I3C mediante asignación dinámica de dirección. 
El modo SDR es muy parecido funcionalmente al I2C, en términos de procedimiento y condiciones de 
funcionamiento. Como resultado, tanto dispositivos I3C como esclavos I2C (los dispositivios configurados 
como maestros no son compatibles) pueden cohexistir en el mismo bus I3C. Sin embargo, SDR también 
incluye ciertas nuevas características que no se encuentran en el protocolo I2C. Esto da como resultado que no 
se pueda trabajar con ambos dispositivos a la vez ya que, si tenemos un I3C que funciona en modo Legacy 
I2C, los dispositivos I3C esclavos ignorarán las trazas de datos y si mandamos mensajes I3C, los dispositivos 
I2C no serán capaces de leerlos ya que el spike filter de los dispositivos I2C hace la información se filtre 
debido a la alta velocidad del protocolo. 
Una configuración general del bus sería la mostrada en la Figura 2-8. 
 
Figura 2-8 Configuración general del bus. 
 
SDR en su raíz es bastante similar al protocolo I2C, pero tiene algunas diferencias como las indicadas a 
continuación. 
 
15 
 
15 Diseño VHDL de un driver I3C 
 
• Las condiciones de START (o REPEATED START) y STOP, son idénticas salvo por presentar una 
temporización ligeramente más estricta. 
• Las trazas de dirección son iguales que que las del I2C en forma de señales y bits utilizados, pero con 
una temporización más estricta. 
• Las trazas de datos de 9 bits (8 bits de datos más 1 bit de ACK/NACK en I2C), son idénticas salvo en 
el noveno bit. En vez de las condiciones de ACK o NACK se crea una nueva condición llamada 
TRANSICTION BIT. Esta nueva condición determina si se van a seguir leyendo o enviando mensajes 
en ráfaga. 
• En I3C la línea SCL solo la maneja el maestro. Esto significa que el clock stretching del I2C no 
funciona en I3C. Normalmente es una línea push-pull pero puede también trabajar a drenador abierto. 
Entonces un mensaje se considera I3C SDR si el valor en la dirección es el 7’h7E (valor perteneciente al 
CCC BROADCAST) y por tanto los dispositivos I3C leerán este valor y empezarán la comunicación (los 
dispositivos I2C no podrán leer este valor de dirección ya que en su protocolo este es un valor reservado) o 
si la dirección de la traza de dirección coincide con su dirección asignada de manera dinámica. 
De forma resumida, los mensajes en SDR pueden ser de los siguientes tipos. 
 
Figura 2-9 Mensajes SDR I3C. 
 
En la Figura 2-10 se ilustra un ejemplo de una transacción utilizando el modo I3C SDR. En ella se muestra un 
maestro leyendo un byte de datos de un esclavo con la dirección 7h2B. 
 
Protocolo I2C VS I3C 
 
 
 
16 
 
Figura 2-10 Ejemplo traza I3C SDR [7]. 
 
En este ejemplo, partimos de la condición de bus libre (ninguno dispositivo está accediendo al mismo), el 
maestro manda la condición de START mediante un flanco de bajada en SDA cuando tenemos SCL a nivel 
alto (de forma similar al bus I2C). Entonces, se envía la dirección de broadcast seguido de un ‘0’ lógico que 
indica una operación de escritura. Esto no puede ser de otra forma ya que los CCC siempre son en modo 
escritura. Después, el maestro deja el bus en modo drenador abierto o alta impedancia para que el esclavo tome 
el control y pueda responder con un ACK (cualquiera puede responder dado que todos reciben el CCC). 
Posteriormente, el maestro vuelve a tomar control del bus y manda la condición de REPEATED START 
seguido de la dirección del esclavo con el que se quiere comunicar y el modo de operación (en este caso 1 
dado que vamos a leer). El maestro vuelve a dejar la línea en drenador abierto y pasa el control del bus al 
esclavo que debe responder con el ACK (aquí únicamente el que coincida con la dirección privada). Como se 
encuentra en modo de escritura, el control del bus sigue en manos del esclavo, que manda los datos que le 
toque enviar (en este caso se manda una traza de valor 0x4A). Una vez mandada la traza datos se manda el bit 
de transición T. En este caso T = ‘1’ significa que hay más trazas de datos para mandar en cascada y por tanto 
en el ejemplo se puede ver que se envía otra traza adicional. Una vez no se quieren recibir más datos el esclavo 
pone T = ‘0’ y acaba la comunicación. El bit T es una forma bidireccional de comunicación ya que una vez 
se le ha dado control al maestro este puede también cambiar el valor de T para comunicar al esclavo que ha 
acabado de leer y que por tanto no va a leer mas datos y que retoma el control del bus. Esto significa que para 
que la comunicación continúe, tanto el maestro como el esclavo deben establecer T = ‘1’. Finalmente, el 
maestro envía la condición de STOP mediante un flanco de subida cuando SCL está a nivel alto (al igual que 
en I2C). 
 
17 
 
 
3 APLICACIÓN Y HARDWARE 
 
 
 
 
 
 
 
Na vez descrito el protocolo a implementar, procederemos a describir la aplicación desarrollada para 
probar su funcionamiento, así como el hardware que se va a utilizar para implementarlo. 
 
3.1 Aplicación 
Con el fin de probar el protocolo de comunicación, se ha desarrollado una aplicación para comunicarse con un 
sensor de temperatura que es capaz de hablar en I3C. Para ello vamos a intentar establecer una serie de bloques 
para hacer posible la comunicación del sensor con una FPGA, después para comprobar que los datos se han 
recibido correctamente utilizaremos un puerto serie para comunicarnos desde la FPGA a un ordenador, del 
cual leeremos datos abriendo un puerto COM mediante el programa Docklight. De esta manera podremos leer 
los datos de temperatura desde nuestro ordenador. Además, podremos controlar algunos aspectos del 
funcionamiento del sistema mediante algunos botones e interruptores de los que dispone la propia FPGA y 
mediante el uso de jumpers en la placa de adaptación. Debido a la naturaleza del sensor, también se ha tenido 
que hacer una placa de adaptación para poder hacer la comunicación sensor-FPGA. 
Por lo tanto, tenemos una aplicación con 4 bloques fundamentales. Un primer bloque, que es el propio sensor 
de temperatura. Un segundo bloque, que se corresponde con una tarjeta de adaptación, que es responsable de 
hacer posible la comunicación sensor-FPGA. El tercer bloque está asociado con la propia FPGA. Esta gestiona 
y transmite la información recibida. El último bloque es el encargado de la lectura de datos desde un puerto 
serie, que se puede hacer directamente desde el ordenador. 
 
 
Figura 3-1 Esquema de aplicación del proyecto. 
U 
 
Si el conocimiento puede crear problemas, no es conla 
ignorancia que podemos resolverlos. 
-Isaac Asimov - 
 
 
Aplicación y hardware 
 
 
 
18 
3.2 Hardware 
Como cualquier proyecto que se quiera llevar a una aplicación del mundo real, se precisa de elementos 
hardware que soporten la implementación del diseño que se ha realizado. En cuanto a las partes hardware, 
solamente disponemos de tres bloques (sin contar el ordenador): FPGA, la placa de adaptación y el sensor. 
3.2.1 Sensor de temperature TMP139 
El TMP139 es un sensor de temperatura de gran precisión que tiene una interfaz digital capaz de comunicarse 
en los protocolos I2C e I3C. Tiene una precisión de ±0.25 ºC y un rango de temperatura de medida que va 
desde los -40 ºC a los 125 ºC. El tiempo de conversión del sensor es de 125ms. Sus dimensiones son 1.328 
mm x 0.828 mm. Además, presenta dos tensiones de alimentación diferentes: 
• 1.8V para alimentar la electrónica digital/analógica que integra el sensor. 
• 1.0V para alimentar las interfaces de entrada-salida a 1.0 V con una corriente media de 4.7 µA. 
Este sensor está pensado para los siguientes usos: 
• Gestionar la temperatura de memorias DDR5. 
• Integración en placas base de servidores, ordenadores portátiles, estaciones de trabajo o discos SSD. 
En la carcasa del sensor posee tres pares de pines de cuyo diámetro es de 0.20 mm separados verticalmente 0.5 
mm. Dos de los pines, se corresponden con las líneas SCL y SDA, dos pines de alimentación para el núcleo y 
los I/O, una tierra y un último pin, llamado SA, para gestionar la dirección del IC. Este último, puede estar 
conectado a VDDIO o a tierra, en función de si queremos utilizar una dirección u otra. Como se puede ver, el 
tamaño de los pines es un problema para intentar conectarlos directamente a una FPGA, además el uso de dos 
voltajes de alimentación (distintos a los 3.3 ó 5 V que suminitstra la FPGA elegida) crea la necesidad de 
diseñar y fabricar una placa de adaptación, descrita posteriormente en el presente capítulo. 
 
 
Figura 3-2 Esquema pines externos TMP139. 
 
Internamente, el sensor posee el transductor de temperatura, un ADC, los registros de temperatura y 
configuración, una interfaz de comunicación I3C/I2C y la lógica de control tanto de la interfaz de bus como de 
los registros y el ADC. En la Figura 3-3 se puede ver el esquema completo del sensor elegido. 
 
19 
 
19 Diseño VHDL de un driver I3C 
 
 
Figura 3-3 Esquema módulos internos TMP139. 
 
De todos los registros del sensor, centraremos nuestra atención en dos de ellos, asociados a la medida actual de 
la temperatura. En uno de ellos, se guarda la parte alta de la medida de temperatura y, en el segundo, la parte 
baja. De esta manera, tendremos que leer los dos para poder obtener una medida de la temperatura registrada 
por el sensor. Además, aunque los dos registros son de ocho bits, lo que conforman una palabra de 16 bits, 
únicamente 11 de estos presentan información útil. Los datos se distribuyen como se presentan en la siguiente 
figura. 
 
Figura 3-4 Registros internos de temperatura del TMP139. 
 
Por lo tanto, cuando concatenemos los datos de los dos registros, tenemos que ignorar los 3 primeros bits y los 
2 últimos. Un ejemplo de una lectura sería el “000001010 0101000”, al eliminar los bits no utilizados, nos 
quedaría un valor de +85 ºC. Como se puede observar, el rango máximo es de -128 ºC a 128 ºC, pero los 
valores límites son de -40 ºC a 125 ºC por lo que, aunque se puedan medir temperaturas fuera de ese rango 
esto no es recomendable. La dirección de los registros está recogida en el mapa de memoria descrito la hoja de 
especificaciones del sensor [8]. Esto se corresponde con las direcciones 31h y 32h, expresadas en formato 
hexadecimal. 
Otro valor que nos interesa es la dirección del chip ya que, dado que no vamos a utilizar la gestión dinámica de 
direcciónes, vamos a tener que utilizar la dirección por defecto establecida por el fabricante. Esta puede tener 
dos valores en función de la tensión conectada al pin SA. La siguiente figura muestra el valor de dicho 
identificador. 
 
Aplicación y hardware 
 
 
 
20 
 
Figura 3-5 Dirección variable TMP139. 
 
a) Operación de lectura y escritura 
La gestión tanto de escritura como de lectura se hace de la siguiente manera. Vamos a necesitar dos 
direcciones, la dirección del chip que se define en función de SA y la dirección de los registros a los que se van 
a acceder en modo lectura. Una traza de lectura de registro funcionaría del siguiente modo: 
1. Se manda la dirección del chip y se pone el modo escritura. 
2. A continuación, se envía la dirección más baja del registro que se desea leer. En nuestro caso, se 
manda la dirección 31h. 
3. Una vez se recibe el bit de transacción cambiamos el modo de funcionamiento a modo de lectura. 
Para ello, se genera la condición REPEATED START para realizar una operación de lectura. 
4. Volvemos a mandar la dirección del chip con el bit R/W a ’1’. 
5. A partir de este punto, ya podemos leer los datos del registro devueltos por el sensor. Si decidimos que 
la condición del bit de transacción es de seguir leyendo, entonces leeremos los datos del registro de 
dirección+1, si seguimos así; leeremos el registro de dirección+2 y así, sucesivamente. Cuando 
queramos abortar la lectura en serie de registros mandamos la condición de transición T = 0 y dejamos 
de leer datos. 
El procedimiento anteriormente descrito se muestra en la Figura 3-6. Cabe indicar que el color gris indica una 
escritura por parte del maestro mientras que el color blanco representa una escritura en el bus por parte del 
esclavo. El color negro indica el final de la negociación ya sea por parte del esclavo o del maestro, cualquiera 
de los dos pondrá su bit de transición a ‘0’. 
 
 
Figura 3-6 Traza de lectura de registro sensor TMP139 usando I3C. 
 
La implementación del procedimiento anterior sería suficiente para poder recuperar las medidas de 
temperatura efectuadas por el sensor. Sin embargo, es necesario solventar una problemática previa. Tras 
conectar la alimentación, el sensor elegido establece su comunicación en modo I2C. Por tanto, antes de 
empezar a leer información, necesitamos inicializar la configuración del sensor mediante el uso de un CCC 
llamado SETAASA. Este comando hace que el dispositivo pase de modo I2C a I3C. Para que sea reconocido 
por el sensor, se debe enviar la trama mostrada en la ¡Error! No se encuentra el origen de la referencia.. 
 
 
21 
 
21 Diseño VHDL de un driver I3C 
 
 
Figura 3-7 Traza de envio de SETAASA. 
 
Una vez configurado el sensor para usar el procolo I3C, ya se puede leer y escribir datos mediante lecturas y 
escrituras I3C [8] 
3.3 Placa de adaptación 
El encapsulado del sensor (WLCSP) hace que sea muy poco manejable por lo que para trabajar con él 
necesitamos una placa de adaptación. La placa de adaptación consta de dos partes, una primera parte que sirve 
para que los 6 pines del sensor estén a la misma distancia que un socket PMOD y una segunda placa que se 
encarga de gestionar los reguladores de tensión necesarios para alimentar la placa y de rutar los cables de SDA 
y SCL a otro socket PMOD para conectarlo a la FPGA. 
3.3.1 PCB de ajuste 
Este PCB tiene un diseño muy simple, únicamente se rutan los pines para que pasen de estar separados 0.5 mm 
y usar una conexión de tipo BGA a una separación de 2.54 mm, compatible con los conectores tipo PMOD 
que presenta la tarjeta Basys 3. Además, se incrementa el tamaño de los pads y de los agujeros para que sea 
mucho más sencillo su frabicación. La PCB queda de la siguiente manera. 
 
 
Figura 3-8 PCB del adaptador del sensor. 
 
El sensor va en medio de los 6 pines interiores. Para su conexión, se procederá a soldar cables de espesor 
30AWG que unan eléctricamente cada pin con su pad correspondiente. 
3.3.2 PCB de voltajes 
En esta placa incorpora dos reguladores de tensión para generarlos voltajes de 1.0 y 1.8V necesarios. Además, 
permite rutar las señales SCL y SDA a un PMOD de 12 pines para su conexión directa a la FPGA. Se van a 
utilizar dos reguladores de tensión. El LM317 para bajar de 3.3V a 1.8V y el TPS74401 para reducir de 3.3V a 
1.0V. 
Además, tenemos que introducir una serie de condensadores y resistencias que vienen dadas por el datasheet 
de ambos dispositivos. Dado que ambos permiten ajustar las tensiones de salida, se ha optado por utilizar 
potenciómetros para ajustar manualmente dichas tensiones. El esquema final queda de la siguiente manera. 
 
 
Aplicación y hardware 
 
 
 
22 
 
 
Figura 3-9 Esquemático placa de voltajes. 
 
Cabe destacar que de los jumpers J4 y J5, sólo uno de ellos puede estar conectado a la vez ya que es la manera 
de elegir la dirección por defecto que tiene el sensor. La placa del adaptador del sensor va encajada entre los 
dos headers J1 y J2. Esto permite que el sensor pueda ser reemplazado fácilmente en caso de avería sin tener 
que modifcar la tarjeta de adaptación. 
Una vez rutado y aplicado un plano de tierra, tanto en la capa sueprior como la inferior, el diseño queda de la 
siguiente manera. 
 
 
Figura 3-10 PCB placa de voltajes, vista superior. 
 
23 
 
23 Diseño VHDL de un driver I3C 
 
 
Figura 3-11 PCB placa de voltajes, vista inferior. 
 
Ambas placas fueron hechas y soldadas manualmente en el Laboratorio de Ingeniería Electrónica de la 
Universidad de Sevilla. 
3.4 Cableado 
Para el cableado entre los distintos bloques, se utilizan cables con pines doble macho o hembra-macho. 
Excepto para la comunicación de la FPGA con el PC, que esta se realiza mediante un cable conversor USB-
UART. 
 
 
25 
 
4 IMPLEMENTACIÓN EN VHDL 
 
 
 
 
Aquellas personas que piensan que lo saben todo, son 
una gran molestia para aquellos de nosotros que lo 
estamos intentando 
 
 -Isaac Asimov- 
 
 
 
n este capítulo vamos a describir las partes de las que consta la implementación VHDL del proyecto. Se 
pueden distinguir cuatro bloques diferentes que están integrados de la siguiente manera. Tenemos un 
inicializador del sensor que también trabaja manejando al maestro I3C, un módulo que se comunica con 
el ordenador mediante puerto serie, el propio maestro I3C y un top level que incluye todo lo anterior rutado 
correctamente con dos registros para almacenar de forma temporal la información leída ya que el I3C trabaja 
más rápido que el puerto serie. 
4.1 Máquinas de estado y esquemas de funcionamiento 
Debido a la necesidad que presenta el sistema de alterar su comportamiento en función de los estímulos de 
entradas recibidos, así como generar las salidas correspondientes en instantes de tiempo determinados; se han 
implementado diferentes máquinas de estado que supervisan y controlan la ejecución del controlador I3C y de 
la propia aplicación. Cada bloque tiene su propia máquina que va a ser detallada en su respectivo subapartado. 
El código utilizado se podrá ver en la segunda parte de este capítulo. 
 
4.1.1 Maestro I3C 
Este es el módulo principal de todo el proyecto, el resto sóo se utilizan para comprobar su correcto 
funcionamiento. Su principal funcionalidad es la de leer o escribir una trama I3C y pasar dicha información a 
un nivel superior, por esto necesitamos una máquina de estados externa que controle su operación (el sensor 
initializer). 
La máquina de estados que rige el funcionamiento principal del módulo es la siguiente. 
E 
 
Implementación en VHDL 
 
26 
 
26 
 
Figura 4-1 Máquina de estados I3C maestro. 
 
27 
 
27 Diseño VHDL de un driver I3C 
 
En la máquina podemos encontrar los siguientes estados: 
• Ready: Empezamos la ejecución en este estado y nos mantenemos en él mientras el enable se 
encuentre a 0. Durante este estado la máquina se encuentra en reposo y por tanto las salidas se 
encuentran en alta impedancia. 
• Start: Una vez el enable se encuentre activo, se genera la condición de START del protocolo de 
comunicación y una vez finalizada se pasa al siguiente estado. 
• Broadcast: Se escriben por SDA los 8 bits del Broadcast concatenado con el modo (siempre es 
“11111100”). Mientras no se hayan mandado todos los bits permanecemos en este estado y bajamos 
un contador para leer el siguiente bit. Una vez el contador llega a 0 reiniciamos el contador y pasamos 
al siguiente estado. 
• Broadcast ACK: Esperamos a que el sensor nos responda con un ACK clásico (igual que en I2C). Si 
recibimos el ACK pasamos al siguiente estado y si no pasamos al estado de error. 
• Repeated Start: A este estado venimos la primera vez que queremos empezar una trama de 
comunicación y cada vez que queramos mandar una traza con distinto modo o dirección sin 
interrumpir la comunicación. Se genera una segunda condición de START igual a la primera. Una vez 
finalizada se avanza al siguiente estado. 
• Addressing + Mode (o Command): Se escriben por SDA los 8 bits correspondientes a a dirección 
del dispositivo concatenado con su modo de funcionamiento. Utilizamos un contador para ver cuando 
se han transmitido los 8 bits. 
• Cmd ACK: La máquina espera a recibir un ACK. En caso de recibirlo pasamos a la rama de lectura o 
escritura según el modo definido en el estado anterior o en caso contrario pasamos al estado de error. 
• Write: La máquina escribe en el bus SDA los 8 bits que se han leído del puerto de entrada. Una vez 
finalizados se pasa al estado siguiente. 
• Transit Bit Write: En este caso en la última mitad de ciclo de escritura se escribe el valor del bit de 
transit por parte del maestro, una vez finalizado se libera el bus y se recibe el valor del bit transit por 
parte del esclavo. Una vez finalizado se evalúa si ha habido un cambio en las entradas que y se pasa al 
estado correspondiente en función de dichos valores. Si hemos cambiado el modo o dirección 
tenemos que volver a empezar la trama con el Repeat Start, si alguno de los bits de transición o el 
enable valen 0 pasamos al estado de Stop y si no ha cambiado nada podemos seguir escribiendo en 
ráfaga (El dato de entrada si que puede cambiar entre ráfaga y ráfaga). 
• Read: La máquina libera el bus SDA para leer datos. Una vez se han leído los 8 bits pasamos al 
siguiente estado. Los datos se guardan en un registro de salida. 
• Transit Bit Read: En este caso tenemos que empezar a leer la última mitad de ciclo del ultimo bit de 
lectura para leer el trasit bit por parte del esclavo. Una vez leído se pone el valor del transit bit maestro 
en el bus. Una vez finalizado se evalúa si ha habido un cambio en las entradas que y se pasa al estado 
correspondiente en función de dichos valores. Si hemos cambiado el modo o dirección tenemos que 
volver a empezar la trama con el Repeat Start, si alguno de los bits de transición o el enable valen 0 
pasamos al estado de Stop y si no ha cambiado nada podemos seguir leyendo en ráfaga. 
• Stop: Se genera la condición de STOP y se libera el bus. 
• Error: A este estado sólo se va a llegar en caso de recibir un NACK o si se llega a un estado 
imposible. Se reinicia la máquina y se vuelve a empezar la traza. 
4.1.2 Sensor initializer 
El sensor arranca por defecto en modo I2C por lo que hay que mandar un comando CCC para cambiar el 
modo de funcionamiento a I3C antes de intentar interactuar con el sensor. Este comando es el SETAASA. 
Además, necesitamos una máquina de estados externa que maneje el funcionamiento del I3C Maestro una vez 
se ha puesto en marcha ya que necesitamos hacer una escritura seguida de dos lecturas para leer los datos de 
 
Implementación en VHDL 
 
28 
 
28 
temperatura del sensor. La máquina de estados que rige este módulo es la siguiente. 
 
Figura 4-2 Máquina de estados Sensor Initalizer. 
 
Está máquina no es más que una versión simplificada de la del maestro I3C ya que tenemos que mandarúnicamente una sola traza con el CCC SETAASA. Sin embargo, dado que queremos que esta misma máquina 
 
29 
 
29 Diseño VHDL de un driver I3C 
 
maneje al maestro una vez ha finalizado la trama, tenemos tres estados cíclicos que se encargan de ello. Por lo 
tanto, está máquina tiene dos partes bien diferenciadas: el envío del CCC y el manejo del maestro. 
Para que esté modulo sea capaz de enviar una traza y después activar al maestro, tiene que ser capaz de 
multiplexar los pines SDA y SCL para ceder el control. A continuación, se muestra un diagrama de bloques 
del sistema. 
 
 
Figura 4-3 Esquema de montaje Sensor Initializer. 
 
Una vez aclarado esto, la maquina consta de los siguientes estados: 
• Ready: La máquina comienza en este estado, mientras el enable no se encuentre activo se mantendrá 
en este. 
• Broadcast: Se escriben por SDA los 8 bits del Broadcast concatenado con el modo (siempre es 
“11111100”). Mientras no se hayan mandado todos los bits permanecemos en este estado y bajamos 
un contador para leer el siguiente bit. Una vez el contador llega a 0 reiniciamos el contador y pasamos 
al siguiente estado. 
• ACK Broadcast: Esperamos a que el sensor nos responda con un ACK clásico (igual que en I2C). Si 
recibimos el ACK pasamos al siguiente estado y si no pasamos al estado de error. 
• SETAASA CCC: Se escriben por SDA los 8 bits del CCC SETAASA. Mientras no se hayan 
mandado todos los bits permanecemos en este estado y bajamos un contador para leer el siguiente bit. 
Una vez el contador llega a 0 reiniciamos el contador y pasamos al siguiente estado. 
• Transit bit: En este caso en la última mitad de ciclo de escritura se escribe el valor del bit de transit 
 
Implementación en VHDL 
 
30 
 
30 
por parte del maestro, una vez finalizado se libera el bus y se recibe el valor del bit transit por parte del 
esclavo. Una vez finalizado se evalúa el valor del bit transit del esclavo. Si se recibe un 1 se pasa al 
siguiente estado, en caso contrario se pasa al estado de error. 
• Stop: Se genera la condición de STOP. Una vez ha finalizado se procede al siguiente estado. 
• Write Master: Primer estado de la segunda parte de la máquina de estados. Se activa el enable, se 
cambia el multiplexor de salida y se pone la entrada del modo del maestro I3C a modo escritura. El 
valor necesario que hay que escribir es siempre el mismo luego en esta aplicación se le asigna desde el 
top level. Se espera a recibir un pulso de write_ready por parte del maestro para saber cuando ha 
finalizado la transacción y se pasa al siguiente estado. 
• Read Master 1: Segunda estado de la segunda parte de la máquina. Se cambia el modo del maestro a 
modo escritura. Se espera a recibir un pulso de data_ready por parte del maestro para saber cuando ha 
finalizado la transacción y se pasa al siguiente estado. 
• Read Master 2: Segunda estado de la segunda parte de la máquina. Se cambia el modo del maestro a 
modo escritura. Se espera a recibir un pulso de data_ready por parte del maestro para saber cuando ha 
finalizado la transacción y se pasa al siguiente estado. 
4.1.3 Top level registers 
Para comprobar el correcto funcionamiento del sensor y del protocolo se necesitan leer los datos en algún sitio. 
Para ello hay que establecer una comunicación entre el maestro I3C y el Serial Transmiter. Sin embargo, estos 
dos trabajan a distintas velocidades de transmisión, además dado que los datos se tienen que leer por parejas 
para que tengan sentido, necesitamos implementar una pequeña adaptación entre ambos bloques. Para ello se 
implementan los registros del nivel superior. 
Esquemáticamente, los registros funcionan de la siguiente manera. 
 
Figura 4-4 Esquema general registros del nivel superior. 
 
El registro 1 se encarga de comunicarse con el Serial Transmiter y el Registro 2 con el I3C Master. Ambos 
tienen que serializar datos de 2 bytes. Por lo tanto, primero leen o escriben en el primer byte del registro y 
después en el segundo de manera cíclica. Estos cambian en función de las señales Data_ready y Busy_serial 
que generan un pulso cada vez que se ha finalizado una transacción de cualquiera de los dos. Además, el 
registro 1 copia los datos del registro 2 cuando el segundo avisa al primero mediante el flag Ready_reg2. 
Las máquinas de estado de los dos registros funcionan de la siguiente manera. 
 
31 
 
31 Diseño VHDL de un driver I3C 
 
 
Figura 4-5 Máquinas de estado de registros de nivel superior. 
 
La máquina del registro 1 posee los siguientes estados: 
• Ready: La máquina se mantiene en este estado hasta que Ready_reg2 tenga valor 1. 
• Serial Byte 1: Se escribe en el registro de entrada del Serial Transmiter el primer byte de datos. Se 
espera a que el Serial Transmiter acabe la transacción para actualizar el dato al segundo dato. 
• Serial Byte 2: Se escribe en el registro de entrada del Serial Transmiter el segundo byte de datos. Se 
espera a que el Serial Transmiter acabe la transacción para volver al estado inicial. 
La máquina del registro 2 posee los siguientes estados: 
• Master Byte 1: Se lee el primer byte del registro de salida de datos del Master I3. El ready_reg2 se 
mantiene a 1 ya que tenemos el dato completo (salvo la primera iteración que va a mandar el valor del 
reset). Una vez se recibe el fin de la transacción con el data ready pasamos a leer el segundo byte. 
• Master Byte 2: Se lee el segundo byte del registro de salida de datos del Master I3C. Ready_reg2 se 
pone a 0 para no mandar datos incompletos (byte 1 actualizado, pero byte 2 de una medida antigua). 
De esta manera podemos transmitir los datos de dos en dos sin importar la velocidad de transmisión de ambos 
protocolos. 
4.1.4 Serial transmiter 
Este bloque se encarga de transmitir la información que recibe por puerto serie. Este se leerá desde el 
ordenador. La máquina de estados funciona de la siguiente manera. 
 
Implementación en VHDL 
 
32 
 
32 
 
Figura 4-6 Máquina de estados de Serial Transmiter. 
 
La máquina posee lo siguientes estados: 
• Ready: La máquina se mantiene en este estado mientras el enable se encuentre a 0. 
• Start: Se manda la condición de comienzo del protocolo de transmisión por puerto serie. 
• Bit transfer: Se mandan los datos 8 bits del puerto de entrada por el puerto serie. Una vez se han 
transmitido todos se pasa al estado siguiente. 
• Parity bit: Se manda un bit de paridad para ver el correcto funcionamiento de la traza (ya que este es 
un protocolo asíncrono). En este caso se trata de una paridad par medianta un XOR de todos los bits 
anteriores. 
• Stop: Se manda la condición de fin del protocolo de transmisión por puerto serie. 
4.2 Código VHDL 
Cada una de las máquinas de estado anteriores han sido implementadas en VHDL y testeadas. Todas las 
máquinas de estado poseen un reset asíncrono que reinicia la máquina de estados y una variable enable que 
habilita su funcionamiento. 
4.2.1 I3C_master.vhd 
Este módulo consta de dos partes fundamentales que corresponden a dos procesos distintos. El primer proceso 
genera las señales de reloj internas de SDA y SCL. 
 
33 
 
33 Diseño VHDL de un driver I3C 
 
 
 
Como ya se ha visto, los datos se leen durante los ciclos de subida de SCL. Por lo tanto, si queremos tener los 
datos estabilizados cuando sea el momento de leerlo necesitamos que se vuelquen al bus con un poco de 
 --generate the timing for the bus clock (scl_clk) and the data clock 
(data_clk) 
 PROCESS(clk, reset_a) 
 VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock 
generation 
 BEGIN 
 IF(reset_a = '0') THEN --reset asserted 
 stretch <= '0'; 
 data_clk <= '0'; 
 data_clk_prev <= '0'; 
 scl_clk <= '0'; 
 scl_clk_prev <= '0'; 
 count := 0; 
 ELSIF(rising_edge(clk)) THEN 
 data_clk_prev <=data_clk; --store previous value of 
data clock 
 scl_clk_prev <= scl_clk; 
 IF(count = divider*4-1) THEN --end of timing cycle 
 count := 0; --reset timer 
 ELSIF(stretch = '0') THEN --clock stretching from slave 
not detected 
 count := count + 1; --continue clock generation 
timing 
 END IF; 
 
 CASE count IS 
 WHEN 0 TO divider-1 => --first 1/4 cycle of clocking 
 scl_clk <= '0'; 
 data_clk <= '0'; 
 WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking 
 scl_clk <= '0'; 
 data_clk <= '1'; 
 WHEN divider*2 TO divider*3-1 =>--third 1/4 cycle of clocking 
 scl_clk <= '1'; --release scl 
 data_clk <= '1'; 
 WHEN OTHERS => --last 1/4 cycle of clocking 
 scl_clk <= '1'; 
 data_clk <= '0'; 
 END CASE; 
 END IF; 
 END PROCESS; 
 
Código 4-1 Generación de señales de reloj SDA y SCL. 
 
Implementación en VHDL 
 
34 
 
34 
antelación. Por lo tanto, para los relojes internos necesitamos que las señales de reloj tengan las siguientes 
formas. 
 
 
Figura 4-7 Diagrama de timings de SDA y SCL. 
 
Donde 1, 2, 3 y 4 son los cuartos del ciclo total de las señales. De esta manera dejamos ¼ de ciclo para que el 
valor de SDA se estabilice. 
En este proceso primeramente guardamos los valores anteriores de la señal de reloj para detectar los flancos de 
subida y de bajada que nos servirá para cambiar de estado más adelante. Tenemos también un contador que 
cuenta hasta llegar al ciclo entero. En cada cuarto de ciclo se actualiza el valor de las doce señales de reloj para 
generar la forma de onda de la figura anterior. Definimos por tanto el valor de divider como el numero de 
ciclos de reloj que hay que contar hasta llegar a ¼ de ciclo. 
 
Esta forma de generar las señales de reloj se mantiene también en el módulo SENSOR_INITIALIZER.vhd ya 
que es una versión simplificada de esta. 
En cuanto al resto del código, se trata de una implementación de la máquina de estados de la Figura 4-1 con 
alguna excepción. En esta implementación hay más estados, pero tiene la misma funcionalidad. Esto es debido 
a que necesitamos más de un solo estado para hacer condiciones de espera o sincronización de los estados de 
START y STOP. 
CONSTANT divider : INTEGER := (input_clk/bus_clk)/4; --number of clocks in 
1/4 cycle of scl, we want the scl_clk to delay 1/4 of a cycle to let the data 
in sda stabilize 
 
Código 4-2 Divider. 
 --state machine and writing to sda during scl low (data_clk rising edge) 
 PROCESS(clk, reset_a) 
 BEGIN 
 IF(reset_a = '0') THEN --reset asserted 
 state <= ready; --return to initial state 
 busy <= '0'; --indicate not available 
 
 ena_scl <= '1'; --sets scl high impedance 
 ena_sda <= '1'; 
 
35 
 
35 Diseño VHDL de un driver I3C 
 
 
 sda_o_m2s <= '0'; 
 
 ack_error_flg <= '0'; --clear acknowledge error flag 
 bit_cnt <= 7; --restarts data bit counter 
 
 addr_m2s <= (others => '0'); --clear address read port 
 data_ready <= '0'; --clear data ready flag 
 write_ready <= '0'; 
 cmd_m2s <= (others => '0'); 
 
 data_m2s <= (others => '0'); 
 data_s2m <= (others => '0'); 
 
 ELSIF(rising_edge(clk)) THEN 
 busy <= '0'; 
 ena_sda <= '1'; 
 sda_o_m2s <= '0'; 
 ena_scl <= '1'; 
 ts <= '0'; 
 data_ready <= '0'; --clear data ready flag 
 write_ready <= '0'; 
 CASE state IS 
 when READY => --idle state 
 cmd_m2s <= ccc_i & ccc_op_i; 
 IF(ena = '1') THEN --transaction requested 
 state <= SYNC_RISE_EDGE_DATA_CLK; --go to start bit 
 END IF; 
 
 when SYNC_RISE_EDGE_DATA_CLK => 
 busy <= '1'; -- flag busy 
 if data_clk = '1' and data_clk_prev = '0' then 
 state <= SYNC_RISE_EDGE_SCL_CLK; 
 end if; 
 
 when SYNC_RISE_EDGE_SCL_CLK => 
 busy <= '1'; -- flag busy 
 if scl_clk = '1' and scl_clk_prev = '0' then 
 state <= BIT_START; 
 end if; 
 when BIT_START => 
 ack_error_flg <= '0'; 
 busy <= '1'; 
 ena_sda <= '0'; 
 --sda_o_m2s <= '0'; 
 ena_scl <= '0'; 
 
 if scl_clk = '0' and scl_clk_prev = '1' then 
 state <= INIT_CCC; 
 end if; 
 
 
Implementación en VHDL 
 
36 
 
36 
 
 when INIT_CCC => 
 busy <= '1'; 
 ena_sda <= '0'; -- enable iobuf sda 
 sda_o_m2s <= '0'; -- set first CCC bit. 
 ena_scl <= '0'; -- enable iobuf scl 
 if data_clk = '1' and data_clk_prev = '0' then 
 state <= CCC_SEND; 
 end if; 
 
 when CCC_SEND => -- BROADCAST 
 busy <= '1'; 
 ena_sda <= '0'; 
 sda_o_m2s <= cmd_m2s(bit_cnt); 
 ena_scl <= '0'; 
 
 if data_clk = '1' and data_clk_prev = '0' then 
 if bit_cnt = 0 then 
 ena_sda <= '1'; 
 bit_cnt <= 7; 
 state <= CCC_ACK; 
 else 
 bit_cnt <= bit_cnt - 1; 
 end if; 
 end if; 
 
 when CCC_ACK => -- BROADCAST ACK 
 busy <= '1'; 
 ena_scl <= '0'; 
 
 if data_clk = '0' and data_clk_prev = '1' then 
 if sda_i_s2m = '0' then 
 state <= SYNC_RISE_EDGE_SCL_CLK_2; 
 else 
 ack_error_flg <= '1'; 
 ena_scl <= '1'; 
 ena_sda <= '1'; 
 busy <= '1'; 
 state <= ERROR; 
 end if; 
 end if; 
 
 when SYNC_RISE_EDGE_SCL_CLK_2 => 
 busy <= '1'; -- flag busy 
 data_ready <= '0'; 
 write_ready <= '0'; 
 ena_scl <= '0'; 
 sda_o_m2s <= '0'; 
 if scl_clk = '1' and scl_clk_prev = '0' then 
 
 
37 
 
37 Diseño VHDL de un driver I3C 
 
 
 state <= REPEATED_START; 
 end if; 
 
 when REPEATED_START => 
 busy <= '1'; 
 ena_sda <= '0'; 
 ack_error_flg<= '0'; 
 --sda_o_m2s <= '0'; 
 ena_scl <= '0'; 
 if scl_clk = '0' and scl_clk_prev = '1' then 
 state <= INIT_CMD; 
 end if; 
 
 when INIT_CMD => 
 busy <= '1'; 
 ena_sda <= '0'; -- enable iobuf sda 
 sda_o_m2s <= '0'; -- set first CCC bit. 
 ena_scl <= '0'; -- enable iobuf scl 
 addr_m2s <= i3c_addr_i & i3c_op_i; 
 if data_clk = '1' and data_clk_prev = '0' then 
 state <= CMD_SEND; 
 end if; 
 
 when CMD_SEND => 
 busy <= '1'; 
 ena_sda <= '0'; 
 sda_o_m2s <= addr_m2s(bit_cnt); 
 ena_scl <= '0'; 
 
 if data_clk = '1' and data_clk_prev = '0' then 
 if bit_cnt = 0 then 
 ena_sda <= '1'; 
 bit_cnt <= 7; 
 state <= CMD_ACK; 
 else 
 bit_cnt <= bit_cnt - 1; 
 end if; 
 end if; 
 
 when CMD_ACK => -- BROADCAST ACK 
 busy <= '1'; 
 ena_scl <= '0'; 
 
 if data_clk = '0' and data_clk_prev = '1' then 
 if sda_i_s2m = '0' then 
 if i3c_op_i = '0' then 
 state <= INIT_WRITE; 
 else 
 state <= INIT_READ; 
 
 
Implementación en VHDL 
 
38 
 
38 
 
 end if; 
 else 
 ack_error_flg <= '1'; 
 ena_scl <= '1'; 
 ena_sda <= '1'; 
 busy <= '1'; 
 state <= ERROR; 
 end if; 
 end if; 
 
 when INIT_WRITE => 
 busy <= '1'; 
 ena_sda <= '0'; -- enable iobuf sda 
 sda_o_m2s <= '0'; -- set first CCC bit. 
 ena_scl <= '0'; -- enable iobuf scl 
 data_m2s <= i3c_data_i; 
 if data_clk = '1' and data_clk_prev = '0' then 
 state <= WRITE; 
 end if; 
 
 when WRITE => -- BROADCAST 
 busy <= '1'; 
 ena_sda <= '0'; 
 sda_o_m2s <= data_m2s(bit_cnt); 
 ena_scl <= '0'; 
 if data_clk = '1' and data_clk_prev = '0' then 
 if bit_cnt = 0 then 
--No deberia llegar aqui nunca 
 else 
 bit_cnt <= bit_cnt - 1; 
 end if; 
 
 elsif data_clk = '0' and data_clk_prev = '1' then 
 if bit_cnt = 0 then 
 write_ready <= '1'; 
 bit_cnt <= 7; 
 --sda_o_m2s <= '0'; 
 state <= SET_TM_BIT_WR; 
 end if; 
 
 end if; 
 
 when SET_TM_BIT_WR => 
 busy <= '1'; 
 ena_sda <= '0'; 
 sda_o_m2s <= tm; 
 ena_scl <= '0'; 
 if data_clk = '1' and data_clk_prev = '0' then 
 state <= READ_TS_BIT_WR; 
 
 
39 
 
39 Diseño VHDL de un driver I3C 
 
 
 end if; 
 when READ_TS_BIT_WR => 
 busy <= '1'; 
 ena_scl <= '0'; 
 ena_sda <= '1'; --Free the bus 
 sda_o_m2s <= '0'; 
 
 if data_clk = '0' and data_clk_prev = '1' 
then 
 if ena = '1' and sda_i_s2m = '1' and tm = '1' then 
 if addr_m2s = (i3c_addr_i & i3c_op_i) then 
 state <= INIT_WRITE; 
 else 
 state <= SYNC_RISE_EDGE_SCL_CLK_2; --
Repeated start 
 end if; 
 else 
 ack_error_flg <= '1'; 
 ena_scl <= '1'; 
 ena_sda <= '1'; 
 busy <= '1'; 
 state <= SYNC_RISE_EDGE_DATA_CLK_STOP; 
 end if; 
 end if; 
 
 when INIT_READ => 
 busy <= '1'; 
 sda_o_m2s <= '0'; 
 ena_scl <= '0'; 
 data_ready <= '0'; 
 if scl_clk = '0' and scl_clk_prev = '1' then 
 state <= READ; 
 end if; 
 
 when READ => 
 busy <= '1'; 
 sda_o_m2s <= '0'; 
 ena_scl <= '0'; 
 
 if data_clk = '1' and data_clk_prev = '0' then 
 data_s2m(bit_cnt) <= sda_i_s2m; 
 elsif data_clk='0' and data_clk_prev='1' then 
 if bit_cnt = 0 then 
 --ts <= sda_i_s2m; 
 data_ready <= '1'; 
 bit_cnt <= 7; 
 state <= READ_TS_BIT_RD; 
 else 
 bit_cnt <= bit_cnt - 1; 
 
 
Implementación en VHDL 
 
40 
 
40 
 
 end if; 
 end if; 
 
 when READ_TS_BIT_RD => 
 busy <= '1'; 
 sda_o_m2s <= '0'; 
 ena_scl <= '0'; 
 
 if data_clk = '1' and data_clk_prev = '0' then 
 ts <= sda_i_s2m; 
 state <= WRITE_TM_BIT_RD; 
 end if; 
 
 when WRITE_TM_BIT_RD => 
 busy <= '1'; 
 sda_o_m2s <= tm; 
 ena_scl <= '0'; 
 ena_sda <= '0'; 
 if data_clk = '0' and data_clk_prev = '1' 
then 
 ts <= '0'; --Reset the slave flag 
 if ena = '1' and ts = '1' and tm = '1' 
then 
 if addr_m2s = (i3c_addr_i & i3c_op_i) then 
 state <= INIT_READ; 
 else 
 state <= SYNC_RISE_EDGE_SCL_CLK_2; --Repeated 
start 
 end if; 
 else 
 ack_error_flg <= '1'; 
 ena_scl <= '1'; 
 ena_sda <= '1'; 
 busy <= '1'; 
 state <= SYNC_RISE_EDGE_DATA_CLK_STOP; 
 end if; 
 end if; 
 WHEN SYNC_RISE_EDGE_DATA_CLK_STOP

Continuar navegando