[MÚSICA] Hola. Continuamos con nuestro módulo de Verilog. Vamos a aprender algunas cosas. Tipos de datos, conexiones, registros, asignaciones y procedimientos. Muchas materias importantes. A ver. Existen varios tipos de datos en Verilog, cuatro para ser exactos. 0, que es un cero lógico. 1, que es un uno lógico. x, que es un dato desconocido. Ocurre cuando, por ejemplo, no sabemos si es un cero o un uno, porque puede ser algo intermedio, puede ser algo que no se entiende bien, puede ser una conexión entre un cero y un uno que da cualquier resultado. Y z significa alta impedancia, o también significa don't care. Más adelante vamos a ver qué es un don't care. ¿Qué significa alta impedancia? Bueno, cuando tenemos una compuerta lógica, la entrada es de alta impedancia. ¿Qué significa eso? Que la entrada no entran corrientes ni salen corrientes. La corriente es 0. Mientras que la salida es baja impedancia, porque la salida realmente lo que es, si uno se mete en el circuito, y esto lo vamos a ver con un poco más de detalle más adelante, la salida es algo como esto. Y aquí tenemos la alimentación positiva, aquí tenemos tierra, y esta es la salida. Y la salida suele ser una conexión, you sea a la alimentación positiva con un suiche o a tierra con un suiche. Entonces, la salida es un valor firme dado por la alimentación positiva o dado por tierra. No es un nodo que está volando en cualquier parte, es un nodo que está bien definido, o es VDD o es tierra, cualquiera de los dos. No puede ser, VDD es la alimentación positiva, por si acaso. Entonces, no puede ser cualquier cosa entremedio. Entonces, la salida de una compuerta lógica en general es un nodo de baja impedancia porque está manejado por VDD y por tierra. En cambio, las entradas son de alta impedancia, lo que significa que nadie la está manejando, que están flotando, y van a tomar el valor de tierra o de VDD, según donde las conectemos. Entonces, una entrada o un dato, que es z, significa que es un dato que no tiene un valor definido y que va a tomar el valor al cual lo conectemos. Eso es alta impedancia. Alta impedancia se usa para salidas, entradas, las entradas son de alta impedancia, las salidas son de baja impedancia. Entonces, podemos usarlo de diferentes formas. Por ejemplo, aquí tenemos una definición de 4'b0011, esto significa que hay cuatro bits. Cuatro bits y lo que viene ahora es en binario y en binario 0011 corresponde a un número 3, el 11 es el número 3, you lo vimos hace algunas clases, escrito con palabras de cuatro 4 bits. Aquí hay 4 bits. En cambio, este otro dice 3, entonces vienen 3 bits a continuación; apóstrofe b, esto significa que vamos a escribirlo en binario; xz1, aquí el primer bit es desconocido, el segundo bit es alta impedancia, el tercer bit es un uno lógico. Aquí tenemos 12'b, lo cual significa que vienen 12 bits en binario y aquí tenemos tenemos cuatro bits separados por una rayita baja, otros cuatro bits y luego otros cuatro bits. Ese guión abajo ayuda a la lectura, no es parte de las palabras. No es que aquí falte algo. Luego tenemos este otro. 8 bits apóstrofe h, esto significa hexadecimal y A. A es un dígito hexadecimal que corresponde al número 10, you eso lo vamos a ver más adelante. Y en binario corresponde a diez días. Y está escrito con ocho bits, o sea, los otros bits, los bits más significativos en este caso son todos 0. Y luego viene aquí otro, 4'd, lo que viene es decimal de cuatro bits, 15. Es el número 15, es decir, 1111 escrito en binario, en este caso se lo especificamos como un decimal. Y aquí viene 3'o6, la o es por octal, you vamos a ver más adelante de qué se tratan todas estas formas de describir números. Estas son bases numéricas y las vamos a conocer más adelante. Pero es bueno que sepan que existen. Luego vienen las conexiones o wires. A ver, en Verilog existen como dos tipos de datos importantes, unos son los wires y otros son los registros. Los wires vamos a ver de qué se trata. Verilog describe hardware, you vimos que utiliza jerarquía para instanciar los módulos y los módulos se comunican mediante conexiones. Entonces esas conexiones son las que llamamos wires. Los wires conectan módulos mediante puertos de entrada y salida, entonces si un wire no va conectado a una salida, entonces su valor es indefinido, es alta impedancia. Y cada wire lleva un nombre y lleva una señal. Entonces, estos de aquí son wires, por ejemplo, G es un wire. [AUDIO_EN_BLANCO] Todo esto, X1 es un wire, etcétera. Todos estos son wires. Los wires no tienen memoria y podemos usarlos con el comando assign para hacer bloques estructurales. Muy bien, esos son los wires. Ahora tenemos los otros, que son registros. Con frecuencia, en Verilog necesitamos guardar datos, algo que tenga memoria y más adelante vamos a aprender que estos circuitos con memoria son una categoría súper importante dentro de los circuitos digitales. De hecho, existen dos grandes familias de circuitos, los circuitos combinacionales, que no tienen memoria, y los secuenciales, que sí tienen memoria. Nosotros hasta ahora hemos visto una introducción a los circuitos combinacionales. Vamos a ver después los secuenciales. Para almacenar datos en Verilog usamos registros y se describen con la palabra reg. Entonces, la sintaxis de los registros es similar a la de wires, vamos a ver ejemplos más adelante. Los registros son actualizados en lo que se llaman bloques always, que son bloques de comportamiento que describen procedimientos. Y lo vamos a ver durante esta clase. Entonces, no podemos usar un comando assign para actualizar registros, eso no está permitido en Verilog y tampoco podemos usar el comando assign dentro de un bloque always. Entonces, vamos a aprender un poco más al respecto. Señales vectorizadas. ¿Qué son las señales vectorizadas? Esto se puede aplicar a wires o a registros. En Verilog, un vector es un arreglo unidimensional de elementos. Puede ser wire o puede ser reg. Los vectores se definen indicando el tipo de variable y el número de bits. Entonces, yo defino el tipo, el índice del bit más significativo, el índice del bit menos significativo entre llaves y con dos puntos entre medio, y luego el nombre del vector. Entonces, aquí vemos un módulo, este es un sumador, que más adelante lo vamos a ver, que suma dos vectores de 32 bits con una señal de un bit que se llama carryin, que vamos a aprender más adelante, no se estresen, esto es parte de la materia más adelante. Lo importante es lo siguiente. Aquí defino n parámetro, n = 32, entrada carryin, entrada de n bits, desde el bit n- 1 hasta el bit 0, X y luego Y, que también es entrada del mismo tipo, del mismo tamaño. Y la salida tiene el mismo tamaño, estos son vectores de n bits. Y yo luego tengo always, esto lo vamos a ver a continuación, no se estresen. Pero lo importante aquí es esta definición que está acá. Asignaciones continuas, you algo de esto vimos hace unas láminas atrás. Permiten asignar una expresión a un wire. Así de simple y corresponden a asignaciones continuas que yo describo en hardware y que están fijas ahí y esa asignación no se puede cambiar. Ocurren constantemente todo el tiempo, eso significa que no es algo que vaya siendo leido como un programa. Este es un ejemplo. Y aquí estoy asignando estas expresiones, g, h y f. Procedimientos, que es justo lo contrario a una asignación continua, diría yo. No exactamente, pero un procedimiento es distinto, es algo muy distinto a una asignación continua. Un procedimiento es un bloque que describe algo que ocurre bajo alguna condición. ¿Cómo es eso? No es una asignación que estoy asignando todo el tiempo, sino que más bien estoy esperando a que ocurra algo y cuando eso ocurre, yo miro qué es lo que hay dentro de ese bloque y ese bloque define lo que pasa. Entonces, esta es la sintaxis de un bloque always, always @ eventos begin elementos y luego termino. Entonces, el always me dice, siempre que ocurra, @ significa cuando ocurra, eventos, yo describo esta de eventos. Esta lista de eventos se llama lista de sensibilidad. Luego, Inicio, hago una serie de cosas, y luego termino. Los bloques always actúan sobre registros, no actúan sobre wires. Entonces, cada vez que ocurre algo, yo puedo asignar un nuevo valor a un registro de memoria. Esos son los que guardan. Por eso son memorias, por eso los registros son memorias, porque guardan el dato entre llamados al bloque always. Y cuando no estoy llamando al bloque always, ellos mantienen el dato que habían grabado. En cambio, en una asignación continua de un wire, yo no le pido al wire que recuerde el valor. Yo estoy asignándole continuamente el valor. Entonces, hay una gran diferencia. Los procedimientos realizan asignaciones, pero no son asignaciones continuas, sino que son asignaciones que ocurren solo cuando el procedimiento es llamado, solo cuando el bloque always ocurre, alguno de los eventos de la lista de sensibilidad. Existen dos tipos de asignaciones. Asignaciones bloqueantes, que ocurren en secuencia y para ello usamos el signo igual, y entonces se lee una después de la otra. Y las asignaciones no bloqueantes que ocurren en paralelo, y usamos este signo que es mayor que, y luego, igual, que es como decir, lo que está a la derecha entra a lo que está a la izquierda. Esa es como una descripción de lo que ocurre. No mezclarla en un mismo bloque always si no van a tener problemas. Aquí hay un ejemplo. Entonces, entradas, salidas. Y aquí decimos, siempre que ocurra un cambio en a o en b, o en c, o en d, o sea, cada vez que cambie alguna de las entradas, entonces la salida pasa a ser asignación no bloqueante esta expresión lógica de las entradas. Listo. Entonces, nosotros podemos describir hardware con un procedimiento y para ello usamos bloques always. Los bloques always son extremadamente útiles para describir circuitos con memoria. Aunque no siempre describimos circuitos con memoria en bloques always. Okay, estos son ejemplos de declaraciones de wire y de reg. Al definir las entradas y salidas en un módulo, estas por defecto son variables tipo wire, entonces, a veces no necesitamos describirlas como wire. Entonces, aquí hay ejemplo. Esta es una salida, esta es una variable de tipo wire por defecto. Aquí wire A, B, C, estos son wires. Wire 7 a 0 Byte, este es un bus de ocho bits. Es un vector. Luego tengo reg, Q1, Q2, estos son registros de un bit, y aquí tengo un registro de ocho bits. Y aquí estoy asignando salida igual Byte 6, esto es una asignación continua que no requiere un wire, que no requiere un procedimiento, perdón. Hablemos de constantes ahora. you algo dijimos recién hace un rato. Pero vamos a decirlo con más detalle aquí. Usamos las constantes para apoyo de la descripción del hardware. Entonces, son útiles para definir módulos que procesan datos de tamaño arbitrario, entonces yo puedo describir un módulo por ejemplo que haga algo y yo no sé de cuántas entradas va a ser ese módulo. Entonces, yo parametrizo ese número, el número de entradas, para que yo pueda al momento de instanciar el módulo le diga, mira, esta instanciación va a ser con entrada de ocho bits, esta otra instanciación va a ser con entrada de cuatro bits. Entonces, ¿cómo se hace? Vamos a hacer un multiplexor mux, mux es la palabra que usamos para multiplexor, donde le definimos con un símbolo número o símbolo gato, el parámetro ancho que va a ser el número de entradas, y en este caso el ancho por defecto es 1, y luego ponemos las diferentes entradas, un selector y una salida. Entonces, esto es un mux. Imagínense un mux con una salida S, aquí Z, perdón. Con un selector y con cuatro entradas. Tiene cuatro entradas, pero lo que estoy diciendo aquí es que es de ancho 1, o sea, es un puro mutiplexor. Yo podría tener varios multiplexores operando en paralelo, donde las entradas son el primer bit, por ejemplo, corresponde a un grupo de cables, el segundo bit corresponde a un grupo de cables, y eso lo puedo describir con este parámetro WIDTH. En este caso, puedo decir 1. Entonces, luego dentro de la descripción del módulo mux, uso ese parámetro WIDTH para describir las diferentes compuertas. Por ejemplo, las entradas son de un cierto ancho, las salidas son del mismo ancho, aquí hay cables intermedios y luego hago la asignación del mux. Esto lo vamos a aprender después, no se estresen. Entonces, luego podemos instanciar este módulo especificando ese parámetro. Yo ahora quiero que, por ejemplo, este mux sea de 32 bits de ancho, o sea, son 32 mux operando en paralelo con la misma selección. Eso es lo que estamos diciendo. Son 32 mux de cuatro entradas, y eso se lo defino de esta forma. Instancia mux 4, con 32 entrada, y esto el mux lo va a entender porque you se lo habíamos dicho en su definición. Con 32 entradas, no, no, un momento. Son cuatro entradas, pero las entradas son de 32 bits. Muy bien. ¿Qué aprendimos hoy? Aprendimos tipos de datos en Verilog, aprendimos 0, 1 X y Z, aprendimos conexiones, aprendimos variables tipo Wires, aprendimos también los registros que son muy importantes aquí, aprendimos asignaciones, aprendimos asignaciones bloqueante y no bloqueante para los procedimientos, y aprendimos asignaciones continuas para los Wires. Y finalmente, vimos constantes. Muchas gracias.