VIII. Jerarquías de diseño en VHDL 1 Introducción Una descripción funcional especifica un sistema en términos de sus operaciones. Una descripción estructural especifica cómo el sistema está hecho, cuales son sus subsistemas o componentes y cómo es que estos se comunican. Algunos autores definen una descripción de flujo de datos cuando únicamente contiene asignaciones concurrentes (sin procesos). Un sistema puede tener múltiples niveles de jerarquía, en el nivel más alto puede contar con una descripción estructural. Los componentes a la vez pueden contener una red de elementos mas primitivos (estructurales). Hasta alcanzar un nivel con descripciones funcionales. 2 Diferentes jerarquias en un sistema COMP 11 COMP 4 COMP 12 COMP 1 COMP 132 COMP 3 COMP 131 COMP 2 COMP 13 3 Componentes de una descripción estructural En una descripción estructural, los componentes se comunican entre si a través de señales. Un componente es un sistema individual especificado por su Entidad y Arquitectura, que posteriormente es utilizado en otro sistema con mayor jerarquía. Para ello, se hace una instanciación del componente. La instanciación de componentes es una proposición básica en una arquitectura estructural. Un componente puede ser instanciado cuantas veces sea necesario. Las diferentes instancias son concurrentes una con otra. Un componente instanciado no está completo sin un mapa de sus puertos – una referencia de cómo se hará la conexión entre los puertos del componente con las señales del nivel jerárquico mas alto. 4 Instanciación de Componentes Existen 2 tipos de instanciaciones: Instanciación Directa: Es una forma simple de instanciar un componente. Requiere que los componentes hayan sido previamente compilados, para después ligarlos desde la biblioteca de trabajo (Work). Es adecuada para sistemas con baja complejidad. Instanciación por Componente: Permite instanciar a los componentes aún cuando éstos no han sido descritos. Para ello, los componentes primeramente deben ser declarados, en la declaración se describe la interfaz del componente. La declaración se ubica en la parte declarativa de la arquitectura. Es adecuada para sistemas complejos, dado que sus módulos pueden realizarse por diferentes desarrolladores. 5 Instanciación Directa de componentes La instanciación sigue la siguiente sintaxis: nom_instancia : entity work.nom_entidad ( nom_arquitectura ) El nombre de la arquitectura puede omitirse si sólo hay una. Posterior a la instancia se tiene al mapa de puertos, en donde se especifica el orden en que se realizarán las conexiones con el módulo de mayor jerarquía. Ejemplo: Dlatch_en DLatch Dex Clkex En D AND2 Clk A C B Clkin Q Qout 6 Los Componentes Entity And2 is port ( A, B : in bit; C : out bit ); End Entity And2; Architecture Beh of And2 is Begin C <= A and B after 2 ns; End Architecture Beh; Entity Dlatch is port ( D, Clk : in bit; Q : out bit ); End Entity Dlatch; Architecture Beh of Dlatch is Begin Process (clk) begin if clk = ‘1’ then Q <= D after 3 ns; end if; end process; End Architecture Beh; 7 Instanciación Directa Entity Dlatch_en is port ( Dex, Clkex, En : in bit; Qout : out bit ); End Entity Dlatch_en; Architecture Struct of Dlatch_en is Signal Clkin : bit; Begin gate: entity work.And2 (beh) port map ( A => Clkex, B => En, C => Clkin ); latch: entity work.DLatch (beh) port map ( D => Dex, clk => Clkin, Q => Qout ); End Architecture Struct; 8 Instanciación por Componente Es posible hacer referencia a otros componentes cuyo comportamiento aún no ha sido especificado. Requiere una declaración del componente, antes de su instanciación. La declaración se realiza en la parte declarativa de la arquitectura, antes de la clausula begin. La declaración sigue la misma sintaxis que la descripción de entidades, excepto que se remplaza la palabra entity, por la palabra component. Sintaxis: component nom_componente is generic ( lista de parámetros ); port ( lista de puertos ); end component nom_componente; Para la instanciación básicamente se indica el nombre del componente seguido de la definición de parámetros y la conexión de los puertos. 9 Entidades y Componentes Existen dos diferencias importantes entre Entidades y Componentes: La declaración de una Entidad define una interfaz de un módulo “real”, es decir, un sistema o circuito que físicamente existe; el sistema es una unidad de diseño separada y puede ser simulada individualmente, analizada o sintetizada. La declaración de un Componente define la interfaz de un módulo “virtual” o que “no-existe”; es especificado dentro de una arquitectura para indicar que ahí se va a situar al componente “real”. 10 Dlatch_en DLatch Dex D AND2 Clkex A En B Q Qout Clk C Clkin Entity Dlatch_en is port ( Dex, Clkex, En : in bit; Qout : out bit ); End Entity Dlatch_en; Component Dlatch is port ( D, Clk : in bit; Q : out bit ); End Component Dlatch; Architecture Struct of Dlatch_en is Signal Clkin : bit; Begin gate: And2 port map ( A => Clkex, B => En, C => Clkin ); Component And2 is port ( A, B : in bit; C : out bit ); End Component And2; latch: DLatch port map ( D => Dex, clk => Clkin, Q => Qout ); End Architecture Struct; 11 Mapeo de puertos por posiciones Los mapas de puertos especifican las conexiones entre los puertos de una entidad (componente) y las señales en la arquitectura donde los componentes son instanciados. Existen dos formas para hacer el mapeo de puertos: Asociación de puertos posicional o asociación de puertos por nombre. En la asociación posicional, las señales en el mapa de puertos deben listarse en el mismo orden en el cual se declararon los puertos en la entidad del componente. Para que la asociación sea posible, las señales deben ser del mismo tipo. Architecture Beh of And2 is Begin C <= A and B after 2 ns; End Architecture Beh; X SomeSystem Entity And2 is port ( A, B : in bit; C : out bit ); End Entity And2; A B Y Z C Entity SomeSystem is . . . . End Entity SomeSystem; Architecture Struct of SomeSystem is Begin . . . gate: entity work.And2 (beh) port map ( , , ); . . . . End Architecture Struct; 12 Mapeo de puertos por nombre En el mapeo por posiciones se debe tener cuidado del orden para no cometer errores. La asociación de puertos por nombre da mayor claridad y reduce la posibilidad de cometer errores, por que para cada asociación debe especificarse:el nombre de la señal a asociar, el símbolo “ => ” y el nombre del puerto como aparece en la entidad del componente. No importa el orden en que se realicen las asociaciones. Architecture Beh of And2 is Begin C <= A and B after 2 ns; End Architecture Beh; X SomeSystem Entity And2 is port ( A, B : in bit; C : out bit ); End Entity And2; A B Y Z C Entity SomeSystem is . . . . End Entity SomeSystem; Architecture Struct of SomeSystem is Begin . . . gate: entity work.And2 (beh) port map ( A => , B => , C => ); . . . . End Architecture Struct; 13 Asociaciones complejas BANDERAS Signal Banderas : Bit_Vector ( 3 downto 0); MEMORIA Signal Memoria : Bit_Vector ( 7 downto 0); ACUMULADOR Signal Acumulador : Bit_Vector ( 3 downto 0); 3 2 1 0 CF ZF OF MF 7 6 5 4 Opcode(3) Opcode(2) Opcode(1) Opcode(0) 3 2 1 0 OperandA(3) OperandA(2) OperandA(1) OperandA(0) 3 2 1 0 OperandB(3) OperandB(2) OperandB(1) OperandB(0) Entity Op_Reg is port ( CF : out bit; ZF : out bit; OF : out bit; MF : out bit; Opcode : in bit_vector( 3 downto 0); OperandA : in bit_vector( 3 downto 0); OperandB : in bit_vector( 3 downto 0) ); End entity Op_Reg; OPERACIÓN_DE_REGISTROS 14 Asociaciones complejas VHDL proporciona flexibilidad para asociaciones complejas. Tanto señales como puertos pueden ser asignadas elemento a elemento o bien bloques. Cualquier asignación de señales y puertos es permitida, siempre que se conserve que los elementos son compatibles (del mismo tipo y tamaño). . . . . Operation_Register : Entity Work.Op_Reg port map ( CF => Flags(3), ZF => Flags(2), OF => Flags(1), MF => Flags(0), Opcode => Memoria ( 7 downto 4), OperandA => Memoria (3 downto 0), OperandB => Acumulador ); . . . . 15 Puertos sin conexión Es posible que un puerto no este conectado, para ello debe especificarse como abierto (open). El estándar de VHDL permite manejar esta situación simplemente sin agregar al mapa de puertos al puerto que se quedará sin conexión. Sin embargo, una herramienta de simulación no puede determinar si el puerto no aparece por que no estará conectado o por olvido del usuario. Comp1 SigA SigB SigC Input1 Output1 SigD Output2 SigE Input2 Input3 Comp2 SigA SigB SigC Input1 Output1 SigD Output2 SigE Input2 Input3 Comp1 : Entity Work.SomeEntity port map ( Inpu1 => SigA, Input2 => SigB, Input3 => SigC, Output1 => SigD, Output2 => SigE ); Comp2 : Entity Work.SomeEntity port map ( Inpu1 => SigA, Input2 => SigB, Input3 => SigC, Output1 => SigD, Output2 => Open ); 16 Ejemplo REG4B RegQ(0) Q RST Clk CLK D B I T 0 RegQ(1) Q RST Clk RegD(0) D B I T 1 RegD(1) RegQ(2) Q RST Clk D B I T 2 RegD(2) RegQ(3) Rst Q RST Clk D B I T 3 RegD(3) Entity Reg4B is port ( RegD : in STD_LOGIC_VECTOR(3 downto 0); RegQ : out STD_LOGIC_VECTOR(3 downto 0); Rst, Clk : in STD_LOGIC ); End entity Reg4B; 17 Architecture Struct of Reg4B is component FFD is port ( d, clk, rst : STD_LOGIC; q : STD_LOGIC ); end component FFD; Begin bit0: FFD port map ( D => RegD(0), Q => RegQ(0), Rst => Rst, Clk => clk ); bit1: FFD port map ( D => RegD(1), Q => RegQ(1), Rst => Rst, Clk => clk ); bit2: FFD port map ( D => RegD(2), Q => RegQ(2), Rst => Rst, Clk => clk ); bit3: FFD port map ( D => RegD(3), Q => RegQ(3), Rst => Rst, Clk => clk ); End Architecture Struct; 18 Subprogramas o funciones Las funciones pueden ser declaradas en la entidad, en la arquitectura o en un paquete. Entinty ... Is Existen bibliotecas comerciales que incluyen funciones comunes, como sin, cos, sqrt, etc., y que pueden ser usadas en diferentes diseños. Architecture ...of ...is - - Declaración de funciones (2) Begin - - Declaración de funciones (1) End... Process - - Declaración de funciones (3) Begin -- Llamada a la función End process; End...; 19 Subprogramas o funciones Ejemplo. Función para convertir un bit_vector en entero. Function vect_to_int (s: bit_vector (0 to 7) ) return integer is variable result : integer :=0; begin for i in 0 to 7 loop result := result*2; if s (i) = ‘1’ then result := result + 1; end if; end loop; return result; end vect_to_int; Las funciones tienen un retorno explícito. 20 Subprogramas o funciones Ejemplo: Declaración y uso dentro de un proceso. PROCESS function C_to_F (c: real) return real is variable F: real; -- Declaración Begin F := C*9.0/5.0 + 32.0; Return (F); end C_to_F; variable new_temp: real; begin new_temp := C_to_F (5.0) + 20.0; -- La función se describe -- en la parte declarativa -- del proceso -- Llamada a la función -- en el proceso end PROCESS; 21 Subprogramas - Procedimientos En los procedimientos las entradas y salidas se especifican por separado. -- Definición de un procedimiento -- Uso de un procedimiento Procedure PARITY (A: in bit_vector (0 to 7); Result1, result2: out bit) is variable temp: bit; begin temp := ‘0’; for i in 0 to 7 loop temp :=temp xor A(i); end loop; architecture behavior of receiver is process variable TOP, BOTTOM, ODD, dummy : bit; variable Y: bit_vector (15 downto 0); begin ... PARITY (Y(15 downto 8), TOP, dummy); PARITY (Y(7 downto 0), BOTTOM, dummy); ODD := TOP xor BOTTOM; end process; result1 := temp; result2 := not temp; end; end behavior; 22 Diseño e implementación de un sistema Especificación del sistema Descripción física Arquitectura Desarrollo de componentes (desc. funcional) Fases de diseño (manual) Metodología TOP-DOWN Desc. Estructural Jerárquica Conjunto de bloques y módulos básicos Biblioteca de celdas Implementación (Asistido por Computadora) 23 Herramientas de Desarrollo 24 Editor de diagramas a bloques U1 clk_ext c lk _e x t error c lk_ 3_ 1 25 M U2 div_frec rst RXD bot D ato _s e r(7 :0 ) rs t E rro r rx U3 D IN (7:0 ) dl flanco LEDs(7:0) c lk rec_serial b o t_ ex t D O U T (7 :0 ) D ir(7 :0 ) U5 c lk Lim(7:0) c lk b o t_int mwr U4 mem_int B o to n L im ite (7:0 ) C T A (7:0 ) mem_wr c lk dr rs t ctrl_prueba4 25 Editor de diagramas de estados 26 Desarrollo de dos ejemplos Contador ascendente de 4 dígitos. Marquesina para un mensaje en 7 segmentos. 27 Contador ascendente de 4 dígitos Diseño e implementación de un contador ascendente de 4 dígitos, con salida en los visualizadores de 7 segmentos con que cuenta la tarjeta. El contador se incrementará cuando esté habilitado, pero la velocidad de los incrementos deberá poderse modificar, para permitir incrementos a 8 velocidades diferentes. El contador estará basado en el diseño de un contador de 0 a 9, re-utilizándolo 4 veces para el manejo de 4 dígitos. Los visualizadores de 7 segmentos están conectados en paralelo, manejados por un bus común para los datos y habilitaciones independientes. 28 Contador ascendente de 4 dígitos Salidas del Contador Habilitador Para regular la velocidad Reset 29 Nivel Jerárquico Superior Clk_50 DATOS [6:0] Hab Rst HABS [3:0] VEL [2:0] 30 Diseño del Contador Contador de 4 dígitos (0 – 9999) Divisor de Frecuencia Generador de pulsos para el contador Contador de 1 dígito (0 a 9) Decodificador de 7 segmentos Manejador de los displays de 7 segmentos El divisor de frecuencia debe generar una señal con una frecuencia del orden de KHz para el sistema y una señal que sirva de base para la generación de los pulsos del contador. Se necesitarán 4 objetos del tipo: Contador de 1 dígito, y 4 del tipo: Decodificador de 7 segmentos. 31 Marquesina para un mensaje en 7 segmentos. En los visualizadores de 7 segmentos se mostrará un mensaje de texto, con un mínimo de 25 caracteres. Los caracteres estarán limitados por la resolución de los displays. El mensaje se desplazará de izquierda a derecha o viceversa, controlando la dirección por medio de un interruptor. La velocidad de desplazamiento también será configurable. El mensaje se ubicará en un módulo que funcionará como una memoria ROM. Se sugiere utilizar 2 contadores manejados a diferentes frecuencias, para que al sumarse, proporcionen la dirección efectiva de la localidad de memoria a la que se tendrá acceso. Nota: Es posible reutilizar algunos módulos del ejercicio anterior. 32 Marquesina para mensajes en 7 segmentos Salidas para el Mensaje Dirección Velocidad de desplazamiento Reset 33 Nivel Jerárquico Superior Clk DATOS [6:0] Dir Rst HABS [3:0] VEL [2:0] 34 Diseño de la Marquesina Marquesina de mensajes Divisor de Frecuencia ROM (mínimo 25 localidades) Contador de 0 a 3 (Barrido) Contador para direcciones Sumador Decodificador de 2a4 35 Sistema 1 Contador de Automóviles en los visualizadores de 7 segmentos. Desarrollar la máquina de estados con ayuda del Active-HDL, para una generación automática de código. Acondicionar la máquina de estados para llevar la cuenta de automóviles en los 4 visualizadores de 7 segmentos de la tarjeta Nexys 2. Simular los sensores con 2 de los botones de la tarjeta. 36 Sistema 2 Comunicación Serial con una PC Enviar datos seriales desde una PC y mostrarlos en los LEDs de la tarjeta Nexys 2. Considerar una comunicación a 9600 bps, datos de 8 bits, un bit de paro y sin paridad. El dato recibido se mostrará de manera inmediata, sin conservar los datos anteriores. El flujo de datos será unidireccional, PC – Tarjeta Nexys 2. 37 Sistema 3 Marquesina Configurable por el Puerto Serie Modificar el sistema para que en lugar de conservar el mensaje en una ROM, éste sea guardado en una RAM. Acondicionar el hardware para que el contenido de la RAM pueda remplazarse con datos recibidos serialmente desde una PC. Considerar que un nuevo mensaje puede llegar en cualquier momento. El tamaño del mensaje puede ser variable, de manera que el final del mensaje se marcará con el carácter $. 38