Skip to content

Notas Verilog

José Fernando Picó Antolí edited this page Aug 31, 2018 · 4 revisions

Crear una puerta AND-XOR-OR de múltiples entradas

Una forma de crear una puerta AND, XOR, OR a partir de múltiples entradas, es usar, el operator de bit &,^, | delante de la señal de datos múltiples.

Si por ejemplo, queremos detectar cuando todos los bits de un bus están a 1 lógico, podríamos realizar una AND con todos los datos del bus de la siguiente forma:


wire [15:0] bus;

wire TodosAUno;



assign TodosAUno = &bus;

Igualmente podríamos usar una XOR para detectar si los datos del bus tienen un número impar de 1's usando:


wire Impar;



assign Impar = ^bus;

Igualmente detectar si el bus no tiene todos los datos a cero, usando una OR de la forma:


wire NoCero;

wire Cero;



assign NoCero=|bus;

assign Cero=~NoCero;

Multiplicar y dividir por potencias de 2

Desplazar un número a la izquierda, equivaldrá a multiplicar dicho número por 2,4,8,16... en función del número de deslizamientos a la izquierda se realicen del número.

Igualmente desplazar un número hacia la derecha será equivalente a dividir el número por potencias de 2.


assign num = A << 2;  // Desplazar A dos veces hacia la izquierda equivale a  

                      // multiplicar por 4 ( 2^2 )  

assign num = A >> 3;  // Desplazar A 3 veces hacia la derecha equivale a dividir  

                      // por 8 ( 2^3 ).

Cómo hacer una extensión de signo.

Dados dos números de diferente longitud:


reg[3:0] numA = 1101;  // -3    (Complemento a 2 de 3)

wire[7:0] numB;



assign numB={{4{numA[4]}},numB}; 

el número "numA" de 4 bits se adapta a "numB" de 8 bits completando los 4 bits que le faltan con el bit de signo de "numA (4º bit)".

En Icestudio podríamos probarlo de la siguiente forma:

Extensión de Signo

Formas de crear un Multiplexor

Forma 1. o = (Si x ) ? a: b --> Si x o=a si no o = b

Podemos crear un multiplexor 4:1 usando en la asignación el condicional ? de la siguiente forma:

Mux 4 a 1 Usando Condicional ?

Usando "Yosys" podemos ver que se sintetizarán tres multiplexores en cadena formando un decodificador con prioridad ( a > b > c > d "a" mayor prioridad)

Sintesis Mux 4 a 1 Usando Condicional ?

Forma 2. if-else

Podemos crear el multiplexor 4:1 igualmente mediante la extructura if-else usado en los lenguajes de programación.

Sintesis Mux 4 a 1 Usando if-else

La síntesis de este circuito será igual que la de la "Forma1" donde tendremos un decodificador de prioridad.

Sintesis Mux 4 a 1 Usando Condicional ?

Forma 3.

Una tercera forma es usar "case"

Mux 4 a 1 Usando CASE

La síntesis realizada con "CASE" es un multipelxor trabajando en paralelo ( sin prioridades), usando "yosys" obtenemos una síntesis como la de la siguiente figura:

Sintesis Mux 4 a 1 Usando CASE

Biestable RS para iniciar-parar eventos.

El biestable RS permite, parar o iniciar eventos de una forma fácil, podemos activando la señal de Set o Reset ( bien por una activación continua o por un pulso ("tic") ) poner a 1 o 0 la salida del biestable de forma continua, usando esto, para habilitar/deshabilitar partes del sistema.

El biestable RS vendrá definido como:

Biestable RS

Aquí podemos ver que hay tres niveles de prioridad, la señal "reset" tendrá la prioridad máxima, la señal "S" (set) tendrá el segundo nivel de prioridad y la señal "R" tendrá la prioridad menor, por lo que, siempre que "reset=1" q=0 independientemente de las demás señales, siendo "reset=0" si S=1 q=1 independientemente del valor de R, siendo "reset=0 y S=0" si R=1 q=0.

Introduciendo pulsos ("tics") por S,R,reset podemos activar ( q=1) o desactivar el biestable ( q=0), esto suele ser útil para lanzar eventos de "Start" o de "Stop" de alguna parte de un sistema digital.

Vamos a mostrar a continuación un ejemplo del uso de biestable RS:

Start-Stop con RS

Mediante el uso de este circuito se puede parar o iniciar la cuenta de un contador de módulo 14, es un ejemplo sencillo pero que nos puede dar una visión del uso del biestable RS.

Podemos descargar el ejemplo en el siguiente enlace:

Ejemplo RS

Generador de Tics Por eventos de flanco/Cambio

Vamos a intentar presentar un circuito que a mi juicio puede ser muy interesante ya que nos permitirá lanzar unos "tics" ( un pulso de duración el periodo del reloj empleado) en función de que evento se produzca en la entrada del circuito.

Tendremos tres salidas:

T (toggle), R (Rinsing) y F(Falling) sobre las cuales apararecerá un "tic" en función de lo que pase en la entrada. Si en la entrada se produce un flanco de subida (Rinsing), aparecerá un "tic" en la salida R, si en la entrada se produce un flanco de bajada ( Falling ), aparecerá un "tic" en la salida F y siempre se haya un cambio de nivel, por que tanto cuando haya un flanco de subida como de bajada también nos aparecerá un "tic" en la salida T ( Toggle).

El circuito que realiza esta operación es el siguiente:

Detector Flanco-Cambio de nivel

El circuito se compone de un biestable D sobre el cual podemos captura el estado actual de la entrada "in" (en la puerta de entrada del biestable) y el estado anterior de la entrada "in" ( en la salida Q del biestable ). Con esos dos datos de valor actual y anterior de la entrada podemos realizando simples operaciones booleanas saber si se ha producido en la entrada un flanco de subida, uno de bajada o se ha detectado un cambio de nivel sin especificar si es flanco de subida o de bajada.

¿Como lo hacemos?

  1. Si el valor actual y anterior son distintos, sabremos que se ha producido un cambio (sin especificar si ha habido un flanco de subida o de bajada) y se puede detectar realizando una simple OR entre el valor anterior y actual de la entrada.
  2. Si el valor Actual de la entrada es un 0 y el valor anterior era un 1, sabremos que se ha producido un flanco de bajada y se puede detectar haciendo una AND del valor negado de la entrada actual y el valor anterior.
  3. Si el valor Actual de la entrada es un 1 y el valor anterior era un 0, sabremos que se ha producido un flanco de subida y se puede detectar haciendo una AND del valor de entrada actual y el valor anterior negado.

Con esto podemos tener un circuito con el cual se nos dispararán "tics" de aviso por un evento producido por flanco de subida de bajada o simplemente por notificación de cambio de nivel de una señal de entrada.

Hemos creado un módulo para este bloque intentando representar lo que el circuito hace creando un pequeño dibujo con inkscape, el módulo resultante sería:

Módulo Detector Flanco-Cambio de nivel

Un pequeño ejemplo de aplicación es el siguiente:

Ejemplo Detección cambio de nivel

En este pequeño ejemplo usamos la salida T (Toggle) sobre la cual se produce un "tic" cada vez que en entrada se produce una cambio de nivel ( sin especificar si es un flanco de subida o de bajada ), esta salida ataca a un biestable tipo T que cada vez que recibe un "tic" cambiará de nivel y cuya salida habilitará o no un contador de 5 bits. Por lo tanto, al pulsar el pulsador de la entrada "in" se iniciará la cuenta en el contador ( al detectar un cambio por flanco de subida) y se mantendrá contando hasta que se suelte el pulsador y detecte otro cambio de nivel que nos producirá la parada del contador. Este ejemplo podría valer para medir el ancho de un pulso introducido en la entrada "in".

==Este ejemplo asume para su perfecto funcionamiento que la señal de "in" está sincronizada con el reloj del sistema.== En caso contrario la señal de entrada "in" debe sincronizarse con el reloj del sistema así como eliminar rebotes posibles (un pulsador mecanico por ejemplo).

Podemos ver otro ejemplo donde como entrada "in" se introduce una señal de reloj de periodo 1sg. Estudiaremos el funcionamiento del módulo generador de "tics" empleando el analizador digital de señales a 24MHz de "Saleae logic" de bajo coste empleando el software que trae de ¨PulseView". Podemos ver un ejemplo del uso del analizador en la wiki del maestro "Obijuan" en:

Obijuan Analizador lógico Salease

El ejemplo sobre el cual vamos a estudiar el módulo creado es el siguiente:

Ejemplo Usando entrada sincronizida con el reloj del sistema

Usando el analizador lógico obtenemos un diagrama como el siguiente:

Tics Obtenidos

Podemos ver que hay una señal de reloj de sistema de 12Mhz "clk" y que en la entrada del módulo "in" aparece una señal de reloj de periodo 1sg. La señal de salida "Toggle"(T) generará un "tic" en cada cambio de nivel (se remarca con círculo rojo ), la salida "Rising"(R) generará un "tic· cada vez que la señal de entrada presente un flanco de subida ( Se remarca alguno de estos eventos con círculo verde)y la salida "Falling"(F) generará un "tic" cada vez que la señal de entrada presente un flanco de bajada (Se remarca alguno de ests eventos con un círculo en amarillo).

Si hacemos un zoom sobre la señal de entrada vemos:

Zoom "in"

Pero para apreciar mejor el "tic" necesaitamos ampliar aún más el zoom.
Si hacemos un zoom en alguno de los flancos de subida de la señal de entrada "in" podemos ver el siguiente diagrama:

Tic Flanco de Subida "in"

Ahora si podemos observar con claridad que en el flanco de subida de la señal "in" se produce un "tic" tanto en la salida "Toggle" como en la salida "Rising" y además el "tic" tiene una duración de 1 periodo del reloj del sistema.

Si hacemos un zoom en alguno de los flancos de bajada de la señal de entrada "in" podemos ver el siguiente diagrama:

Tic Flanco de bajada "in"

Ahora si podemos observar con claridad que en el flanco de bajada de la señal "in" se produce un "tic" tanto en la salida "Toggle" como en la salida "Falling" y además el "tic" tiene una duración de 1 periodo del reloj del sistema.

Podemos ver un pequeño video sobre el último ejemplo realizado, donde podemos ver como cada vez que se habilita el contador, este corre 4 cuentas y para, luego vuelve a correr otras 4 cuentas y para, así sucesivamente.

Video

Podemos ver el Módulo y algún ejemplo realizado en :

Detector Flanco-Cambio