Está en la página 1de 23

0:00

>> Hola, y bienvenido de nuevo. Tal vez recuerde que estamos en la mitad de este módulo de
Verilog 1,

0:07

que, a su vez, consta de cuatro unidades. La primera unidad fue solo una introducción al diseño
basado en HDL.

0:13

Esta segunda unidad pretende ser un ejemplo completo diseñado desde cero, un simple
mostrador.

0:19

Y luego, en unidades posteriores, pasaremos por la síntesis de verificación. La idea, de nuevo, es


darte una visión completa

0:27

de todo el proceso de diseño, verificación y síntesis de principio a fin.

0:35

Además, estoy usando un ejemplo de contador aquí, y un contador es un elemento muy común en
el diseño,

0:41

particularmente en la ruta de control.

0:47

Así que este submódulo es el contraejemplo completo. Voy a enfatizar tres cosas diferentes.

0:53

dentro de esta unidad particular de la clase. Diseñar antes de codificar, el contador del ejemplo,

1:01

y luego, en un submódulo posterior, cómo funciona Verilog internamente. Mi objetivo es perforar


realmente en ti el mantra,

1:10

"diseñar siempre antes de codificar", y ahí es donde vamos a empezar. Además, quiero que
entiendas cómo funciona Verilog.

1:17

internamente, y cómo podemos simular los paralelos intrínsecos del hardware en una
computadora serial,
1:25

lo cual no es obvio al principio, cuando lo piensas. Una vez más, el objetivo de todo este módulo es
darle la gran

1:30

imagen todos juntos antes de entrar en los detalles. Y en particular, para empezar a enfatizar

1:37

para ti cómo escribir HDL, o más precisamente, diseñar hardware y capturar en HDL, es muy
diferente del código normal,

1:48

y cómo funcionan internamente los simuladores HDL. Aquí están las referencias.

1:55

Esta es la primera vez que me refiero a esta referencia principal, que es una referencia basada en
la web. Esto es -- Sutherland produce un set muy bonito

2:03

de guías de referencia bastante concisas. Dan una explicación de las características del lenguaje,

2:11

característica por característica, y luego dar buenos ejemplos de ellos. Y encuentro cuando estoy
escribiendo código,

2:17

o al menos cuando estaba aprendiendo a escribir código, que esto fue bastante útil para una guía
de referencia muy sucinta

2:23

para ayudarme a escribir, particularmente porque el ejemplo está dentro de él. Este módulo está
relacionado con nuestra tarea,

2:30

lo que requiere algún diseño y [inaudible] asociado con él. Además, los libros de referencia tienen
características en ellos

2:37

que le ayudará a entender este material, si lo necesita.

2:44

Este es el esquema de toda esta unidad, y lo que vamos a hacer


2:51

en este primer submódulo se enfatiza el diseño antes de codificar

2:57

antes de meterse en el mostrador y mostrar diferentes formas de codificarlo.

3:04

Bien, esto es entrar en el segundo mantra de este curso.

3:10

Por supuesto, el primero fue un reloj, un borde,

3:15

solo chanclas, al menos dentro de un módulo. El segundo mantra es el más importante:

3:22

"Diseña siempre antes de codificar". El uso de Verilog para diseñar hardware no es principalmente
un

3:31

ejercicio de codificacion Usted resuelve su intención de diseño en el nivel de transferencia de


registro,

3:38

luego traducir eso en código. Si haces eso, obtendrás resultados mucho mejores.

3:45

que tratar de simplemente sentarse y empezar a escribir. ¿Por qué hago hincapié en esto?

3:50

Mucha gente piensa, bueno, voy a tener esta herramienta Synthesis.

3:58

¿No funcionará un montón de cosas para mí? no lo hace No funcionará para usted lo que debe
estar en los registros,

4:04

y no construirá correctamente el comportamiento de la combinación de la lógica.

4:11

Tienes que hacer eso. Te ayuda mucho y mejora tu productividad dramáticamente sobre el
trabajo.
4:18

a nivel de transistores, pero no te exime de la tarea de diseño lógico.

4:24

Más específicamente, lo que Synthesis hace es optimizar la lógica por usted,

4:31

obtenga el momento adecuado para usted, si eso es posible dado lo que presentó

4:38

a la herramienta Síntesis. Y hacer algo del diseño lógico detallado

4:45

en que a menudo puede capturar la descripción del comportamiento de cómo debería


comportarse la combinación de lógica,

4:51

y no tienes que preocuparte por los detalles de las puertas dentro de él. Sin embargo, más
adelante mostraremos que agregar algunos

4:59

de ese detalle en realidad puede conducir a un diseño mucho más eficiente, y es posible que
recuerde la discusión al final

5:05

de las notas de tiempo que muestran algunas de esas diferencias, al menos en la estructura. Si no
sigue este mantra de diseño antes de codificar,

5:17

entonces lo que sucederá es que es muy probable que termines con un diseño muy pobre.

5:23

Tendrás, si funciona, lo que tendrás es un reloj muy lento, una ruta crítica larga. Podría ser muy
grande.

5:30

También podría ser que no funcione, que no sea un objetivo adecuado para una herramienta de
síntesis.

5:37

Y, por ejemplo, la herramienta Synthesis produce estos errores de pelusa HDL, que marcan RTL
que en realidad no es sintetizable.
5:48

Te daré un ejemplo que vi hace unos años. Un estudiante vino a mí quejándose de lo lento

5:54

y grande era su diseño. Miré el código y tenía un bucle for: for I is equal

6:01

de 1 a 1024, A es igual a A más BI por CI.

6:09

Era un tipo de producto oscuro. Y este era un bucle for dentro de un bloque de procedimiento.

6:21

Bien como código, pero como hardware, lo que acababa de especificar es que haya 1.024
acumuladores multiplicadores encadenados en serie.

6:35

entre un par de registros. Puedes imaginarte lo lenta que es la lógica si te tienes que ir

6:43

a través de más de 1.000 multiplicadores en un ciclo de reloj.

6:48

Y te imaginas lo grande que es el diseño, y también lo ineficiente que es ya que mientras esa
lógica,

6:55

lo que esos datos se están propagando a través de esa cadena de multiplicadores, la mayoría

7:01

de los multiplicadores están inactivos la mayor parte del tiempo. Necesitaba diseñarlo primero con
un multiplicador.

7:08

y un contador para recorrer los 10.000, los 1.024 ciclos antes de escribir el código.

7:19

Ahora, voy a entrar en la tentación. Podría ser como un predicador y decir, evita la tentación,

7:25

porque les voy a describir algunas de las tentaciones que tendrán dentro de esta clase.

7:31
La primera tentación es a la que se sucumbe con mayor frecuencia, y es que Verilog se parece
mucho a C,

7:39

tiene fuertes raíces en C, es muy tentador capturar una intención algorítmica en C, convertirlo en
Verilog

7:49

con algunas declaraciones de "siempre en", [inaudible] siempre en el reloj posedge, y una especie
de esperanza para lo mejor.

7:57

Esto rara vez funciona. Un ejemplo es el que acabo de dar, arrancando 1.024 multiplicadores.

8:06

Por lo general, termina con problemas de síntesis, a veces termina con una sincronización de nivel
de reloj muy vaga,

8:13

y a menudo termina con demasiados registros porque olvida todo lo demás, después de una
declaración de reloj siempre at posedge,

8:20

se convierte en un registro, lo hayas querido o no. Así que es mejor que tengas la intención de
hacerlo,

8:25

y lo haces esbozando el diseño, particularmente los registros, con algo de comprensión

8:31

de lo que sucede entre ellos antes de escribir el código.

8:38

La siguiente tentación es pensar que la Síntesis automática es esta herramienta mágica.

8:44

eso puede convertir un mal diseño en un buen diseño, y no puede.

8:49

Todo lo que es, es un optimizador de mapas [inaudible] consciente del tiempo, eso es todo lo que
es.

8:56
No te arregla las cosas. Y he tenido estudiantes que vienen a mí y me dicen, ¿por qué la
herramienta no puede arreglar esto por mí y darme un buen resultado?

9:03

No lo es, no tiene inteligencia artificial incorporada. Es solo un optimizador de mapas [inaudible]


consciente del tiempo.

9:10

E incluso entonces, en realidad es solo aproximado. Así que no escribas código y solo espera que
funcione.

9:16

Tienes que pasar por la disciplina de hacer un diseño, traducirlo a RTL y luego presentarlo a las
herramientas.

9:25

La tercera tentación es un poco diferente, y es empezar a intentar escribir un código elegante,

9:34

posiblemente con estructuras de codificación que en realidad no he enseñado. Hay algunos que
son sintetizables que funcionan.

9:41

Particularmente para los diseñadores neófitos, les insto a evitar esto; es decir, pasar por la
disciplina

9:48

de traducir el diseño en código de la manera más sencilla posible en lugar

9:54

que hacer algo sofisticado. Los expertos pueden considerar hacer otra cosa, pero ciertamente, los
neófitos no deberían hacer esto.

10:01

Además, muy a menudo, el código menos elegante da un mejor diseño.

10:09

Cortar y agregar conocimiento a nivel humano sobre la estructura del diseño, lo que hace que el
código sea más voluminoso

10:15

en proceso y, como resultado, eso conduce a un mejor diseño que uno que tiene solo unas pocas
líneas.
10:24

Daré ejemplos de esto más adelante, pero nuevamente, un ejemplo que vimos en las notas de
tiempo.

10:30

Los ejemplos allí que se ejecutaron de manera más eficiente al final de ese derecho en el
comparador de etapas múltiples, esos ejemplos

10:37

que se ejecutó de manera más eficiente en realidad tienen más código en ellos.

10:45

Entonces, hablemos de los pasos en el diseño antes de comenzar con este mostrador.

10:51

El primer paso en el diseño es elaborar el algoritmo de hardware

11:01

y la estrategia general. En realidad, esto podría llevar bastante tiempo, especialmente a medida
que avanzamos en diseños más grandes, y veremos ejemplos de esto.

11:08

en módulos posteriores de esta clase. En términos de diseño de detalle, el siguiente paso más
importante es

11:17

identificar y nombrar todos los registros. Porque hacer esto realmente determina el tiempo del
sistema,

11:28

y como hay que nombrar todos los registros de todos modos, porque hay que asignarlos y siempre

11:33

en el bloque de reloj posedge, entonces este es el momento de hacerlo. Aquí es donde se debe
tener cuidado.

11:40

Es muy fácil agregar demasiados registros, lo que inflará su diseño y lo hará lento.

11:46

Sin embargo, necesita los registros que necesita, y posiblemente algunos más para mejorar el
rendimiento.
11:53

por ejemplo, usando micropipelines. ¿Cómo se decide si algo debe estar en un registro?

11:59

¿Es necesario preservarlo entre ciclos de reloj? Puedes pensar en todo lo que no está en un
registro

12:06

en el código como si se perdiera entre ciclos de reloj y se reconstruyera a partir de lo que hay en
los registros.

12:13

Así, los registros tienen

conservar al menos los datos habilitadores

12:20

entre ciclos de reloj, si no los datos que necesita en sí. Luego identifica el comportamiento de cada
nube y combinación

12:27

de lógica, y aquí es donde Synthesis es tu amigo, porque puedes hacer esto a un nivel bastante
alto, y luego,

12:36

de hecho, tengo muchos detalles aquí en mi mente después de determinar los registros.

12:42

En este punto, en realidad es útil hacer una breve simulación

12:48

en tu cabeza del diseño. Y de hecho te insto a que lo hagas, así que no ilustraré

12:54

eso en las próximas notas, porque es un poco tedioso de hacer. Pero una vez que estés seguro

13:00

que su diseño en papel tiene una posibilidad razonable de estar cerca, entonces lo que hace es
traducir el diseño en papel

13:09

a HTL. No, esto no es realmente un ejercicio de codificación,

13:15
como en sus clases de C++, donde a menudo solo configura la pantalla

13:21

y empezar a diseñar y escribir el código al mismo tiempo. Aquí, no puedes hacer eso. El diseño es
un paso separado que conduce a un diseño en papel.

13:30

Luego toma esto y lo verifica usando el simulador,

13:35

y muy a menudo, aquí tendrá que volver a consultar los diagramas de tiempo previstos para
comprender los errores en la simulación.

13:43

Y finalmente, sintetizas el diseño y así obtienes lógica a nivel de puerta.

13:50

Así que este es nuestro ejemplo, que llevaremos

13:57

a través de los siguientes dos submódulos y las unidades dentro, y las unidades que van más allá
de eso,

14:03

y ese es el temporizador de cuenta regresiva. Esto es muy simple. Tengo un contador de 4 bits.

14:09

Tengo una entrada "in", que carga el conteo

14:15

en el mostrador cuando el pestillo está alto. El pestillo de aviso tiene prioridad.

14:20

Cuando dec es alto, para decremento, quiero seguir contando

14:25

abajo perdiendo uno por ciclo de reloj. Quiero parar en cero y quiero la bandera cero

14:32

para ir alto cuando llegue a cero. Una vez más, un mostrador es un elemento muy común en el
diseño,

14:38
a menudo tenemos que contar los bytes que pasan, los ciclos, todo tipo de cosas que queremos
contar. Es un elemento muy común, particularmente

14:45

en el controlador en el diseño. Así que de nuevo, esto es lo que no se debe hacer.

14:53

El primer ejemplo en la parte superior es un ejemplo clásico de escribir C, golpeando un reloj


siempre en posedge en el frente

15:00

y esperar lo mejor, y en este caso, puede obtener un resultado bastante malo.

15:07

Cuando todo está dicho y hecho, ¿qué crees que esto realmente construye?

15:12

Debo admitir que nunca lo he ejecutado a través de la herramienta, pero veamos qué sucede.

15:20

Recuerde, el comportamiento implica función, por lo que aparece el reloj posedge.

15:27

Luego ejecutamos ese ciclo for desde el valor hacia abajo, igual hasta cero.

15:34

Cuando llegue a cero, la bandera cero será uno. Cero es lo único que se asigna explícitamente en
este ciclo for;

15:45

el valor se asigna implícitamente. Entonces, probablemente obtendremos un flip-flop cuya entrada


D esté vinculada

15:53

a uno. Y en el reloj posedge, Q se vuelve igual a uno

16:00

a través de ese flip-flop. Nuevamente, no he verificado esto a través de Synthesis, pero no vas a

16:07

para obtener lo que espera, donde se necesitan N ciclos de reloj para bajar a cero.

16:14
Todo esto va a suceder en un ciclo de reloj. El segundo intento aquí en esta página es más
sofisticado,

16:20

y en realidad es más probable que esté realmente cerca de algo que realmente funcionaría. Y eso
es poner esto en el gatillo del reloj posedge

16:26

en medio del ciclo for, de modo que cada ciclo del ciclo for se retrase un ciclo de reloj, y eso es
más probable

16:32

para construir lo que queremos. Sin embargo, este es un ejemplo de código elegante, entre
comillas,

16:37

que no es mejor código. No produce un mejor diseño, pero ciertamente lo hace más difícil de
entender y mucho más difícil

16:44

seguir el proceso de diseño que recomiendo enfáticamente en esta clase.

16:52

Así que pasemos al diseño real. Elaborar una estrategia para un ejemplo tan simple es una
exageración,

16:58

pero vamos a describir brevemente lo que es. Voy a tener un registro para cargarlo, decrementar,

17:04

cuando la dec es alta, controle el valor del registro para determinar dónde la salida es cero.

17:11

Pero cualquier cosa más allá de un ejemplo trivial, tiene que pensar en su estrategia en su diseño.

17:17

Hablaremos de eso más adelante en el módulo de complejidad.

17:22

Así que a continuación, un paso muy importante. Porque si lo haces bien, ya has recorrido la
mayor parte del camino.

17:29
Entonces, el próximo y crítico paso es identificar y nombrar todos los registros, es decir, los rayos
de flip-flops.

17:38

¿Qué hay que registrar? Cualquier cosa que necesite ser preservada entre ciclos de reloj.

17:44

En este diseño, lo único que debe conservarse entre ciclos de reloj es el conteo actual,

17:49

que voy a llamar valor. Es un registro de 4 bits que produce el valor de la señal.

17:58

El siguiente paso es identificar el comportamiento de cada nube de lógica.

18:05

Y aquí puedo estar un poco suelto. Entonces, una forma muy útil, muy a menudo, de abordar esto
es

18:12

decir, bueno, el registro tiene múltiples alternativas diferentes renta

18:18

fuentes de datos. Así que pongamos un mux delante, enumeremos esas alternativas,

18:25

y lo de las líneas de control de esas alternativas. Entonces cuales son las alternativas,

18:31

los siguientes valores alternativos de valor? Bueno, ahí está, por eso queríamos cargarlo
originalmente.

18:42

Hay valor menos uno, si estamos haciendo una disminución real. Y a menudo dejo este cable fuera
de mis ejemplos,

18:49

pero aquí estoy siendo explícito, y también está el valor mismo. Si el decremento es bajo, solo
queremos reciclar el valor en sí

18:59

a través del flip-flop.

19:04
Entonces eso obtiene ese mux. Antes de hacer líneas de control para el mux, también necesitamos
un bloque

19:11

de lógica que produce una bandera cero. Bueno, eso es bastante fácil. Simplemente tomamos el
valor en un bloque de lógica que lo compara

19:18

con cero, y si la comparación es verdadera, la bandera cero subirá.

19:24

Finalmente, necesito determinar las líneas de selección para este mux. Algunos de ellos provienen
de las especificaciones de entrada.

19:35

Cuando el pestillo está alto, desea engancharse, por lo que tiene que haber una línea de selección.

19:41

Cuando dec es alto, quiero disminuir, por lo que debe ser una línea de selección.

19:46

Y quiero detenerme cuando llegue a cero, por lo que el indicador cero también es una línea de
selección para este mux.

19:58

Ahora dices, espera, espera, espera, espera. ¿Vas a usar mux de 3 entradas con tres líneas de
selección?

20:05

Y aquí es donde Synthesis le ayuda. No necesito preocuparme por eso.

20:11

Puedo escribir ese mux así en el código como una declaración if-else y dejar que Synthesis
funcione

20:19

averiguar qué será en realidad, si en realidad será un mux de 8 entradas con tres líneas de control,
o algunas puertas de síntesis

20:28

que conducen a un mux más pequeño. Realmente no lo sé, y no importa. La síntesis determinará
cuál es el óptimo razonable

20:35
para este diseño. No necesito entrar en ese nivel de detalle.

20:40

Entonces, ahora que hemos esbozado el diseño, lo que hacemos es traducirlo a Verilog.

20:46

Ya has visto las tres construcciones, el RTL sintetizable.

20:53

Piénsalo, vuelve a eso, si quieres. ¿Qué de esas construcciones usaríamos aquí?

21:00

Tal vez recuerdes que dijimos que cualquier cosa que sucediera

21:07

fuera de registro tiene que ser asignado y siempre tener una declaración de reloj positiva.

21:12

Y podemos juntar eso con un poco de combinación

21:17

de la lógica, en particular la de un mux y sus alimentadores en el mismo bloque de procedimiento.

21:25

Así que todo esto que estoy circulando ahora se convierte en un bloque de procedimiento.

21:30

Necesitaré un bloque de procedimiento separado, uno de lógica combinacional o una declaración


asignada

21:40

para producir una bandera cero. Así que hagamos eso y veamos el resultado en el código,

21:50

y por primera vez vea un módulo completo que es un ejemplo no trivial. Así que lo que tengo aquí
son dos bloques de código.

22:03

Tenga en cuenta que el orden de estos dos bloques de código no importa, porque estamos
modelando hardware paralelo,

22:10
y entonces Verilog te permite cambiar el orden del código porque no hay una secuencia implícita
en el orden

22:17

de estos diferentes bloques de código. Se activa el primer bloque de código.

22:23

por siempre en posedge reloj. Obviamente, eso producirá mi registro junto con su mux de
entrada.

22:32

Ingrese mux, piense en una declaración de caso o en una declaración if-else.

22:38

Es un ejemplo simple, así que if-else. Latch tiene prioridad, por lo que si latch es alta, el valor se
vuelve igual

22:46

a N; de lo contrario, si dec es alta y no hemos llegado a cero,

22:52

valor es igual a valor menos uno. Aviso que no necesito un else adicional

23:00

para este cable aquí. ¿Porqué es eso? ¿Por qué no necesito otro más?

23:08

de lo contrario, el valor es igual al valor, ¿para ese cable allí? Puedo dejarlo implícito, es la
respuesta.

23:19

¿Qué sucede con el valor de value si no se ejecuta ninguna de las declaraciones "if"?

23:27

Es decir, el latch es bajo y dec es bajo o cero es alto.

23:34

¿Qué sucede con el valor? Simplemente permanece igual.

23:40

Como no cambia, el comportamiento del código es tal que tiene que permanecer igual.

23:46
Es decir, estamos dando a entender que hay una memoria en este código. Bueno, ese recuerdo es
intencional;

23:51

estamos construyendo intencionalmente un registro. Así que no necesitamos la declaración else


aquí para capturar ese bucle final.

23:57

Está implícito en que el valor no cambia si ninguno de los ifs se ejecuta, solo activa la ejecución

24:07

de un cambio de valor.

24:12

El segundo bloque de código aquí es una declaración de asignación continua de una línea.

24:18

Es decir, estamos comparando valor contra cero. Recuerde que doble igual significa "es igual a".

24:26

Esto produce un resultado verdadero o falso de un bit y se asigna a cero, que es un dato de un bit.

24:35

Tenga en cuenta que, aunque esto no va a crear un comparador,

24:40

en realidad, bajar al resultado óptimo, que son puertas [inaudibles], que no necesitamos pensar

24:48

a través de lo que podría ser la estructura lógica. Podemos simplemente describir el


comportamiento de esto en términos

24:54

de ser un comparador y dejar que Synthesis determine cuál es la representación óptima,

25:01

cuál es la versión óptima de esa lógica es. Bien, ahora que hemos visto las entrañas del código,

25:08

y siempre aborda esto escribiendo primero la llamada del código, necesitamos completar las
variables locales y los polos.

25:17
Así que vayamos a las variables locales aquí. Puedes ver que hay dos variables locales.

25:23

Necesitamos una variable local, ya sea explícita o implícitamente, y le recomiendo que la haga
explícita.

25:29

El hecho de que cero sea una salida significa que en realidad no tuvimos que declararlo aquí.

25:34

Pero te animo a que declares explícitamente todas tus variables locales. Necesitamos dos de ellos,
valor y cero.

25:43

El valor es de cuatro bits de ancho y el más significativo está a la izquierda.

25:48

Lo especifiqué muy explícitamente, para comenzar la variable [inaudible].

25:53

Y es de tipo reg. Desafortunadamente, escribir reg no siempre significa que es un registro,

26:01

aunque sucede que en este caso. Escriba reg solo significa que está asignado

26:06

dentro de un bloque procesal. Todas las variables asignadas dentro de un bloque de


procedimiento toman

26:17

en tipo reg. Y de nuevo, en este caso, tiene cuatro bits de ancho.

26:24

Notas que el cero es de tipo cable. La razón de esto es que la regla de Verilog es

26:31

que todas las variables asignadas en una declaración de asignación continua tienen que ser

26:38

de tipo cable o tipo prueba, y volveremos a intentarlo más tarde. Es un ejemplo bastante raro.

26:43
Entonces, la mayoría de las veces, cuando asigna una variable en una declaración de asignación
continua,

26:49

como el cero está aquí, será de tipo alambre. Y todo el tiempo si asigna una variable después de
un

26:56

declaración "siempre en" de cualquier tipo, será de tipo reg ya sea un registro o no.

27:07

Finalmente, tenemos nuestras entradas y salidas aquí. Estos esencialmente solo provienen del
diseño.

27:12

Observe que la entrada se especifica como de cuatro bits de ancho, del bit tres al bit cero,

27:19

el bit tres es el bit más significativo a la izquierda. En el siguiente conjunto de notas, el módulo
Verilog 2,

27:26

hablaremos sobre otras formas de abordar esto, cómo especificar la lógica little-endian,

27:31

o variables little-endian. Pero te animo a que te limites a big endian.

27:38

Si mezcla little endian y big endian, puede volverse confuso muy rápido.

27:45

Así es como se ve este diseño en RTL. Solo algunas notas sobre esto antes de mirarlo.

27:55

desde algunos ángulos diferentes. Nuevamente, las variables de múltiples bits se especifican
usando la estructura

28:03

se muestra en la parte superior aquí. Aquí tenemos una señal de 4 bits de ancho. El hecho de que
el gran número, el tres, esté a la izquierda,

28:10

significa que esto es big endian; es decir, la matriz del valor tiene el valor tres a la izquierda
28:18

y el valor cero a la derecha. Y, por cierto, las estructuras de datos básicas en Verilog son bastante
sencillas.

28:25

Todo es un bit en una matriz de bits, ya sea de tipo reg, tipo cable o prueba. Eso es.

28:31

No hay mucha complejidad más allá de eso. Además, vimos un par de números constantes, uno y
cero.

28:39

Y luego aquí voy a presentarles la forma específica en Verilog

28:44

que puede especificar números constantes. Por cierto, hubiera estado bien decir cero o uno.

28:51

sin esta N guión B delante de él. Sin embargo, te animo a que uses este N guión B,

28:58

porque está especificando con el número y eso puede ser útil en ciertas circunstancias.

29:03

Entonces, la forma en que se especifican los valores constantes en Verilog es,

29:09

en general, tenemos este enfoque de valor N guión B donde el primer número es el tamaño, y eso
siempre es

29:18

en el número de bits.

29:23

La siguiente letra después del guión es la base, B para binario, y volveremos a esto en el próximo
conjunto de notas,

29:30

pero D para decimal, H para hexadecimal. Lo último es el valor, que está en la base.

29:41

Así que aquí la base es binaria, el valor puede ser simplemente cero o uno, o una cadena de ceros
y unos.
29:47

Tienes guión H para hexadecimal, podría ser una cadena de números hexadecimales. No te
preocupes demasiado por esto,

29:53

solo apégate al ejemplo en la página aquí. Vamos a revisar esto con todo detalle

29:58

en las notas de Verilog 2. Y nuevamente, el concepto en un bloque de procedimiento es

30:05

que cuando las variables en la lista de sensibilidad cambien de valor como se indica, en este caso,
flanco positivo en el reloj

30:12

y sólo un borde positivo, en las declaraciones entre un comienzo y un final ejecutados en


secuencia, eso es procesalmente.

30:21

Esto es muy parecido a cómo C es un lenguaje de procedimiento. En realidad, solo necesitas


comenzar y terminar si hay más.

30:31

de una declaración en el bloque. Entonces, en el ejemplo que tengo aquí, en realidad solo hay una
declaración, un if-else-if,

30:39

y en realidad no necesito el comienzo y el final. solo estoy usando esto

30:45

para ilustrar el uso de begin y end. Sin embargo, no hay nada de malo en poner principio y fin aquí.

30:55

Voy a continuar con algunas preguntas aquí. Pero antes de hacer eso,

31:00

Les recordaré que la asignación continua solo implementa la lógica directamente y, básicamente,

31:07

cada vez que cambia el lado derecho, se vuelve a evaluar. Pero solo para recordarte a través de
preguntas y respuestas, 31:14
¿cuándo se ejecuta el bloque de procedimiento que sigue a la declaración de reloj always at
posedge?

31:20

Siempre que haya una ventaja positiva en el reloj. ¿Cuándo se evalúa el cero? En una asignación
continua, nunca ninguna variable

31:30

en los cambios del lado derecho. ¿Cómo se hacen los comentarios en la página anterior?

31:37

Hachís, hash o ponerlos entre hash hash de estrella a estrella. ¿Qué significa 1'b1?

31:47

Una constante de un bit con un valor de uno. ¿Y qué declara el valor reg [3:0] como una variable
local?

31:55

Es un valor de cuatro bits, una variable de cuatro bits, el bit más significativo

32:04

a la izquierda, y debido a que es de tipo reg, solo se puede asignar en bloques de procedimiento.

32:11

Démosle la vuelta a esto y veamos cómo el comportamiento implica la función.

32:17

Y aquí lo que he hecho es codificar con colores la correspondencia del código con la lógica.

32:22

Nuevamente, si observa el código, puede ver que esta es la lógica que se derivaría de él.

32:28

Siempre al reloj posedge significa un flip-flop. If-else significa un mux.

32:33

Los valores entre paréntesis son las señales de control para los multiplexores.

32:39

Los valores de la derecha son los valores, son las entradas al mux, in y value menos uno.

32:50

Para la lógica combinacional, lo que estamos haciendo es comparar el valor con cero.
32:57

Eso da un resultado verdadero-falso y luego se convierte en la bandera cero. Eso nos lleva al final
de este submódulo.

33:07

Solo para enfatizar algunos puntos importantes aquí, siempre diseñe antes de codificar.

33:13

Esboza el diseño al menos hasta el nivel de registro antes de que tus dedos toquen un teclado.

33:20

Y luego podrías, y te sugiero que incluso vayas más allá, tengas una idea de la combinación de
lógica e incluso la simules.

33:27

en un diagrama de tiempo simple para tener una idea de si estás en el camino correcto.

33:33

Después de diseñar, comienzas a codificar, y en realidad es solo un ejercicio de traducción.

33:41

Los registros y muxes de entrada se vuelven siempre al reloj posedge con sentencias if-else o case
dentro de ellos.

33:48

La lógica combinacional se convierte en asignación o siempre en estrella, bloques de


procedimiento.

33:54

Lo que me gustaría que hiciera ahora es continuar con el cuestionario de este submódulo antes de
pasar al siguiente submódulo.

34:01

Muchísimas gracias.

También podría gustarte