PRÁCTICA DE SÍNTESIS El sumador – restador en complemento a dos 1.- Introducción Mediante el complemento a dos se simplifica la circuitería necesaria para realizar las operaciones suma y resta de números binarios con signo. El empleo de esta técnica permite realizar estas operaciones empleando un sencillo sumador binario junto con una lógica adicional. La figura 1 presenta el esquema de un circuito aritmético para números en complemento a 2 de 3 bits, mostrando los componentes principales y sus conexiones. X Y 3 3 3 Selector de datos 3 Selector de datos Control 1 Control 2 3 3 Complemento a 1 Sumador binario de 3 bits Detector de desbordamiento 3 OP_SELECT 3 Salida Figura 1. Diagrama de bloques de un circuito para sumar o restar números en complemento a dos. El sumador en el centro de la unidad está diseñado para números binarios sin signo. Si se activa un complementador (un circuito lógico bastante sencillo) en una de sus entradas de datos, el mismo sumador puede realizar restas, aprovechando el hecho de que la operación X-Y es la suma de X y el complemento a dos de Y (o sea, X+(-Y)). El complementador se controla con una señal externa OP_SELECT, que selecciona la operación, suma o resta, que efectúa la unidad aritmética. Dos componentes controlados 1/9 externamente, llamados selectores de datos (o multiplexores), determinan cuáles serán los operandos que se aplicarán a la entrada derecha y la entrada izquierda del sumador. Con esta disposición, podemos aplicar X o Y a la entrada de la izquierda del sumador, y X, Y, -X o –Y a la entrada de la derecha del sumador, lo que permitiría calcular las siguientes operaciones aritméticas: X+Y X-Y Y-X 2X (ó X+X) 2Y (ó Y+Y) Las otras 3 operaciones que podría realizarse con el resto de las combinaciones de las 3 señales de control son obvias o redundantes y no se tomarán en cuenta (estas son: Y+X = X+Y, X-X=0, Y-Y=0). Este sumador-restador es mucho más sencillo que un sumador-restador similar para números codificados mediante magnitud-signo, ya que se necesitarían sumadores y restadores separados, además de circuitos para comparar la magnitud de los operandos de entrada. El objetivo de la presente práctica es diseñar, simular e implementar un circuito capaz de realizar las operaciones anteriormente expresadas, donde X e Y son números en complemento a 2. 2.- Pasos a seguir 2.1. DISEÑO DE LOS MULTIPLEXORES Primeramente hay que diseñar un multiplexor 2 a1 de un bit (esta parte ya ha sido realizada en clase). Una vez sintetizado el componente, éste debe simularse para comprobar el correcto funcionamiento del mismo (ver figura 2). d0 MUX 2a1 z d1 sel Figura 2. Esquema de un multiplexor 2 a 1 de 1 bit y simulación funcional del mismo. Tras comprobar que el diseño funciona correctamente, se procede a la implementación de un multiplexor 2 a 1 de señales de 3 bits, que son los que necesitamos en el diseño 2/9 global que aparece en la figura 1. El diseño de un multiplexor de estas características se consigue conectando 3 multiplexores 2 a 1 sencillos tal y como se muestra en la figura 3. unit0 d0(0) d1(0) d0 MUX 2a1 z z(0) d1 sel unit1 d0(1) d1(1) d0 MUX 2a1 z z(1) d1 sel unit2 d0 d0(2) 3 MUX 2a1 d1 3 d0 MUX 2a1 z d1(2) 3 z z(2) d1 sel sel sel Figura 3. Esquema de un multiplexor 2 a 1 de 3 bits (componente y detalle de implementación) Para implementar este componente creamos un nuevo código con el asistente, en el que pondremos en este caso que las señales d0, d1 y z son buses de 3 bits (es decir, de 2 a 0). A continuación, en la plantilla generada, hay que inicializar el componente básico creado anteriormente (mux2a1 de 1 bit) en la parte declarativa de la arquitectura mediante la cláusula COMPONENT según se vio en el tutorial. Además, en el cuerpo de la arquitectura habría que instanciar (o usar) tres veces dicho componente básico (cláusula PORT MAP). Ambas sintaxis se pueden obtener generando una plantilla para tal fin en Processes → Design Utilities → View HDL Instantiation Template. Una vez realizadas las conexiones pertinentes en los PORT MAP, hay que comprobar nuevamente que el módulo funciona correctamente, por lo que creamos un nuevo archivo de simulación (mux2a1_3bits_tb) que asociamos a este nuevo módulo. Para corroborar el correcto funcionamiento, en este caso nos basta con poner dos datos distintos a las entradas de d0 y d1 y comprobar que la salida z conmuta entre estos dos valores en consonancia con la señal de selección (sustituir en la parte declarativa de d0 3/9 y d1 las inicializaciones de todo a 0, others=>'0', por valores tipo “010”). El formato de los datos de los buses puede verse en distintas codificaciones, sin más que hacer click con el botón derecho del ratón en los valores, tal y como se aprecia en la figura 4. Figura 4. Simulación funcional del multiplexor 2 a 1 de 3 bits (en formato binario puro y decimal sin signo) 2.2. DISEÑO DEL COMPLEMENTADOR A 1 El complementador a 1 es un sencillo bloque que, a través de la señal de control OP_SELECT hace que la señal de 3 bits entrante se obtenga a la salida tal cual o complementada (es decir, cambiando 0’s por 1’s y viceversa). Así, creamos un nuevo componente denominado ca1_3bits, que tendrá una señal simple de control (op_select) y dos buses de 3 bits de datos (din y dout), tal y como se muestra en la figura 5. Para realizar esta operación empleamos el operador xor (or-exclusiva) para cada una de las componentes del bus din, ya que din ⊕ 0 = din din ⊕ 1 = din según vimos en clase. Figura 5. Esquema del complementador y simulación funcional del mismo 4/9 2.3. DISEÑO DEL SUMADOR DE 3 BITS El último bloque que queda por diseñar en la figura 1 es el sumador completo de 3 bits. Para implementar este bloque haremos uso de 3 sumadores completos de 1 bit conectados en cascada. Las ecuaciones algebraicas de un sumador completo son: s = a ⊕ b ⊕ cin = (a ⊕ b) ⊕ cin cout = a ⋅ b + a ⋅ cin + b ⋅ cin = (a ⋅ b + a ⋅ cin) + b ⋅ cin En las ecuaciones descritas arriba se ha aplicado la propiedad asociativa respecto a la suma lógica y a la suma exclusiva, ya que los operadores or y xor están definidos en el lenguaje como operadores binarios (entre dos operandos). En la figura 6 aparece el módulo que debe implementarse y su simulación funcional. a cout b S. C. cin s Figura 6. Esquema del sumador completo de 1 bit y simulación funcional del mismo El sumador de 3 bits se obtiene conectando en cascada 3 bloques iguales al anterior. Como el módulo está pensado para realizar sumas y restas en complemento a 2, en esta representación numérica el último acarreo de salida no se tiene en cuenta, pero sí es útil implementar un detector de desbordamiento u overflow, que se obtiene tal y como se muestra en la figura 7. Figura 7. Implementación del sumador completo de 3 bits con bloques básicos Como sabemos, para 3 bits, el rango de números que podemos representar en complemento a 2 está en el intervalo [-4:+3]. En la simulación funcional de la figura 8 se ha optado por dejar uno de los sumandos fijo y variar el otro. Todos los buses se han representado en notación Decimal (Signed), o sea, en complemento a dos, haciendo click con el botón derecho del ratón en los mismos. Se puede comprobar que la suma se realiza correctamente en todos los casos excepto en los dos últimos en donde se produce desbordamiento (overflow=1). 5/9 S. C. cin 3 overflow 3 b 3 a s Figura 8. Interfase del sumador completo de 3 bits y simulación funcional del mismo 2.4. DISEÑO DEL SISTEMA GLOBAL 3 3 Una vez hallamos implementado y simulado todos los componentes anteriores, estos deben conectarse tal y como se mostraba en la figura 1. En las figuras 9 y 10 se muestran, respectivamente, el módulo de jerarquía superior que debe crearse con sus puertos de interfase y el esquema de conexionado de los bloques creados anteriormente x y sumador restador ca2 3 overflow control1 control2 op_select salida Figura 9. Esquema del sumador restador completo de 3 bits op_select control2 sel x 3 cin d0 MUX 2a1 y 3 z Ca1 din dout 3 int1 d1 3 b int2 op_select S. C. control1 s 3 salida sel 3 d0 MUX 2a1 3 z 3 int0 overflow a d1 Figura 10. Conexión de los bloques creados que conforman el sumador restador 6/9 overflow que lo componen. Se han declarado los buses internos int0, int1 e int2 como std_logic_vector (2 downto 0) para conectar algunos módulos, según puede apreciarse. Para calcular el opuesto a un número en complemento a 2, una manera de obtenerlo es realizar el complemento a 1 y sumar 1. Es por ello que la señal op_select se conecta al complementador a 1 Ca1 y al puerto de entrada cin del sumador. Con esta combinación en realidad hacemos el complemento a 2 pues. Llegados a este punto, hemos realizado un diseño jerárquico de 3 niveles, como se aprecia en la figura 11. Figura 11. Esquema jerárquico del diseño implementado En la figura 12 se muestra la simulación funcional del sistema diseñado. En este caso se han puesto como operandos X=+1 e Y=-3 y se han realizado las 8 combinaciones de las señales de control op_select, control1 y control2. En la tabla adjunta se puede comprobar la operación que se está realizando con cada combinación. Comprobar que los resultados son los esperados para otros valores. op_select 0 0 0 0 1 1 1 1 control2 0 0 1 1 0 0 1 1 control1 0 1 0 1 0 1 0 1 operación X+X Y+X X+Y Y+Y X-X Y-X X-Y Y-Y resultado +2 -2 -2 +2 (ov) 0 -4 -4 (ov) 0 Figura 12. Simulación funcional del sumador/restador implementado 7/9 2.5. ASIGNACIÓN DE PINES Para realizar la asignación de pines hay que crear un archivo de restricciones de usuario donde se incluye esta información. Como vimos en el tutorial, Processes → User Constraints → Floorplan IO – Pre-Synthesis, asegurándonos de tener seleccionada en la ventana de Sources el top del diseño. Nuestro diseño consta de 9 puertos de entrada (3 para X, 3 para Y, y 3 para las señales de control). Lo ideal sería asignar dichos puertos a interruptores, pero lo placa SPARTAN-3 sólo tiene 8. Así pues, asignaremos SW7 a control2, SW6 a control1, SW5-SW3 para X y SW2-SW0 para Y. La referencia de los pines a los que están conectados estos interruptores se encuentran en el anexo. La señal op_select se asignará a un botón (BTN0, por ejemplo). Para la salida no tenemos ningún problema en cuanto a recursos y podemos asignar el overflow al LD7 y la salida a los leds más a la derecha (LD2-LD0), por ejemplo. 2.6. IMPLEMENTACIÓN DEL DISEÑO Una vez que se han diseñado y simulado correctamente todos y cada uno de los bloques, y se ha realizado la asignación de pines de la FPGA, debemos sintetizar nuestro diseño. Seleccionando el módulo de jerarquía superior, hacemos doble-click en Processes → Generate Programming File (cerrar el cuadro de diálogo que aparece). Esto hará que se ejecuten todos los procesos anteriores para generar el archivo de programación. Ya con la placa conectada, el último paso es programarla (Generate Programming File → Configure Device (iMPACT)). Switches and LEDs Slide Switches The Spartan-3 Starter Kit board has eight slide switches, indicated as 11 in Figure 1-2. The switches are located along the lower edge of the board, toward the right edge. The switches are labeled SW7 through SW0. Switch SW7 is the left-most switch, and SW0 is the rightmost switch. The switches connect to an associated FPGA pin, as shown in Table 4-1. A detailed schematic appears in Figure A-2. Table 4-1: Slider Switch Connections SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0 Switch J14 H13 H14 G12 F12 FPGA Pin K13 K14 J13 Push Button Switches The Spartan-3 Starter Kit board has four momentary-contact push button switches, indicated as13 in Figure 1-2. These push buttons are located along the lower edge of the board, toward the right edge. The switches are labeled BTN3 through BTN0. Push button switch BTN3 is the left-most switch, BTN0 the right-most switch. The push button switches connect to an associated FPGA pin, as shown in Table 4-2. A detailed schematic appears in Figure A-2. Table 4-2: Push Button Switch Connections Push Button BTN3 BTN2 BTN1 BTN0 L14 L13 M14 M13 FPGA Pin 8/9 LEDs The Spartan-3 Starter Kit board has eight individual surface-mount LEDs located above the push button switches, indicated by 12 in Figure 1-2. The LEDs are labeled LED7 through LED0. LED7 is the leftmost LED, LED0 the right-most LED. Table 4-3 shows the FPGA connections to the LEDs. Table 4-3: LED Connections to the Spartan-3 FPGA LD7 LD6 LD5 LD4 LD3 LD2 LD1 LD0 LED FPGA Pin P11 P12 N12 P13 N14 L12 P14 K12 Figure 1-2: Xilinx Spartan-3 Starter Kit Board (Top Side) 9/9