martes, 26 de enero de 2016

Uso de ' - ' (don't care) en VHDL

Introducción
El valor ' - ' (normalmente llamado don't care, o no importa) normalmente es usado en funciones booleanas para representar indistintamente un '1' o un '0'. Se usa principalmente para minimizar una función booleana al poder usar el valor lógico ('1' o '0') que resulta en una menor imeplementación de hardware. Sin embargo en VHDL el tipo std_logic define a ' - ' como un valor en si. Es decir no puede ser indistintamente '1' o '0' porque es ' - '. 
Veremos a continuación como se describe en VHDL una función en la que ' - ' puede tomar valor '1' o '0'. 
Nota: en alguna bibliografía se usa 'X' en lugar de ' - ' para representar el don't care. En VHDL 'X" es otro valor definido en el tipo std_logic, por lo que NO se debe usar para representar don't care. 'X' en VHDL es un valor 'don't know', o 'no sé'. 

' - ' como entrada en funciones Booleanas
Normalmente las funciones booleanas son representadas por una tabla de verdad que describe los distintos valores que se obtendrán en la salida de la función como respuesta a distintos valores de entrada. Veamos un ejemplo, la función de un decodificador con prioridad tiene la siguiente tabla de verdad: 


Fácilmente se puede observar que la salida de la función es '10' cuando I2 es '1', sin importar en lo mas mínimo el valor de I1 e I0. Así, la tabla de verdad se puede re-escribir de manera reducida teniendo en cuenta lo recién explicado, quedando expresada de la siguiente manera:


' - ' como salida en funciones Booleanas
En el caso de usar ' - ' como el valor que toma la función ante cierta condición de entrada, significa que realmente el valor de la salida 'no importa' que sea '0' o '1'. Aunque esto suene raro, como no va importar el valor de salida?!?!?!, en realidad se usa para los casos en que esa condición/valor particular de las entradas no es esperado, ni debería darse bajo ninguna circunstancia. 
Veamos en detalle la siguiente tabla de verdad

Para este caso cuando la entrada es '11' la salida puede ser '1' o '0'. Si, por ejemplo cuando se implementa la función, y se le asigna valor '0' para la combinacion de entradas '11', el mapa de Karnough de la funcion es el siguiente: 

Y la funcion resultante de la lectura del mapa es, f = a'b + ab'
Cuando se le asigna un valor '1', el respectivo mapa de Karnaugh es: 



y la función resultante: f = a+b . 
Esta ultima función requiere menos hardware, por ello el uso de ' - ' puede ser importante en casos en que el número de componentes lógicos (compuertas, LUTs, etc) sea clave en el diseño que se quiere implementar. 

Uso de ' - ' en VHDL
El valor ' - ' esta definido en el tipo std_logic. SIN EMBARGO, VHDL considera ' - ' como un valor lógico en si, totalmente diferente de lo explicado anteriormente. Es decir ' - ' no puede tomar valor '0' o '1' porque en sí tiene un valor, que es ' - '. 
Así por ejemplo el siguiente código evalúa siempre como falso, 

1      if data = "1- - 1" then ...;

porque nunca en hardware existirá el valor "1 - - 1". 

Veamos entonces como hacer para que ' - ' pueda, de algún modo, ser usado como es usado en el álgebra de Boole, pudiendo tomar valor '1' o '0'. 

Uso de ' - ' como entrada en código VHDL 
Usando los conocimientos de VHDL  (q se supone q tienes :) . . . ) la tabla de verdad del decodificador con prioridad se podría describir como:

1 y <= "10" when I = "1--" else --siendo I la concatenación de I2I1I0
2      "01" when I = "01-" else
3      "00" when I = "001" else
4      "00";

Escrito como está, este código NO describe un decodificador con prioridad, porque?,,, Bien, cuando este código es implementado la condición "1--" o la condición "01-" NUNCA es verdadera. Porque?,,, bueno físicamente en un circuito digital solo se tienen dos valores lógicos o '1' o '0'. Así, si por ejemplo la señal de entrada tienen un valor "111", ninguna expresión será verdadera y el valor asignado a Y será "00'. 
Una solución a este problema sería describir el decodificador con prioridad de la siguiente manera: 

1 y <= "10" when I(2) = '1' else
2      "01" when I(2 downto 1) = "01" else
3      "00" when I(2 downto 0) = "001" else
4      "00";

Este código se acerca mas a lo que estamos buscando, sin embargo la mejor solución es la siguiente: En el paquete numeric_std hay una función llamada std_match(), que básicamente realiza una interpretación de ' -' de acuerdo a lo q el diseñador espera, es decir trata el valor ' - ' del tipo std_logic como valor '1' o '0'. La función compara dos vectores de tipo std_logic_vector e interpreta ' - ' como un valor 'no importa', y da como resultado un boolean (F/T). Usando la función std_match() se puede re-escribir el primer ejemplo como: 

1      if std_match(data, "1 - - 1") then . . . .


Lo que hace la función std_match() es comparar el vector data con el vector "1 - - 1", evaluando como verdadero si el primer y el último elemento de data son '1', sin interesar los otros dos valores. 
Nota: std_match también puede usarse con tipos unsigned, signedstd_ulogic, std_ulogic_vector, y std_logic.  

Del mismo modo el código del decodificador con prioridad anterior puede re-escribirse así: 

1 use ieee.numeric_std.all;
2      ....
3
4 y <= "10" when std_match( I, "1--") else  
5      "01" when std_match(I, "01-") else
6      "00" when std_match(I, "001") else
7      "00";

Uso de ' - ' como salida en código VHDL
Es bastante común el uso de ' - ' en una salida. Normalmente se lo utiliza como el valor que se la asigna  a la salida cuando todos los valores de entradas han sido ya asignados y queda solo 'when others' , 'else' ,etc. Por ejemplo la tabla de verdad descrita anteriormente se puede describir en VHDL de la siguiente manera:

1 tmp <= a & b;
2 with tmp select
3     y <= '0' when "00",
4          '1' when "01",
5          '1' when "10",
6          '-' when others;

De este modo el sintetizador puede utilizar el '-' como '1' o '0' para optimizar el hardware a implementar.

Espero q' sirva de algo lo acá escrito.... 
Suerte ! 

Nuevo: bajá la versión pdf de este artículo haciendo click acá  ->  :)

miércoles, 28 de octubre de 2015

INTEL - ALTERA ... preocuparnos? alegrarnos?

Mucho se ha dicho de esta gran operación comercial. 

Para los que trabajamos con FPGAs y más aún para los que nos gustan ALTERA FPGAs, no deja de ser una preocupación. Y si a eso le agregamos que mientras estuve en Intel ví como vendían y compraban grupos enteros de diseñadores de IC como si nada, mi preocupación escaló a niveles insospechados :) ...

Encontré un interesante articulo al respecto de este tema. Creo que explica bastante claro, como siempre Kevin Morris, los teje y manejes, suposiciones y preocupaciones de lo que puede llegar a ser el futuro de esta unión. 

Les dejo acá el link del articulo: 

Altera’s Long Game 


Espero lo disfruten.... 

domingo, 6 de septiembre de 2015

ISE-ModelSim: Como 'ver' mejor las formas de ondas y facilitar el debug

Cuando se invoca cualquier tipo de simulación desde el ISE, ModelSim es automáticamente abierto. Una de las ventanas que se abre es la Wave View. Por defecto solo las señales de la entidad top son mostradas, y ... nada más... Entonces, si se desean ver señales internas, cambiar la posición y/o color de las señales, agregar divisores, y tantas otras características que ofrece ModelSim, se puede hacer, pero . . . solo temporariamente hasta cerrar ModelSim. Cuando se corra la misma simulación de nuevo, se deberá empezar otra vez con las modificaciones.
En esta Application Note se detallan los pasos a seguir, para que cuando se invoque ModelSim desde el ISE, la simulación, y específicamente, el Wave View contenga toda la información que uno desea/necesita para una buena verificación o un fácil debug:


C7T AN-05



Happy design !

sábado, 11 de abril de 2015

Tutorial ISE - ISim - IMPACT

Hace tiempo que me vienen pidiendo un tutorial introductorio completo del ISE de Xilinx... la verdad es que habiendo tantos en la red me negaba a invertir tiempo en escribirlo, testearlo, implementarlo, etc.... Sin embargo un día realicé una especie de leída general en la web de los tutoriales disponibles, y me quedé, insatisfecho con lo que encontré... Así es que, me puse manos a la obra y la verdad es que me llevó bastante tiempo, por lo que espero les sea útil.

Este tutorial incluye creación de proyecto en ISE, uso de los procesos mas importantes del ISE, comprensión de reportes, uso del ISim (bastante detallado), uso de IMPACT, e implementación en un board Nexys2 del ejemplo del tutorial (por supuesto que se puede perfectamente adaptar a otros boards como Nexys3, Nexys4, XUPV5, etc). También hay un anexo del uso básico de FPGA Editor, Post P&R Timing y la instalación del ISE Web Pack. 

Para bajar el documento hacer click en este link: Tutorial ISE ISim IMPACT

Los archivos usados en el tutorial se pueden bajar de: Archivos del Tutorial ISE


Una vez mas EXITO en sus proyectos....! !

miércoles, 11 de marzo de 2015

Error: "cannot match operand(s) in the condition to the corresponding edges. . ." "An edge descriptor must be applied to an expression of size 1"


Introducción

Hace poco una alumna me pidió le revise su código Verilog porque tenía problemas y no encontraba como se originaba el error. Obviamente, la herramienta de síntesis que usaba generaba un mensaje de error, y obviamente ese mensaje daba muy poca idea de cual era el origen del problema. Lo primero que hice, y que a veces me da resultado, es sintetizar el código en la herramienta de la competencia, y .... lo mismo, mensaje de error encriptado. Lo segundo que normalmente se hace en estos casos es "googelar" el mensaje de error y ver que se encuentra al respecto.... No encontré nada... No me quedaba otra que estudiar el tema y ver que originaba el error. 
Detallo entonces debajo problema, mensajes y finalmente solución ....

Mensajes de Error Encriptados

ISE genera el siguiente mensaje de error: 

"ERROR:Xst:904 - "../../RTL_Src/semaforo.v" line 64: An edge descriptor must be applied to an expression of size 1."

El mensaje de error de Quartus: 

"Error (10200): Verilog HDL Conditional Statement error at semaforo.v(64): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct"

Las líneas del código correspondiente al número de línea indicado por el mensaje de error son las siguientes: 

 

A simple vista no se ve nada raro en el código. Revise muchísimas veces cada instrucción, cada simbolo, cada nombre y todo se veía perfectamente bien. 
Por supuesto una de las cosas que hice fue, por ejemplo, ir a la referencia del mensaje de error generado por la herramienta. En el caso del ISE el error es Xst:904, 

al hacer doble click en el link del error aparece: 
 

 
 Que ayuda, no? !!!

Quartus, directamente no tenía un link o explicación del error más allá del mensaje en sí. 
Bueno, después de dar tantas vueltas, como siempre la solución era muy sencilla. En realidad el problema no estaba en el código en sí, sino en la definición de clk y rst

Estas son las primeras lineas del código donde están definidas las E/S: 



Se dan cuenta del problema ?..... 

PROHIBIDO seguir leyendo sino encuentran el error :) ....

Por ahorrarse unas líneas de código, clk y rst fueron definidos en la misma línea que los vectores de dos bits sensor y boton.... por lo que clk y rst en realidad están definido como vectores de dos bits, por eso la instrucción negedge o posedge no puede determinar cual edge ejecutar. 

Como siempre una vez encontrado el error, uno dice: "Como no lo encontré antes!", "Que facil la solución", etc. etc, ... Lo que sí me parece extraño es que los compiladores no puedan generar un mensaje de error más sencillo, con mejor indicación del problema y una mejor guía de la solución.

Bueno, espero que les sea útil este artículo. 




 




jueves, 5 de marzo de 2015

Generador De Secuencia Binaria Pseudo Aleatoria (PRBS/LFSR)


Introducción

La generación de una secuencia pseudo aleatoria de números binarios es muy útil en ciertas ambientes de test y desarrollo. Un generador de secuencia binaria pseudo aleatoria, SBSA, (en  inglés,  Pseudo Random Binary Sequence, PRBS) es un circuito que genera una seria de números binarios de n-bits, un número por ciclo de reloj,  sin seguir un patrón determinado, pero que se repite luego de 2n-1 ciclos de reloj. Por lo general un PRBS se implementa como un registro de desplazamiento de realimentación lineal (en ingles Linear Feedback Shift Register, LDFSR). Dicho de otra manera con el término PRBS se describe lo que el circuito hace, mientras que con el término LFSR se describe como el circuito está implementado.

En esta nota técnica se describe en VHDL un LFSR que genera la secuencia binaria pseudo-aleatoria. Se presentan en VHDL distintos ejemplos de código y su implementación en FPGA. Finalmente se detalla un ejemplo de código VHDL parametrizado a fin de tener un PRBS genérico.

----------------------------------------------------------------------------------------

Me pasó de nuevo.... Comencé a escribir este blog, investigué, y encontré que hay de todo, por todos lados, pero nada en un solo lugar respecto de este tema. Otra vez, junté todo lo consideré importante, mas mi experiencia, etc, etc, y me quedaron unas cuantas páginas escritas, las cuales creo que la manera mas conveniente de presentárselas es a travéz de un buen documento. Podes bajar el pdf en este -link- 

Clq duda... solo preguntame... :)  

lunes, 9 de febrero de 2015

Partición de Diseño Basada en Dominio de Reloj

Introducción

Cuando el sistema a diseñar tiene varios módulos y a su vez cada uno de estos módulos tiene su propio reloj, y los módulos interactuan entre sí, es conveniente realizar lo que se llama partición del diseño basado en dominio de reloj, y seguir un par de simples reglas con respecto al modo de realizar la partición como así también con respecto al nombre de las señales de E/S, y de las señales de comunicación entre módulos.

Partición del Diseño

Supongamos tenemos un sistema como el que se muestra en la siguiente figura:


En este caso el sistema se ha dividido en tres módulos, A, B y C. Esta división está basada en función de los distintos relojes que tiene el sistema y en la funcionalidad de cada módulo; por ello cada módulo en este partición tiene su propio reloj. Así, cada módulo tiene lo que comúnmente se llama su propio dominio de reloj (clock domain). 
Esta partición de un sistema basada en dominio de reloj es muy importante por diversos motivos, principalmente facilita el trabajo de la herramienta de síntesis, mejora las tareas de las herramientas de cálculo de frecuencia máxima (Static Timing Analysis), ahorra tiempo en la herramienta de place and route. Otra ventaja de este tipo de partición, es que  ahorra mucho tiempo de procesamiento de CPU en sistemas complejos.

Sincronizadores

Al hacer la particion basada en dominio de reloj, y si los distintos módulos deben interactuar entre sí es necesario realizar algún tipo de sincronización entre las señales de comunicación entre módulos, ya que cada señal tiene su propio reloj. Esta sincronización puede ser realizada mediante sincronizadores o mediante FIFOs (no es el objetivo de este blog explicar los diferentes métodos de sincronización). Así por ejemplo, si se desea comunicarse una señal del módulo A con el módulo B, es necesario un sincronizador que sincronice la señal proveniente del módulo A basada en el reloj aclk, con el reloj bclk del módulo B. Del mismo modo para comunicarse o transferir datos desde el módulo B al módulo A, es necesario un sincronizador para pasar del dominio bclk al dominio aclk
De este modo todos los módulos principales tiene solo un solo reloj, mientras que los módulos sincronizadores, tienen múltiples relojes. 

Nombre de Señales

Con este tipo de partición es fácil seguir una convención para el nombre de las señales. Así, todas las señales que solo son controladas por un solo reloj, son definidas con nombres referenciando a ese dominio de reloj. Por ejemplo las señales del módulo A que solo son controlada por el reloj de A, aclk, se pueden nombrar comenzando con la letra a (referenciando al módulo A), así se puede nombrar la señal adata, aadrr, aen, etc., como también bdata, baddr, ben, etc, para las señales controladas por el dominio de reloj del modulo B (bclk). 
Por otro lado las señales que cruzan los dominios de reloj (a travez de los sincronizadores) deberían ser nombradas de forma que sea fácil de deducir el origen y el destino de la señal. Por ejemplo, si la señal ack debe cruzar del dominio bclk al dominio aclk se podría denominar b2a_ack
Usando este tipo de nomenclatura fácilmente se puede identificar cuales son las señales que cruzan diferentes dominios de reloj. Una de las grandes ventajas de esto es que se puede escribir la respectiva restricción (constraint) de false path para facilitar el trabajo de la herramienta de análisis de tiempo estático (Static Timing Analysis). 

Otras Ventajas de Partición por Dominio de Reloj

Ademas de las ventajas mencionadas anteriormente, este tipo de partición facilita el trabajo de floorplanning de la herramienta de síntesis, y como consecuencia se puede llegar más fácilmente a una reducción de área, mejoramiento del rendimiento, e incluso reducir la potencia de consumo del sistema. 
También, al tener los módulos separados por dominio de reloj, las herramientas de síntesis actuales permiten que cada módulo sea optimizado individualmente (ya sea por área, velocidad o potencia). 

Es todo por hoy.....

Espero sea de utilidad.....