El lenguaje VHDL se estructura en unidades de diseño. Hay cinco unidades de diseño que son la entidad, la arquitectura, el package declaration, el package body y la configuration. De todas ellas, en esta breve introducción, solo trataremos con tres, que serán la entidad, la arquitectura y el package. La entity o entidad identifica un módulo definiendo su nombre y el conjunto de señales o puertos de entrada salida del mismo, pero sin dar ningún tipo de información sobre su funcionalidad. La arquitectura siempre está asociada a una entidad, tiene acceso a los puertos de entrada y salida de dicha entidad y describe o modela la funcionalidad que esta arquitectura asocia a la citada entidad. Por lo tanto en la arquitectura sí que definimos la función de dicho bloque. Puede haber más de una arquitectura para una misma entidad pero todas comparten el mismo conjunto de puertos de entrada/ salida declarados en la entidad. En general todas las arquitecturas de una misma entidad comparten todas las declaraciones realizadas en dicha entidad. En la mayoría de ejemplos que usaremos en este curso tendrán una única arquitectura para cada entidad. Pero a veces puede ser útil describir distintas soluciones arquitecturales para una misma entidad o arquitecturas de distintos niveles de abstracción para una misma entidad. La tercera unidad de diseño que veremos es el package o paquete que contiene declaraciones y definiciones de tipos de datos, objetos y funciones para facilitar su uso compartido en distintos códigos VHDL. En la parte declarativa del paquete se declaran los tipos de datos, objetos y funciones mientras que en el cuerpo del paquete, en el package body, se definen, por ejemplo, los valores de las constantes y se describen las funciones, luego el package body siempre va asociado a un package declaration. En este curso apenas utilizaremos el package body pues todo lo que necesitamos declarar y definir lo podemos hacer en el package declaration. Veamos con un poco más de detalle estas unidades de diseño. La entidad es como una caja negra que solo define la interfaz de cada módulo con el exterior. Es decir su nombre y las entradas/salidas del mismo, los puertos de entrada/salida, mientras que no proporciona ninguna información sobre su comportamiento o funcionalidad. En la sintaxis de esta unidad de diseño podemos distinguir el nombre o identificador de la entidad, los parámetros genéricos en base a los cuales podemos tener definidos distintos aspectos de nuestro módulo, por ejemplo, el tamaño de los buses o de los puertos de entrada/salida. Y que nos permitirán personalizar e inyectar valores distintos cada vez que usemos o instanciemos el módulo utilizando estos parámetros genéricos. Los puertos de entrada/salida que definen la interface del módulo con su entorno y declaraciones globales y sentencias pasivas que no serán utilizadas en este curso. Aquí tenemos un ejemplo que define la entidad correspondiente al módulo de la figura de abajo a la derecha. El nombre de la entidad es MUX21, tiene tres entradas, A, B y Ctrl de tipo bit y una salida Z de tipo bit, y de momento de esta entidad no sabemos nada sobre su funcionalidad. Si ahora observamos esta otra entidad vemos que hemos utilizado un parámetro genérico para poder personalizar el número de bits de los buses de entrada/salida, de los puertos de entrada/salida. Primero definimos un parámetro genérico N con un valor entero al que damos como valor por defecto el número 8. Y a continuación utilizamos dicho parámetro "n" para definir el tamaño de los puertos de entrada/salida A, B y Z. De esta forma cada vez que instanciemos al componente MUX21n podremos hacerlo con un valor de "n" distinto, esto es con un número de bits distinto para los buses de entrada/salida y así podremos utilizar este componente en distintos contextos sin necesidad de retocar su descripción. Ahora que hemos visto cómo una entity define una caja negra con entradas y salidas veamos cómo se define la función que esta entity contiene o realiza. Esto lo hacemos con una unidad de diseño llamada arquitectura, architecture, cuya sintaxis podemos ver aquí donde hay un identificador que es el nombre de la arquitectura, otro apuntador a la entidad de la que depende esta arquitectura. Y a continuación viene la zona de declaraciones locales de esta arquitectura de tipos de datos constantes, variables, señales o componentes propios de esta arquitectura. Y después entre el "begin" y el "end" es donde viene la descripción propiamente dicha de esta arquitectura que se hace mediante sentencias concurrentes, entre las que destacamos asignaciones concurrentes, instancias de componentes y procesos. Los bloques tampoco los veremos en este curso. Recuperemos la entidad MUX21 y vamos a definir una arquitectura que defina la función de esta entidad. La arquitectura se llama "functional", como tenemos aquí, y apunta a la entidad MUX21. Dentro de la arquitectura entre el "begin" y el "end" es donde está descrita esta arquitectura y vemos que hay un único proceso que utiliza las señales A, B, Ctrl y Z que se habían definido como puertos de nuestra entidad. Dentro del proceso hay una construcción simple: if_then_else_endif en donde si la señal "Ctrl = 0" la salida Z tomará el valor de A y si no la salida Z tomará el valor de B. Este comportamiento corresponde al de un multiplexor de entrada de control Ctrl con dos entradas de datos A y B y una salida de datos Z, que es lo que tenemos dibujado aquí abajo. Si ahora analizamos la otra entidad que hemos definido con un parámetro genérico MUX21n, el parámetro genérico N, vemos que dicha entidad es muy distinta de la anterior al intervenir dicho parámetro en el dimensionado de los buses de entrada/salida. Sin embargo si nos fijamos en su arquitectura observamos que la única e importante diferencia es que esta arquitectura apunta a MUX21n, en lugar de apuntar al MUX21 del ejemplo anterior. El resto de esta arquitectura es exactamente idéntica a la arquitectura del primer caso, por lo tanto también hemos definido un multiplexor pero ahora las entradas/salidas no son señales de un bit sino buses de "n" bits. Las dos arquitecturas que hemos visto hasta ahora nos describían el multiplexor a nivel funcional, pero el VHDL nos permite realizar descripciones a otros niveles de abstracción como por ejemplo, una arquitectura de tipo estructural basada en puertas lógicas que responderá a este esquema de aquí. En este caso la arquitectura se basa en puertas lógicas, que definimos como componentes en la parte de declaraciones de esta arquitectura. Después en la zona de descripción propiamente dicha de la arquitectura realizamos las instancias convenientes a estos componentes y les conectamos sus puertos de entrada salida a las señales que también habíamos definido en esta arquitectura. En este caso todas estas instancias son también sentencias concurrentes y pueden intercambiar su orden sin alterar la funcionalidad. Los nombres U0, U1, U2 y U3 son simples etiquetas para identificar cada una de estas instancias. Hemos visto dos arquitecturas de una misma entidad con niveles de abstracción muy distintos, funcional y estructural. Pero entre ambos hay otras posibles descripciones intermedias como la que responde a esta figura donde vemos distintas funciones lógicas, En forma de grafo que va respondiendo al flujo de datos que les llega por sus entradas primarias. Esta arquitectura podría describirse tal como vemos aquí, en una arquitectura que hemos llamado "DataFlow", del mismo MUX21, dentro de la cual hemos definido una serie de señales propias suyas. Y a continuación en la zona de descripción arquitectural ponemos cuatro asignaciones concurrentes, a señal que modelan el grafo de funciones lógicas que habíamos visto aquí arriba. Estas asignaciones son sentencias concurrentes y no importa en qué orden se realicen. Estas dos ordenaciones son 100% equivalentes. Hemos visto pues una única entidad con varias arquitecturas diferentes que responden a descripciones equivalentes, pero de distintos niveles de abstracción. Teniendo todas ellas en común los puertos de entrada o salida primarios definidos en la entidad. Abordamos ahora la última unidad de diseño que veremos, el paquete o package. Esta entidad es una forma de empaquetar definiciones de tipos de datos, objetos, funciones y procedimientos para facilitar su reutilización en distintos códigos VHDL. De hecho son dos unidades, el package declaration y el package body con la sintaxis siguiente. Aquí tenemos el package declaration que tiene un nombre del paquete y una serie de declaraciones. Por su parte el package body también tiene un nombre del paquete que coincidirá con el nombre del package declaration correspondiente y contendrá la definición de los valores asociados a las constantes o la descripción de las funciones y procedimientos o bien otras informaciones. Para utilizar dentro de un determinado código el contenido de un package utilizaremos esta sentencia use, que tenemos aquí abajo al principio de dicho código. El usuario puede también definir sus propios package y a su vez utilizar unos estándares que dentro de los sistemas digitales son los paquetes más habituales. El STANDARD y el TEXTIO son los paquetes por defecto del propio lenguaje VHDL. El Standard_logic_1164 define un conjunto de valores y una serie de funciones y el Standard_logic_arithmetic se basa en el anterior y define una serie de operaciones aritméticas. A partir de estos paquetes el diseñador puede definir sus propios paquetes que le ayudaran a simplificar los trabajos de modelado del VHDL y reutilización de código para permitir el desarrollo colaborativo de proyectos. Aquí tenemos un ejemplo de un paquete definido por el diseñador y que corresponde a un paquete que utilizaremos en el desarrollo en VHDL del procesador sencillo asociado a este curso de sistemas digitales. Antes de iniciar la descripción del paquete indicamos qué paquetes estándar del IEEE queremos utilizar. Y a continuación empieza la declaración del paquete que hemos llamado main_parameters, que hemos definido como paquete de usuario. Como vemos este paquete utiliza tipos de datos y funciones que están definidos en los paquetes previamente identificados del IEEE y vemos que para cada objeto tenemos indicado el tipo de objeto, su identificador, el nombre, el tipo de datos al que pertenece y el valor asociado a esa constante. Por último comentar que el símbolo de los dos guiones medios indica comentario, desde este símbolo hasta el final de la línea se considera comentario. En este caso no necesitamos package body puesto que tanto la declaración de constantes como la definición de sus valores se ha realizado en el propio package declaration. Por último un breve comentario en relación con algunos de los paquetes estándar del IEEE. Aquí tenemos el paquete Standard 1164 que define una lógica multivaluada de hasta 9 valores lógicos distintos y no solo el "0" y "1", tiene el valor "U" como no inicializado, el "X" como desconocido fuerte, el "0" como valor lógico "0" fuerte, el "1" como valor lógico 1 fuerte, la "Z" es alta impedancia o desconectado, la "W" desconocido débil, la "L" es el "0" débil, la "H" el "1" débil. Y el guión medio "-" es el término redundante o indistinto, significa que donde está ese guión puede tomar cualquiera de los otros valores indistintamente. Un comentario es que todos estos valores de esta lógica multivaluada son necesarios para poder simular los circuitos digitales con una mayor precisión, más allá del 0 y 1 binarios puros y así poder manejar las distintas situaciones en las que se puede encontrar una señal digital dentro de una simulación. Este paquete también tiene algunos subtipos más sencillos, tiene algunas operaciones aritmético lógicas definidas contra estos tipos de datos y después también contiene algunas funciones de conversión de datos de integer a lógica multivaluada o al revés. También tenemos otro paquete estándar importante que es el standard arith que define operaciones y funciones más complejas de las que teníamos aquí arriba, pero también para el Std._1164 y también funciones de conversión un poco más elaboradas. Hay otros paquetes como son los Standard_logic_signed y unsigned, en los que se definen funciones para facilitar el trabajo con números con signo y números sin signo. Todos estos paquetes estan definidos y estandarizados por el IEEE son reconocidos y utilizados de forma óptima por las herramientas de modelado, simulación y síntesis, lo que facilita los procesos correspondientes cuando los modelos a tratar utilizan estos paquetes. Por lo tanto estos paquetes estándar del IEEE son de uso muy recomendado y recomendable. Bueno y como resumen de esta primera sesión de VHDL hemos presentado el concepto y los objetivos principales de los lenguajes de descripción de hardware que son el modelado, la simulación y la síntesis de hardware. Hemos introducido el léxico y la sintaxis del VHDL abordando los objetos de lenguaje: constantes, variables y señales, los tipos de datos de tales objetos y los operadores y expresiones del lenguaje. También hemos visto cómo se estructura el lenguaje en unidades de diseño básicamente entidad, arquitectura y paquete, y todo ello se ha ilustrado con pequeños ejemplos de las distintas unidades de diseño. Y esto es todo por hoy, saludos y hasta la próxima. [AUDIO_EN_BLANCO]