Práctica 2: VHDL y FPGAs Tutorial del MAX+plus II y Tarjeta con FLEX EPF8282ALC84-4 La práctica consiste en el diseño VHDL de un sistema digital para un dispositivo FPGA de la familia FLEX 8000 de Altera. En concreto el diseño estará basado en una placa con el dispositivo EPF8282ALC84-4. Las especificaciones del dispositivo FLEX8000 se encuentra en el anexo del documento. El diseño del sistema digital deberá realizar el control de uno de los módulos PROMAX usados con el microinstructor TM683, pero realizando el control mediante una FPGA que mapea un circuito digital diseñado en VHDL. El diseño y simulación del código VHDL se realizará usando el programa MAX+plus II de Altera. Se incluye un breve tutorial del diseño y simulación de un sistema digital que usaría la misma placa El tutorial explicado a continuación es un diseño jerárquico de un sistema que cuenta de 0 a 9 mientras se pulse una tecla, sacando el resultado por un display de 7 segmentos. El sistema completo es llamado tutor y estará diseñado en un fichero tutor.vhd, que será el diseño de jerarquía superior. Este sistema estará compuesto a su vez de dos sistemas de menor jerarquía, un contador BCD y un decodificador de 7 segmentos. El contador estará diseñado en un fichero contador.vhd que contiene un diseño secuencial con su señal de reloj clk, la señal de reset asíncrono activa a bajo nivel n_rst, y una señal de habilitación e para contar hacia arriba. El otro sistema es un sistema combinacional que decodifica la salida del contador para un display de 7 segmentos Puerto paralelo PC Fuente de alimentación VDD Generador de funciones n_inc clk tutor o 7 n_rst o(6)=a o(5)=b o(4)=c o(3)=d o(2)=e o(1)=f o(0)=g a f g e EPF8282 ALC84-4 b c d tutor U1 Módulo Promax • • • • El puerto paralelo del PC se usa para programar la memoria SRAM de configuración dispositivo, con el programa Flex.exe El conector de fuente de alimentación se usa junto con la fuente de alimentación laboratorio El conector del generador de funciones se conecta para generar la señal de reloj dispositivo. El conector del módulo promax conecta los PB<7:0> y PA<7:0> a pines de usario dispositivo. SEÑAL PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 CLK PIN EPF8282 8 15 18 22 25 30 35 39 51 56 60 63 67 71 76 81 12 n_inc del del del clk e contador clk cont U2 4 a dec7seg b 7 o n_rst n_rst del 1. Crear una carpeta TUTORIAL en un directorio de trabajo. Esta es la carpeta donde se guardarán los ficheros VHDL y los archivos generados por el MAX+plus II 2. Arrancar el programa MAX+plus II de diseño para dispositivos de Altera. 3. Crear un nuevo fichero de texto, para editar el diseño VHDL. Para ello presionar el icono de nuevo fichero y seleccionar en el diálogo el tipo de fichero texto. entity dec7seg is port ( a: in std_logic_vector(3 downto 0); b: out std_logic_vector(6 downto 0) ); end dec7seg; Nuevo fichero architecture comb of dec7seg is begin with a select b<= "1111110" when "0110000" when "1101101" when "1111001" when "0110011" when "1011011" when "1011111" when "1110000" when "1111111" when "1110011" when "0000000" when end comb; Fichero de texto (VHDL) "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", others; 7. Guardar el fichero seleccionando icono de guardar, cambiar la extensión del fichero a VHD y usar como nombre de fichero dec7seg. 4. Se abrirá una ventana de edición de texto donde se realizará el diseño VHDL. 5. Seleccionar del menu File|Project|Name y seleccionar la carpeta TUTORIAL del directorio de trabajo, y cambiar el nombre de proyecto a TUTORIAL Guardar fichero Nombre del fichero VHDL Fichero de texto (VHDL) Directorio de almacenamiento del proyecto Nombre del proyecto Seleccionar extensión VHD para fichero VHDL 8. Crear y guardar un nuevo fichero contador.vhd siguiendo los anteriores pasos, con el siguiente código: 6. Escribir código del primer fichero de VHDL, un decodificador de 7 segmentos: library ieee; use ieee.std_logic_1164.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity contador is port ( clk, n_rst: in std_logic; e: in std_logic; cont: out std_logic_vector(3 downto 0)); end contador; architecture seq of contador is signal icont: unsigned(3 downto 0); begin cont<=conv_std_logic_vector(icont,4); process(clk, n_rst, e) begin if n_rst='0' then icont<="0000"; elsif clk='1' and clk'event then if e='1' then if icont=9 then icont<="0000"; else icont<=icont+1; end if; end if; end if; end process; end seq; 10. Seleccionar la ventana con el fichero de mayor jerarquía (tutor.vhd) y seleccionar del menú Project|Set Project to Current File Seleccionar fichero VHDL de mayor jerarquía 9. Crear y guardar un nuevo fichero tutor.vhd que unirá los otros dos ficheros VHDL para crear el diseño de jerarquía superior: library ieee; use ieee.std_logic_1164.all; entity tutor is port ( clk, n_rst: in std_logic; n_inc: in std_logic; o: out std_logic_vector(6 downto 0)); end tutor; architecture struct of tutor is component contador is port ( clk, n_rst: in std_logic; e: in std_logic; cont: out std_logic_vector(3 downto 0)); end component; component dec7seg is port ( a: in std_logic_vector(3 downto 0); b: out std_logic_vector(6 downto 0) ); end component; signal s: std_logic_vector(3 downto 0); signal inc: std_logic; begin inc<=not n_inc; u1: contador port map(clk,n_rst,inc,s); u2: dec7seg port map(s,o); end struct; 11. Seleccionar el dispositivo EPF8282ALC84-4 usado en la placa, con el menu Assign|Device Familia FLEX8000 EPF8282ALC84-4 Desactivar la opción 12. Seleccionar los pines que se usarán de la FPGA para las señales de entrada/salida del diseño. La señales clk debe ir al pin 12 que está conectado a la entrada de reloj de la placa. La señal n_rst y reset, mientras que las señales n_inc y o(6:0) deberán ir en pines de usuario, dependiendo como estén conectados los pulsadores y el display de 7 segmentos a la FPGA. Para la selección de los pines seleccionar del menú Assign|Pin/Location/Chip. A cada señal se le debe asignar un pin, escribiendo la señal directamente |nombre_señal o buscándola de la lista, asignándole el pin del control de selección, y finalmente añadir la asignación señal-pin a la lista que será tenida en cuenta durante el proceso de compilación del diseño. Pin asignado Compilar proyecto Nombre de la señal Escoger señal Añadir señal y pin asignado a la lista 13. El siguiente paso es compilar el proyecto. Este proceso está compuesto de varios pasos, entre los cuales está la síntesis y el proceso de placement&routing. También se extrean los parámetros necesarios para poder hacer una simulación post-layout, incluyendo los retardos de los recursos lógicos y rutado. Proyecto compilado sin errores 14. Se puede visualizar un report del resultado de la compilación, que se almacena en un fichero tutor.rpt. Para visualizarlo se puede usar la visualización de la jerarquía del diseño, donde aparece que tutor.vhd está compuesto por U1 tipo contador.vhd y U2 tipo dec7seg.vhd. Haciendo doble click sobre tutor.rpt se habre el fichero de report, donde aparecen, entre otros datos, el número de células lógicas (LC) usadas en valor absoluto y en % respecto al número total de LCs del dispositivo, y los pines asignados para las señales. Ver jerarquía del proyecto Report del resultado de la compilación 15. Para realizar la simulación es necesario crear un fichero de estimulación llamado tutor.scf, en el que se estimulan o dan valores a las señales de entrada al circuito en función del tiempo, y permitirá ver como evolucionan las señales de salida para verificar el correcto funcionamiento del circuito. Para crear el fichero se pulsa el icono de nuevo fichero, y en el diálogo se selecciona fichero de estimulación scf. Tiempo de simulación Tamaño del grid del tiempo Nuevo fichero Fichero de estimulos (SCF) 16. Se abre entonces una ventana gráfica donde se dibujarán las formas de onda de las señales de entrada en función del tiempo, y se obtendrán en esta la forma de onda de las señales de salida. Por defecto el tiempo de simulación es 1us, pero se puede cambiar con el menú File|End Time, que abre una ventana de diálogo para modificarlo. También es posible cambiar el grid para el dibujo de las señales (resolución del dibujo de las formas de onda) con el menú Options|Grid Size. En este ejemplo se usará un tamaño de grid de 25ns y un tiempo de simulación de 500ns. 17. Se pasa a continuación a seleccionar todas las señales de entrada (clk, n_rst, n_inc), y todas las señales de salida (o6, o5…o0). Para ello seleccionar del menú contextual (boton derecho del ratón) de la ventana de formas de onda la opción Enter Nodes from SNF. En la ventana de diálogo seleccionar tipos de señales de entrada (I) y salida (O), listar las señales, seleccionar todas y añadirlas para su visualización. La forma más rápida de seleccionar un rango de señales es seleccionar la primera, y después la última manteniendo la tecla SHIFT del teclado apretada. Seleccionar y añadir señales a visualizar Tipos de señales a listar 18. Se pueden añadir más señales internas (B) para comprobar nodos que no son de entrada/salida del circuito. En este caso se visualizará la entrada a del dec7seg (es la salida del contador). Debido al proceso de síntesis las señales internas cambian de nombre o desaparecen por optimizaciones. Se puede volver a usar el método anterior para añadir varias señales, o usar la opción Insert Node del menú contextual para añadir una única señal. En este caso se añade la señal |dec7seg:u2|a Seleccionar y añadir la señal a visualizar Tipos de señales a listar 19. Para visualizar más cómodamente las salidas o6, o5…o0 se pueden agrupar varias señales seleccionándolas todas y con el menú contextual seleccionar Enter Group. En la ventana de diálogo es posible seleccionar el formato de representación entre binario, decimal, octal o hexadecimal. Se puede ajustar el tiempo de visualización con los iconos de zoom dentro o fuera, o ajustar la vista para ver todo el tiempo de simulación, usando el icono de ajuste automático a todo el fichero de simulación. Visualiza todo el tiempo de simulación Seleccionar señales para agrupar Formato de visualización 20. Guardar el archivo como tutor.scf 21. Una vez seleccionadas todas las señales a excitar y visualizar, se empieza a dibujar las formas de onda de las entradas. Se empieza en este caso por clk, seleccionando la señal y a continuación el icono para excitarla como reloj. En la ventana de diálogo se selecciona el valor inicial de la señal, y cada cuantos grid cambia. En este caso si se selecciona 1, el reloj cambia de valor cada 25ns, y por tanto el periodo será de 50ns. Señal clk a excitar Excitar clk como reloj Configuración del reloj: 1.valor inicial ‘0’ 2.cambia cada 1xgrid 22. Seleccionar el tramo desde 350ns a 450ns de n_inc, y pulsar el icono para que este tramo tenga el valor lógico ‘1’ para desactivarla. La señal n_inc es desactivada entre 350ns y 450ns 23. Realizar doble click sobre la señal n_rst. En la ventana de diálogo seleccionar el valor por defecto como ‘1’ para activarla en toda el tiempo de simulación. Se pretende comprobar el funcionamiento de la señal n_rst asíncrona, activándola durante un intervalo de tiempo en que no aparezca el flanco positivo del clk. Para ello desactivar el grid usando el menú Options|Snap To Grid y seleccionar el tramo de n_rst alrededor de 400ns y de unos 25ns de duración y usando el icono para cambiar el valor a ‘0’ para activarla en este tramo. Una vez hecho esto volver ha activar el grid con el menú Options|Snap To Grid. La señal n_rst es desactivada en toda la simulación La señal n_rst es activa asíncronamente alrededor de 400ns 24. Una vez excitadas todas las entradas, se pasará a realizar la simulación del diseño sintetizado con la excitación. Es una simulación que incluye los retardos que introducen los bloques lógicos y los recursos de rutado. Pulsar el icono de simulación, que abre una ventana de diálogo, donde el boton de start comienza la simulación. Observar que la señal de entrada a dec7seg es una señal síncrona con el flanco positivo del reloj, con un cierto retardo, mientras que la salida del bloque dec7seg aparecen transitorios debido al carácter combinacional del bloque, tras un cambio en sus entradas. Observar además que la señal de n_rst es asíncrona, ya que resetea el contador independientemente del clk. Simulación Comienzo de simulación Resultados de la simulación 25. Para ver con mayor detalle los retardos se puede ampliar la vista alrededor del primer flanco positivo de clk, a los 25ns. Observar el transitorio en o(6..0), en el que cambian al principio o1, o2, o3 a los 44.8ns (25ns+19.8ns) y después o6 a los 48.3ns (25ns+23.3ns). Los transitorios son debidos a que cada señal combinacional tiene retardos diferentes. cambio de o6 a los 48.3ns flanco de clk a los 25ns cambio de o1,o2,o3 a los 44.8ns 26. Se puede realizar un análisis estático de los retardos de las salidas respecto a clk usando el icono de análisis estático de retardos, que abre un diálogo donde aparece el retardo min/max para cada salida respecto al clk. Se puede verificar que estos retardos se corresponden con los resultados obtenidos por simulación. Análisis estático de retardos Retardos min/max entre clk y salidas 27. Finalmente, una vez verificado el funcionamiento del diseño por simulación, se puede programar la FPGA usando el programa Flex.exe, que transfiere el fichero tutor.ttf (bitstream de configuración) a la memoria de configuración SRAM. Para ello seleccionar la configuración passive-serial, y escribir tutor al pedir el nombre del fichero. Una vez se ha transferido correctamente el bitstream el programa informa de la correcta programación de la FPGA. Tutorial de Veribest VHDL Este tutorial muestra cómo realizar la simulación funcional del código VHDL del anterior diseño usando el simulador VHDL Veribest. 1. Crear una nueva carpeta desde Windows donde se almacenará el diseño VHDL y la librería de trabajo WORK. 2. Seleccionar el menú File/New (o el icono New de la barra de botones), apareciendo un cuadro de diálogo, donde se seleccionará VHDL Workspace y se pulsará OK. 3. Aparecerá una segunda ventana de diálogo donde se introducirá un nombre al Workspace (o proyecto), y el directorio de trabajo. Como nombre del Workspace escribir tutorial y como directorio de trabajo una nueva carpeta ha creado al principio. Seleccionar en este mismo diálogo la opción Use Synopsys IEEE Library, para poder usar las librerías STD_LOGIC_ARITH, STD_LOGIC_SIGNED y STD_LOGIC_UNSIGNED. Pulsar finalmente el botón Create para crear el Workspace. Menú File/New o Botón New Nombre del Workspace y directorio de trabajo Añadir ficheros al proyecto tutorial.vpd VHDL Workspace 5. Para realizar la simulación del diseño VHDL es necesario crear un fichero VHDL de testbench. Para ello seleccionar del menú File/New o botón New, y en la ventana de diálogo seleccionar VHDL Source File, y pulsar Create. Seleccionar librería Synopsys IEEE 4. Se crea entonces el archivo de proyecto tutorial.vpd, que contiene la referencia a los ficheros VHDL que debe compilar y simular. Se abré también una ventana donde se muestra una lista (vacía de momento) de estos ficheros, y el orden de compilación. Para añadir ficheros al proyecto seleccionar en la ventana del proyecto el botón de añadir ficheros, que abré una segunda ventana de diálogo que permite navegar por los directorios de Windows. Ir a la carpeta donde están los ficheros fuentes que ya fueron usados con el Max+PlusII, seleccionando los tres ficheros contador.vhd, tutor.vhd y dec7seg.vhd a la vez usando la tecla control + botón izquierdo del teclado, y finalmente pulsando OK. Otra opción es copiar estos tres ficheros de la carpeta del Max+PlusII a la carpeta donde se trabaja con Veribest. Una vez seleccionados los tres ficheros, estos se deben mostrar en la ventana del proyecto tutorial.vpd. Menú File/New Guardar fichero VHDL o Botón New VHDL Source File 6. Escribir el fichero VHDL de testbench que aparece a continuación. Guardar el fichero con el nombre test.vhd, y añadir el fichero al proyecto. Comprobar que el orden de compilación es contador.vhd, dec7seg.vhd, tutor.vhd y test.vhd. Si no es así, pulsar las teclas de ordenación de ficheros VHDL dentro del proyecto. Ordenación de compilación de los ficheros VHDL en el proyecto library ieee; use ieee.std_logic_1164.all; entity test is end test; architecture test1 of test is signal clk: std_logic:='0'; signal n_rst,n_inc: std_logic; signal o: std_logic_vector(6 downto 0); begin n_rst<='1', '0' after 30 ns, '1' after 60 ns, '0' after 400ns, '1' after 425 ns; n_inc<='0', '1' after 350 ns, '0' after 450 ns; process(clk) begin clk<=not clk after 25 ns; end process; DUT: entity work.tutor port map(clk,n_rst,n_inc,o); end test1; Añadir el fichero test.vhd al proyecto tutorial.vpd 7. Compilar el proyecto, pulsando el botón de Compille All (Alt+F8), y comprobar que no hay errores comprobando la salida del compilador VHDL que es mostrada en la ventana de Build. Workspace Settings Opciones de compilación Selección entidad+arquitectura a simular Compile All Lista de ficheros VHDL a compilar Salida del compilador Activar Trace On Unidades de diseño en la librería WORK 9. Para realizar la simulación funcional del código pulsar el botón de Execute Simulator (CTRL+F5) o dentro del menú Workspace/Execute Simulator. Aparece un mensaje indicando que el simulador funcionará en modo limitado al no disponer de licencia. Comprobar en la ventana de salida del simulador que al final del proceso aparece el mensaje: Message Summary: Total: 0 error(s), 0 warning(s), 0 note(s). 8. Para empezar a simular, es necesario indicar al Workspace que unidad se va a simular, que en nuestro caso es el testbench, es decir, la entidad test de arquitectura test1 que ha sido escrita en el fichero test.vhd. Para ello seleccionar el botón Workspace Settings o el menú Workspace/Settings… y aparece una ventana de diálogo para ajustar opciones de la compilación y simulación. En la pestaña Compile, seleccionar las opciones que aparecen en la figura de abajo, y en la pestaña Simulate seleccionar como unidad de simulación (desde la lista de unidades de diseño de la librería WORK) la arquitectura test1 de la entidad test, y pulsando el botón Set. No olvidar activar la opción Trace On, que permitirá más adelante depurar el código VHDL. Execute Simulator 10. Para visualizar gráficamente las formas de onda del resultado de la simulación, se debe abrir una ventana de Waveform. Se puede maximizar la ventana para ver mejor la salida gráfica si se desea. Pulsar el botón de añadir las señales a visualizar, apareciendo un diálogo que permite seleccionar jerárquicamente las señales a añadir. Seleccionar de la entidad TEST todas la señales pulsando el botón Add, y de la instancia DUT la señal interna s(3 downto 0) que es la que conecta la salida cont de U1 con la entrada a de U2. Una vez añadidas estas 5 señales pulsar el botón close para cerrar el diálogo. Añadir señales a visualizar Run (F5) Zoom to Fit Abrir ventana de Waveform •TEST(TEST1) •clk •n_rst •n_inc •o(6 downto 0) •DUT: TUTOR(STR) •s(3 downto 0) 11. Para realizar una simulación funcional de 500ns, escribir 500 y seleccionar ns en los controles destinados a indicar el tiempo de simulación deseado. Pulsar a continuación el botón Run (F5) y observar el resultado gráfico de la simulación. Se puede hacer un Zoom to Fit para ver todo el resultado de la simulación entero. Se puede observar que el simulador VHDL genera una salida de texto de unos Warnings a los 25ns en la instancia U1 de la entidad CONTADOR y arquitectura SEQ, por lo que se va a continuación a ver a que son debidos. Formas de onda 500 ns Salida de texto del simulador 12. La simulación funcional VHDL permite no sólo ver formas de onda, sino la depuración de código usando ejecutación paso a paso, puntos de ruptura, visualización del contenido de señales, etc… de forma similar a cuando se depura un fichero fuente en un lenguaje de programación como C. Ir al menú Simulate/Restore para reiniciar la simulación al principio (a los 0ns). A continuación se va a colocar un punto de ruptura en la entidad CONTADOR que está descrito en el fichero contador.vhd. Abrir el fichero contador.vhd con doble click en la ventana de proyecto, seleccionar la primera línea de código del proceso, donde aparece la comprobación if n_rst=’0’ then y colocarle un punto de ruptura.. Seleccionar línea donde aparece la comprobación if n_rst=‘0‘ then y colocar breakpoint Doble click sobre contador.vhd Nueva ventana Watch Menú Simulate/Restore a los 0ns 13. Pulsar el botón Run (F5) para simular durante los 500ns deseados. Observar que a los 0ns+1δ el breakpoint ha parado la ejecución del código en la primera línea del proceso de la entidad CONTADOR. Volver a pulsar el botón Continue varias veces hasta que se vuelva a parar la simulación en la misma línea, pero a los 25ns+0δ, que es el instante en el cual nos interesa depurar el código. Se puede visualizar el contenido de las señales que usa este proceso en una ventana de Watch. Para ello abrir una ventana Watch, y pulsando el botton Add Watch añadir para el U1: CONTADOR(SEQ) dentro del DUT:TUTOR(STRUCT) todas las señales usadas por CONTADOR, que son clk, n_rst, e, cont e icont. Una vez finalizada la selección se puede observar el valor de todas estas señales en el instante de simulación, que en este caso es 25ns+0δ. 14. Continuar la ejecución paso a paso observando como se simula el código en función del contenido de las señales visualizadas en la ventana de Watch. A los 25ns+0δ se ha producido un flanco ascendente de reloj, n_rst=’1’, e=’1’, icont=’U’ (no inicializado) por lo que el código pasa a ejecutar la asignación icont<=icont+1. Esta operación aritmética produce un Warning en el simulador debido a que uno de los operandos tiene un valor ‘U’ (no inicializado), por lo que la suma de cómo resultado ‘X’ (indefinido), mostrando este aviso al usuario con el mensaje. Assertion [WARNING] in :TEST(TEST1):DUT@TUTOR(STRUCT):U1@CONTADOR(SEQ) :_P1 at time 25 ns, cycle 0: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es). •DUT: TUTOR(STR) •clk •n_rst •e •icont •cont Continuar hasta parar en el breakpoint a los 25ns+0δ 15. Si se continua ejecutando paso a paso se obseva que el código se detiene en la asignación cont<=conv_std_logic_vector(icont,4) a los 25ns+1δ, y el simulador muestra un nuevo mensaje de Warning. Assertion [WARNING] in TEST(TEST1):DUT@TUTOR(STRUCT):U1@CONTADOR(SEQ): _P at time 25 ns, cycle 1: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es). 16. Estos mensajes de Warning no son problemáticos, ya que son debidos a que no se ha hecho el reset del dispositivo todavía, con lo que aquellas señales que son registradas tienen un valor inicial ‘U’ (indefinido) y provoca que cualquier asignación que leen estas señales den mensajes de Warning. Una vez hecho el reset a los 30ns el valor de icont se inicializa a ‘0’ y los mensajes de Warning ya no vuelven a aparecer. Si se visualiza de nuevo la ventana de formas de onda, añadiendo además la señal icont de la instancia U1 del DUT, se puede observar como el valor inicial es x”U”, pasando a los 25ns a x”X”, y a los 30ns se inicializa por el n_rst=’0’ a x”0”. Para observar mejor las formas de onda se puede cambiar la escala de visualización a 1ns. Cambiar escala a 1ns 25ns La señal icont del U1 cambia de x”U” a x”X” a los 25ns y a x”0” a los 30ns 30ns
© Copyright 2024