Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Traduccion Video Verilog
Traduccion Video Verilog
>> 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
0:27
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
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
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
2:44
2:57
3:04
3:10
3:15
3:22
"Diseña siempre antes de codificar". El uso de Verilog para diseñar hardware no es principalmente
un
3:31
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
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
4:11
Tienes que hacer eso. Te ayuda mucho y mejora tu productividad dramáticamente sobre el
trabajo.
4:18
4:24
4:31
obtenga el momento adecuado para usted, si eso es posible dado lo que presentó
4:38
4:45
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
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
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
8:31
8:38
8:44
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
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
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
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
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
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
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
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
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
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
13:50
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
14:15
14:20
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
14:53
15:00
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
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
15:53
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
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
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
18:05
Y aquí puedo estar un poco suelto. Entonces, una forma muy útil, muy a menudo, de abordar esto
es
18:12
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
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
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
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
20:53
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
21:17
21:25
Así que todo esto que estoy circulando ahora se convierte en un bloque de procedimiento.
21:30
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
22:23
por siempre en posedge reloj. Obviamente, eso producirá mi registro junto con su mux de
entrada.
22:32
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
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
23:34
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
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
24:40
en realidad, bajar al resultado óptimo, que son puertas [inaudibles], que no necesitamos pensar
24:48
24:54
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
25:48
25:53
26:01
aunque sucede que en este caso. Escriba reg solo significa que está asignado
26:06
26:17
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
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
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
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
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
30:21
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
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
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
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
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
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.