Unidad de Control

Página Principal      Anterior      Siguiente

Introducción    Arquitectura    ISA     Prácticas     Hardware    Circuitos Simples    Unidad de Control    Microcódigo

 

    Hasta ahora he dicho que esta unidad se las arregla para generar en tiempo y forma (secuencia correcta) las señales de lectura, escritura, operación de la ALU, cBus y el Mux de los flags. Son las señales que salen de esta unidad. Por otro lado, las señales externas que le llegan condicionan o dictan su funcionamiento: IR, el estado de los Flags, si la memoria está lista (Ready) etc. Es todo lo que sabemos hasta ahora.

Básicamente se encarga de hacer transferencias de un lado a otro y para esto hay que realizar lo siguiente:

A) Determinar que es lo siguiente a hacer: quien es origen, quien es destino, que debe hacer la ALU etc.
B) El Origen se Lee y su contenido fija las señales del dBus
C) El Destino se Escribe con el valor del dBus
D) El Origen se desconecta del dBus y este queda en flotación o tercer estado (nadie lo maneja)


La señal de reloj que entra a la Unidad de Control va directamente a un circuito que genera dos señales derivadas Ck1 y Ck2, entre estas dos señales se marcan 4 tiempos que indican las 4 partes de una transferencia descriptos recién por A, B, C y D.

 Un ciclo de máquina lleva 2 períodos de reloj (en Rojo) y en él se dan los 4 tiempos citados en los que se produce toda transferencia.

    Se inicia con el flanco de subida de la señal Ck1. Se carga la siguiente microinstrucción (dice lo siguiente a hacer).
    Luego sube Ck2, el registro Origen carga el bus (fija el estado de las líneas del bus)  el Origen Habla. 

    En el medio del tiempo en que Ck2 es 1, baja Ck1, este flanco de bajada ordena la memorización del estado del bus por parte del registro Destino, aquí es cuando Destino se hace Igual al Origen, el destino Escucha.

    La señal Ck2 baja, el registro Origen se desconecta del bus, el bus vuelve a estar libre, nadie está Hablando.

 

    Refinando un poco lo dicho anteriormente, una instrucción lleva en promedio 20 ciclos de reloj, ahora podemos decir que lleva unos 10 ciclos de máquina. Para algo tan simple como las instrucciones de esta CPU se necesitan realizar 10 transferencias!

Recordemos que habíamos manejado esta notación para las transferencias.

        Destino = Origen

Destino puede ser cualquier registro o latch de la CPU, si es Resultado, entonces hay que indicar la operación de la ALU
Origen puede ser cualquier registro o buffer de la CPU.

El Destino puede ser un puerto de salida o una celda de memoria.
El Origen puede ser un puerto de entrada o una celda de memoria.
En estos dos últimos casos, la CPU genera las señales mem, e/s, Rd y Wr apropiadas y el Registro MAR debe haberse cargado con la dirección de la celda o puerto a leer/escribir.


El ciclo de instrucción en ciclos de máquina

La búsqueda implica traer el contenido de la celda apuntada por PC cargarlo en IR esto lleva 2 ciclos de máquina:

Búsqueda

MAR = PC                                                ;fijo MAR con la dirección de la celda a leer (la apuntada por PC)
IR = mem                                                ;se lee la celda que MAR indica: IR = Mem(PC)

Supongamos que la instrucción que se trajo desde la memoria es Load A,(Dirección)

Dirección se encuentra en el segundo byte de la instrucción, hay que leer este segundo byte y usarlo como dirección de memoria de la celda cuyo contenido hay que escribir en el registro Acumulador.

Esto lleva otros 7 ciclos de máquina:


Ejecución: Load
 

Resultado = PC                            :incremento PC para que apunte al segundo byte de la instrucción
Resultado = Resultado +1
PC = Resultado                            PC = PC+1
MAR =  PC                                      PC apunta al segundo byte de la instrucción
Temp = mem                                Temp = Contenido del segundo byte (que es la dirección de la celda a leer)
MAR = Temp                                 MAR = Dirección a leer
A = mem                                        A = contenido de la celda que se mandó leer.

Antes de pasar a una nueva búsqueda, hay que Incrementar PC en una unidad, para que quede apuntando a la siguiente instrucción:

IncrementarPC 

Resultado = PC
Resultado = Resultado +1
PC = Resultado                            PC = PC+1 

Ir a Búsqueda.   


Otro ejemplo


Ejecución: Not

    Resultado =  A
    Resultado = Not(Resultado)
    A = Resultado
    Ir a IncrementarPC

 

    Esta instrucción no necesita leer un segundo byte, asi que realiza la operación y luego, nuevamente, antes de pasar a la búsqueda, hay que incrementar PC, asi que, podemos utilizar las mismas transferencias que habíamos escrito anteriormente al final de la ejecución de la instruccion Load.

       Ir a Búsqueda, Ir a IncrementarPC se entienden conceptualmente: es por donde hay que seguir

     Estas secuencias de transferencias, se asemejan mucho a sentencias de un programa. Asumamos que el lenguaje es capaz de soportar una instrucción Ir a Direccción y además otra de salto condicional: Si Condición Ir a Dirección.

    El capítulo siguiente, muestra el listado completo de un programa escrito en este lenguaje que hace que la unidad de control realice el ciclo de instrucción e implemente cada una de las instrucciones citadas del Conjunto de Instrucciones. 

    Lo que debo hacer es demostrar que, el hardware de la Unidad de Control, es capaz de interpretar y ejecutar instrucciones como las que he citado. 

    Estas instrucciones tienen: Un origen, un destino, una operación para la ALU (relevante si el destino es el registro Resultado). El origen o el destino (no ambos) puede estar en memoria o en puertos (no ambos). Además, se ha impuesto la capacidad de que las instrucciones puedan ordenar un salto condicional o incondicional que modifique o controle su secuencia.

    Estas instrucciones no deben confundirse con las instrucciones que la CPU debe interpretar. Son más pequeñas que una instrucción. Son una microinstrucción.   Un conjunto de microinstrucciones logicamente concatenadas forman el microprograma que se almacena en una micromemoria, que es apuntada por un microPC o contador de microprograma implementados dentro de la Unidad de Control.

                A esto se le llama microcódigo y por tanto esta es una CPU microprogramada.

    En la CPU hay un registro que apunta a la siguiente instrucción de programa y se llama PC. El programa se almacena en memoria. Las instrucciones del programa le dicen a la CPU que hacer. Sin un programa una computadora no tiene tarea específica. Es el programa el que le dice que hacer.

    La CU tiene una tarea: Realizar el cilco de instrucción. La CU tiene una memoria con un programa que le dice como hacer su tarea, para saber donde está la siguiente instrucción de programa, tiene un registro que le dice la dirección de la siguiente instrucción.

    Para no confundir Instrucciones del programa de la memoria que definen la tarea de la CU con todo lo mismo pero para la CPU es que se agrega el prefijo micro a todo lo relacionado con la CU.

    No todas las unidades de control se microprograman, se puede construir una máquina de estados que genere las señales adecuadas en tiempo y forma, en ese caso se dice que la unidad de control es “cableada” (hardwired control). La ventaja del microcódigo es que es más  fácil de modificar y adecuar a nuestras necesidades. Un cambio en el conjunto de instrucciones, implicaría un rediseño completo si el control es cableado, en cambio a la CPU actual que es microprogramada, le podemos cambiar todo el conjunto de instrucciones, incluso la forma en que se realiza el ciclo de instrucción sin cambiar una sola compuerta lógica de la unidad de control, lo único que debemos hacer es, escribir un microprograma nuevo, o modificar alguna parte del que ya está.

    E aquí el circuito interno de la unidad de control:

    El capítulo anterior, presentó a cada uno de los circuitos que constituyen esta computadora. Aquí, asumo que ya se sabe que hace cada uno, lo que importa explicar entonces es su funcionamiento colectivo. 

    Una microinstrucción puede en sus 16 bits codificar a cada una de las posibles transferencias que la CPU puede ordenar, sean estas en registros o en el exterior. Los campos de 3 bits Origen y Destino indican justamente el elemento de la CPU que aporta el dato y el que lo recibe respectivamente, el valor binario es decodificado para lograr la señal individual que llegara a cada elemento. En caso de una Lectura o Escritura en el exterior, se inhibe el decodificador correspondiente, de esta manera si el destino esta en el exterior de la CPU, el campo DDD es irrelevante, lo mismo que si hay una lectura de un elemento externo, el campo OOO es irrelevante, pues se inhibe el decodificador que genera las señales de lectura internas a la CPU. Los 4 bits menos significativos de la microinstrucción salen en todo momento hacia la ALU para indicarle la operación a realizar, pero esta es relevante, solo si Destino es el registro Resultado.

    Hay una orden de escritura adicional para los flags, que se da explícitamente desde la microinstrucción. Para diferenciar cuando la ALU está haciendo una operación interna de una ordenada por la instrucción (Ver Practicas I, Programa 1). Hay solo 5microinstrucciones que indican escribir al registro de banderas y están ubicadas en el momento en que se obtiene el resultado de cada una de las 4 instrucciones aritméticas del conjunto de instrucciones (Add, Sub, And y Not) y en la instrucción iRet, en el momento en que se recuperan los flags desde la pila.

    Esta es la parte facil!

  Vamos a no apurarnos, por ejemplo supongamos una microinstrucción: IR = 0

Destino debe ser IR y Origen debe ser K0. Debe generar la señal de Escritura en IR (Salida 4 del decodificador de arriba: Ordenes de Escritura) y debe generar una señal de Lectura en K0 (Salida 4 del decodificador de abajo: Ordenes de Lectura). Asi que los campos Origen y destino deben tener 100 cada uno, porque en este caso, si bién origen y destino conceptualmente no son lo mismo, internamente el registro de solo escritura IR es el 4 y el registro de solo lectura K0 es el 4. No se debe escribir el registro de banderas, no se debe acceder al exterior, asi que F = W = R, y M puede valer lo que quiera, podemos dejarla en 0. Una parte de la microinstrucción está resuelta y se muestra en negritas:

    FMWR CC DDD OOO SSSS    (DDD<>111 = Resultado)

 Estos 10 bits proporcionan la información necesaria para casi todas las transferencias, salvo para aquellas en que el destino es el registro Resultado (111), en este caso, los bits SSSS indican la operación a realizar:

    FMWR CC 111 OOO SSSS   (DDD=111 = Resultado => SSSS = Operación)

El estado de los 16 bits de la microinstrucción, permanece invariable durante todo el ciclo de máquina. El decodificador de las órdenes de lectura, es habilitado por la señal Ck2 y el decodificador de las órdenes de escritura es habilitado por la señal Ck1. De esta manera, las señales de lectura y escritura se sincronizan como se indicó al inicio de esta página, garantizando que la escritrua del Destino se realiza en la mitad del período de lectura, donde se espera que las lineas de datos estén estabilizadas.


Microsecuenciamiento

    Las lineas de direcciones de la ROM en que residen las microinstrucciones, son gobernadas por un latch: uPC_Alto y por un contador de carga paralela: uPC_Bajo.  Concatenados, forman el uPC o microPC o microcontador de programa. Más alla del nombre, sus bits, indican la dirección de la microinstrucción que está siendo leída y que gobierna el presente ciclo de máquina.

        Ante cada flanco ascendente de la señal Ck1, uPC genera una nueva dirección y sale de la memoria la nueva microinstrucción que controlará el presente ciclo de máquina que acaba de iniciarse.

Ante cada flanco de subida de Ck1: 

    1)    uPC_Alto: Se carga desde los 4 bits más significativos de IR

    2)    uPC_Bajo:

                 Si Wr=0 se incrementa en una unidad, desde 0 hasta 15 (máximo numero con 4 bits) y pasa a 0 nuevamente.

                 Si Wr es 1, adopta el valor de que se le indiquen los bits SSSS de la microinstrucción. 

    El valor de la señal Wr es controlado por las propias microinstrucciones y de esta manera, el microcódigo se auto controla. El campo CC indica que pasará en Wr. CC tiene 2 bits y tenemos 4 casos:

CC = 00 uPC = uPC + 1

CC actuan sobre un multiplexor, asi que el valor en Wr es la copia de lo que halla en la entrada direccionada por CC. La entrada 0 del multiplexor está cableada a masa, el negativo de la fuente o lo que es más simple está a 0, por tanto si CC son 00, Wr es 0 siempre y por tanto uPC_Bajo se incrementa.

CC = 10  Salta

La entrada 2 del multiplexor, también está cableada, pero en este caso a fuente, o lo que es más simple a 1. Wr entonces va a ser 1 siempre que CC sean 10 y por tanto uPC_Bajo se carga con el valor indicado por SSSS.

CC = 11 Salta si Interrupción

La entrada 3 del multiplexor es la entrada de solicitud de interrupción (Int), asi que Wr va a ser igual a lo que valga Int, asi que si hay interrupción se salta (Int=1 => Wr=1) y si no la hay no (Int=0 => Wr=0). Hay una puerta Y que indica cuando CC=11, su salida se denomina IntA: Reconocimiento de Interrupción. Esta señal sube cuando entramos en la microinstrucción que sensa si hay interrupcion pedida y baja al final de la misma. Su propósito es generar una indicación hacia el dispositivo que genera la interrupción para que sepa que ha sido atendido y por tanto que debe cesar la solicitud.

CC = 01 Salta si Flag indicado en el OpCode está activo

La entrada 1 del multiplexor, viene de otro multiplexor que elige una de las cuatro banderas que arroja la ALU. El control de este segundo multiplexor proviene de la propia instrucción. Los dos bits menos significativos del OpCode determinan que bandera verificar. Si la bandera indicada es 0 no se salta y si es 1 se salta. CC=01 solo aparece en una sola microinstrucción dentro de la ejecución de la instrucción de salto condicionall. Es en el único momento en que los bits menos significativos de IR tienen importancia.

 

Ciclo de instrucción al 100%


    Luego de un reset, las primeras microinstrucciones se encargan de inicializar PC en 0 y SP en 0xFF. 

    Si no hay interrupción solicitada, se lee la celda de memoria apuntada por PC y por tanto se almacena en IR el OpCode de la siguiente instrucción.

    Modificar IR implica direccionar otra zona de la microMemoria en la que están las microinstrucciones que ejecutan la instrucción. Una vez finalizada la instrucción se regresa a incrementar PC o no. Depende de la instrucción. Por ejemplo si es un salto incondicional, PC ya apunta al OpCode de la siguiente instrucción y en ese caso no hay que incrementarlo.

    Si hay una interrupción pedida, se genera un pulso en la señal de salida IntA, el cual supuestamente hace que la señal Int vuelva al estado 0  (supongo que  hay un solo dispositivo potencialmente interruptor). En vez de ir a buscar el OpCode de la siguiente instrucción desde memoria según diga PC, en el caso de que halla una interrupción se carga en IR el valor 0xF0 que es el OpCode de la instrucción Call ISR y por tanto se ejecuta dicha instrucción.

 

    La manera más simple que se me ocurre de explicar lo que es una interrupción es la siguiente: 

        Es la posibilidad que se le da a un dispositivo periférico de solicitar un llamado a una subrutina.

    Esta definición dice mucho si se entiende. Hace un tiempo leí una definición simple que entendí después de un buen rato y decía: Los registros de la cpu son una memoria cache cuya organización es manejada por software. (no es textual, pero ese es el concepto)