Universidad de Costa Rica Facultad de Ingeniería Escuela de Ingeniería Eléctrica Procedimiento de diseño e implementación de circuitos digitales utilizando herramientas EDA de código abierto Por: Gerardo Castro Jiménez Ciudad Universitaria Rodrigo Facio Junio del 2008 Procedimiento de diseño e implementación de circuitos digitales utilizando herramientas EDA de código abierto Por: Gerardo Castro Jiménez Sometido a la Escuela de Ingeniería Eléctrica de la Facultad de Ingeniería de la Universidad de Costa Rica como requisito parcial para optar por el grado de: LICENCIADO EN INGENIERÍA ELÉCTRICA Aprobado por el Tribunal: _________________________________ Ing. Enrique Coen Alfaro, M.Sc. Representante del Director, Escuela de Ingeniería Eléctrica _________________________________ Ing. Randolph Steinvorth Fernández, PhD. Director, Comité Asesor _________________________________ Ing. Jorge Romero Chacón, PhD. Miembro, Comité Asesor Director, Escuela de Ingeniería Eléctrica _________________________________ Lic. Roberto Rodríguez Rodríguez Miembro, Comité Asesor _________________________________ Ing. José Luis López Sauma, M.Sc. Miembro del Tribunal ii DEDICATORIA A Dios por guiarme y por ser la luz de mi camino. A mi familia por estar siempre conmigo, por su apoyo y ser incondicionales. A mis amigos por las experiencias que hemos vivido. “Creo más en la imaginación que en el conocimiento” iii RECONOCIMIENTOS A todos los educadores y personas que invirtieron tiempo valioso de sus vidas para transmitirme sus conocimientos y experiencias. Este trabajo es el reflejo de todo lo que me enseñaron. Que Dios los bendiga. iv ÍNDICE GENERAL ÍNDICE DE FIGURAS................................................................................ viii ÍNDICE DE TABLAS......................................................................................x NOMENCLATURA........................................................................................xi RESUMEN.................................................................................................... xiii CAPÍTULO 1: Introducción ...........................................................................1 1.1 1.2 Alcances..................................................................................................................1 Objetivos.................................................................................................................1 1.2.1 Objetivo general..............................................................................................1 1.2.2 Objetivos específicos ......................................................................................1 1.3 Justificación ............................................................................................................1 1.4 Planteamiento del problema....................................................................................2 1.5 Metodología ............................................................................................................3 CAPÍTULO 2: Desarrollo teórico ..................................................................6 2.1 Historia y estado del arte de los FPGAs ...........................................................................6 2.2 Antecedentes en la UCR ...................................................................................................6 2.3 FPGAs...............................................................................................................................7 2.4 Flujo de diseño mediante FPGAs utilizando las herramientas de Xilinx .......................11 2.5 Introducción a la codificación de predicción lineal (LPC) de la voz humana................14 CAPÍTULO 3: Planteamiento de un procedimiento basado en herramientas de código abierto ....................................................................17 CAPÍTULO 4: Diseño del codificador/decodificador de voz.....................21 4.1 Descripción general ........................................................................................................21 4.2 Componentes ..................................................................................................................21 4.3 Diagrama de estados general ..........................................................................................23 4.4 Descripción de los circuitos digitales .............................................................................25 4.5 Arquitectura de las máquinas de estado y de la asignación de registros ........................28 4.5.1 Protocolo de comunicación entre circuitos..........................................................28 4.5.2 Protocolo de cambio de estado y asignación de estado .......................................29 CAPÍTULO 5: Compilación y Simulación Funcional ................................30 5.1 5.2 Descripción en Verilog .........................................................................................30 Etapa de Compilación y Simulación Funcional....................................................32 5.2.1 Simulación funcional ....................................................................................32 v CAPÍTULO 6: Síntesis en Icarus Verilog....................................................36 6.1 6.2 Descripción del proceso de síntesis con Icarus Verilog .......................................36 Descripción del proceso de síntesis para la arquitectura Virtex ...........................37 6.2.1 Características del sintetizador de Icarus Verilog.........................................37 6.2.2 Verilog sintetizable para la arquitectura Virtex ............................................39 6.2.3 Adición de parámetros y restricciones en el proceso de síntesis para la arquitectura Virtex ........................................................................................................47 CAPÍTULO 7: Implementación, Programación y Simulaciones postimplementación...............................................................................................50 7.1 Proceso de implementación ...........................................................................................50 Proceso de Traducción: Translate.................................................................................50 7.1.2 Proceso de Mapeo: Map ......................................................................................52 7.1.3 Proceso de Posicionamiento y Enrutamiento: Place and Route ..........................54 7.1.4 Programación del FPGA y pruebas en circuito ............................................55 CAPÍTULO 8: Conclusiones y recomendaciones .......................................56 BIBLIOGRAFÍA............................................................................................58 APÉNDICE A: Diagrama de estados de los circuitos ................................60 A.1 Controlador A/D ............................................................................................................60 A.1.1 Registros: ............................................................................................................60 A.1.2 Diagrama de Estado: ...........................................................................................60 A.2 Controlador D/A ............................................................................................................61 A.2.1 Registros: ............................................................................................................61 A.2.2 Diagrama de Estado: ...........................................................................................61 A.3 Controlador de Memoria................................................................................................62 A.3.1 Registros: ............................................................................................................62 A.3.2 Diagrama de Estado: ...........................................................................................63 A.4 Controlador de Reproducción ........................................................................................64 A.4.1 Registros .............................................................................................................64 A.4.2 Diagrama de Estado ............................................................................................64 A.5 Controlador de Codificación..........................................................................................66 A.5.1 Registros .............................................................................................................66 A.5.2 Diagrama de Estado ............................................................................................67 A.6 Sonido con/sin Voz ........................................................................................................69 A.6.1 Registros .............................................................................................................69 A.6.2 Diagrama de Estado ............................................................................................70 A.7 Detección del Pitch ........................................................................................................71 A.7.1 Registros .............................................................................................................72 A.7.2 Diagrama de Estado ............................................................................................72 A.8 Coeficientes R ................................................................................................................74 vi A.8.1 Registros .............................................................................................................74 A.8.2 Diagrama de Estado ............................................................................................75 A.9 Coeficientes LPC ...........................................................................................................76 A.9.1 Registros .............................................................................................................76 A.9.2 Diagrama de Estado ............................................................................................77 A.10 Filtro de Análisis..........................................................................................................79 A.10.1 Registros ...........................................................................................................79 A.10.2 Diagrama de Estado ..........................................................................................80 A.11 Filtro de Síntesis ..........................................................................................................82 A.11.1 Registros ...........................................................................................................82 A.11.2 Diagrama de Estado ..........................................................................................83 A.12 Sumador/Restador........................................................................................................85 A.12.1 Registros ...........................................................................................................85 A.12.2 Diagrama de Estado ..........................................................................................85 A.13 Multiplicador................................................................................................................87 A.13.1 Registros ...........................................................................................................87 A.13.2 Diagrama de Estado ..........................................................................................87 A.14 Divisor..........................................................................................................................88 A.14.1 Registros ...........................................................................................................88 A.14.2 Diagrama de Estado ..........................................................................................88 A.15 Raíz Cuadrada..............................................................................................................89 A.15.1 Registros ...........................................................................................................89 A.15.2 Diagrama de Estado ..........................................................................................90 APÉNDICE B: Modelos Matemáticos y Algoritmos de LPC ....................92 APÉNDICE C: Código en Matlab, equivalente en Software del circuito diseñado...........................................................................................................96 APÉNDICE D: Problemas de temporización durante la etapa de implementación.............................................................................................102 D.1 Problema de convergencia de la arquitectura microprogramada .................................102 D.2 Problema de alineación entre relojes ...........................................................................103 APÉNDICE E: Guía del procedimiento de diseño e implementación de circuitos digitales utilizando herramientas EDA de código abierto........106 vii ÍNDICE DE FIGURAS Figura 1.1: Flujo de diseño e implementación mediante FPGAs [8] ...................................3 Figura 1.2: Metodología de diseño .....................................................................................4 Figura 2.1: Diagrama de un FPGA [8] .................................................................................7 Figura 2.2: Estructuras de FPGAS [8]..................................................................................8 Figura 2.3: Estructuras de CLB [8] ......................................................................................8 Figura 2.4: Líneas de interconexión [9] ...............................................................................9 Figura 2.5: Fabricantes de FPGAs [8] ................................................................................10 Figura 2.6: Flujo de diseño mediante FPGAs [8] ...............................................................11 Figura 2.7: Modelo del tracto vocal [3] ..............................................................................14 Figura 2.9: Esquema de decodificación LPC [3] ...............................................................16 Figura 3.1 Flujo de diseño basado en herramientas EDA de código abierto....................18 Figura 4.1 Diagrama de bloques del diseño......................................................................23 Figura 4.2 Diagrama de estado general del diseño ...........................................................24 Figura 4.3 Arquitectura de la asignación de registros ......................................................28 Figura 4.4 Protocolo de comunicación entre los circuitos................................................29 Figura 4.5 Protocolo de cambio de estado y asignación de estado..................................29 Figura 5.1 Estructura de la descripción en Verilog para los circuitos diseñados ............30 Figura 5.2 Estructura jerárquica establecida para el proyecto .........................................31 Figura 5.3 Esquema jerárquico para simulación funcional...............................................32 Figura 5.4 Simulación funcional del controlador de memoria DRAM en GTKWave ....33 Figura 5.5 Simulación funcional del divisor de 32bits ....................................................34 Figura 5.6 Simulación funcional del codificador/decodificador de voz en GTKWave...35 Figura 6.1 Proceso de Síntesis con Icarus Verilog ..........................................................36 Figura 6.2 Archivo EDIF para multiplexor 4 a 1 (if-else) ................................................43 Figura 6.3 Esquemático del archivo de síntesis para multiplexor 4 a 1 (if-else) ..............43 Figura 6.4 Archivo EDIF, sección para multiplexor 4 a1 (case) .....................................44 viii Figura 6.5 Esquemático del archivo de síntesis para multiplexor 4 a 1 (case) .................44 Figura 6.6 Esquemático de celdas de tipo PAD en la arquitectura Virtex........................48 Figura 7.1 Resumen de recursos utilizados en el FPGA, circuito completo ....................54 Figura 7.2 Reporte final de relojes del WebPack, circuito completo ...............................54 Figura 6. Filtro de análisis de voz.....................................................................................94 Figura 7. Filtro IIR todo polos para síntesis de voz..........................................................94 Figura D.1 Arquitectura microprogramada ....................................................................102 Figura D.2 Arquitectura one-hot.....................................................................................103 Figura D.3 Diagrama temporal, problema de alineación de relojes ...............................104 Figura D.4 Diagrama temporal, solución al problema de alineación de relojes .............105 ix ÍNDICE DE TABLAS Tabla 4.1 Circuitos diseñados para el codificador/decodificador de voz .........................22 Tabla 5.1 Nombre de los módulos en Verilog para cada circuito....................................31 Tabla 6.1 Celdas de la librería Virtex que maneja Icarus Verilog....................................40 Tabla A.1 Diagrama de Estado del Controlador A/D.......................................................61 Tabla A.2 Diagrama de Estado del Controlador D/A.......................................................62 Tabla A.3 Diagrama de Estado del Controlador de Memoria ..........................................64 Tabla A.4 Diagrama de Estado del Controlador de Reproducción...................................66 Tabla A.5 Diagrama de Estado del Controlador de Codificación ....................................69 Tabla A.6 Diagrama de Estado de Sonido con/sin Voz....................................................71 Tabla A.7 Diagrama de Estado de Detección del Pitch....................................................74 Tabla A.8 Diagrama de Estado de Coeficientes R............................................................76 Tabla A.9 Diagrama de Estado de Coeficientes LPC.......................................................79 Tabla A.10 Diagrama de Estado del Filtro de Análisis ....................................................82 Tabla A.11 Diagrama de Estado del Filtro de Síntesis .....................................................85 Tabla A.12 Diagrama de Estado del Sumador/Restador ..................................................87 Tabla A.13 Diagrama de Estado del Multiplicador ..........................................................88 Tabla A.14 Diagrama de Estado del Divisor ....................................................................89 Tabla A.15 Diagrama de Estado de la Raíz Cuadrada......................................................91 x NOMENCLATURA CLB Configurable Logic Block – Bloque Lógico Configurable CMOS Complementary Metal Oxide Semiconductor – Semiconductor de Óxido Metálico Complementario EDA Electronic Design Automation - Automatización del Diseño Electrónico EDIF Electronic Design Interchange Format - Formato de Intercambio de Diseño Electrónico EEPROM Electric Erasable Programmable Read Only Memory - Memoria de Solo Lectura Eléctricamente Borrable EPROM Erasable Programmable Read Only Memory – Memoria de Solo Lectura Borrable FPGA Field Programmable Gate Array - Arreglo de Puertas Programables por Campo FPLA Field Programmable Logic Array – Arreglo de Lógica Programable por Campo GAL Gate Array Logic – Arreglo de Puertas Lógicas HDL Hardware Description Language – Lenguaje de Descripción de Hardware IIR Infinite Impulse Response – Respuesta Infinita al Impulso IOB Input/Output Block - Bloque Entrada/Salida LPC Linear Prediction Coding – Codificación por Predicción Lineal LPM Library of Parameterized Modules – Librería de Módulos Parametrizable PAL Programmable Array Logic – Arreglo de Lógica Programable PCM Pulse Code Modulation – Codificación por modulación de pulsos xi PEEL Programmable Electric Erasable Logic – Lógica Programable Eléctricamente Borrable PLD Programmable Logic Device – Dispositivo Lógico Programable RAM Random Access Memory – Memoria de Acceso Aleatorio VLSI Very Large Scale Integration – Integración a Escala Muy Alta xii RESUMEN Este trabajo presenta un procedimiento de diseño e implementación de circuitos digitales utilizando herramientas de código abierto. Para su desarrollo se utilizó el diseño de un codificador/decodificador de voz. Como herramientas de código abierto se emplearon Icarus Verilog como simulador y sintetizador en HDL Verilog y GTKWave como visor de ondas en combinación con la herramienta propietaria WebPack de Xilinx. Se describieron en Verilog un conjunto de circuitos digitales de forma conductual y jerárquica que utilizaban codificación predictiva lineal para codificar y decodificar la voz. Se realizaron simulaciones funcionales y con Icarus Verilog se sintetizó el circuito completo para la arquitectura Virtex de Xilinx. La implementación se realizó para un FPGA SPARTAN3E de Xilinx. Se programó físicamente el circuito diseñado con resultados de funcionamiento exitosos. Durante este proceso se revelaron las capacidades y limitaciones de las herramientas de código abierto. Como resultado se obtiene una guía detallada del procedimiento para que sea utilizada en trabajos futuros y en cursos en la Universidad. Se concluye que el procedimiento y las herramientas tienen la capacidad suficiente para el desarrollo de circuitos digitales, pero se recomienda completar y mejorarlas para que el procedimiento sea más robusto. xiii CAPÍTULO 1: Introducción 1.1 Alcances En este proyecto se presenta un procedimiento de diseño e implementación de circuitos digitales utilizando herramientas EDA de código abierto. El procedimiento se desarrolló a través de una aplicación de procesamiento digital de señales. La aplicación que se seleccionó fue un codificador/decodificador de voz, cuyo diseño parte del modelo teórico de predicción lineal de la voz humana. No constituyó un objetivo de este proyecto el analizar u optimizar el algoritmo utilizado ya que este fue únicamente un vehículo para demostrar el procedimiento de diseño que se presenta. Se utiliza Verilog, como lenguaje de descripción de hardware estándar, para describir la arquitectura del circuito digital. Las etapas de compilación, simulación y síntesis se realizaron mediante herramientas EDA de código abierto y con formatos estándar que permiten intercambiar la información con otras herramientas disponibles en la industria. Las herramientas EDA de código abierto están disponibles al público en general sin costo alguno. Esto constituye la base del procedimiento y su principal distinción. Se obtuvo un circuito digital en el FPGA: SPARTAN3E de Xilinx como resultado final del procedimiento desarrollado. 1 1.2 Objetivos 1.2.1 Objetivo general Desarrollar un procedimiento de diseño e implementación de circuitos digitales basa- do en herramientas EDA de código abierto, utilizando como ejemplo un codificador/decodificador de voz 1.2.2 • Objetivos específicos Diseñar la arquitectura de un circuito digital que realice en hardware el algoritmo de codificación/decodificación de voz a partir del método de codificación de predicción lineal de la voz humana. • Describir el circuito digital del codificador/decodificador de voz mediante el lenguaje de descripción de hardware Verilog. • Utilizar herramientas de código abierto de uso general que permitan construir el circuito digital en cualquier dispositivo independientemente del fabricante del mismo. • Establecer la etapa de síntesis del procedimiento de diseño para que se pueda programar en el FPGA SPARTAN3E de Xilinx. • Verificar mediante pruebas cualitativas que el circuito programado en el FPGA realiza el algoritmo de codificación de voz utilizado. • Documentar el procedimiento de diseño propuesto para que pueda ser utilizado ampliamente y permita profundizar en el estudio de los dispositivos lógicos programables. 1.3 Justificación El proyecto surgió a partir de la dependencia que tiene el flujo de diseño e implementación en FPGAs de Xilinx. El flujo actual utiliza herramientas y formatos propietarios del fabricante limitando así la portabilidad de los diseños a otras plataformas. Esto motivó a buscar un procedimiento que utilice herramientas EDA de có1 2 digo abierto y formatos estándar de la industria que lograra obtener mayor flexibilidad. Con el uso de herramientas EDA de código abierto se obtiene independencia del fabricante y libertad para modificar y mejorar sus capacidades por parte de la Universidad de Costa Rica. Los formatos estándar, que no dependen del fabricante, permiten que el diseño se pueda transportar a otras marcas o tipos de dispositivos programables y hasta a VLSI. Está claro que existen etapas del flujo que siempre van a depender de la marca del dispositivo pero lograr una independencia en la mayoría de las fases es el principio para diseñar e implementar en cualquier tipo y marca de dispositivo programable. Por otro lado, las ventajas que presentan los FPGAs en el diseño de circuitos digitales y su potencial a nivel académico, se ve limitado por los pocos proyectos realizados en la Universidad de Costa Rica. Esta situación genera la necesidad de ampliar la documentación y profundizar en este campo. La documentación de este procedimiento dará una mayor referencia y podría ser de utilidad para futuros proyectos de graduación y cursos en la Universidad en esta área. 1.4 Planteamiento del problema El flujo de diseño e implementación general de un circuito digital FPGA consiste del diagrama de bloques mostrado a continuación [8]: 3 Figura 1.1: Flujo de diseño e implementación mediante FPGAs [8] Actualmente todas las etapas del proceso se realizan mediante el conjunto de herramientas EDA de Xilinx conocidas como: ISE Webpack (versión gratuita con limitaciones) o ISE Foundation (versión completa). Estas herramientas están orientadas hacia dispositivos FPGA de esta marca por lo que no son útiles para otras plataformas, esto hace que el flujo sea poco flexible. Durante el proceso se crean y se utilizan archivos con formatos propietarios de Xilinx, lo cual impide se puedan utilizar en otro tipo de herramientas o aplicaciones. Es decir que etapas ya realizadas se volverán a repetir si se cambia de plataforma. Por otro lado, la poca documentación que se encuentra acerca de la utilización de FPGAs como método para implementar circuitos digitales, provoca que los dispositivos no se puedan utilizar en los cursos impartidos en la Universidad ya que no se tiene la suficiente experiencia en el uso de ellos. 1.5 Metodología 4 Para cumplir con los objetivos planteados, se contó con las herramientas de código libre Icarus Verilog y GTK Wave. Icarus Verilog es un simulador de Verilog y sintetizador [17] y GTK Wave se utilizó para análisis temporal [16]. La metodología constó de 7 etapas que se enuncian a continuación: 1. A partir del método de predicción lineal para codificación de la voz, se extrajo las especificaciones arquitectónicas y elementos básicos para el diseño del codificador/decodificador de voz. 2. Con base en las fórmulas del modelo matemático se construyeron los módulos en Verilog que describían el circuito digital. Se utilizó la metodología que se muestra en la figura 2, donde se define el circuito completo y dentro de este se encuentran circuitos complejos que a su vez contienen circuitos sencillos. Figura 1.2: Metodología de diseño 3. Cada circuito simple pasó por una simulación funcional en Icarus Verilog y un análisis temporal mediante GTKWave. 4. Obtenida una descripción funcional en Verilog de los circuitos simples, estos se sintetizaron en el formato estándar EDIF mediante Icarus Verilog y se implementaron mediante la herramienta ISE Webpack de Xilinx. 5. Al finalizar este proceso para cada circuito simple, se continuó con los circuitos complejos que pasaron por las etapas 3 y 4. De esta forma el procedimiento se ejercitó en cada iteración. 5 6. Finalmente, el circuito completo formado por los circuitos complejos y sencillos se sometió a las etapas 3 y 4, donde se obtuvo una síntesis general del circuito. 7. Seguidamente, se hizo la programación del circuito completo en el FPGA, donde se realizaron las pruebas en circuito. SPARTAN3E de Xilinx fue el FPGA utilizado el cual se encontraba disponible en la bodega de la Escuela de Ingeniería Eléctrica. 8. Finalmente, se documentó el procedimiento en forma de guía, donde se detalla cada etapa. CAPÍTULO 2: Desarrollo teórico 2.1 Historia y estado del arte de los FPGAs En 1984, Ross Freeman funda Xilinx y crea el circuito del tipo FPGA, distinto de otros dispositivos lógicos programables (PLD). Estos circuitos tuvieron un gran éxito en el mercado y permitieron el desarrollo de la que hoy es empresa líder del sector de FPGAs [7]. Por otra parte, en esta época se fundaron otras dos empresas. Atmel se fundó en 1984, fabricando PLDs y FPGAs [7]. Actel se fundó en 1985, desarrollando FPGAs con tecnología basada en antifusibles y convirtiéndose en los líderes de esta tecnología desde 1994, presentando además la segunda cuota más grande del mercado de FPGAs [7]. Por su parte, Altera también introdujo circuitos del tipo FPGA, de arquitectura cuadrícula, siendo actualmente el tercer fabricante en cuota de mercado [7]. Actualmente, los fabricantes introducen mejoras en las nuevas FPGAs como [7]: • Reconfiguración parcial en el sistema (“Field partial reconfiguration”), es decir, de sólo una parte de la FPGA, en lugar de su totalidad como es habitual actualmente. • Incremento de la capacidad lógica, es decir, mayor número de puertas lógicas equivalentes. • Incremento de la capacidad de interconexión y disminución de los retardos de propagación, con el fin de alcanzar un mayor aprovechamiento de la capacidad de lógica y aumento en la velocidad del FPGA. 2.2 Antecedentes en la UCR Los trabajos realizados en la Universidad de Costa Rica en el área de los dispositivos lógicos programables no son muchos. Se ha sintetizado e implementado la CPUCR [2] [5], un filtro digital [4] y un probador de escaneo controlado por una PC para realizar pruebas es- tructurales a microprocesadores [1]. Para el desarrollo de todas estas aplicaciones se han utilizado PLD’s de la marca Xilinx modelo SPARTAN2E. Como herramienta principal EDA 6 7 se ha utilizado ISE Webpack del fabricante en combinación con algunas otras herramientas propietarias como Verilogger y ModelSim. 2.3 FPGAs Un FPGA es un dispositivo lógico programable o PLD (“Programmable Logic Device”), cuyas características pueden ser modificadas y almacenadas mediante programación [9]. Poseen una estructura interna formada por: matriz de bloques lógicos configurables CLB (“Configurable Logic Block”) que se comunican entre sí y con los bloques de Entrada/Salida I/OB (“Input/Output Block”) a través de canales de ruteo horizontal. Figura 2.1: Diagrama de un FPGA [8] Estructura de una FPGA Dependiendo del fabricante se pueden encontrar diferentes soluciones. Las FPGAs que existen actualmente en el mercado, dependiendo de la estructura que adoptan los bloques lógicos que tengan definidos, se pueden clasificar como pertenecientes a cuatro grandes familias [9]: 1. Matriz Simétrica (“Symmetrical Array”). 2. Basada en Filas (“Row Based”). 3. Mar de puertas (“Sea-of-Gates”). 4. PLDs Jerárquicos (Hierarchical PLD). 8 Figura 2.2: Estructuras de FPGAS [8] CLBs: Bloques Lógicos Configurables Cada CLB presenta una sección de lógica combinacional programable y registros de almacenamiento: Figura 2.3: Estructuras de CLB [8] Los registros de almacenamiento sirven como herramientas en la creación de lógica secuencial. La sección de lógica combinacional suele consistir en una LUT (“Look Up Table”), que permite implementar cualquier función booleana a partir de sus variables de entrada. Se presentan también multiplexores y conmutadores, como elementos adicionales de direccionamiento de los datos del CLB, los cuales permiten variar el tipo de salidas (com- 9 binacionales o registradas), facilitan caminos de realimentación, o permiten cambiar las entradas de los biestables. Bloques entrada/Salida (I/OBs) La periferia del FPGA está constituida por bloques de entrada/salida configurables por el usuario. Cada bloque puede ser configurado independientemente para funcionar como entrada, salida o bidireccional, admitiendo también la posibilidad de control triestado. Los IOBs pueden configurarse para trabajar con diferentes niveles lógicos (TTL, CMOS,…). Además, cada IOB incluye flip-flops que pueden utilizarse para registrar tanto las entradas como las salidas. Líneas de interconexión Constituyen un conjunto de caminos que permiten conectar las entradas y salidas de los diferentes bloques. Están constituidas por líneas metálicas de dos capas que recorren horizontal y verticalmente las filas y columnas existentes entre los CLBs. Dos elementos adicionales participan activamente en el proceso de conexión: Puntos de Interconexión Programable PIP (“Programmable Interconnection Point”) que permiten la conexión de CLBs e IOBs a líneas metálicas cercanas. Matrices de interconexión SW (“ Switch Matrix o Magic Box”) que son dispositivos de conmutación distribuidos de forma uniforme por la FPGA. Figura 2.4: Líneas de interconexión [9] Los diferentes modelos comerciales se diferencian en [8]: • Arquitectura: Gate Array (Filas), Mar de puertas, Matriz simétrica. • Tipo de CLB: Puertas lógicas, multiplexores, tabla de búsqueda (LUT). 10 • Arquitectura de las interconexiones: Canales de routing, red de interconexión. • Tecnología de la programación: antifusibles, memoria no volátil (EPROM, EEPROM), memoria FLASH (RAM, FLASH). A continuación se presentan una tabla con los principales fabricantes de FPGAs y sus características [8]: Figura 2.5: Fabricantes de FPGAs [8] Ventajas y Desventajas de los FPGAs con respecto a otras tecnologías Las ventajas que poseen los FPGAs en el área de diseño de circuito digital son las siguientes [15]: • Reducción del tiempo de introducción al mercado de productos. • Habilidad de ser reprogramados después de haber salido al mercado a fin de corregir posibles errores, y reducir los costos de investigación, diseño y pruebas de un nuevo producto. • Facilidad de diseño, en la mayoría de las FPGAs se pueden encontrar funciones de alto nivel (como sumadores y multiplicadores) embebidas en la propia matriz de interconexiones, así como bloques de memoria. • Mayor densidad de los elementos lógicos programables en puertas lógicas equivalentes, en el orden de cientos de miles hasta millones de ellas, que otras tecnologías. • Mayor flexibilidad debido a su arquitectura y la enorme libertad disponible en la interconexión. 11 Las desventajas que poseen los FPGAs en el área de diseño de circuito digital son las siguientes [15]: • Son generalmente más lentos. • No pueden soportar diseños muy complejos. • Consumen más energía. 2.4 Flujo de diseño mediante FPGAs utilizando las herramientas de Xilinx La figura muestra el diagrama de flujo para el diseño de sistemas implementados sobre FPGAs de Xilinx. El proceso de diseño se divide en cuatro fases: descripción del modelo, síntesis, implementación y programación [8]. Figura 2.6: Flujo de diseño mediante FPGAs [8] Al finalizar cada una de las fases es preciso comprobar la validez del diseño mediante simulación, utilizando distintos tipos de simulación en cada una de ellas [11]: • Simulación funcional RTL para validar el modelo creado. • Simulación funcional post-síntesis a nivel de puertas para validar el modelo sintetizado. • Simulación temporal post-implementación para validar la implementación del modelo implementado. 12 • Verificación en circuito. El banco de pruebas creado para validar el modelo es único, siendo utilizado en todos los tipos de simulación mencionados. Las dos últimas son simulaciones a nivel de puertas, ya que el diseño esta expresado como una descripción estructural HDL en términos de las celdas de la tecnología destino para la que se va a implementar. Creación del modelo El primer paso consiste en crear un modelo RTL del diseño que se pretende realizar. Para ello se puede utilizar: • Un lenguaje de descripción de Hardware HDL (“Hardware Description Language”) como: Verilog, VHDL y ABEL. • Un esquemático. El diseño puede contener: • Código HDL genérico que describe lógica independiente de la tecnología donde se va a implementar. • Componentes con instancias propias de la arquitectura del dispositivo en el que se va a implementar. Para el caso de utilización de componentes propios de la arquitectura del dispositivo el sintetizador obtiene la descripción de dichos componentes de la biblioteca de celdas de la tecnología destino. El formato de esta biblioteca dependerá de la herramienta de síntesis utilizada. Antes de proceder a la síntesis del diseño es preciso verificar el modelo creado mediante una simulación funcional la cual se puede construir con Test Bench Wave Form Editor (Editor de Formas de Onda de Prueba) de Xilinx. También se pueden crear archivos con restricciones temporales o espaciales para la síntesis. Síntesis del modelo 13 Una vez validado el modelo creado se procede a la síntesis de éste para lo cual se utiliza la herramienta de síntesis de Xilinx: XST [18]. El resultado de la síntesis es una lista de conexiones en formato NGC propio de Xilinx (anteriormente XNF). Si en el proceso de síntesis se fijan restricciones de diseño (topológicas o temporales) que afectan al proceso de implementación éstas se exportan en la propia lista de conexiones. Para comprobar los resultados de la síntesis es preciso realizar una simulación funcional (retardos unitarios) a nivel de puertas. El procedimiento a seguir es similar a la simulación funcional RTL. Implementación del modelo Una vez sintetizado el diseño se procede a su implementación. La implementación en Xilinx consta de cuatro pasos [18]: 1. Traslate – Traducción: En esta fase, se enlazan los ficheros de lista de conexiones (EDIF, NGC, XNF) creando un único fichero de salida en el que queda reflejada la jerarquía citada. El formato de este fichero de salida se denomina: NGD (Native Generic Design) y contiene componentes lógicos: puertas lógicas, biestables, RAMs, etc. 2. Map – Mapeo: En esta etapa se mapean los componentes lógicos en los componentes físicos de que dispone la FPGA: tablas LUT, biestables, buffers triestado, etc. A continuación se encapsulan estos componentes físicos en bloques configurables (CLBs e IOBs), creando un fichero de salida en formato NCD (Native Circuit Design). 3. Place and Route – Posicionamiento y Ruteo: En esta etapa se pasa a realizar el posicionamiento e interconexión de los bloques configurables en el FPGA y se genera un fichero de lista de conexiones en formato NCD. Una vez finalizado este proceso se dispone de toda la información de retardos internos (elementos activos e interconexiones) y se puede realizar de nuevo un análisis estático de tiempos esta vez con todos los datos de retardos internos. Después de realizar estas fases se obtiene la información para realizar simulaciones temporales del diseño completo y se puede 14 crear un archivo HDL estructural con base en los componentes físicos de la FPGA y un fichero SDF con los retardos internos del FPGA. Utilizando estos ficheros se puede realizar la verificación del diseño final mediante una simulación temporal HDL post-síntesis. 4. Programming File Generation – Generación del archivo de programación: Finalmente en esta fase se genera el fichero BIT de configuración de la FPGA. Programación Una vez que se genera el archivo BIT se procede a configurar el dispositivo. Durante la configuración se descargan los archivos de programación desde una computadora anfitriona al dispositivo FPGA de Xilinx. 2.5 Introducción a la codificación de predicción lineal (LPC) de la voz humana Este método de predicción lineal se utiliza para el análisis y síntesis de la voz humana. Este modelo supone que el tracto vocal se puede describir de la siguiente forma [3]: Frecuencia del Pitch Generador de pulsos periódicos Selector de voz con o sin sonido Filtro IIR todo polos Señal de voz Generador de Ruido Blanco Figura 2.7: Modelo del tracto vocal [3] El filtro lineal IIR todo polos, tiene la siguiente función de transferencia: H ( z) = G M 1 − ∑ ai z i =1 (1) −i 15 Donde i es el número de polos, G la ganancia del filtro y ai son los parámetros de los polos. A este filtro se le conoce también como filtro LPC (Lineal Predictive Coding) [18]. Existen dos funciones de excitación mutuamente exclusivas que modelan los sonidos con voz (periódica con periodo igual al pitch) y los sonidos sin voz (ruido blanco). Se supone que cada muestra es una combinación lineal de las muestras anteriores. Los coeficientes del filtro se calculan para minimizar el error cuadrático entre la muestra actual y su predicción. Se trabaja sobre bloques de 20 ms de voz, sobre lo que se conoce como modelo corto, donde las características de la voz se suponen que no varían con el tiempo en intervalos pequeños. Esos bloques se analizan para determinar los coeficientes de predicción. Estos se cuantifican y se envían al receptor junto con otros parámetros. Los parámetros que se envían son: los coeficientes del filtro (coeficientes de predicción y ganancia), la intensidad de la excitación, un bit que indica si la excitación es un sonido sin voz ó un sonido con voz, y, en caso de ser este último, la frecuencia de la excitación del formante (pitch) [3]. Figura 2.8: Esquema de codificación LPC [3] Con esta información el decodificador puede reconstruir la señal fuente, la cual hace pasar por el filtro, obteniéndose la voz sintetizada. En el decodificador, los sonidos con voz se obtienen al pasar una serie de impulsos periódicos con la misma frecuencia e intensidad de la formante por el filtro (caracterizado por los coeficientes de predicción). Los sonidos sin voz se obtienen al pasar por el filtro ruido aleatorio con la amplitud de la excitación [3]. 16 Figura 2.9: Esquema de decodificación LPC [3] Típicamente, el periodo del pitch requiere 6 bits y el parámetro de la ganancia se puede representar con 5 bits. Los coeficientes de predicción requieren entre 8 y 10 bits por coeficiente para una representación precisa. Si se utiliza un modelo de décimo orden el número de bits asignado por segmento es 82, con segmentos de 20ms se obtiene un bit rate de 4,6 kbps que es muy bajo con respecto a PCM (64Kbps), donde se observa la compresión que se obtiene con este procesamiento [3] . Hoy día se puede codificar la voz con LPC a velocidades entre 2.4 y 4.8 kbps con una señal de voz reconstruida con una calidad razonable. LPC basa su funcionamiento en dos tipos de sonidos: con voz y sin voz, sin embargo otros tipos de sonidos existentes no se pueden reproducir con este método, resultando esto en la producción de una voz artificial y es imposible reconocer, a partir de la voz sintetizada, a la persona que la origina [10]. CAPÍTULO 3: Planteamiento de un procedimiento basado en herramientas de código abierto En la sección 1.4, se presentó el flujo de diseño de los FPGA de Xilinx. Este procedimiento presenta ciertamente varias ventajas: • Estabilidad: las herramientas que se utilizan han sido ampliamente probadas y se encuentran en una etapa estable donde es difícil encontrar un error de programación y el fabricante provee soporte en caso de encontrar alguna falla. • Optimización: las herramientas fueron diseñadas por el fabricante para obtener el máximo provecho de las capacidades del FPGA. Sin embargo, está claro que el procedimiento fue concebido para FPGAs de la marca Xilinx, de donde surgen las siguientes desventajas: • Falta de compatibilidad y portabilidad: las herramientas se diseñaron específicamente para FPGAs de Xilinx, durante las diferentes etapas del flujo se generan archivos con formatos propietarios, esto impide que los resultados se puedan utilizar con otras herramientas EDA de otro fabricante y que los diseños no se puedan redireccionar a otras marcas o tecnologías. • Falta de flexibilidad: no es posible modificar las herramientas para obtener nuevos resultados durante el flujo de diseño. Desde el punto de vista académico no permite que la Universidad desarrolle y aporte conocimientos en esta área. El estudiante aprende solo a desarrollar circuitos digitales para FPGAs de Xilinx. A partir de estas desventajas se plantea un procedimiento para diseño e implementación de circuitos digitales concebido en forma generalizada, en el cual sea posible seleccionar la tecnología en la cual se va a implementar el diseño y que los resultados obtenidos durante el proceso sean estándares de la industria que provean de portabilidad y flexibilidad. Además este procedimiento debe permitir que el estudiante pueda realizar modificaciones y mejoras a las herramientas. Bajo estas ideas se presenta el siguiente flujo de diseño: 17 18 Creación del Diseño Compilación (Icarus Verilog) Simulación Funcional (Icarus Verilog - GTK Wave) Síntesis (Icarus Verilog) VLSI ASIC’s CPLD FPGA Xilinx Altera, Amtel, Actel,Lattice, otros Simulación Lógica (Icarus Verilog / GTK Wave) Implementación (Xilinx WebPack) Verificación Temporal (GTK Wave) Programación (Xilinx WebPack) Verificación en circuito Figura 3.1 Flujo de diseño basado en herramientas EDA de código abierto El flujo se inicia con una etapa de diseño, compilación y simulación funcional. Se crea un modelo ideal independiente de la tecnología donde vaya a implementar el circuito digital. En la etapa de síntesis se presenta la principal característica del flujo, donde es posible seleccionar la tecnología para implementar el proyecto. En esta etapa de síntesis se decide la tecnología en la que se va a implementar el proyecto y se realiza el proceso mediante las especificaciones de la tecnología seleccionada. Una vez que se obtenga la síntesis del diseño, se continuará con los pasos necesarios para la implementación física que dependerá de la tecnología seleccionada. 19 Como se observa en la figura 3.1, se seleccionaron dos herramientas EDA para el desarrollo de este flujo: Icarus Verilog y GTKWave. Estas herramientas se seleccionaron ya que satisfacían las necesidades del procedimiento planteado. Icarus Verilog es una herramienta de simulación y síntesis de Verilog, lenguaje de HDL estándar (IEEE-1364). Para el proceso de síntesis utiliza un formato estándar llamado EDIF independiente de la tecnología. También permite la generación de archivos VCD, un formato estándar especificado en IEEE-1364 para análisis de modelos de simulación de Verilog. GTKWave es un analizador de formas de ondas. Permite visualizar las formas de ondas de simulaciones en diferentes formatos, como el formato VCD. Esta herramienta complementa a Icarus Verilog para simulaciones funcionales, lógicas y temporales. Ambas herramientas son de código abierto y están asociadas al proyecto de herramientas EDA open source: gEDA. Está condición da la libertad a la UCR para modificar y mejorar las herramientas con el fin de conseguir una mayor eficiencia y aportar en la automatización del desarrollo de circuitos digitales. Ambas herramientas, se encuentran disponibles para: Windows, Linux y otras plataformas. Sin embargo estas herramientas poseen ciertas debilidades como toda herramienta de código abierto: • Estas herramientas no poseen soporte y se utilizan bajo propio riesgo. • No están completamente terminadas y es posible encontrar errores de programación. Este proyecto utiliza las herramientas de forma exhaustiva para verificar que tienen la capacidad para desarrollar circuitos digitales de cualquier tipo y tamaño. Para cumplir con este propósito se seleccionó el desarrollo de un codificador/decodificador de voz que utiliza el modelo de predicción lineal de la voz humana. Esta aplicación contaba con las condiciones necesarias de tamaño y complejidad para estresar las herramientas y revelar sus limitaciones. 20 Como primer paso, en este proyecto se utilizó este procedimiento y las herramientas para la tecnología FPGA de Xilinx para comprobar que se puede llegar a resultados equivalente a los obtenidos con las herramientas propias del fabricante. En lo posterior, se presentan los resultados obtenidos en cada etapa del procedimiento y que permitieron elaborar la guía presentada en el apéndice E. Esta guía documenta con detalle cada paso del flujo y el uso de las herramientas Icarus Verilog y GTKWave. Además se explican las limitaciones y las soluciones a los errores que se pueden presentar durante el proceso. CAPÍTULO 4: Diseño del codificador/decodificador de voz En este capítulo se presenta en alto nivel la arquitectura del codificador/decodificador de voz que se diseñó para ejecutar el procedimiento planteado. Se revisan las características, los componentes y los flujos principales del diseño. Para mayor detalle se puede revisar el apéndice A y los archivos de Verilog adjuntados. 4.1 Descripción general Se diseñó un codificador/decodificador de voz, que permite realizar grabaciones de voz por ocho minutos y hacer reproducciones mediante dos tipos de codificaciones: PCM y codificación predictiva lineal (LPC). La voz es filtrada mediante un filtro pasivo RC de un polo para limitar el ancho de banda y muestreada de forma uniforme a una frecuencia de muestreo de 8kHz (satisface el teorema de Nyquist). Se utilizaron 14 bits para la conversión analógica-digital y las muestras se almacenaron en una memoria RAM dinámica. Para realizar la codificación predictiva lineal se utilizaron tramas de voz de 20 milisegundos y diez coeficientes de predicción lineal. Todos los cálculos se realizan en punto flotante en precisión simple (32bits) bajo el estándar IEEE 754. Para la reproducción se utilizaron 12 bits para la conversión digital-analógica y un retenedor de orden cero. 4.2 Componentes El codificador/decodificador de voz posee los siguientes componentes: • Pre-amplificador programable, modelo LTC6912-1, marca Linear Technology. • Convertidor analógico-digital, modelo LTC1407A-1, marca Linear Technology. • Convertidor digital-analógico, modelo LTC2624, marca Linear Technology. • Memoria RAM dinámica, modelo MT46V32M16, marca Micron. • Oscilador de reloj, modelo SG-8002JF, marca EPSON. • FPGA, modelo XC3S1600E-FG320-4, marca Xilinx 21 22 Todos estos elementos se encuentran interconectados en la tarjeta de desarrollo: Spartan-3E Starter-kit de Xilinx. Dentro del FPGA se desarrollaron los siguientes circuitos digitales que permitieron verificar el procedimiento planteado: Para control de interfaces y almacenamiento Controlador A/D Controlador Controlador de Controlador de Re- Memoria RAM está- D/A Memoria producción tica 160X32 Coeficientes R Coeficientes LPC Para codificación/decodificación predictiva lineal Controlador de Codifi- Sonido con/sin Detección del cación voz pitch Filtro de análisis Filtro de síntesis Para cálculo en punto flotante en 32 bits (FPU) Sumador/Restador Multiplicador Divisor Raíz Cuadrada Tabla 4.1 Circuitos diseñados para el codificador/decodificador de voz A continuación se presenta un diagrama de bloques del diseño: 23 Figura 4.1 Diagrama de bloques del diseño 4.3 Diagrama de estados general A continuación se presenta el diagrama estado general del codificador/decodificador de voz: 24 S0: Estado Inicialización S1: Estado Listo S2: Estado Grabando S3: Estado Codificacion/Decodificación Automática S4: Estado Reproducción PCM Rotativa S5: Estado Reproducción LPC Rotativa Reset S0 S1 S3 Listo no si Grabar ? si Memoria Llena ? S2 no no Reproducir ? no Continuar ? si si Codificar ? si no S4 Continuar ? no S5 si Continuar ? si no Figura 4.2 Diagrama de estado general del diseño La señal Reset inicializa el sistema y se entra al estado S0 donde se inicializan las máquinas de estado y se configuran los dispositivos externos al FPGA. Cuando se termina esta fase se pasa en forma incondicional al S1 donde el sistema se encuentra listo para operar y se indica con la señal Listo. En este estado se revisan las señales Grabar y Reproducir. Si la señal Grabar está en alto, se pasa al estado S2 donde se graba y almacena las muestras de voz hasta que se llene la memoria o que se finalice la grabación bajando la señal Grabar. Inmediatamente se continúa al estado S3 donde se realiza una codificación predictiva lineal de las muestras, seguidamente se decodifican y se almacenan listas para reproducirse. Si la señal Reproducir está en alto, se revisa la señal Codificar. Si la señal Codificar esta en bajo, se pasa al estado S4 donde se reproduce la voz con la codificación PCM hasta que la señal Reproducir baje. Si la señal Codificar está en alto, se pasa al estado S5 donde 25 se reproduce la voz con la codificación LPC hasta que la señal Reproducir baje. Se reproduce en forma repetida hasta que la señal Reproducir baje. La señal Grabar tiene prioridad sobre la señal Reproducir si ambas están en alto al mismo tiempo. No es posible grabar y reproducir al mismo tiempo. 4.4 Descripción de los circuitos digitales A continuación se describen los circuitos digitales que se diseñaron: Para control de interfaces y almacenamiento: Controlador del convertidor analógico-digital Consiste en una máquina de estado y una asignación de registros, que inicializa y configura el pre-amplificador programable y el convertidor analógico-digital. Controla la frecuencia de muestreo a 8kHz de la señal de voz entrante y posee la interfaz para introducir las muestras de voz de 14 bits del convertidor A/D al FPGA. Controlador del convertidor digital-analógico Consiste en una máquina de estado y una asignación de registros, que inicializa y configura el convertidor digital-analógico. Controla la frecuencia de reproducción a 8kHz de la voz saliente y posee la interfaz para llevar las muestras de voz de 12 bits del FPGA al convertidor D/A. Controlador de memoria RAM dinámica Consiste en una máquina de estado y una asignación de registros, que inicializa y configura la memoria RAM dinámica para el almacenamiento de muestras de voz. Realiza el proceso de inicialización de la memoria. Controla los periodos de refrescamiento de la memoria. Permite realizar escrituras y lecturas de datos, solo un dato a la vez. Controlador de reproducción Consiste en una máquina de estado y una asignación de registros, posee la interfaz con las señales de control disponibles para el usuario. Se encarga de almacenar las muestras que provee el controlador de convertidor A/D en el banco 1 de la memoria RAM a través del controlador de memoria durante la grabación. Controla el controlador de codificación 26 para que se ejecute el procedimiento de predicción lineal. Durante la reproducción según la codificación seleccionada lleva las muestras del banco 1 (PCM) o 2 (LPC) de la DRAM al controlador de convertidor D/A. Memoria RAM estática 160X32 Consiste en una memoria Ram estática de 160x32, que permite el almacenamiento temporal de 160 muestras de voz en 32 bits, que corresponde a la trama de voz que es analizada. Posee una escritura sincrónica y una lectura asincrónica. Para codificación/descodificación predictiva lineal: Controlador de codificación. Consiste en una máquina de estado y una asignación de registros, que convierte tramas de voz de 20 ms (160 muestras a 8kHz) almacenadas en la memoria DRAM en 14 bits, al formato de punto flotante en 32 bits. Se encarga de mover cada trama de voz convertida a la memoria RAM estática para aplicarle el procedimiento LPC. Controla las máquinas de estado para realizar el procedimiento de codificación predictiva lineal, tanto la codificación como la decodificación. Sonido con/sin voz Consiste en una máquina de estado y una asignación de registros, que analiza la trama de voz en la memoria RAM estática con el procedimiento llamado “Cruce por cero” para determinar si la muestra de voz se caracteriza como un sonido con voz o sin voz. Se utiliza un umbral de 25 cruces para su identificación. Si el resultado es un sonido con voz, controla la máquina de estado “Detección del pitch”. Detección del pitch Consiste en una máquina de estado y una asignación de registros, que analiza la trama de voz en la memoria RAM estática con el procedimiento llamado AMDF (Average Magnitude Difference Function) para determinar el periodo del pitch de la muestra de voz. Coeficientes R: Cálculo de los coeficientes de autocorrelación 27 Consiste en una máquina de estado y una asignación de registros, que analiza la trama de voz en la memoria RAM estática y calcula los coeficientes de autocorrelación. Se obtienen 11 coeficientes. Esta máquina controla la máquina de estado “Coeficientes LPC”. Coeficientes LPC: Cálculo de los coeficientes de predicción lineal Consiste en una máquina de estado y una asignación de registros, que utiliza los coeficientes R de autocorrelación y calcula los 10 coeficientes de predicción lineal mediante el método Levinson-Durbin. Filtro de análisis Consiste en una máquina de estado y una asignación de registros, constituye el filtro de análisis del método LPC. Filtra la trama de voz en la memoria RAM estática y obtiene el error y la ganancia a partir de los coeficientes de predicción lineal. Filtro de síntesis Consiste en una máquina de estado y una asignación de registros, constituye el filtro de síntesis del método LPC. Utiliza los parámetros obtenidos para decodificar la trama de voz que fue analizada. Se construye el filtro mediante los coeficientes LPC y la ganancia. La entrada del filtro puede consistir en ruido gaussiano que se encuentra pre-almacenado en una ROM o una señal de pulsos con la frecuencia del pitch. La selección de la entrada se realiza con la detección de un sonido con/sin voz. Convierte los resultados obtenidos de 32 bits a 14 bits y lo almacenada en el banco 2 de la DRAM para reproducción. Para cálculo en punto flotante en 32 bits: Sumador/Restador/Multiplicador/Divisor/Raíz Cuadrada Consisten en una máquina de estado y una asignación de registros por cada operación aritmética, que ejecuta la operación correspondiente de dos operandos en 32 bits, excepto la raíz cuadrada que ocupa solo un operando de 32 bits. Se utiliza el estándar IEEE754 de precisión simple para realizar el cálculo de los resultados. El resultado es truncado y se da en el mismo formato que los operandos. Se puede ejecutar una operación a la vez. Las operaciones que generan overflows o los underflows se resuelven dando como resultado el numero más grande y el numero más pequeño respectivamente que permite el estándar. En el 28 caso de la división por cero se resuelve dando como resultado el número más grande posible. 4.5 Arquitectura de las máquinas de estado y de la asignación de registros Para el diseño de las máquinas de estado se utilizaron dos tipos de arquitectura: un flip-flop por estado (“One-hot”) y microprogramación. La arquitectura micro-programada se utilizó para los circuitos cuya frecuencia de reloj no era importante como el controlador A/D y D/A ya que la frecuencia de muestreo es muy baja. Para los demás circuitos se utilizó la arquitectura one-hot para obtener una frecuencia de reloj alta para el procedimiento de predicción lineal a cambio de más flip-flops por máquina y mayor consumo de potencia. Entrada n Estado n Entrada 1 Estado 1 Entrada 0 Estado 0 Para la asignación de registros (datapath), se usó la siguiente arquitectura: Figura 4.3 Arquitectura de la asignación de registros 4.5.1 Protocolo de comunicación entre circuitos Para la comunicación entre circuitos digitales se utilizó un Full Handshake completamente sincrónico con el reloj de referencia como se muestra a continuación: 29 Figura 4.4 Protocolo de comunicación entre los circuitos Las máquinas se pueden utilizar si la señal listo está en alto. Se inician con la señal inicio. La máquina iniciada indica su estado ocupado bajando la señal listo y la máquina que la controla puede bajar la señal inicio. Cuando la máquina termina lo indica subiendo listo, todos los cambios se realizan en los flancos negativos del reloj de referencia. 4.5.2 Protocolo de cambio de estado y asignación de estado Se definió la siguiente convención: Todas las máquinas de estado cambian de estado en los flancos positivos del reloj de referencia y las asignaciones de los registros se realizan en los flancos negativos de reloj. A continuación se muestra la convención definida: Figura 4.5 Protocolo de cambio de estado y asignación de estado CAPÍTULO 5: Compilación y Simulación Funcional En este capítulo se explica la forma en que se realizó la compilación y simulación funcional de los circuitos digitales descritos en Verilog por separado y después en conjunto. 5.1 Descripción en Verilog El diseño del codificador/decodificador de voz se describió en Verilog. La descripción se realizó en forma conductual y de forma jerárquica. Cada circuito se describió, en general, utilizando dos módulos de la siguiente forma: Figura 5.1 Estructura de la descripción en Verilog para los circuitos diseñados El primer módulo consiste en la máquina de estados con la arquitectura correspondiente y el segundo con la asignación de registros. A continuación se presenta los nombres de módulos en Verilog: Nombre del Circuito Módulos en Verilog Controlador A/D AD_controlador.v AD_registros.v Controlador D/A DA_controlador.v DA_registros.v Controlador de Memoria mem_controlador.v mem_registros.v Controlador de Reproducción repro_controladorv2.v repro_registros.v Controlador de Codificación CODE_controlador.v CODE_registros.v Sonido con/sin Voz Cruce_controlador.v Cruce_registros.v Detección del Pitch Pitch_controlador.v Pitch_registros.v Coeficientes R R_controlador.v R_registros.v Coeficientes LPC C_controlador.v C_registros.v Filtro de Análisis FG_controlador.v FG_registros.v Filtro de Síntesis FPR_controlador.v FPR_registros.v Sumador/Restador microcontrolador.v asignacion_registros.v Multiplicador multiplicador_controlador.v multiplicador_registros.v Divisor divisor_controlador.v divisor_registros.v 30 31 Raíz Cuadrada raiz_controlador.v ROM de Ruido ruido.v Memoria RAM Estática 160x32 ram.v raiz_registros.v Tabla 5.1 Nombre de los módulos en Verilog para cada circuito La estructura jerárquica que se estableció fue la siguiente: Controlador A/D Controlador D/A Controlador de Memoria Controlador de Memoria Controlador de Reproducción Controlador de Codificación Filtro de análisis Módulo principal Módulo Coeficientes R y LPC Módulo FPU Sumador/ Restador Multiplicador Divisor Raíz Cuadrada Coeficientes R Coeficientes LPC Módulo Sonido y Pitch Sonido con/sin Voz Detección del Pitch Filtro de síntesis ROM Ruido Figura 5.2 Estructura jerárquica establecida para el proyecto En un principio la descripción en Verilog se realizó con las reglas básicas que se deben respetar para cualquier proceso de síntesis en Verilog. A continuación se mencionan [6]: • No modificar una variable en dos procesos diferentes. • En una asignación procedural, todas las variables de las que dependa la asignación deben aparecer en la lista de sensibilidad, para evitar inferencia equivocada de latches. • No realizar asignaciones al mismo tiempo donde una depende de la otra. • No se admiten procesos initial. • No se admiten algunos operadores como la división. En esta etapa se utilizaron estas reglas con el fin de asegurar una síntesis exitosa. Pos- teriormente se encontraron problemas con el sintetizador de Icarus Verilog donde se tuvo que modificar la descripción en Verilog y el diseño para resolverlos. La estructura jerárquica establecida permitió aislar fácilmente los problemas. 32 En el capítulo 6, se hace una caracterización del sintetizador en Icarus Verilog y se discute las limitaciones y problemas que se encontraron en la herramienta. 5.2 Etapa de Compilación y Simulación Funcional En esta etapa se comprobó en forma individual y grupal que los módulos en Verilog no tuvieran ningún error de sintaxis y alguna directiva no soportada por Icarus Verilog. Para este proyecto se utilizó la versión 8.6 para Windows. Todos los comandos se ejecutaron en la consola, como por ejemplo para la compilación del circuito completo: %iverilog –o REP.vvp –c REP.prj Donde iverilog invoca a la herramienta Icarus Verilog, REP.prj es el nombre del archivo con las direcciones a los archivos fuente .v y la opción -o define el nombre del archivo que va a contener el ejecutable de simulación que este caso se va a llamar REP.vvp. 5.2.1 Simulación funcional La simulación funcional verifica que la descripción en Verilog del circuito digital sea la correcta y que su comportamiento funcional satisface las especificaciones. Para realizar las simulaciones funcionales se utilizó el siguiente esquema: Figura 5.3 Esquema jerárquico para simulación funcional Se creó un módulo llamado banco de pruebas para cada circuito diseñado. De esta forma todas las sentencias que tenían que ver con la simulación quedaron definidas dentro de este módulo y posteriormente se utilizó solo el módulo con el diseño para el proceso de síntesis. Cada banco de pruebas posee un conjunto de estímulos que simula el entorno alrededor del circuito. Se ejercitó cada circuito por separado para comprobar su funcionalidad de 33 forma ideal ya que no emplearon retardos temporales, esto para que las simulaciones durante la implementación coincidieran. Para los circuitos de control de interfaces y almacenamiento, los bancos de pruebas se desarrollaron de forma tal que simularan el comportamiento del dispositivo externo. En el caso de la memoria DRAM se utilizaron las descripciones en Verilog que provee el fabricante, Micron, que facilitó y aseguró la simulación funcional del controlador de memoria. Para cada circuito se obtuvo un archivo VCD y se utilizó para comprobar que los cambios de estados y las asignaciones a registros fueran correctos en la simulación. Figura 5.4 Simulación funcional del controlador de memoria DRAM en GTKWave Para los circuitos de cálculo en punto flotante en 32 bits (FPU) se emplearon pruebas para ejecutar operaciones con casos esquinas básicas y conjuntos de operaciones aleatorias. No se hizo una validación exhaustiva puesto que se salía de los objetivos del proyecto. Para las pruebas con operaciones aleatorias se utilizó Matlab para generar los archivos binarios en precisión simple y se consideró como el resultado ideal. Sin embargo los resultados de Matlab eran redondeados a diferencia de los circuitos diseñados cuyo resultado es truncado. Por lo que en los resultados de las simulaciones se aceptaron errores por redondeo con respecto al resultado ideal (Matlab). A continuación se muestra los resultados de las simulaciones para el divisor: 34 Figura 5.5 Simulación funcional del divisor de 32bits Similarmente, para los circuitos de codificación/decodificación predictiva lineal se desarrollaron bancos de pruebas que utilizaban tramas de 20ms de señales senoidales. Además de las simulaciones individuales, se desarrollaron dos simulaciones intermedias: • Los circuitos de predicción predictiva lineal en conjunto para comprobar el algoritmo LPC. • Los circuitos de interfaz y almacenamiento en conjunto para comprobar la grabación, almacenamiento y reproducción. Finalmente se realizó una simulación del circuito completo para comprobar el funcionamiento global del sistema. Para este tipo de simulaciones se tuvo que limitar los niveles en las jerarquías de los módulos que se iban a acceder para la creación del archivo VCD, ya que el archivo se volvía muy grande debido a la duración de la simulación y la cantidad de señales por jerarquía. También, para disminuir el tiempo y tamaño de la simulación se utilizaron tramas de voz pequeñas, se aumentó la frecuencia de muestreo y solo se simuló una trama a la vez por simulación. Según el tamaño del archivo VCD (entre 0.5 y 1 GB), así duraba la aplicación GTKWave en abrirlo y se veía limitado por la memoria de la computadora donde se corría la aplicación (para el proyecto se utilizó una computadora portátil con 1 GB de memoria RAM, un procesador Pentium M de 1.8 GHz). 35 Figura 5.6 Simulación funcional del codificador/decodificador de voz en GTKWave Estas etapas de descripción, compilación y simulación funcional se realizaron reiteradamente debido a los cambios ocasionados por el proceso de síntesis. CAPÍTULO 6: Síntesis en Icarus Verilog En este capítulo se describe el proceso de síntesis con Icarus Verilog y específicamente para la arquitectura Virtex de Xilinx para la cual se realizó este proyecto. Se presentan las características del sintetizador y las limitaciones que se encontraron en la herramienta. Se hace referencia la implementación sobre el FPGA SPARTAN-3E y la tarjeta de desarrollo SPARTAN-3E Starter-Kit Board. 6.1 Descripción del proceso de síntesis con Icarus Verilog La síntesis es el proceso de mapear y optimizar una descripción en HDL de alto nivel a una tecnología de compuertas (compuertas lógicas, latches, flip-flops, etc.). A continuación se presenta este proceso en general de síntesis para la herramienta Icarus Verilog que se definió como resultado de este proyecto: Figura 6.1 Proceso de Síntesis con Icarus Verilog Descripción en HDL: consiste en la descripción del diseño en Verilog. Se debe utilizar un subconjunto de instrucciones soportadas por el sintetizador de Icarus Verilog. Librería de tecnología: el sintetizador de Icarus Verilog posee información acerca de la descripción funcional de celdas para la arquitectura Virtex (Xilinx), Virtex2 (Xilinx) y LPM (estándar genérico). El fabricante de la arquitectura provee documentación de la librería y de las celdas disponibles. En este caso, el sintetizador es limitado y conoce un subcon36 37 junto de las celdas de la arquitectura por lo que el resultado no siempre está optimizado. También no posee información temporal de la arquitectura por lo que no se obtienen resultados de análisis temporal. Restricciones y Parámetros: Es información adicional acerca de las características físicas del diseño, como asignación de pines, estándar de voltaje de salida y entrada, periodo de reloj, ubicación de celdas, entre otros. Esta información es provista por el fabricante de la arquitectura. Icarus Verilog permite indicar ciertos parámetros y restricciones en forma limitada directamente en el archivo de Verilog. Netlist: es un archivo de texto que describe los componentes y la conexión física entre ellos para la implementación del diseño y es el resultado final del proceso. Icarus Verilog utiliza el formato estándar EDIF, versión 2. Debido a las limitaciones de Icarus Verilog y a las características propias del circuito digital, es posible que el archivo EDIF resultante sea incompleto y que sea necesario editarlo para completar la síntesis. Esta edición principalmente se hace para agregar parámetros y restricciones no soportados. 6.2 Descripción del proceso de síntesis para la arquitectura Virtex 6.2.1 Características del sintetizador de Icarus Verilog La herramienta Icarus Verilog posee un compilador para sintetizar un código en Veri- log y transformarlo a formato EDIF. El compilador trabaja a nivel de sentencias always, asignaciones continuas y compuertas lógicas en Verilog. Por esta razón, estructuras como for, task, while, wait, repeat, initial no son sintetizables. Aún con estas limitaciones, se puede sintetizar diseños jerárquicos con circuitos combinacionales y secuenciales. Esto debido a que la sentencia always modela casi todo tipo de lógica digital. Por defecto se intenta sintetizar todas las instrucciones, sin embargo mediante directivas se identifica las estructuras que se desean sintetizar y cuales no. Desde el punto de vista formal de lenguaje, se probó con la descripción en Verilog del diseño que Icarus Verilog sintetiza para la arquitectura Virtex: 38 • Procesos always. 1. Operadores binarios aritméticos: suma (+) y resta (-). 2. Operadores relacionales: >=, <=, !=, ==. 3. Operadores lógicos: !, &&, ||. 4. Operadores lógicos de bit ~, &, |, ^. 5. Concatenaciones {,}. 6. Desplazamiento hacia la izquierda o derecha, con adición de ceros. 7. Estructuras de control: if-else y case (con anidaciones). 8. Asignaciones procedurales no bloqueantes. 9. Eventos de nivel y de flanco positivo. • Asignaciones continuas: 1. Operadores binarios aritméticos: suma (+) y resta (-). 2. Operadores relacionales: >=, <=, !=, ==. 3. Operadores lógicos: !, &&, ||. 4. Operadores lógicos de bit: ~, &, |, ^. 5. Concatenaciones: {,}. 6. Desplazamiento hacia la izquierda o derecha, con adición de ceros. 7. Condicional: ?: . • Compuertas lógicas: and, or, xor, nor, xnor, buf, not. • Utilización de parámetros. • Utilización de variables tipo: reg, wire, input, output, inout. Por otro lado, se probó mediante códigos de prueba en Verilog que Icarus Verilog no sintetiza: • Procesos initial. • Operadores aritméticos: multiplicación (*), división (/), modulo (%). • Operadores relacionales: >,<. • Operadores lógicos: ~|, ~&, ~^, ^~. 39 • Operadores lógicos de reducción: &, |, ^, ~&, ~|, ~^, ^~. • Eventos de flanco negativo. • Estructuras de control: for, while, repeat, wait. • Asignaciones procedurales bloqueantes. • Estructuras: Task y Function. • Compuertas lógicas: nand, bufif, notif. 6.2.2 Verilog sintetizable para la arquitectura Virtex Como se mencionó anteriormente existen ciertas normas para lograr una descripción sintetizable en Verilog. Según el sintetizador y el nivel de complejidad el código será sintetizable. Como resultado de este proyecto se presenta las capacidades que posee el sintetizador de Icarus Verilog. Para la comprobación de las capacidades del sintetizador se revisó los archivos EDIF de síntesis. La verificación se realizó manualmente puesto que no se encontró ninguna herramienta de código abierto que permitiera transformar el archivo EDIF a esquemático de forma satisfactoria. Esto constituye una de las debilidades del procedimiento planteado y una oportunidad para la Universidad para desarrollar una herramienta para este fin. Para empezar un proceso de síntesis dirigido a la arquitectura Virtex, se encontró que Icarus Verilog soporta un subconjunto de celdas de la librería de la arquitectura Virtex. La librería de celdas la provee Xilinx y se puede encontrar en el sitio web de Xilinx. El estudio de los esquemáticos y las funciones de las celdas ayudó a comprobar que el archivo EDIF de la síntesis utilizaba las celdas esperadas y que no aparecían celdas mal inferidas del código en Verilog. A continuación se presenta una lista de celdas que maneja Icarus Verilog según el código fuente de la herramienta: Celda Descripción BUFE BUFT Buffer tri-estado con habilitador activo en alto y en bajo respectivamente IBUF, OBUF, Buffer de entrada y salida individuales respectivamente 40 IPAD Puerto de entrada, salida y entrada/salida respectivamente BUF, INV Buffer e inversor de propósito general respectivamente FDCE, FDRE, FDCPE Flip-flop D de flanco positivo con habilitador de reloj VCC, GND Conexión a fuente y a tierra respectivamente LUT2,3,4 Tablas de búsqueda de salida general de 2,3,4 bits y salida general XORCY XOR con lógica de acarreo con salida general MUXCY_L , MUXF5,6 MUXCY BUFG * MULT_AND* Multiplexores 2 a 1 Buffer global de reloj AND de multiplicación rápida Tabla 6.1 Celdas de la librería Virtex que maneja Icarus Verilog Las celdas BUFG y AND_MULT son celdas que no se infieren directamente durante la síntesis sino que hay que indicarle al sintetizador que se va a utilizar este tipo de celda. Por otro lado no se encuentran disponibles celdas complejas presentes en la documentación del fabricante como: RAM16X1D, ROM16X1, DCM, OBUFT, MULT18X18SIO, ADD4 entre otras. En general, el subconjunto de celdas presentado que posee Icarus Verilog es suficiente para sintetizar la mayoría de circuitos digitales, sin embargo no se aprovecha al máximo la arquitectura. Para este proyecto fue necesario utilizar celdas no soportadas por Icarus Verilog. Sin embargo se encontró que la herramienta permite resolver el problema mediante directivas especiales. Descripciones sintetizables de lógica combinacional utilizando compuertas lógicas. El proceso de síntesis para compuertas lógicas con Icarus Verilog es muy directo, basta con describir la función lógica que se desea como en cualquier sintetizador. Icarus Verilog implementa funciones lógicas como: and, or, xor, nor, xnor, buf, not, excepto funciones con compuertas nand, bufif, notif. Sin embargo, este tipo de descripción prácticamente no se utilizó en la descripción del codificador/decodificador de voz. Este tipo de descripción se utilizó solo si se deseaba ser explícitos en la lógica y se quería utilizar una celda especial, como se verá más adelante. 41 Descripciones sintetizables de lógica combinacional utilizando asignaciones continuas. La otra forma de sintetizar funciones lógicas en Verilog es mediante asignaciones continuas. Es importante destacar que descripciones equivalentes con asignaciones continuas y con compuertas lógicas, conllevan a resultados distintos durante la síntesis. Según la descripción el sintetizador puede utilizar más compuertas durante el mapeo tecnológico que puede ocupar más espacio e influir en la velocidad del circuito durante la implementación. Descripciones sintetizables de lógica combinacional utilizando procesos always. Además de asignaciones continuas y compuertas lógicas para especificar lógica combinacional, en Verilog se puede utilizar sentencias de proceso como always, aunque la descripción parezca secuencial. Existen reglas básicas para describir lógica combinacional mediante sentencias always en Verilog. Se encontró que para Icarus Verilog se deben cumplir las siguientes: 1. El evento de la sentencia always de contener todas las variables de entrada de la función combinacional, conocida como lista de sensibilidad. 2. En caso de utilizar condiciones if, se deben anidar de forma tal que siempre sea if seguido de else-if y finalizar con else. No se permite utilizar if seguido de if o olvidar el else. Si se utiliza una estructura case se deben presentar todos los casos o utilizar el caso por defecto para completar las posibilidades. Si no se cumplen estas dos condiciones, Icarus Verilog genera un error en el proceso de síntesis, lo cual indica que la herramienta no infiere latches lo cual no tuvo ningún impacto en el diseño, ya que se utilizó solamente flip-flops. A continuación se presenta un ejemplo de la descripción en Verilog de un multiplexor 4 a 1 con ancho de palabra parametrizado sintetizable por Icarus Verilog: module mux4x1 (salida, seleccion,in0,in1,in2,in3); parameter ancho_palabra = 0; output [ancho_palabra:0] salida; reg [ancho_palabra:0] salida; 42 input [ancho_palabra:0] in0,in1,in2,in3; input [1:0] seleccion; always @(seleccion or in0 or in1 or in2 or in3) begin if (seleccion == 2'b00) salida <= in0; else if (seleccion == 2'b01) salida <= in1; else if (seleccion == 3'b10) salida <= in2; else salida <= in3; end endmodule Esta descripción presenta un proceso always donde en la lista de sensibilidad se encuentran todas variables de entrada del multiplexor (seleccion e in0..4). Seguidamente se presentan condiciones definidas por la variable seleccion. En este caso esta variable tiene un tamaño de 2 bits, por lo que existen 4 condiciones diferentes correspondientes a cada entrada del multiplexor. Se observa que se utiliza una estructura if, else-if y else donde se presentan todos los casos posibles. Es importante aclarar que aunque la variable salida es declarada como un registro, el sintetizador trata el proceso como lógica combinacional. También, para efectos de síntesis en Icarus Verilog siempre sintetiza las asignaciones procedurales como no bloqueantes, y no distingue entre asignaciones bloqueantes (=) y no bloqueantes (<=) aunque en simulación se obtengan resultados distintos al utilizar alguna de las dos formas. A continuación se muestra la sección contents del archivo EDIF y el esquemático correspondiente: 43 Figura 6.2 Archivo EDIF para multiplexor 4 a 1 (if-else) Figura 6.3 Esquemático del archivo de síntesis para multiplexor 4 a 1 (if-else) El multiplexor presentado anteriormente se puede describir utilizando una sentencia case, como se muestra a continuación: module mux4x1 (salida, seleccion,in0,in1,in2,in3); parameter ancho_palabra = 0; output [ancho_palabra:0] salida; reg [ancho_palabra:0] salida; input [ancho_palabra:0] in0,in1,in2,in3; input [1:0] seleccion; always @(seleccion or in0 begin case (seleccion) 0: salida = 1: salida = 2: salida = 3: salida = endcase or in1 or in2 or in3) in0; in1; in2; in3; 44 end endmodule Si se revisa el archivo EDIF de síntesis, la utilización de la sentencia case hace que el archivo de síntesis resultante sea más simple ya que se infieren celdas específicas de multiplexación, lo cual hace el circuito resultante mas óptimo en relación a retardos y espacio en comparación con la descripción basada en estructuras if anidadas como el ejemplo anterior. A continuación se muestra la sección contents del archivo EDIF y el esquemático correspondiente: (interface (port in0 (direction INPUT)) (port in1 (direction INPUT)) (port in2 (direction INPUT)) (port in3 (direction INPUT)) (port salida (direction OUTPUT)) (port (rename PORT5 "seleccion[0]") (direction INPUT)) (port (rename PORT6 "seleccion[1]") (direction INPUT)) ) (contents (instance U3 (viewRef net (cellRef MUXF5 (libraryRef VIRTEX)))) (instance U2 (viewRef net (cellRef LUT3 (libraryRef VIRTEX))) (property INIT (string "CA (instance U1 (viewRef net (cellRef LUT3 (libraryRef VIRTEX))) (property INIT (string "CA (net N0 (joined (portRef O (instanceRef U2)) (portRef I1 (instanceRef U3)))) (net N1 (joined (portRef O (instanceRef U1)) (portRef I0 (instanceRef U3)))) (net N2 (joined (portRef S (instanceRef U3)) (portRef PORT6))) (net N3 (joined (portRef I2 (instanceRef U2)) (portRef I2 (instanceRef U1)) (portRef PORT (net N4 (joined (portRef O (instanceRef U3)) (portRef salida))) (net N5 (joined (portRef I1 (instanceRef U2)) (portRef in3))) (net N6 (joined (portRef I0 (instanceRef U2)) (portRef in2))) (net N7 (joined (portRef I1 (instanceRef U1)) (portRef in1))) (net N8 (joined (portRef I0 (instanceRef U1)) (portRef in0))) ) Figura 6.4 Archivo EDIF, sección para multiplexor 4 a1 (case) U1 in0 N8 I0 in1 N7 I1 O N1 U3 LUT3 (init=CA) I0 I2 Seleccion[0] N3 in2 in3 N6 N5 I0 I1 N4 salida S O LUT3 (init=CA) O I1 U2 N0 N2 Seleccion[1] I2 Figura 6.5 Esquemático del archivo de síntesis para multiplexor 4 a 1 (case) Conocer este comportamiento propio del sintetizador y las inferencias que realiza según el código, permitió analizar la descripción en Verilog del diseño para utilizar la más conveniente. 45 Sin embargo, se encontró que Icarus Verilog tiene una limitación en la síntesis de estructuras case para la arquitectura Virtex, ya que permite sintetizar multiplexores de máximo 4 entradas de tamaño M, esto implica que el selector de entradas puede tener a lo sumo 2 entradas (2 bits). Esta limitación produce que por ejemplo la descripción en Verilog de un multiplexor 8 entradas no sea sintetizable aunque la descripción sea correcta para síntesis. Para corregir esta limitación era posible modificar el código fuente de la herramienta, no obstante para este proyecto no se realizó ya que se escapaba de los objetivos del proyecto. Esta limitación implica que se deben construir niveles de multiplexación para obtener multiplexores de mayor número de entradas o utilizar una descripción mediante sentencias if. Icarus Verilog soporta estructuras case y if-else anidadas para síntesis sin limitación. Esta situación resultó muy incómoda para realizar una descripción de una máquina de estados utilizando sentencias case. Durante el proceso de síntesis, existió un problema cuando se utilizan desplazamientos variables ya sea hacia la derecha o hacia la izquierda ya que si la variable de desplazamiento era muy grande se producía un error de síntesis. No se encontró una regla clara para saber cuando Icarus Verilog iba a generar el error por lo que este tipo de estructuras se eliminaron en la descripción del diseño y se utilizaron desplazamientos fijos dentro de lazos para ejecutarlos cuantas veces fuera necesario. También, existe una limitación con los operadores relacionales, las relaciones condicionales mayor que (>) y menor que (<) no son sintetizables. Esta limitación se solucionó combinando los operadores relacionales mayor igual que (>=) y menor igual que (<=) con diferente de (!=) mediante un operador “Y” (&&), para obtener mayor y menor estricto y que fuera sintetizable en la arquitectura Virtex. Inferencia de flip-flops Los flip-flops en Verilog no se especifican explícitamente, sino que son inferidos por su comportamiento para su síntesis y existen plantillas para especificarlos. Sin embargo, Icarus Verilog posee una limitación que le impide inferir flip-flops de flanco negativo y se debe a que en la lista de celdas de arquitectura Virtex que maneja, se encuentran elementos secuenciales solamente de flanco positivo. Esta limitación implicó 46 que se tuviera que agregar un inversor e invertir la señal de reloj en la descripción en Verilog del diseño propuesto para resolver esta limitación Inferencia de memorias RAM Para este proyecto se diseñó una memoria RAM estática cuya descripción en Verilog debía ser sintetizable, sin embargo Icarus Verilog no infiere memorias RAM, ya que su motor de síntesis no infiere una descripción en Verilog de este tipo de dispositivo y además no posee ninguna celda de la arquitectura Virtex para realizar el mapeo tecnológico durante la síntesis. Sin embargo mediante directivas especiales se logró sintetizar la memoria que necesitaba el diseño. Direccionamiento a celdas especiales de arquitectura Para este proyecto era imprescindible utilizar celdas especiales como: memoria RAM y celdas de reloj específicas de la arquitectura Virtex (BUFG, DCM). Se encontró que existen dos métodos para hacer referencia de celdas de arquitectura especiales para que se utilicen durante el proceso de síntesis. El primer método consiste en hacer referencia a alguna celda específica mediante la siguiente sintaxis: $attribute(Nombre de la instancia, "cellref", "Tipo de celda :Nombre de puertos,… "); Esta directiva “cellref” presentó el problema, en la última versión de Icarus Verilog, que no está completamente terminada y las únicas celdas de referencia especiales que se pueden direccionar son IBUF, OBUF, BUFG y MULT_AND. El segundo método es mucho más robusto pero más complicado y se utilizó con la celda especial DCM y con la memoria RAM estática debido a las limitaciones del método anterior. Consiste en crear módulos en Verilog cuyo nombre e interfaz corresponden a alguna celda de librería en combinación con la directiva para el sintetizador ivl_synthesis_cell *). (* 47 6.2.3 Adición de parámetros y restricciones en el proceso de síntesis para la arquitectura Virtex Hasta el momento no se ha discutido la adición de parámetros y restricciones en el proceso de síntesis. Los parámetros y restricciones permiten especificar completamente las características físicas del circuito digital diseñado. Esta información es dependiente de la arquitectura, del modelo, del empaquetado y de la velocidad del FPGA en el cual se va a implementar el diseño. Para este proyecto se utilizó un FPGA SPARTAN3E, modelo X3S1600E, empaquetado FG320 y velocidad 4 con un Starter-Kit. Algunos de los parámetros y restricciones que se utilizaron en el diseño fueron los siguientes: • Asignación de pines de entrada y salida. • Estándar de niveles lógicos de voltaje de salida y de entrada. • Corriente de salida. • Periodo de reloj. • Resistencias de pull-up y pull-down. El formato EDIF que se utiliza en los archivos de síntesis tiene la capacidad para incluir estos parámetros y restricciones, por lo que no es necesario crear un archivo por separado, sino que el archivo de síntesis puede contener todas las especificaciones del circuito de forma implícita. Asignación de pines de entrada y salida Para que un circuito digital sintetizado se pueda implementar en la arquitectura Virtex, es necesario que las entradas y salidas posean ciertas características para que sea posible la asignación de pines ya sea por el usuario o por la herramienta de implementación de forma aleatoria. En general: Las entradas deben poseer una celda de tipo puerto de entrada (IPAD) y una celda de tipo buffer de entrada (IBUF) antes de entrar al sistema. Las salidas deben poseer una celda de tipo puerto de salida (OPAD) y una celda de tipo buffer de salida (OBUF) al salir del sistema. 48 Las salidas tri-estado deben poseer una celda de tipo puerto entrada-salida (IOPAD), una celda tipo buffer tri-estado de salida (por ejemplo: OBUFT o BUFE) en conjunto con un buffer de entrada (IBUF). Si el circuito posee elementos secuenciales, debe poseer una entrada con una celda adicional tipo buffer de reloj (BUFG o BUFGMUX) para la entrada general del reloj. Las celdas tipo IPAD, OPAD o IOPAD se le debe asignar el nombre del pin físico del chip mediante el parámetro: LOC correspondiente a la entrada o salida que se desea utilizar. A continuación se presenta un diagrama general: Figura 6.6 Esquemático de celdas de tipo PAD en la arquitectura Virtex Icarus Verilog permite asignar las celdas tipo PAD y el parámetro LOC mediante la directiva $attribute a las señales de entrada y de salida. El archivo EDIF de síntesis resultante hace referencia a las celdas tipo IPAD, OPAD, IOPAD IBUF, OBUF, cuando se usan estas directivas. Además cada instancia tipo PAD posee un parámetro LOC con el nombre del pin deseado. En general en el formato EDIF, las restricciones y parámetros se hacen mediante la sentencia property, de la siguiente forma: (property PARAMETRO (string ”VALOR” )) Para la asignación de pines en salidas tri-estado, se encontró que es necesario agregar el buffer de entrada de forma explícita mediante a un direccionamiento especial a la celda IBUF, ya que Icarus Verilog no lo crea durante el proceso de síntesis y ocasiona un error 49 durante la implementación. También, Icarus Verilog no posee ninguna celda de librería triestado de salida, por lo que se tuvo que editar manualmente el archivo de síntesis. La directiva $attribute ciertamente tiene el potencial para realizar asignaciones de parámetros y restricciones directamente en la descripción en Verilog. Sin embargo por el momento en la última versión de Icarus Verilog (8.6), el único parámetro de arquitectura que el usuario puede utilizar es LOC a través del parámetro PAD sobre celdas tipo PAD. Aunque con este solo parámetro, se obtiene un archivo EDIF que cumple con las condiciones necesarias de interfaz, para ser implementado por la herramienta WebPack de Xilinx, se le dejaba al WebPack la selección aleatoria de algunos parámetros de las entradas como iostandard (estándar de voltaje), slew rate (velocidad), driver (corriente de salida), pull-up o pull-down (resistencias de pull-up o pull-down). Estas características eran muy importantes en este proyecto ya que el FPGA se debía conectar con dispositivos externos como: DAC, ADC, DRAM y el oscilador que se debían seleccionar adecuadamente para mantener la integridad de estos. También era necesaria la utilización de restricciones internas del diseño sobre celdas y conexiones como period (periodo de reloj), uselowskewlines (uso de conexiones de bajo retardo de reloj). Para agregar restricciones no soportadas sobre señales de interfaz se engañó a la directiva $attribute incluyendo información extra en el nombre del pin y luego se editó el archivo EDIF. Este método resolvió la limitación para incluir parámetros o restricciones a la interfaz del circuito (celdas PAD). No obstante, otro tipo de celdas internas solo se pudo realizar mediante la edición del archivo EDIF, siguiendo la sintaxis de este formato. Para este punto, el proceso de síntesis había finalizado, obteniéndose un archivo EDIF que posee toda la información del circuito y se encontraba listo para continuar con la etapa de implementación. Una limitación del proceso de síntesis de Icarus Verilog es que no posee información temporal de las compuertas para proveer un análisis temporal estático y conocer si las expectativas que se tienen se pueden cumplir. CAPÍTULO 7: Implementación, Programación y Simulaciones post-implementación. En este capítulo se utiliza la herramienta WebPack de Xilinx para implementar el archivo EDIF de síntesis. Se generan los archivos en Verilog para la simulación lógica y la simulación temporal que completan el flujo de diseño. Además se programa el circuito digital en el FPGA. 7.1 Proceso de implementación En el proyecto que creó el WebPack, se seleccionó que se iba a utilizar un archivo EDIF de síntesis para implementar el proyecto. Como se mencionó anteriormente, todas las restricciones y parámetros del diseño se incluyeron en el archivo EDIF por lo que no era necesario un archivo de restricciones del diseño. El formato EDIF permite que toda la información vaya implícita. También, era importante revisar que la familia, el modelo, el empaquetado y la velocidad del FPGA en el cual se iba a programar el proyecto concordaran con el dispositivo para el cual se realizó el proceso de síntesis. Proceso de Traducción: Translate En el proceso de translate, se toma el archivo EDIF de síntesis y se convierte a un formato propietario de Xilinx llamado: NGD (Native Generic Design) contiene componentes lógicos: puertas lógicas, biestables, RAMs, etc. En este proceso se revisa que el archivo EDIF no contenga errores, de ser así se detiene el proceso. Todos los mensajes de información, de error y de advertencia son escritos en el archivo de texto Translation Report. Los errores se producen por una incorrecta escritura del archivo o por problemas propios del circuito diseñado como cortocircuitos, conexiones sin carga, entre otros. Se encontraron en el archivo Translation Report, mensajes de información como el siguiente: 50 51 INFO:NgdBuild:889 - Pad net 'clk' is not connected to an external port in this design. A new port 'clk' has been added and is connected to this signal. Donde se están creando los puertos del circuito y aparece uno por cada puerto de entrada o salida del circuito. También aparecieron mensajes de error como el siguiente: ERROR:NgdBuild:455 - logical net 'N602' has multiple driver(s): pin Q on block U322 with type FDCE, pin Q on block U306 with type FDCE Este error indicaba que existía una conexión que es manejada por más de una celda y significaba una contención (cortocircuito) en el circuito sintetizado. Este tipo de errores no son identificados por Icarus Verilog durante el proceso de síntesis. Solucionar este error fue difícil, ya que se conocía la conexión y las instancias que lo generaban en el archivo EDIF, pero no el código en Verilog, ni el módulo de donde se inferían. Básicamente Icarus Verilog asigna nombres genéricos a las conexiones, excepto en los puertos de salida o entrada, en vez de nombres relacionados a la descripción en Verilog, esta situación constituye una debilidad del proceso de síntesis y de la herramienta que se debe mejorar. Para solucionar estos errores, se tuvo que sintetizar cada módulo en Verilog del diseño por separado y realizar la etapa de traslate con cada uno de ellos. Esto permitió aislar el módulo en Verilog que causaba la contención y posteriormente revisarlo exhaustivamente hasta encontrar el error de diseño o de escritura. Durante la etapa de traslate, se puede generar un módulo en Verilog del circuito sintetizado que describe en bajo nivel el circuito diseñado y utiliza la librería de Xilinx de primitivas de Verilog. No representa la verdadera implementación del circuito y no es sintetizable, pero es un modelo funcional del circuito sintetizado por Icarus Verilog. Simulación Lógica El archivo anterior permitió realizar la simulación lógica para comprobar que el archivo de síntesis no poseía ningún error y que concordaba con las especificaciones del di- 52 seño. No obstante, esta simulación era ideal pues todavía no se posee información de los retardos de cada compuerta y de enrutamiento. Este archivo constituyó la forma de comprobar que Icarus Verilog, sintetizaba correctamente las descripciones en Verilog de cada circuito en forma individual. La simulación para el circuito completo se logró compilar sin embargo no se utilizó debido al tamaño del archivo y al tiempo de simulación. Además, se tenían las simulaciones individuales de los circuitos para verificar el proceso de síntesis de Icarus Verilog. Como se mencionó anteriormente, este archivo necesita de la librería de Verilog de Xilinx para su compilación, pero además se debe incluir un archivo extra llamado glbl.v que contiene el módulo glbl. Para realizar simulaciones con este archivo de translate era necesario modificar el módulo principal con el siguiente código: reg GSR; assign glbl.GSR =GSR; initial begin GSR =1; #100 GSR = 0; end Este código se utiliza para simular el tiempo de inicialización del FPGA. Con el proceso initial se indica que el tiempo de inicialización es de 100 unidades hasta que la señal GSR sea cero. También, se debía modificar el banco de pruebas adecuadamente para que se inicien las pruebas 100 unidades de tiempo después ya que durante el tiempo de inicialización el circuito no va a responder en la simulación hasta que GSR sea cero. Cuando se realizaba la compilación con Icarus Verilog, la librería de Verilog de Xilinx contenía expresiones que eran no soportadas por la herramienta. Por lo que se optó por copiar el directorio de la librería para cambiar las expresiones que generaban los errores por otras equivalentes soportadas por Icarus Verilog, para luego utilizar el nuevo directorio para la compilación con Icarus Verilog para obtener una compilación exitosa. 7.1.2 Proceso de Mapeo: Map 53 En esta etapa se mapean mediante los componentes lógicos en los componentes físicos de que dispone la FPGA las tablas LUT, los biestables, los buffers triestado, etc. Se encapsulan estos componentes físicos en bloques configurables (CLBs e IOBs), creando un fichero de salida en formato NCD (Native Circuit Design). Todos los errores, advertencias y mensajes de información durante esta etapa se escriben en el archivo de texto: Map Report. En el Map Report, se encontraron los siguientes mensajes de información: INFO:MapLib:535 - The following Virtex BUFG(s) is/are being retargetted to Virtex2 BUFGMUX(s) with input tied to I0 and Select pin tied to constant 0: BUFG symbol "U9" (output signal=N0) INFO:MapLib:159 - Net Timing constraints on signal clk are pushed forward through input buffer. Este primer mensaje indicaba que se va a utilizar la celda BUFGMUX en vez de la celda BUFG para manejar la señal de reloj. Esto ocurre porque el SPARTAN3E solo posee BUFGMUX y el cambio no afectaba el circuito. El segundo mensaje indicaba que se identificó una restricción de tiempo en la señal clk que corresponde al periodo de reloj establecido. En esta etapa era importante revisar que se identificaron correctamente las restricciones y parámetros de los puertos de entrada y salida del circuito. A continuación se presenta la utilización de recursos: Design Summary -------------Number of errors: Number of warnings: 0 29 Logic Utilization: Number of Slice Flip Flops: Number of 4 input LUTs: 4,327 out of 29,504 14% 10,466 out of 29,504 35% Logic Distribution: Number of occupied Slices: 7,476 out of Number of Slices containing only related logic: 14,752 7,476 100% 0 out of 7,476 0% Number of Slices containing unrelated logic: *See NOTES below for an explanation of the effects of unrelated logic Total Number 4 input LUTs: 11,870 out of 50% 7,476 out of 29,504 40% 54 Number used as logic: Number used as a route-thru: 10,466 1,084 Number used for 32x1 RAMs: 320 (Two LUTs used per 32x1 RAM) Number of bonded IOBs: 68 out of IOB Flip Flops: 250 27% 38 Number of GCLKs: 2 out of 24 8% Number of DCMs: 1 out of 8 12% Total equivalent gate count for design: 160,733 Figura 7.1 Resumen de recursos utilizados en el FPGA, circuito completo 7.1.3 Proceso de Posicionamiento y Enrutamiento: Place and Route En esta etapa se pasa a realizar el posicionamiento e interconexión de los bloques configurables en el FPGA y se genera un fichero de lista de conexiones en formato NCD. Una vez finalizado este proceso se dispone de toda la información de retardos internos (elementos activos e interconexiones). Todos los resultados obtenidos son escritos en el archivo de texto: Place and Route Report. En este reporte era importante el Clock Report, que muestra las conexiones de reloj, y se podía revisar si se cumplían con las restricciones temporales del diseño. Este reporte muestra el periodo de reloj solicitado y el periodo de reloj obtenido. En caso que no cumplan, se muestra el máximo de niveles lógicos que existen entre los elementos secuenciales de la conexión, muestra el tiempo faltante para cumplir con las restricciones y el número de caminos que no satisfacen el periodo de reloj. ************************** Generating Clock Report ************************** -----------------------------------------------------------------------------------------------------Constraint | Requested | Actual | Logic | Absolute |Number of | | | Levels | Slack |errors -----------------------------------------------------------------------------------------------------* PERIOD analysis for net "N37717" derived | 20.000ns | 19.923ns | 1 | 0.077ns | 0 from NET "N37742" PERIOD = 20 ns HIGH 50 | | | | | % | | | | | -----------------------------------------------------------------------------------------------------PERIOD analysis for net "N37723" derived | 200.000ns | 197.003ns | 5 | 2.997ns | 0 from NET "N37742" PERIOD = 20 ns HIGH 50 | | | | | % | | | | | -----------------------------------------------------------------------------------------------------NET "N37742" PERIOD = 20 ns HIGH 50% | N/A | N/A | N/A | N/A | N/A ------------------------------------------------------------------------------------------------------ Figura 7.2 Reporte final de relojes del WebPack, circuito completo 55 Este reporte de reloj constituyó la única forma de conocer si las especificaciones de diseño se cumplían. En esta etapa, ocurrió que las máquinas de estado con arquitectura microprogramada no convergían cuando se tenían muchos estados, razón por la cual se optó por la arquitectura one-hot y se tuvo que realizar un ajuste en la alineación de los diferentes relojes para llegar a obtener un circuito libre de errores temporales. Simulación Temporal Después de realizar esta fase, se tiene la información para realizar simulaciones temporales del diseño completo. Se puede generar un archivo en Verilog con base en los componentes físicos de la FPGA y un fichero SDF con los retardos internos del FPGA. Sin embargo, Icarus Verilog en su última versión, no posee soporte para utilizar el archivo SDF (Standard Delay Format) que contiene los retardos correspondientes para cada compuerta. Lo cual impidió realizar simulaciones post-implementación de retardos reales. Esta limitación hizo que la simulación en esta etapa fuera solamente lógica como en la etapa de translate y complicó la identificación de los problemas de temporización de diseño. Para más detalle revisar el apéndice D. 7.1.4 Programación del FPGA y pruebas en circuito Para esta etapa se programó el FPGA con el archivo .bit obtenido. Se preparó en Ma- tlab un código equivalente al circuito diseñado para realizar comparaciones cualitativas que se puede encontrar en el apéndice C. Durante las pruebas del circuito real, se obtuvieron resultados exitosos, ya que el circuito logró grabar, almacenar y reproducir voz en PCM y LPC exitosamente. Los resultados fueron sustancialmente equivalentes al equivalente en software del circuito elaborado en Matlab. CAPÍTULO 8: Conclusiones y recomendaciones Este capítulo presenta las principales conclusiones y recomendaciones a las que se llegó una vez finalizado el proyecto. Conclusiones con respecto a los objetivos del proyecto: • Se desarrolló un procedimiento de diseño e implementación de circuitos digitales mediante herramientas EDA de código abierto. Se utilizaron herramientas de código abierto de uso general que permiten construir el circuito digital en cualquier dispositivo con una dependencia en el fabricante para el proceso de implementación. El procedimiento fue extensamente documentado y como resultado del proyecto se obtuvo una guía detallada para que sea utilizada ampliamente. • Se diseñó y se describió en Verilog la arquitectura de un circuito digital que realiza en hardware la codificación/decodificación de predicción lineal de la voz humana. • Se estableció la etapa de síntesis para la arquitectura Virtex y se programó en el FPGA SPARTAN3E de Xilinx, obteniéndose un circuito digital real con un funcionamiento exitoso. Conclusiones con respecto al procedimiento planteado: • El procedimiento y las herramientas utilizadas tienen la capacidad de desarrollar circuitos digitales de forma generalizada. Sin embargo se debilita conforme aumenta el tamaño del circuito que se desea implementar y se tiene como límite la capacidad de la computadora anfitriona donde se lleve acabo. • Existen vacíos durante el flujo principalmente en el análisis temporal y la visualización de esquemáticos donde se depende de la herramienta del fabricante. Recomendaciones para trabajos futuros: 56 57 • Solucionar las limitaciones y errores de Icarus Verilog presentados en este proyecto para el proceso de síntesis en la arquitectura Virtex mediante modificaciones en el código fuente. • Adicionar soporte para SDF al proceso de compilación para simulaciones no ideales. • Mejorar el proceso de síntesis para que sea más robusto: Agregar información temporal de la arquitectura para análisis y reportes de temporización, obtención de un archivo EDIF resultante que posea una correspondencia con el código en Verilog. Incluir estimaciones de consumo de potencia. • Desarrollar una aplicación para la visualización en forma parcial o completa de esquemático a partir de un archivo en formato EDIF. • Ejecutar y verificar el procedimiento para otro tipo de dispositivo programable de otro fabricante y analizar su posible aplicación para VLSI. BIBLIOGRAFÍA Libros y tesis: [1] Alvarado, M. “-PC2SCT- Implementación de Interfaz para Pruebas Estructu- rales en Microprocesadores”, Proyecto Eléctrico, Universidad de Costa Rica, 2004 [2] Arellano, R. Cartin, Cruz J. “Modelado y Síntesis de la CPUCR”, Proyecto Electrico, Universidad de Costa Rica, 2003 [3] Ingle, V. “Digital Signal Processing Using MATLAB”, Brooks/Cole Publishing Company, 2000. [4] Murillo, D. “Filtro Digital implementado en un PLD”, Proyecto Eléctrico, Universidad de Costa Rica, 2004. [5] Rodríguez, R. “Dispositivos lógicos programables, características, flujo de dise- ño e implementación de la CPUCR utilizando un FPGA”, Tesis de licenciatura en ingeniería eléctrica, Universidad de Costa Rica, 2004. [6] Thomas, D. “The Verilog Hardware Description Language”, Tercera Edición, Kluwer Academic Publishers, Estados Unidos de América, 1996. Artículos: [7] Álvarez, L. “Historia de los circuitos digitales configurables”, http://www.dte.uvigo.es/logica_programable/documentos/curso_disenho_digital_con_C DCs/Documento_historia_PLDs.pdf. [8] Barriga, A. “Taller de diseño de sistemas electrónicos basados en FPGA”, Instituto de Microelectrónica de Sevilla – UCR, 2006. [9] Buj, R. “Procedimiento de diseño de circuitos digitales mediante FPGAs”, www.recercat.net/bitstream/2072/3834/1/Buj.pdf, 2007. [10] Fernández, L. “Difusión y Multimedia”, www.neutron.ing.ucv.ve/comunicaciones/Asignaturas/DifusionMultimedia/Difus&Mul timedia04.pps, Universidad Central de Venezuela. 58 59 [11] Mateos, R. “DISEÑO EN VHDL PARA FPGAs”, http://www.depeca.uah.es/docencia/INGECA/dse/lab/course_projects/p2/enunciado.pdf. [12] Morales, M. “Introducción a los FPGAs y el Cómputo Reconfigurable”, http://ccc.inaoep.mx/~mmorales/documents/FPGAsyReconfig.pdf, 2006. [13] Oregon State University, “Chapter 7 Linear Predictive Speech Processing”, www.engineer.tamuk.edu/SPark/chap7.pdf, 2004. Sitios Web: [14] Curso audiovisual interactivo de codificación de voz, http://ceres.ugr.es/~alumnos/luis/codif.htm, Septiembre del 2007. [15] FPGA, http://es.wikipedia.org/wiki/FPGA, Septiembre del 2007. [16] GTKWave, http://home.nc.rr.com/gtkwave/, Septiembre 2007. [17] Icarus Verilog, http://www.icarus.com/eda/verilog/, Septiembre 2007. [18] ISE-Help, http://toolbox.xilinx.com/docsan/xilinx7/help/iseguide/iseguide.htm, Septiembre 2007. [19] Speech Compression, http://www.data-compression.com/speech.shtml , Septiembre del 2007. [20] Wideband Speech Coding with Linear Predictive Coding (LPC), http://www.ee.ucla.edu/~spapl/projects/ee214aW2002/1/report.html, Septiembre del 2007. APÉNDICE A: Diagrama de estados de los circuitos A.1 Controlador A/D A.1.1 Registros: Muestra1 => Almacena la muestra recibida invertida. Ganancia => Almacena la ganancia del pre-amplificador. Listo => Almacena el estado del circuito: controlador A/D. Listo_muestra => Almacena el estado de la muestra recibida. DAC_CS => Almacena el estado del chip select del DAC. AMP_CS => Almacena el estado del chip select del pre-amplificador. Cont => Contador para desplazar bits de la ganancia del pre-amplificador. AD_CONV =>Almacena el estado de la señal de disparo de muestreo del ADC. Muestra =>Almacena la muestra recibida. Est2_8 =>Almacena estados auxiliares para los contadores. Est2_4 => Almacena estados auxiliares para los contadores. Est2_9 => Almacena estados auxiliares para los contadores. Cont2 => Contador para desplazar bits de la muestra recibida. Cont3 => Contador para controlar frecuencia de muestreo. SPI_SS_B => Almacena estado de dispositivo externo que comparte el bus tri-estado en la tarjeta de desarrollo del FPGA. SF_CEO => Almacena estado de dispositivo externo que comparte el bus tri-estado en la tarjeta de desarrollo del FPGA. FPGA_INIT_B => Almacena estado de dispositivo externo que comparte el bus tri-estado en la tarjeta de desarrollo del FPGA. AMP_SHDN => Almacena estado de encendido del pre-amplificador. A.1.2 Diagrama de Estado: Estado Presente Descripción del estado Condición 60 Próximo Estado 61 Verdadera=1 Estado0 AMP_CS =1, AD_CONV =0 Reset==1? Estado1 Estado1 DAC=0 Estado2 Estado2 AMP_CS=0, SPI_MOSI=ganancia[7], cont=0 Estado3 Estado3 SPI_MOSI=ganancia[7]<<1, cont++ Cont==7? Estado4 Estado4 AMP_CS=1, cont=0, cont2 =0, cont3=0, DAC=1 Estado5 Estado5 listo =1 Muestrear==1? Estado6 Estado6 AD_CONV=1 Estado7 Estado7 Cont++, AD_CONV=0, Cont==2? Estado8 Estado8 SPI_MISO => muestra, cont=0, cont2++ cont2==13? Estado9 Estado9 cont2 =0, cont3++, listo_muestra=1 Cont3==606? Estado10 Estado10 cont3=0 Estado5 Tabla A.1 Diagrama de Estado del Controlador A/D A.2 Controlador D/A A.2.1 Registros: DA_registro => Almacena la muestra enviada. Listo => Almacena el estado del circuito: controlador D/A. Listo_muestra => Almacena el estado de la muestra enviada. DAC_CS => Almacena el estado del chip select del pre-amplificador. Cont => Contador para desplazar bits de la muestra enviada. Cont2 => Contador para controlar frecuencia de reproducción. DAC_CLR => Almacena estado de encendido del DAC. A.2.2 Diagrama de Estado: Falso=0 Estado0 Estado3 Estado5 Estado7 Estado8 Estado9 - 62 Estado Presente Descripción del estado Estado0 Estado1 Estado2 SD_CKE =0 DAC_CS_AD Listo=1 SPI_MISO<=DA_registro[23], cont =0, Estado3 listo=0, cont2=0 Estado4 DAC_CS=0 Estado5 SPI_MISO<=DA_registro[23]<<1, cont=32? Estado6 DAC_CS=1, listo_muestra=1, Estado7 Tabla A.2 Diagrama de Estado del Controlador D/A Condición Próximo Estado Verdadero=1 Reset==1? Estado1 DAC_CS_AD==0? Estado2 Reproducir==1? Estado3 Falso=0 Estado0 Estado1 Estado2 - Estado4 - Cont==32? Cont2==598? - Estado5 Estado6 Estado7 Estado2 Estado5 Estado6 - A.3 Controlador de Memoria A.3.1 Registros: SD_CKE => almacena el estado de la señal SD_CKE de la memoria DRAM. CLK_EN => almacena el estado de la señal CLK_EN de la memoria DRAM. Cont1 => contador de comandos Nop. Cont2 => contador de comandos Nop. Cont3 => contador de tiempo de refrescamiento, comando=>Autorefresh.. Comando => almacena la operación que ejecuta la DRAM. Dirección => almacena la dirección que se esta accesando para escritura o lectura. Bandera_escritura => almacena el modo en que se está utilizando la DRAM. Lectura_pb => almacena la parte baja del dato leído de la DRAM. Lectura_pa => almacena la parte alta del dato leído de la DRAM. 63 Listo => Almacena el estado del circuito. A.3.2 Diagrama de Estado: Estado Presente Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Estado8 Estado9 Estado10 Estado26 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Descripción del estado Condición Próximo Estado Verdadero=1 Inicialización CKE=0 Reset==1? Estado1 Habilitar clk y clk# a la memoria inicializar cont1=0 Estado2 Esperar cont1=20000ciclos cont1==20000? Estado3 Comando=Nop CKE=1 Estado4 Comando=Precharge all Estado5 Comando=LMR BA=01 E=0000000000000 Estado6 Comando=LMR, BA=00 E=00000101100001 Estado7 Comando=Precharge all Estado8 Comando=autorefresh, cont2=0 Estado9 Comando=Nop Cont2==7? Estado10 Comando=Autorefresh, cont3=0 Estado26 Listo=1, esperar 200 ciclos de reloj Cont1= =200? Estado11 Revisar tiempo restante para autorefresh Cont3==750? Estado14 Iniciar Iniciar==1? Estado13 Saltar a estado11 Estado11 Comando=Autorefresh, cont2=0, cont3=0 Estado15 Comando=Nop cont2==7? Estado16 Saltar al estado11 Estado11 Comando=Active, listo=0 Estado18 Comando=Nop Escritura? Estado22 Falso=0 Estado0 Estado2 Estado9 Estado26 Estado12 Estado17 Estado15 Estado19 64 Estado19 Comando=Read Estado20 Comando=Precharge all, lectura Estado21 Saltar al estado11 Estado22 Comando=Write, cont2 =0, bandera_escritura=1 Estado23 Comando=Nop Estado24 Comando=Precharge all, bandera_escritura=0 Estado25 Comando=Nop, saltar al estado11 Tabla A.3 Diagrama de Estado del Controlador de Memoria cont2==3? - Estado20 Estado21 Estado11 Estado23 Estado24 Estado25 Estado11 Estado24 - A.4 Controlador de Reproducción A.4.1 Registros SD_banco => Almacena el banco de la memoria DRAM que se esta accediendo. SD_fila => Almacena la fila de la memoria DRAM que esta accediendo. SD_columna => Almacena la columna de la memoria DRAM que esta accediendo. SD_escribir => Almacena el modo en que se esta accediendo la memoria DRAM. REP_fila => Almacena la fila final de la grabación. REP_columna => Almacena la columna final de la grabación. SD_iniciar => Almacena el estado de inicio del controlador de memoria. AD_muestrear => Almacena el estado de muestreo del controlador A/D DA_reproducir => Almacena el estado de reproducción del controlador D/A REP_listo => Almacena el estado del circuito. CODE_iniciar => Almacena el estado de inicio del controlador de codificación. A.4.2 Diagrama de Estado Estado Descripción del estado Condición Próximo Estado 65 Presente Estado0 Estado1 Estado2 Estado3 Estado4 Estado6 Reset Ex negado AD & DA & SD listo Listo=1 Reproducir Saltar a revisar Grabar Listo=0, BA:00, Fila:0, Columna:0, Escribir=1 AD:muestrear=1 Estado7 Esperar AD:listo muestra Estado8 Estado9 Estado10 Estado12 Estado13 Estado14 Estado15 Estado16 SD_dato<=AD:muestra SD:Iniciar=1 Esperar SD:listo=0 SD:iniciar=0, Saltar si es columna es 1022 (máximo) Columna+2 saltar si es fila es 8191 (máximo) Fila++, columna=0 Saltar memoria llena Esperar SD:listo Estado17 Esperar AD:listo_muestra Estado18 Revisar grabar AD:muestrear=0, REP_fila<=SD_fila, REP_columna<=SD_columna CODE: Iniciar=1 Esperar CODE:listo Estado5 Estado11 Estado19 Estado20 Estado21 Reset==1? AD & DA & SD listo==1? Grabar==1? Reproducir==1? - Verdadero=1 Estado1 Estado2 Estado5 Estado24 Estado2 Falso=0 Estado0 Estado1 Estado3 Estado4 - - Estado6 - AD:listo_muestra ==1? SD:listo==0? Estado7 - Estado8 Estado7 Estado9 Estado10 Estado11 Estado10 Columna==1022? Estado13 Estado12 Fila==8191? SD:listo==1? AD:listo_muestra ==0? Grabar==1? Estado16 Estado15 Estado16 Estado19 Estado17 Estado14 - Estado18 Estado17 Estado7 Estado19 - Estado20 - CODE:listo==0? Estado21 Estado22 Estado21 Estado16 66 Estado22 Estado23 CODE:iniciar=0 CODE:listo==1? saltar a revisar grabar Listo=0,BA:Codificado, Fila:0, Columna:0, Estado24 Escribir=0 Estado25 SD: Iniciar=1 Estado26 Esperar SD:listo SD:listo==0? Estado27 SD:iniciar=0,Esperar SD:listo SD:listo==1? Estado28 Copiar dato a DA Estado29 DA: Iniciar=1 Estado30 Esperar DA: listo DA: listo==0? DA:iniciar=0, Estado31 Columna==1022? Saltar si es columna es 1022 (máximo) Estado32 Columna+2 Estado33 saltar si es fila es 8191 (máximo) Fila==8191? Estado34 Fila++, columna=0 Estado35 Saltar memoria llena Estado36 Fila menor igual que Fila grabada? SD_Fila menor <= REP_Fila? Estado37 Columna menor igual que Columna grabada? SD_columna <= REP_columna? Estado38 Esperar DA:listo DA:listo==1? Estado39 Revisar Reproducir Reproducir==1? Estado40 Saltar a inicio Tabla A.4 Diagrama de Estado del Controlador de Reproducción A.5 Controlador de Codificación A.5.1 Registros Cont => contador de datos accedidos en la DRAM. Estado23 Estado2 Estado22 - Estado25 - Estado26 Estado27 Estado28 Estado29 Estado30 Estado31 Estado26 Estado27 Estado30 Estado33 Estado32 Estado36 Estado35 Estado36 Estado40 Estado37 Estado36 Estado39 Estado25 Estado2 Estado34 Estado38 Estado38 Estado38 Estado40 67 Dato_temporal => Almacena dato para escribir de la DRAM a la RAM. SD_banco => Almacena el banco que se está accediendo en la DRAM. SD_fila => Almacena la dirección fila que se está accediendo en la DRAM. SD_columna => Almacena la dirección columna que se está accediendo en la DRAM. SD_escribir => Almacena estado para escritura en la DRAM. SD_iniciar => Almacena estado de inicio del circuito: controlador de memoria. RAM_dir => Almacena dirección de la RAM que está accediendo. RAM_escribir => Almacena estado para escritura en la RAM. CODE_listo => Almacena estado del circuito. CRUCE_iniciar => Almacena estado de inicio del circuito: Sonido con/sin voz. LD_iniciar => Almacena estado de inicio del circuito: Coeficientes R. FG_iniciar => Almacena estado de inicio del circuito: filtro de síntesis. FPR_iniciar => Almacena estado de inicio del circuito: filtro de análisis. A.5.2 Diagrama de Estado Estado Descripción de estado Presente Condición Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 SD_iniciar =0, dato_temporal=0 Listo=1 Listo=0, SD_BA=00, SD_Fila=0, SD_Columna=0, Escribir=0, cont=0, RAM_dir=cont SD: Iniciar=1 Esperar SD:listo SD:iniciar=0 Mantisa_dato_temporal[13:0]= dato DRAM, Próximo Estado Reset==1? Iniciar==1? Verdadero=1 Estado1 Estado2 Falso=0 Estado0 Estado1 - Estado3 - SD:listo==0? SD:listo==1? - Estado4 Estado5 Estado6 Estado7 Estado4 Estado5 - 68 Estado7 Estado8 exp_dato_temporal=23 Dato_temporal[13:0]=0 Dato_temporal=0 Estado9 Dato_temporal[13:0] negativo Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Dato_temporal[13:0]=~Dato_temporal+1, Dato_temporal_signo=1 Dato_temporal normalizado Mantisa_dato_temporal<<1, exp_dato_temporal-RAM_escribir=1 No se usa No se usa No se usa No se usa No se usa CODEcolumna+2, Saltar si es columna es 1022 (maximo) , RAM_escribir=0 Columna+2 Fila++ columna=0 Estado22 Columna menor igual que Columna grabada Estado23 Fila menor igual que Fila grabada Estado24 Estado25 Estado26 Estado27 Estado28 saltar a inicio Cont cont++ saltar a inicio Cruce:Iniciar=1 Esperar Cruce:listo Dato_temporal==0? Dato_temporal[13:0] es negativo? Estado8 Estado13 Estado9 - Estado10 Estado11 - Estado11 - Dato_temporal normalizado? - Estado13 Estado11 Estado19 - Estado12 - Columna==1022? Estado21 Estado20 Columna <= Columna grabada? Fila menor igual que Fila grabada? cont==159? Cruce:listo==0? Estado22 Estado22 - Estado23 Estado25 Estado24 Estado25 Estado1 Estado26 Estado27 Estado28 Estado29 Estado27 Estado26 Estado28 - 69 Estado29 Cruce:iniciar=0, Esperar Cruce:listo Cruce:listo==1? Estado30 LD:Iniciar=1 Estado31 LD:listo LD:listo==0? Estado32 LD:iniciar=0,Esperar LD:listo LD:listo==1? Estado33 FG:Iniciar=1 Estado34 Esperar FG:listo FG:listo==0? Estado35 FG:iniciar=0, Esperar FG:listo FG:listo==1? Estado36 FPR:Iniciar=1 Estado37 Esperar FPR:listo FPR:listo==0? Estado38 FPR:iniciar=0,Esperar FPR:listo FPR:listo==1? Estado39 cont=0, columna=0, saltar inicio Tabla A.5 Diagrama de Estado del Controlador de Codificación A.6 Sonido con/sin Voz A.6.1 Registros Bandera => almacena el estado de la dirección del ultimo cruce por cero. Cont => contador de direcciones accedidas en la memoria RAM. Cont_CRUCE => contador de cruces por cero de la trama de voz de 20 ms. Resultado => Almacena el resultado del circuito: Sumador o Divisor. RAM_dir => Almacena dirección de la RAM que está accediendo. RAM_escribir => Almacena estado para escritura en la RAM. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Div_iniciar => Almacena el estado de inicio del circuito: Divisor. Op1 => Almacena el operando1 para enviar al circuito: Sumador o Divisor. Op2 => Almacena el operando2 para enviar al circuito: Sumador o Divisor. Estado30 Estado31 Estado32 Estado33 Estado34 Estado35 Estado36 Estado37 Estado38 Estado39 Estado3 Estado29 Estado31 Estado32 Estado34 Estado35 Estado37 Estado38 - 70 Pitch_iniciar => Almacena el estado de inicio del circuito: Detección de Pitch. Cruce_listo => Almacena el estado del circuito. Pitch => Almacena el valor del pitch de la trama de voz. A.6.2 Diagrama de Estado Estado Presente Descripción del estado Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 RAM_dir=cont, RAM_escribir=0, cont_160=0 Listo=1 Listo=0,promedio=0, cruce=0,bandera=0,PITCH=0 RAM lectura No se usa No se usa Op2=RAM_dato No se usa No se usa No se usa No se usa Sumador:Iniciar=1, Sumar_restar=1 Esperar Sumador:listo Sumador:iniciar=0, Sumar_restar=0 Promedio=sumador_resultado, op1=sumador_resultado, op2=160 cont cont++, saltar a inicio Div:Iniciar=1, cont=0 Estado14 Estado15 Estado16 Estado17 Condición Próximo Estado Reset==1? Iniciar==1? Sumador:listo==0? Sumador:listo==1? Verdadero=1 Estado1 Estado2 Estado3 Estado6 Estado11 Estado12 Estado13 Estado14 Falso=0 Estado0 Estado1 - - Estado15 - Cont==159? - Estado17 Estado3 Estado18 Estado16 - Estado12 Estado13 71 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado26 Estado27 Estado28 Estado29 Estado30 Estado31 Estado32 Esperar Div:listo Div:iniciar=1, Esperar Div:listo Promedio=divisor_resultado RAM_dato No se usa No se usa op1= RAM_dato No se usa No se usa No se usa No se usa Sumador:Iniciar=1, Sumar_restar=2 Esperar Sumador:listo Sumador:iniciar=0, Sumar_restar=0, Esperar Sumador:listo bandera igual signo sumador_resultado Estado33 bandera = signo sumador_resultado, cruce++ Estado34 cont Estado35 cont_160++, saltar a inicio2 Estado36 Cont_CRUCE mayor a 20? Estado37 Pitch:Iniciar=1, PITCH=1 Estado38 Esperar Pitch:listo Estado39 Pitch:iniciar=0, Esperar Pitch:listo Estado40 cont=0, saltar a inicio Tabla A.6 Diagrama de Estado de Sonido con/sin Voz A.7 Detección del Pitch Div:listo==0? Div:listo==1? Sumador:listo==0? Estado19 Estado20 Estado21 Estado24 Estado29 Estado30 Estado31 Estado18 Estado19 Estado30 Sumador:listo==1? Estado32 Estado31 Estado33 Estado34 Estado34 Estado35 Estado21 Estado37 Estado38 Estado39 Estado40 Estado40 Estado36 Estado40 Estado38 Estado39 - bandera igual == sumador_resultado? Cont==159? Cont_CRUCE >= 20? Pitch:listo==0? Pitch:listo==1? - 72 A.7.1 Registros Cont => contador de direcciones accedidas en la memoria RAM. Cont_K => contador de la variable K del procedimiento AMDF. Resultado => Almacena el resultado del circuito: Sumador o Divisor. RAM_dir => Almacena dirección de la RAM que está accediendo. RAM_escribir => Almacena estado para escritura en la RAM. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Div_iniciar => Almacena el estado de inicio del circuito: Divisor. Op1 => Almacena el operando1 para enviar al circuito: Sumador o Divisor. Op2 => Almacena el operando2 para enviar al circuito: Sumador o Divisor. AMDF => Almacena el valor del AMDF mínimo obtenido en la trama de voz. Kfinal => Almacena el valor de K donde se dio el menor AMDF. Bandera => Almacena el estado de la existencia de un AMDF. PITCH_listo => Almacena el estado del circuito. A.7.2 Diagrama de Estado Estado Presente Descripción del estado Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 cont=0, RAM_dir =cont Listo=1 Listo=0, cont_K=20,resultado=0, AMDF=0 RAM_lectura No se usa No se usa Condición Reset==1? Iniciar==1? - Próximo Estado Verdadero=1 Estado1 Estado2 Estado3 Estado6 - Falso=0 Estado0 Estado1 - 73 Estado6 Estado28 Estado29 Estado30 Estado31 Estado32 Estado33 Estado34 Estado35 Estado7 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 RAM_dir=cont+K, Op1=RAM dato No se usa No se usa No se usa No se usa No se usa No se usa No se usa No se usa RAM lectura No se usa No se usa Op2=RAM_dato, RAM_dir=cont Sumador:Iniciar=1, Sumar_restar=1 Esperar Sumador:listo Sumador:iniciar=0, Sumar_restar=0, Esperar multi:listo op1=resultado y op2=sumador_resultado sumador:Iniciar=1 Esperar sumador:listo Sumador:iniciar=0,Esperar sumador:listo resultado=sumador_resultado cont=159-K? cont++, saltar a inicio cont=0, op1=resultado, op2=160-K op2_normalizado? op2_mantisa<<1, op2_exp-1 Div:Iniciar=1 Esperar Div:listo Sumador:listo==0? Estado11 Estado10 Estado11 Estado12 Estado13 Estado12 Sumador:listo==1? Estado14 Estado13 suamdor:listo==0? suamdor:listo==1? cont==159-K? Div:listo==0? Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado3 Estado22 Estado24 Estado22 Estado25 Estado26 Estado16 Estado17 Estado21 Estado23 Estado25 74 Estado26 Div:iniciar=0, Esperar Div:listo Estado27 bandera=0? Estado36 AMDF=div_resultado, KFINAL=k, bandera=1, Estado37 div_resultado<=AMDF? Estado38 AMDF =div_resultado, KFINAL=k Estado39 k<160? Estado40 k++ saltar a inicio, resultado=0 Tabla A.7 Diagrama de Estado de Detección del Pitch Div:listo==1? Bandera==0? Div_resultado<=AMDF? k<160? - A.8 Coeficientes R A.8.1 Registros Cont => contador de direcciones accedidas en la memoria RAM. Cont_R => contador de la variable R de los coeficientes de auto correlación. Resultado => Almacena el resultado del circuito: Sumador o Multiplicador. RAM_dir => Almacena dirección de la RAM que está accediendo. RAM_escribir => Almacena estado para escritura en la RAM. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Multi_iniciar => Almacena el estado de inicio del circuito: Multiplicador. Op1 => Almacena el operando1 para enviar al circuito: Sumador o Multiplicador. Op2 => Almacena el operando2 para enviar al circuito: Sumador o Multiplicador. R0..10 => Almacena el valor de los coeficientes de auto correlación. C_iniciar => Almacena el estado de inicio del circuito: Coeficientes LPC. R_listo => Almacena el estado del circuito. Estado27 Estado37 Estado39 Estado38 Estado39 Estado1 Estado3 Estado26 Estado36 Estado39 Estado40 - 75 A.8.2 Diagrama de Estado Estado Presente Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado28 Estado29 Estado30 Estado31 Estado32 Estado33 Estado34 Estado35 Estado7 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Descripción del estado cont=0, RAM_Dir=cont Listo=1 Listo=0,R=0,resultado=0 RAM lectura No se usa No se usa Op1=RAM dato RAM_dir=cont+R No se usa No se usa No se usa No se usa No se usa No se usa No se usa No se usa RAM_lectura No se usa No se usa Op2=RAM_dato, RAM_dir=cont multi:Iniciar=1 Esperar multi:listo Bajar multi:iniciar,Esperar multi:listo op1=multi_resultado y op2=resultado Condición Reset==1? Iniciar==1? multi:listo==0? multi:listo==1? - Próximo Estado Verdadero=1 Estado1 Estado2 Estado3 Estado6 Estado7 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Falso=0 Estado0 Estado1 Estado12 Estado13 - 76 Estado15 sumador:Iniciar=1 Estado16 Esperar sumador:listo Estado17 Bajar sumador:iniciar,Esperar ALU:listo Estado18 Resultado=sumador_resultado Estado19 cont=159-R? Estado20 cont++, saltar a inicio Estado21 R=10? Estado22 R[cont_R]=resultado Estado23 resultado=0,cont=0,R++, saltar inicio Estado24 C:Iniciar=1, cont=0, R[cont_R]=resultado Estado25 Esperar C:listo Estado26 C:iniciar=0,Esperar C:listo Estado27 Saltar a R_iniciar Tabla A.8 Diagrama de Estado de Coeficientes R Sumador:listo==1? Sumador:listo==0? Cont==159-R? R==10? C:listo==0? C:listo==1? - Estado16 Estado17 Estado18 Estado19 Estado20 Estado3 Estado22 Estado23 Estado3 Estado25 Estado26 Estado27 Estado1 A.9 Coeficientes LPC A.9.1 Registros M => Almacena la variable M del método Levinson-Durbin. I => Almacena la variable I del método Levinson-Durbin. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Multi_iniciar => Almacena el estado de inicio del circuito: Multiplicador. Div_iniciar => Almacena el estado de inicio del circuito: Divisor. Resultado => Almacena el resultado del Sumador, Divisor o Multiplicador. Op1 => Almacena el operando1 para enviar al circuito: Sumador, Multiplicador o Divisor. Op2 => Almacena el operando2 para enviar al circuito: Sumador, Multiplicador Divisor. Estado16 Estado17 Estado21 Estado24 Estado25 Estado26 - 77 E => Almacena el valor del error de predicción lineal del Método Levinson-Durbin. K => Almacena el valor de K del Método Levinson-Durbin. A1..10 => Almacena el valor de los coeficientes de predicción lineal de la trama de voz. Temp1..9 => Almacena resultados parciales del método Levinson-Durbin. C_listo => Almacena el estado del circuito. A.9.2 Diagrama de Estado Estado Presente Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Descripción del Estado Condición Próximo Estado Verdadero=1 Reset Reset==1? Estado1 Listo=1 Iniciar==1? Estado2 Op1= R1, Op2=R0 Estado3 Div:Iniciar=1 Estado4 Esperar Div:listo Div:listo==0? Estado5 Div:iniciar=0, Esperar Div:listo Div:listo==1? Estado6 op1=op2=Divisor_resultado, a11= Divisor_resultado Estado7 Multi:Iniciar=1 Estado8 Esperar Multi:listo Multi:listo==0? Estado9 Multi:iniciar=0, Esperar Multi:listo Multi:listo==1? Estado10 op1=1, op2=Multi_resultado Estado11 Sumador:Iniciar=1, Sumar_restar=10 Estado12 Esperar Sumador:listo Sumador:listo==0? Estado13 Sumador:iniciar=0, Sumar_restar=00, Esperar Sumador:listo Sumador:listo==1? Estado14 op1=Eo=R0, op2=Sumador_resultado Estado15 Multi:Iniciar==1 Estado16 Falso=0 Estado0 Estado1 Estado4 Estado5 Estado8 Estado9 Estado12 Estado13 - 78 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado26 Estado27 Estado28 Estado29 Estado30 Estado31 Estado32 Estado33 Estado34 Estado35 Estado36 Estado37 Estado38 Estado39 Estado40 Estado41 Estado42 Estado43 Estado44 Esperar Multi:listo Multi:iniciar=1, Esperar Multi:listo m=2, i=1, E=Multi_resultado R[m-i], a[i], resultado=R[m] si i=1 Multi:Iniciar=1 Esperar Multi:listo Bajar Multi:iniciar,Esperar Multi:listo temporal[i]=multi_resultado i=m-1? i++ saltar a estado19 op2=copiar temporal[i], op1=resultado Sumador:Iniciar=1, Sumar_restar=10 Esperar Sumador:listo Sumador:iniciar, Sumar_restar=00, Esperar Sumador:listo q[m]=Sumador_resultado i=1? i-op1=resultado, op2=E Div:Iniciar=1 Esperar Div:listo Bajar Div:iniciar, Esperar Div:listo a[m] =k= div_resultado op1=op2=div_resultado Multi:Iniciar=1 Esperar Multi:listo Bajar Multi:iniciar,Esperar Multi:listo op1=1, op2=Multi_resultado Sumador:Iniciar=1, Sumador_restar=10 Esperar Sumador:listo Bajar Sumador:iniciar, bajar restar, Esperar Sumador:listo Multi:listo==0? Multi:listo==1? Multi:listo==0? Multi:listo==1? i==m-1? Sumador:listo==0? Sumador:listo==1? i==1? Div:listo==0? Div:listo==1? Multi:listo==0? Multi:listo==1? Sumador:listo==0? Sumador:listo==1? Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado26 Estado19 Estado27 Estado28 Estado29 Estado30 Estado31 Estado33 Estado26 Estado34 Estado35 Estado36 Estado37 Estado38 Estado39 Estado40 Estado41 Estado42 Estado43 Estado44 Estado45 Estado16 Estado17 Estado21 Estado22 Estado25 Estado28 Estado29 Estado32 Estado35 Estado36 Estado39 Estado40 Estado43 Estado44 79 Estado45 copiar op1=Sumador_resultado, op2=E Estado46 Multi:Iniciar=1 Estado47 Esperar Multi:listo Estado48 Bajar Multi:iniciar,Esperar Multi:listo Estado49 E=multi_resultado si i=1, op1=a[i], op2=K Estado50 Multi:Iniciar=1 Estado51 Esperar Multi:listo Estado52 Bajar Multi:iniciar,Esperar Multi:listo Estado53 temporal[i]=multi_resultado Estado54 i=m-1? Estado55 i++ saltar a estado49 Estado56 op2= temporal[i], op1=a[m-i] Estado57 Sumador:Iniciar=1, Sumar_restar=10 Estado58 Esperar Sumador:listo Estado59 Sumador:iniciar=0, Sumar_restar=10, Esperar Sumador:listo Estado60 a[m-i]=Sumador_resultado Estado61 i=1? Estado62 i--, saltar a estado56 Estado63 m=10? Estado64 m++ saltar a estado19 Tabla A.9 Diagrama de Estado de Coeficientes LPC A.10 Filtro de Análisis A.10.1 Registros Cont => contador de direcciones accedidas en la RAM. Cont_K => contador de operaciones del filtro. Multi:listo==0? Multi:listo==1? Multi:listo==0? Multi:listo==1? i==m-1? Sumador:listo==0? Sumador:listo==1? i==1? m==10? - Estado46 Estado47 Estado48 Estado49 Estado50 Estado51 Estado52 Estado53 Estado54 Estado56 Estado49 Estado57 Estado58 Estado59 Estado60 Estado61 Estado62 Estado56 Estado1 Estado19 Estado47 Estado48 Estado51 Estado52 Estado53 Estado55 Estado58 Estado59 Estado63 Estado64 - 80 Resultado => Resultado => Almacena el resultado del Sumador, Multiplicador, Divisor. RAM_dir => Almacena dirección de la RAM que está accediendo. RAM_escribir => Almacena estado para escritura en la RAM. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Multi_iniciar => Almacena el estado de inicio del circuito: Multiplicador. Div_iniciar => Almacena el estado de inicio del circuito: Divisor. Op1 => Almacena el operando1 para enviar al circuito: Sumador, Multiplicador, Divisor, Raíz cuadrada. Op2 => Almacena el operando2 para enviar al circuito: Sumador o Multiplicador. u1..10 => Almacena la entradas pasadas del filtro. Error => Almacena el error de predicción. Temp1..10 => Almacena las multiplicaciones parciales del filtro. RAIZ_iniciar => Almacena el estado de inicio del circuito: Raíz Cuadrada. FG_listo => Almacena el estado del circuito. A.10.2 Diagrama de Estado Estado Presente Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Descripción del estado Reset Listo=1 resultado=0, k=1, y[1…10]=0, cont=0, error=0 op1=u[k], op2= a[k] Multi:Iniciar=1 Esperar Multi:listo Multi:iniciar=0,Esperar Multi:listo temporal[k]=Multi_resultado Condición Reset==1? Iniciar==1? Multi:listo==0?? Multi:listo==1? - Próximo Estado Verdadero=1 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Estado8 Falso=0 Estado0 Estado1 Estado5 Estado6 - 81 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado26 Estado27 Estado28 Estado29 Estado30 Estado31 Estado32 Estado33 k=10? k++ saltar a estado3 op2=temporal[k], op1=resultado, u(k-1)=u(k) Sumador:Iniciar=1, Sumar_restar=01 Esperar Sumador:listo Sumador:iniciar=0, Sumar_restar=00, Esperar Sumador:listo resultado=Sumador_resultado k=1? k--, saltar a estado10 RAM lectura No se usa No se usa op1= RAM_dato, op2=resultado No se usa No se usa No se usa No se usa Sumador:Iniciar=1, Sumar_restar=10, u1=op1 Esperar Sumador:listo Sumador:iniciar=0, Sumar_restar=0, Esperar Sumador:listo op1=Sumador_resultado, op2=Sumador_resultado, i=0 No se usa No se usa No se usa No se usa Multi:Iniciar=1 k==10? Sumador:listo==0? Estado10 Estado3 Estado11 Estado12 Estado13 Estado9 Estado12 Sumador:listo==1? Estado14 Estado13 k==1? - Estado15 Estado17 Estado10 Estado20 Estado21 Estado26 Sumador:listo==0? Estado27 Estado16 Estado26 Sumador:listo==1? Estado28 Estado27 - Estado33 - - Estado34 - 82 Estado34 Estado35 Estado47 Estado48 Estado49 Esperar Multi:listo Multi:iniciar=0, Esperar Multi:listo op1=error, op2=Multi_resultado Sumar:Iniciar=1, Sumar_restar=01 Esperar Sumar:listo Sumar:iniciar=0, Sumar_restar=00, Estado50 Esperar Sumar:listo Estado36 error=Sumar_resultado Estado37 cont=160? Estado38 cont++, resultado=0 Estado39 op1=error, op2=R0 Estado40 Div:Iniciar=1 Estado41 Esperar Div:listo Estado42 Div:iniciar=0, Esperar Div:listo Estado51 op1=Div_resultado Estado43 RAIZ: Iniciar=1 Estado44 Esperar RAIZ:listo Estado45 RAIZ:iniciar=0,Esperar RAIZ:listo, Estado46 Saltar a estado1 Tabla A.10 Diagrama de Estado del Filtro de Análisis Multi:listo==0? Multi:listo==1? Sumar:listo==0? Estado35 Estado47 Estado48 Estado49 Estado50 Estado34 Estado35 Estado49 Sumar:listo==1? Estado36 Estado50 cont==160? Div:listo==0? Div:listo==1? RAIZ:listo==0? RAIZ:listo==1? - Estado37 Estado39 Estado3 Estado40 Estado41 Estado42 Estado51 Estado43 Estado44 Estado45 Estado46 Estado1 Estado38 Estado41 Estado42 Estado44 Estado45 - A.11 Filtro de Síntesis A.11.1 Registros Cont => contador de direcciones accedidas en la ROM de ruido. Cont_K => contador de operaciones del filtro. Cont_rotar => Almacena el desplazamiento al valor que se va almacenar en la DRAM. 83 SD_banco => Almacena el banco que se está accediendo en la DRAM. SD_fila => Almacena la dirección fila que se está accediendo en la DRAM. SD_columna => Almacena la dirección columna que se está accediendo en la DRAM. SD_escritura => Almacena el dato que se va a enviar a la DRAM. SD_escribir => Almacena estado para escritura en la DRAM. SD_iniciar => Almacena estado de inicio del circuito: controlador de memoria. Sumador_iniciar => Almacena el estado de inicio del circuito: Sumador. Sumar_restar =>Almacena el modo de suma o resta del circuito: Sumador. Multi_iniciar => Almacena el estado de inicio del circuito: Multiplicador. Resultado => Almacena el resultado del Sumador o Multiplicador. Op1 => Almacena el operando1 para enviar al circuito: Sumador o Multiplicador. Op2 => Almacena el operando2 para enviar al circuito: Sumador o Multiplicador. y1..10 => Almacena la salidas pasadas del filtro. Cont_pulso =>contador para generar los pulsos a la frecuencia del pitch. Temp1..10 => Almacena las multiplicaciones parciales del filtro. FPR_listo => Almacena el estado del circuito. A.11.2 Diagrama de Estado Estado Presente Descripción del estado Condición Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 columna=0,fila=0,banco=01 Listo=1 resultado=0, k=1, y[1…10]=0, cont=0 op1=y[k], op2= a[k] Multi:Iniciar=1 Esperar Multi:listo Reset==1? Iniciar==1? Multi:listo==0? Próximo Estado Verdadero=1 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Falso=0 Estado0 Estado1 Estado5 84 Estado6 Estado7 Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado26 Estado27 Estado28 Estado29 Estado30 Estado31 Estado32 Estado43 Multi:iniciar=0, Esperar Multi:listo temporal[k]=multi_Resultado k=10? k++ saltar a estado3 op2=temporal[k], op1=resultado, y(k-1)=y(k) Sumador:Iniciar=1, Sumar_restar=01 Esperar Sumador:listo Bajar Sumador:iniciar, bajar sumar, Esperar Sumador:listo resultado=Sumador_resultado k=1? k--, saltar a estado10 op1=entrada(segun Pitch) y op2=Ganancia Multi: Iniciar=1, Esperar Multi:listo Bajar Multi:iniciar,Esperar Multi:listo, op1=Multi_resultado, op2=resultado Sumador: Iniciar=1, Sumar_restar=01 Esperar Sumador:listo Bajar Sumador:iniciar,Esperar Sumador:listo, SD_escritura=Sumador_resultado, rotar= (140-exponente), cont_rotar=0 rotar=negativo? SD_escritura=ffff rotar>13? SD_escritura=0 cont_rotar=rotar? SD_escritura>>1, cont_rotar++ signo? ~SD_escritura+1 Multi:listo==1? k==10? Sumador:listo==0? Sumador:listo==1? k==1? Multi:listo==0? Multi:listo==1? Sumador:listo==0? Sumador:listo==1? Estado7 Estado8 Estado10 Estado3 Estado11 Estado12 Estado13 Estado14 Estado15 Estado17 Estado10 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado6 Estado9 Estado12 Estado13 Estado16 Estado19 Estado20 Estado23 Estado24 - Estado26 - rotar==negativo? rotar>13? cont_rotar==rotar? signo? - Estado27 Estado32 Estado29 Estado33 Estado31 Estado30 Estado43 Estado33 Estado28 Estado30 Estado32 Estado33 - 85 Estado33 SD: Iniciar=1, SD_escribir=1 Estado34 Esperar SD:listo Estado35 Bajar SD:iniciar, Estado36 Saltar si es columna es 1022 (máximo) Estado37 Columna+2 saltar a estado41 Estado38 No se usa Estado39 Fila++, columna=0 Estao40 No se usa Estado41 cont=160? Estado42 cont_pulso++,cont++, resultado=0 Tabla A.11 Diagrama de Estado del Filtro de Síntesis SD:listo==0? SD:listo==1? SD_columna= 1022 cont==160? - Estado34 Estado35 Estado36 Estado39 Estado41 Estado41 Estado1 Estado3 A.12 Sumador/Restador A.12.1 Registros Op1 => almacena el sumando1 o minuendo. Op2 => almacena el sumando2 o sustraendo. Signo => almacena el signo del resultado. Exponente => almacena el exponente del resultado. Mantisa => almacena la mantisa del resultado. Listo => almacena el estado de Sumador/Restador. A.12.2 Diagrama de Estado Estado Pre- Descripción del estado Condición Próximo Estado Estado34 Estado35 Estado37 Estado42 - 86 sente Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado23A Estado24A Estado8 Estado9 Estado10 Estado11 Estado12 Estado13 Estado14 Estado15 Estado16 Estado17 Estado18 Estado19 Estado20 Estado21 Estado22 Estado23 Estado24 Estado25 Estado26 Reset Reset==1? op1=Operando1, op2=Operando2 Iniciar==1? Suma Suma==1? Resta Resta==1? op1=0? op1==0? resultado=op2 op2=0? op2==0? resultado=op1 Alineacion? Exponentes iguales? Exp_op1==exp_op2? Signo op1? Op1 negativo? op1= ~op1+1 Signo op2? Op2 negativo? op2= ~op2+1 Mantisa_resultado=mantisa_op1+ mantisa_op2 mantisa=cero? mantisa==cero? Resultado negativo? Resultado negativo? ~Mantisa_resultado+1, signo_resultado=1 Rebase? Rebase? Exp_resultado_max? Exp_resultado_max? listo Normalizado? Normalizado? Exp_resultado_min? Exp_resultado_min? Normalizar Error overflow Resta cambio signo_op2=~signo_op2 Op1==0? Exp1_op1 > exp2_op2 Exp1_op1 > exp2_op2? mantisa_op2>>1, exp_op2++ - Verdadero=1 Estado1 Estado2 Estado4 Estado24 Estado5 Estado1 Estado24A Estado1 Estado9 Estado10 Estado11 Estado12 Estado13 Estado13 Estado28 Estado16 Estado17 Estado18 Estado23 Estado1 Estado21 Estado22 Estado20 Estado1 Estado4 Estado26 Estado8 Falso=0 Estado0 Estado1 Estado3 Estado1 Estado23A Estado8 Estado25 Estado11 Estado13 Estado15 Estado17 Estado20 Estado19 Estado1 Estado29 Estado30 Estado27 - 87 Estado27 Mantisa_exp1>>1, Exp_op1++ Estado28 resultado =0 Estado29 Error underflow Estado30 Cambio signo_op2=~signo_op2 Tabla A.12 Diagrama de Estado del Sumador/Restador - Estado8 Estado1 Estado1 Estado4 - A.13 Multiplicador A.13.1 Registros Cont => almacena la cuenta de multiplicaciones parciales. Op1 => almacena el multiplicando. Op2 => almacena el multiplicador. Signo => almacena el signo del resultado. Exponente => almacena el exponente del resultado. Mantisa => almacena la mantisa del resultado. Listo => almacena el estado de multiplicador. A.13.2 Diagrama de Estado Estado Presente Estado0 Estado1 Estado2 Estado3 Estado4 Descripcion del Estado Condicion Reset Copiar operandos, listo=1 exp1+exp2 Resultado=0 XOR signos, exp_resultado-127, mantisa_resultado =0 Reset==1? Iniciar==1? op1 OR op2 ==0? - Proximo Estado Verdadero=1 Falso=0 Estado1 Estado0 Estado2 Estado1 Estado3 Estado4 Estado16 Estado5 - 88 Estado5 revisar si nuevo exponente rebase arriba Estado6 revisar si nuevo exponente rebase abajo, cont=0 Estado7 mantisa_resultado + (op1&op2[22]), cont++ Estado8 Estado9 op2 <<1 y mantisa_resultado<<1 Estado10 No se usa Estado11 Resultado Normalizado Estado12 mantisa_resultado>>1,exp_resultado++ Estado13 No se usa Estado14 Error, exp_resultado rebase arriba Estado15 Error, exp_resultado rebase abajo Estado16 Listo Tabla A.13 Diagrama de Estado del Multiplicador A.14 Divisor A.14.1 Registros Op1 => almacena el dividendo. Op2 => almacena el divisor. Signo => almacena el signo del resultado. Exponente => almacena el exponente del resultado. Mantisa => almacena la mantisa del resultado. Listo => almacena el estado de divisor. A.14.2 Diagrama de Estado exp_resultado_max? exp_resultado_min? cont ==24? Resultado normalizado? - Estado14 Estado15 Estado8 Estado11 Estado7 Estado12 Estado11 Estado16 Estado16 Estado1 Estado6 Estado7 Estado9 Estado16 - 89 Estado Presente Descripción del Estado Estado0 Estado 1 Estado 2 Reset Copiar operandos, listo=1 op1_exp1-op2_exp2 XOR signos, exp_resultado+127, mantisa_resultado Estado 3 =0 Estado 4 op1<op2 Estado 5 exp_resultado-- , Op1<<1 Estado 6 exp_min Estado 14 exp_max Estado 7 op1>=op2 Estado 8 op1-op2, mantisa_resultado +1 Estado 9 op1<<1 Estado 10 Mantisa_resultado<<1 y saltar a 1 Estado 11 Error Estado 12 Resultado =0 Estado 13 Listo=1 Tabla A.14 Diagrama de Estado del Divisor A.15 Raíz Cuadrada A.15.1 Registros Cont => contador de rotaciones de op1. Reset==1? Iniciar==1? Op2==0? Próximo Estado Falso Verdadero=1 =0 Estado1 Estado0 Estado2 Estado1 Estado3 Estado11 Op1==0? Estado4 Estado12 Op1>=op2? exp_resultado_min? exp__resultado_max? op1>=op2? Resultado Normalizado? - Estado6 Estado6 Estado12 Estado11 Estado8 Estado9 Estado13 Estado7 Estado13 Estado13 Estado1 Estado5 Estado14 Estado7 Estado9 Estado10 - Condición 90 Rotaciones => contador de rotaciones de op2. Op1 => almacena el radicando. Op2 => almacena el operando auxiliar para obtener la raíz cuadrada. Signo => almacena el signo del resultado. Exponente => almacena el exponente del resultado. Mantisa => almacena la mantisa del resultado. Listo => almacena el estado del circuito. A.15.2 Diagrama de Estado Estado Descripción del Estado Estado0 Estado1 Estado2 Estado3 Estado4 Estado5 Estado6 Estado7 Estado8 Estado9 Reset Op1=operando1 op1 ==0 resultado=0 Exp_op1-127 Exp_op1_par? Mantisa_op1>>1 Exp_op1_neg? Exp_op1>>1 completado con 1 Exp_op1>>1 Mantisa_resultado=0, Estado10 op2=01000000000000000000000000 Estado11 mantisa_op1=mantisa_op1-mantisa_op2 Estado12 mantisa_op1 negativo? Condición Próximo Estado Reset==1? Iniciar==1? op1 ==0? op1_exp es par? op1_exp es negativo? - Verdadero=1 Estado1 Estado2 Estado3 Estado1 Estado5 Estado6 Estado7 Estado8 Estado10 Estado10 Falso=0 Estado0 Estado1 Estado4 Estado7 Estado9 - - Estado11 - mantisa_op1 negativo? Estado12 - Estado14 Estado13 91 Estado13 mantisa_resultado++, cont-Estado14 mantisa_op1=mantisa_op1+mantisa_op2 Estado15 Mantisa_op1<<2 Estado16 Resultado normalizado? Estado17 Mantisa_resultado<<1 Estado18 Mantisa_op2= mantisa_resultado<<1+1,rotaciones=0 Estado19 rotaciones==cont? Estado20 Mantisa_op2<<2, rotaciones++ Tabla A.15 Diagrama de Estado de la Raíz Cuadrada Resultado normalizado? rotaciones==cont? - Estado16 Estado15 Estado16 Estado1 Estado18 Estado19 Estado11 Estado19 Estado17 Estado20 - APÉNDICE B: Modelos Matemáticos y Algoritmos de LPC Para el método de codificación predictiva lineal se parte de la siguiente ecuación en diferencias: M ~ x (n) = a1 x(n − 1) + a 2 x(n − 2) + ... + a M x(n − M ) = ∑ ai x(n − i ) (1) i =1 Esta ecuación indica que la muestra presente de la señal de voz x(n) se puede predecir mediante ~ x (n) a partir de una combinación lineal de M muestras pasadas x(n-i) donde los ai son los coeficientes lineales de predicción. La cantidad de muestras pasadas que se utiliza define el orden del filtro IIR. Este sistema es no causal puesto que si se evalúa la expresión (1) en n=0, se observa que se requieren de muestras en un tiempo negativo, esto se resuelve acumulando el número de muestras necesarios para realizar la primera predicción, lo cual provoca un retardo en la transmisión y procesamiento de la señal de voz. El error entre la muestra actual y la predicha se puede expresar de la siguiente forma: M ε (n) = x(n) − ~x (n) = x(n) − ∑ ai x(n − i ) (2) i =1 Entre menor sea el error, mejor es la predicción del modelo. Por lo que se busca que los coeficientes ai minimicen la suma del error cuadrático: M E = ∑ ε ( n) = ∑ x ( n) − ∑ a i x ( n − i ) n n i =1 2 2 (3) Para minimizar el error cuadrático, se debe derivar E con respecto a cada uno de los coeficientes ai, utilizando la regla de la cadena e igualando cada ecuación a cero. La expresión resultante es la siguiente: M 2∑ x(n − k ) x(n) − ∑ a i x(n − i ) = 0 Para k= 1,2,3,…,M n i =1 (4) De la expresión anterior se obtienen M incógnitas y M ecuaciones de la siguiente forma: 92 93 a1 ∑ x(n − k ) x(n − 1) + a 2 ∑ x(n − k ) x(n − 2) + ... + a M ∑ x(n − k ) x(n − M ) = ∑ x(n − k ) x(n) n n n (5) n Para k=1,2,3,…,M Se considera que la señal de voz es dividida en segmentos con N muestras. El tamaño de los segmentos es lo suficientemente corto que se puede considerar que el segmento está estacionario, es decir el tracto vocal va estar fijo durante este periodo de tiempo, debido al comportamiento de la voz, anteriormente mencionado. El tamaño de cada segmento usualmente se escoge entre 20 a 30 ms. Para este proyecto se la señal de voz se muestreó a 8000Hz y con un tamaño de segmento de 20ms, por lo tanto se tuvieron segmentos de 160 muestras. Si hay N muestras en cada segmento con valores desde 0 a N-1, es decir x(0), x(1), x(2), x(3)…x(N-1), la expresión (5) se puede expresar de forma aproximada en términos de una matriz ecuación de la siguiente manera: (6) Con r(k) igual: r (k ) = N −1− k ∑ x ( n) x ( n + k ) (7) n=0 Donde se puede despejar a utilizando la matriz inversa de R: a=R-1 r (8) Esta ecuación se decidió resolver mediante el algoritmo recursivo Levinson-Durbin, sin la necesidad de la inversión de matriz. 94 Después de resolver la ecuación se obtienen los coeficientes de predicción ai, que permite obtener la secuencia de error ε(n), donde x(n) es la entrada y ε(n) las salida, esto es conocido como filtro de análisis: Figura 6. Filtro de análisis de voz Donde A(z) viene dado por la siguiente expresión: M A( z ) = 1 − ∑ ai z −i (9) i =1 La ecuación (1) se puede reescribir como una ecuación de un filtro digital donde ε(n) es la entrada y la salida es x(n): M x ( n) = ∑ a i x ( n − i ) + ε ( n ) (10) i =1 La implementación de la ecuación (9) es llamada el filtro de síntesis: Figura 7. Filtro IIR todo polos para síntesis de voz En ambos filtros, de análisis y de síntesis, se tiene disponible los coeficientes de predicción lineal y la secuencia de error residual, la señal de voz se puede reconstruir utilizando el filtro de síntesis. En la práctica la mayoría de sistemas, necesitan que los coeficientes y el error sea comprimido antes de al transmisión. Por está razón en vez de cuantizar el error, muestra por muestra, se transmiten solo parámetros importantes como el periodo del pitch, tipo de sonido y la intensidad de la excitación. Para estimar el periodo del Pitch se utilizó la función de diferencia de la magnitud promedio (AMDF). Este método supone que una señal x(n) es periódica con periodo T. La diferencia entre dos muestras x(n)-x(n+k) va a ser cero par k = 0, ±T, ±2T y así sucesiva- 95 mente. Un sonido con voz no exactamente periódico, por lo que se define una función de corto tiempo de la diferencia de la magnitud promedio: AMDF (k ) = 1 N −k N −1− k ∑ x ( n) − x ( n + k ) , k > 0 (11) n =0 Para determinar si el segmento de muestras que se analiza es un sonido con o sin voz, se utilizó la razón de cruce por cero. El razón de cruce por cero se obtiene contando los cambios de signos (en ambos sentidos) en las muestras de voz sucesivas. La razón de cruce por cero (ZCR) de un sonido con voz es menor que la de un sonido sin voz. Finalmente el último parámetro de interés es la ganancia de del filtro digital IIR todo polos. Para el cálculo de la ganancia se utilizó la secuencia de error de la siguiente forma: N −1 G 2 = ∑ ε 2 (n) n =0 (12) APÉNDICE C: Código en Matlab, equivalente en Software del circuito diseñado %//////////////////////////////////////////////////////////////////////////////////////////////// %Universidad de Costa Rica. Junio 2008 %Proyecto de Licenciatura %Procedimiento de diseno e implementacion de circuitos digitales utilizando herramientas EDA de codigo abierto %Gerardo Castro Jimenez %A31287 %//////////////////////////////////////////////////////////////////////////////////////////////// %Descripcion: % Codigo en Matlab equivalente en Software al Codificador/Decodificador de voz disenado. % %//////////////////////////////////////////////////////////////////////////////////////////////// clear; tiempo =20; %Tamano de trama de voz 20ms polos =10; %Numero de polos utilizados en la prediccion lineal %Grabacion de voz a codificar mediante LPC [x,fs,bit]=wavread('prueba_hombre_pcm8khz_16bit') %Numero de segmentos de la señal a sintetizar N=fs*(tiempo/1000); N= round(N); %Ruido gaussiano predefinido (equivalente a ROM de Ruido) ra=zeros(1,N); g=1; while (g<161) ra(1,g)=randn; if (abs(ra(1,g))<=1) g=g+1; end end j=1; i=1; %numero de segmento a analizar %numero de muestras %Numero de segmentos de acuerdo al tamaño del archivo de prueba Seg = round(length(x)/N)-1; %------------------------------------- 96 97 % Codificación LPC %------------------------------------for i=1:Seg; y1=x(j:j+N-1); % se define el segmento a codificar y=y1; promedio= sum (y1)/length(y1); y1=y1-promedio; %-----------------------------------------------------------------------%Procedimiento Cruces por cero para determinar si el segmento %corresponde a un sonido con voz o sin voz %-----------------------------------------------------------------------% se define el primer valor como maximo bandera =0; %variable contador=0; % se define el contador de segmentos % Cuenta el numero de veces que la señal cambia de positiva a negativa y % viceversa for s=1:N if y1(s)<0 if bandera ==0; contador = contador +1; bandera =1; end end if y1(s)>=0 if bandera ==1 contador = contador +1; bandera=0; end end end %Toma el valor del contador y lo pone en una variable %cruces por cero = zcrs zcrs(i)=contador; if zcrs(i)>25 %Implica sonido sin voz. Se utiliza una frontera de 25 %cruces por segmento para determinar de un sonido con voz resultado(i)=1; else % implica sonido sin voz resultado(i)=2; end 98 %-----------------------------------------------------------------------%Procedimiento Levinson-Durbin para encontrar los coeficientes de prediccion lineal %-----------------------------------------------------------------------R=zeros(1,11); a1=zeros(1,10); for i1=1:1:11 for i2=1:1:160-i1 R(1,i1)= R(1,i1) + (y(i2)*y(i2+i1-1)); end end R2(i,1)=R(1,1); E=R(1,1); k=R(1,2)/E; a1(1,1)=k; E=E*(1-k*k); for m=2:1:10 temp=0; for i1=1:1:m-1 temp= temp + a1(1,i1)*R(1,m-i1+1); end q= R(1,m+1) - temp; k=q/E; E=E*(1-k*k); b=zeros(1,10); for i1=1:1:m-1 b(1,i1)=a1(1,i1)-k*a1(1,m-i1); end a1=b; a1(1,m)=k; end a(i,1:(polos))= a1; %-----------------------------------------------------------------------%Filtro de Analisis %-----------------------------------------------------------------------error=zeros(1,N); error(1,1) error(1,2) error(1,3) error(1,4) = = = = y(1); y(2)-a(i,1)*y(1); y(3)-a(i,1)*y(2)-a(i,2)*y(1); y(4)-a(i,1)*y(3)-a(i,2)*y(2)-a(i,3)*y(1); 99 error(1,5) = y(5)-a(i,1)*y(4)-a(i,2)*y(3)-a(i,3)*y(2)-a(i,4)*y(1); error(1,6) = y(6)-a(i,1)*y(5)-a(i,2)*y(4)-a(i,3)*y(3)-a(i,4)*y(2)-a(i,5)*y(1); error(1,7) = y(7)-a(i,1)*y(6)-a(i,2)*y(5)-a(i,3)*y(4)-a(i,4)*y(3)-a(i,5)*y(2)-a(i,6)*y(1); error(1,8) = y(8)-a(i,1)*y(7)-a(i,2)*y(6)-a(i,3)*y(5)-a(i,4)*y(4)-a(i,5)*y(3)-a(i,6)*y(2)-a(i,7)*y(1); error(1,9) = y(9)-a(i,1)*y(8)-a(i,2)*y(7)-a(i,3)*y(6)-a(i,4)*y(5)-a(i,5)*y(4)-a(i,6)*y(3)-a(i,7)*y(2)-a(i,8)*y(1); error(1,10) = y(10)-a(i,1)*y(9)-a(i,2)*y(8)-a(i,3)*y(7)-a(i,4)*y(6)-a(i,5)*y(5)-a(i,6)*y(4)-a(i,7)*y(3)-a(i,8)*y(2)a(i,9)*y(1); for c=11:1:N error(1,c) = y(c)-a(i,1)*y(c-1)-a(i,2)*y(c-2)-a(i,3)*y(c-3)-a(i,4)*y(c-4)-a(i,5)*y(c-5)-a(i,6)*y(c-6)-a(i,7)*y(c7)-a(i,8)*y(c-8)-a(i,9)*y(c-9)-a(i,10)*y(c-10); end error2=0; for f=1:1:N error2=error2+error(1,f).*error(1,f); end %Calculo de la ganancia ganancia(i)=sqrt(error2); %-----------------------------------------------------------------------%Procedimiento AMDF para la deteccion del Pitch %-----------------------------------------------------------------------for k=1:N Amdf(k) =0; for n = 1:N-k; Amdf(k) = Amdf(k) + abs(y(n)-y(n+k)); end; Amdf(k) = (Amdf(k)/(N-k+1)); end [Y,I]=min(Amdf(20:N)); pitch(i) = (I(1)+19); %------------------------------------% Decodificación LPC %------------------------------------if (resultado(i)==2) impgen= zeros (1,N); cont=1; while pitch(i)*cont < N; impgen (1,cont*pitch(i)) = 1; cont=cont+1; end impgen (1,1) = 1; 100 else impgen=ra; end %-----------------------------------------------------------------------%Filtro de Sintesis %-----------------------------------------------------------------------salida=zeros(1,N); salida(1,1) = impgen(1,1)*ganancia(i); salida(1,2) = impgen(1,2)*ganancia(i)+ salida(1,1)*a(i,1); salida(1,3) = impgen(1,3)*ganancia(i)+ salida(1,2)*a(i,1) + salida(1,1)*a(i,2); salida(1,4) = impgen(1,4)*ganancia(i)+ salida(1,3)*a(i,1) + salida(1,2)*a(i,2) + salida(1,1)*a(i,3); salida(1,5) = impgen(1,5)*ganancia(i)+ salida(1,4)*a(i,1) + salida(1,3)*a(i,2) + salida(1,2)*a(i,3) + salida(1,1)*a(i,4); salida(1,6) = impgen(1,6)*ganancia(i)+ salida(1,5)*a(i,1) + salida(1,4)*a(i,2) + salida(1,3)*a(i,3) + salida(1,2)*a(i,4) + salida(1,1)*a(i,5); salida(1,7) = impgen(1,7)*ganancia(i)+ salida(1,6)*a(i,1) + salida(1,5)*a(i,2) + salida(1,4)*a(i,3) + salida(1,3)*a(i,4) + salida(1,2)*a(i,5) + salida(1,1)*a(i,6); salida(1,8) = impgen(1,8)*ganancia(i)+ salida(1,7)*a(i,1) + salida(1,6)*a(i,2) + salida(1,5)*a(i,3) + salida(1,4)*a(i,4) + salida(1,3)*a(i,5) + salida(1,2)*a(i,6) + salida(1,1)*a(i,7); salida(1,9) = impgen(1,9)*ganancia(i)+ salida(1,8)*a(i,1) + salida(1,7)*a(i,2) + salida(1,6)*a(i,3) + salida(1,5)*a(i,4) + salida(1,4)*a(i,5) + salida(1,3)*a(i,6) + salida(1,2)*a(i,7) + salida(1,1)*a(i,8); salida(1,10) = impgen(1,10)*ganancia(i)+ salida(1,9)*a(i,1) + salida(1,8)*a(i,2) + salida(1,7)*a(i,3) + salida(1,6)*a(i,4) + salida(1,5)*a(i,5) + salida(1,4)*a(i,6) + salida(1,3)*a(i,7) + salida(1,2)*a(i,8) + salida(1,1)*a(i,9); for c=11:N salida(c) = impgen(1,c)*ganancia(i)+ salida(1,c-1)*a(i,1) + salida(1,c-2)*a(i,2) + salida(1,c-3)*a(i,3) + salida(1,c-4)*a(i,4) + salida(1,c-5)*a(i,5) + salida(1,c-6)*a(i,6) + salida(1,c-7)*a(i,7) + salida(1,c-8)*a(i,8) + salida(1,c9)*a(i,9) + salida(1,c-10)*a(i,10); end final(j:j+N-1)=salida; j=N+j; % Aumento para el proximo segmento end; % Grafico la señal de entrada y la señal de Salida de audio subplot (2,1,1); plot(x,'g'); title ('Sonido Original'); subplot(2,1,2); plot(final,'r'); title ('Sonido Codificado'); 101 sound(final, fs); %Reproduccion wavwrite(final,'prueba_hombre_pcm8khz_16bit_matlab'); %Creacion de un archivo .wav APÉNDICE D: Problemas de temporización durante la etapa de implementación. D.1 Problema de convergencia de la arquitectura microprogramada En un principio, las máquinas de estado del codificador/decodificador de voz se diseñaron con un controlador microprogramado como se muestra a continuación: Figura D.1 Arquitectura microprogramada Las máquinas de estado debían funcionar a una frecuencia de reloj de 50 MHz, sin embargo la frecuencia de reloj de esta arquitectura disminuía conforme la memoria ROM se hacia 102 103 más grande, es decir cuando se agregaban más estados o micro instrucciones. Esto porque los multiplexores de selección debían direccionar más posiciones de memoria, aumentando la lógica próximo de estado, los niveles lógicos y los retardos. Por esta razón se utilizó la arquitectura one-ho,t que minimiza lo lógica de próximo estado, con el fin de cumplir con la frecuencia deseada de 50MHz. Figura D.2 Arquitectura one-hot D.2 Problema de alineación entre relojes El codificador/decodificador posee un reloj de referencia de 50 MHz que proviene del oscilador presente en la tarjeta de desarrollo del SPARTAN3E. El circuito se comunica con 3 dispositivos externos: ADC, DAC y DRAM. Los dispositivos ADC y DAC utilizan un reloj de 5 MHz y la DRAM utiliza dos relojes 100MHz y 100MH@180°. Para el diseño del circuito controlador de memoria, se utilizó un reloj de 50MHz@90°, con el fin de controlar a DRAM con una frecuencia más baja y facilitar la convergencia en la temporización. Por esta razón todos los circuitos del codifica- 104 dor/decodificador utilizan un reloj de 50MHz@90°, con el fin de mantener una alineación entre las máquinas de estado. Sin embargo los circuitos controladores del ADC y DAC no se corrieron los 90°, provocando un problema de temporización cuando estos circuitos interactuaban con el circuito controlador de reproducción. Estos problemas no se identificaron en la simulación funcional, ya que esta simulación es ideal (sin retardos). A continuación se presenta un diagrama temporal del problema: Reloj de Referencia 50MHz Reloj 2X Reloj 2X180° Reloj 90° MAQUINA DE ESTADO A ESTADO PRESENTE REGISTRO Estado Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Reloj 5MHz MAQUINA DE ESTADO B ESTADO PRESENTE REGISTRO Estado 0 Asignación 0 Asignación 1 5ns 5ns Problema de Temporización Figura D.3 Diagrama temporal, problema de alineación de relojes Como se observa, la máquina A utiliza un reloj de 50MHz@90° y la máquina B utiliza un reloj 5MHz. Cuando un registro de la máquina B cambiaba y generaba un cambio de estado en la máquina A y viceversa, se ocasionaba el problema de temporización ya que el 105 cambio en el registro se debía propagar en 5 ns, lo cual no era posible por razones de niveles lógicos y enrutamiento. Para solucionar este problema se recurrió a cambiar el reloj de 50MHz@90° por uno de 50MHz@270°, este desplazamiento aportaba 10ns extras para eliminar el problema y obtener un circuito libre de errores temporales. A continuación se muestra el diagrama temporal con la solución: Reloj de Referencia 50MHz Reloj 2X Reloj 2X180° Reloj 270° MAQUINA DE ESTADO A ESTADO PRESENTE REGISTRO Estado Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Estado Asignación Reloj 5MHz MAQUINA DE ESTADO B ESTADO PRESENTE REGISTRO Estado 0 Asignación 0 Asignación 1 15ns 15ns Temporización adecuada Figura D.4 Diagrama temporal, solución al problema de alineación de relojes Se observa, que el desplazamiento del reloj, permite que el cambio en el registro se logre propagar ya que ahora posee 15ns de tiempo y se de el cambio de estado en forma adecuada. APÉNDICE E: Guía del procedimiento de diseño e implementación de circuitos digitales utilizando herramientas EDA de código abierto. 106