0% encontró este documento útil (0 votos)
5 vistas268 páginas

Notas

El documento presenta una introducción a los sistemas de numeración, destacando la importancia de los sistemas binario y hexadecimal en computación. Se explican los sistemas posicionales y con base, así como los métodos para convertir números entre diferentes bases, incluyendo enteros y fracciones. Además, se menciona la relación entre las bases octal y hexadecimal con el sistema binario y se introducen conceptos sobre códigos y errores en la representación de datos.

Cargado por

santimaropbr
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
5 vistas268 páginas

Notas

El documento presenta una introducción a los sistemas de numeración, destacando la importancia de los sistemas binario y hexadecimal en computación. Se explican los sistemas posicionales y con base, así como los métodos para convertir números entre diferentes bases, incluyendo enteros y fracciones. Además, se menciona la relación entre las bases octal y hexadecimal con el sistema binario y se introducen conceptos sobre códigos y errores en la representación de datos.

Cargado por

santimaropbr
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Sistemas de Numeración

Arquitectura de Computadoras
(Versión 4.4 - 2024)
Arquitectura de Computadoras Notas de Teórico

1 SISTEMAS DE NUMERACIÓN

1.1 Introducción

En este capítulo expondremos brevemente (a modo de repaso) conceptos básicos


sobre los sistemas de numeración.

No por sencillo el tema deja de ser importante pues nos permite comenzar a
acostumbrarnos a los sistemas de numeración utilizados en computación, especialmente el
binario y el hexadecimal, tarea no trivial si tenemos en cuenta el "lastre" que significan años
y años de práctica con el sistema decimal exclusivamente.

Podemos entender un sistema de numeración como un conjunto de símbolos y un


conjunto de reglas de combinación de dichos símbolos que permiten representar los
números enteros y/o fraccionarios.

Dentro de los sistemas de numeración posibles un conjunto importante, y destacado,


es el constituido por los sistemas de numeración posicionales.

1.2 Sistemas Posicionales

En estos sistemas la representación de un número se realiza mediante un conjunto


de símbolos y su posición relativa dentro de una expresión (una “tira” de símbolos).

Como ejemplo de un sistema posicional podemos citar al Romano, en el cual es


claro que la posición relativa de los símbolos influye en la representación. Ej.: VI
corresponde al 6 y IV al 4.

Dentro de los sistemas posicionales están incluidos los que serán objeto de nuestro
estudio: los sistemas con base.

1.3 Sistemas con Base

En los sistemas con base un número cualquiera N, se representa mediante un


polinomio de la forma:

N = anbn + …. + a0b0 + a-1b-1 + ….

donde ai es un símbolo del sistema, al que llamamos dígito, y b es la base.

La base es igual a la cantidad de símbolos del sistema. Notando que los dígitos son
la representación en el sistema de los números enteros menores que la base, tenemos que
se cumple la condición b  ai  0.

La base b la representamos siempre, por convención, en el sistema decimal (si la


representáramos en el sistema del cual es base su representación sería, naturalmente, 10).

Habitualmente la representación omite las potencias de la base y coloca un punto (o


coma) para separar la parte de potencias positivas de la parte con potencias negativas,
quedando:

N = an an-1 ….. a0 , a-1 a-2 …. a-p

Instituto de Computación - Facultad de Ingeniería - UDELAR


2
Arquitectura de Computadoras Notas de Teórico

 Sistema decimal: El sistema de numeración utilizado en la vida cotidiana es el


decimal, cuya base es 10, utilizando los conocidos diez símbolos 0, 1, 2, 3, 4, 5,
6, 7, 8 y 9 .

 Sistema binario: Es el sistema de base 2 en el cual los dos símbolos utilizados


son el 0 y el 1, los que reciben el nombre de bit (binary digit).

 Sistema Octal: Es el sistema de base 8 en el cual se usan los símbolos 0, 1, 2, 3,


4, 5, 6, 7.

 Sistema Hexadecimal: Es el sistema de base 16 en el cual se usan los símbolos


0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F .

La base del sistema en el que está representado un número se suele indicar con un
subíndice al final del número y en los casos particulares de base 2 (binario), base 8 (octal),
base 16 (hexadecimal) con un subfijo con las letras b, o (ó q) y h respectivamente. En el
caso de base 16 también se utiliza el prefijo 0x. Si no se indica nada se asume base 10.
Ejemplos:

1101(2 = 1101b = 1.23 + 1.22 + 0.21 + 1.20 = 13 (decimal)

1011.11(2 = 1011.11b = 1.23 + 0.22 + 1.21 + 1.20 + 1.2-1 + 1.2-2 = 11.75 (decimal)

A2F(16 = A2Fh = 0xA2F = 10.162 + 2.161 + 15.160 = 2607 (decimal)

Estudiaremos a continuación los algoritmos para que, dada la representación de un


número en una cierta base, podamos hallar la correspondiente representación en otra base
dada.

1.4 Conversión de Base de Números Enteros

Nuestro deseo es dado un número N entero en una base B representado por

se desea hallar su expresión en una base b

En definitiva lo que buscamos es hallar los valores de am , am-1 , . . . , a0

 Caso A:

Conversión de una base B a una base b usando la aritmética de la base b (muy útil
para pasar de cualquier base a la base 10).

La conversión se hace a través del polinomio característico, expresando los


símbolos An . . . A0 y la base B en la base b y evaluando el polinomio, realizando las
operaciones en la base b.

Instituto de Computación - Facultad de Ingeniería - UDELAR


3
Arquitectura de Computadoras Notas de Teórico

Ejemplo: Convertir A2Fh a decimal.

 Caso B:

Conversión de una base B a una base b usando la aritmética de la base B (muy útil
para pasar de base 10 a cualquier base)
Previamente notemos que cualquier número N se puede expresar como:

donde se repite la división entera entre b hasta llegar a un Nn menor que b (la
próxima división daría cociente 0).

Por lo que los valores a0 . . . an son los restos de las divisiones de N entre b realizadas
en la aritmética de la base B.

Instituto de Computación - Facultad de Ingeniería - UDELAR


4
Arquitectura de Computadoras Notas de Teórico

Ejemplo: Convertir 653 a binario.

653 = 1010001101b

Ejemplo: Convertir 653 a base 5.

653 = 10103(5

Los ejemplos vistos son siempre de decimal a otra base; si quisiéramos pasar desde
una base b1 (b1 <> 10) a la base b2 existe la posibilidad de hacer las operaciones con la
base b1 o, por simplicidad, cambiar primero a base 10 y luego de esta a la base b2.

1.5 Conversión de Números con parte Fraccionaria

Sea un número N = Ne + Nf = an bn +...+ a1 b + a0 + a-1 b-1 + ... donde Ne y Nf son la
parte entera y la parte fraccionaria respectivamente. La parte fraccionaria sigue siempre a la
parte entera en cualquier base. Por lo tanto Ne puede convertirse igual que antes y Nf se
convierte por separado

Estudiaremos entonces como convertir partes fraccionarias. Sean:

Nf = A-1 B-1 + A-2  B-2 + ... en base B

Nf = a-1 b-1 + a-2  b-2 + ... en base b

Instituto de Computación - Facultad de Ingeniería - UDELAR


5
Arquitectura de Computadoras Notas de Teórico

 Caso A:

Conversión de base B a una base b usando la aritmética de la base b (muy útil para
pasar de cualquier base a base 10 )

Sea Nf = A-1 B-1 + A-2  B-2 + ...+ A-m  B-m

lo que hago es desarrollar el polinomio equivalente.

Sea P(x) = A-1 x1 + A-2  x2 + ...+ A-m  xm

Si se calcula el valor numérico de P(x) para x = B-1 usando aritmética b obtendremos


el valor buscado.
Ejemplo : pasar 0.213(8 a base decimal
N=2  8-1 + 1  8-2 + 3  8-3  P(x) = 3  x3 + x2 + 2  x

1
El valor numérico para x  será:
8

P(x) = 3  (0.125)3 + (0.125)2 + 2  (0.125) = 0.27148...

 Caso B:

Conversión de una base B a una base b operando con la aritmética de la B (lo que la
hace muy útil para pasar de base 10 a cualquier base)

Para determinar los coeficientes a-1, a-2, etc. para la base b se observa que cada uno
de tales coeficientes es, en si mismo un entero.

Primero se multiplica por b (con aritmética B):

b  Nf = a-1 + a-2  b-1 + ...+ a-3  b-2

En donde, la parte entera de b  Nf es a-1. A continuación se resta a-1 y se multiplica


de nuevo por b:
b (b  Nf - a-1) = a-2 + a-3  b-1 + ... determinando así a-2. Se sigue este proceso hasta
que se obtengan tantos coeficientes como se deseen. En el siguiente procedimiento puede
ocurrir que el proceso no termine.

Ejemplo: Convertir 653.61 a base 2

2  (0.61) = 1.22  a-1 = 1

2  (0.22) = 0.44  a-2 = 0

2  (0.44) = 0.88  a-3 = 0

2  (0.88) = 1.76  a-4 = 1

2  (0.76) = 1.52  a-5 = 1

Instituto de Computación - Facultad de Ingeniería - UDELAR


6
Arquitectura de Computadoras Notas de Teórico

653 = 1010001101b  653.61 = 1010001101.10011...b

1.6 Caso Particular bases 8 y 16

La base 8 (octal) y la base 16 (hexadecimal) tienen una íntima relación con la base
2. Puesto que 8 = 23 cada dígito octal corresponde a 3 dígitos binarios. El procedimiento
entonces para convertir un número binario en número octal es dividir en grupos de 3 bits a
partir del punto binario y asignando el dígito octal correspondiente a cada grupo.

Ejemplo: convertir 11001010011.111110011(2 a base 8

11
001010
011.111
110011
 3123.7630 (8
3 1 2 3 7 6 3

La conversión de base 8 a base 2 se hace a la inversa, convirtiendo en binario cada


dígito octal, así:

7328 es
78 = 111b
38 = 011b => 7328 = 111011010b
28 = 010b

El equivalente hexadecimal de un número binario se obtiene, simplemente,


dividiendo al primero en grupos de 4 bits, rellenando con ceros (a la izquierda en la parte
entera y a la derecha en la parte fraccionaria).

Ejemplo :

1101
10111000
0110.1010
0011 0DB86.A3h
D B 8 6 A 3

Análogamente se realiza para pasar de hexadecimal a binario.

La Tabla 1 presenta la combinación binaria equivalente a cada uno de los símbolos


del sistema hexadecimal.

0000 0 1000 8
0001 1 1001 9
0010 2 1010 A
0011 3 1011 B
0100 4 1100 C
0101 5 1101 D
0110 6 1110 E
0111 7 1111 F
Tabla 1 - Conversión binario hexadecimal.

Instituto de Computación - Facultad de Ingeniería - UDELAR


7
Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Códigos y Errores

Arquitectura de Computadoras
(Versión 4.3b - 2016)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

2 CODIGOS Y ERRORES

2.1 Introducción

En el próximo capítulo estudiaremos la forma en que se representan los distintos


tipos de objetos con que trabajamos en computación. En los lenguajes de alto nivel
manejamos distintos tipos de datos: caracteres, strings, números enteros, números reales.
Para trabajar con ellos, en general sólo nos interesa saber que son, como se opera con
cada uno y esto se estudia en los cursos de programación. En esta materia nos
ocuparemos de otro aspecto: como están implementados, a nivel interno, los distintos tipos
de datos.

La unidad elemental de información que se usa en computación es un objeto que


toma solo 2 valores posibles (0, 1): el BIT (dígito binario)

Los distintos tipos de datos se construyen en base a estructuras de bits, los cuales
serán en general “tiras” (sucesión ordenada de bits) de n elementos que reciben el nombre
de palabra de largo n. En el caso particular de n = 8 la tira se denomina byte.

Estudiaremos entonces, la representación interna de los datos como la expresión de


los distintos tipos en función de estructuras de bits.

Por lo anterior resulta que los distintos tipos de datos se representan a través de
códigos binarios. Es decir existe un proceso de codificación de los objetos de información
en función de otros (las estructuras de bits) con los que se trabajará en realidad.

Conviene alertar que el término “código” se usa indistintamente para referirse tanto a
un código binario particular (la respresentación de un objeto), como a un sistema de
codificación. Que sea una u otra acepción dependerá del contexto.

Por esta razón es interesante estudiar, aunque sea brevemente, un problema


fundamental en la manipulación de códigos binarios: la detección y corrección de errores.

No nos referiremos aquí a errores en la codificación de los objetos sino a los que
aparecen cuando se manipula con ellos. Usualmente los objetos de información se
almacenan y/o se transmiten. Estas dos operaciones comunes se realizan, en definitiva,
utilizando medios físicos (memorias, discos, canales de comunicación, etc.) los cuales no
están libres de errores. Por tanto es de particular interés el estudio de la posibilidad de
detectar o corregir errores en códigos binarios. De esta manera nos aseguraríamos que un
dato recuperado de una unidad de almacenamiento es correcto (coincide con el
almacenado) o que un dato recibido por un canal de comunicaciones lo es (coincide con el
enviado por el emisor).

2.2 Detección y Corrección de Errores

Todos los sistemas de codificación que permiten detección y corrección de errores


se basan en una misma idea: redundancia.

El fundamento es sencillo: para poder distinguir si un valor es correcto o no (o sea


representa un objeto válido del sistema o no) debo agregar información adicional al código.
Entonces en todo sistema de codificación con capacidad de detectar errores el número de
objetos representados es siempre menor que el número de valores posibles del código
binario utilizado.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Esta afirmación quedará más clara cuando veamos las distintas estrategias
utilizadas. De todas formas un ejemplo puede ser de utilidad: supongamos que tenemos 16
objetos a representar; en principio, con un código binario de 4 bits alcanzaría (2 4 = 16), pero
con 4 bits no estaríamos en condiciones de detectar errores puesto que todos los valores
posibles del código binario utilizado corresponderían a objetos válidos. De esta manera si,
por ejemplo, hubiera un error en un bit del código que representa a un objeto A se
transformaría en el código que representa a un objeto B por lo que no habría posibilidad de
detectarlo.

Para disponer, en este caso de la posibilidad de distinguir un código binario correcto


de uno incorrecto, deberíamos utilizar un código binario de, por ejemplo, 6 bits. Con 6 bits
tendríamos 64 valores posibles de los cuales sólo 16 representarían objetos reales. Si
elegimos convenientemente los códigos asociados a cada objeto estamos en condiciones
de detectar errores producidos por el cambio de un bit en el código que representa un
objeto.

2.3 Distancia

La distancia entre dos representaciones binarias se define como el número de bits


distintos entre los dos códigos.

Es decir si tenemos dos códigos binarios a y b

(a0 , a1, . . ., an)

(b0, b1, . . ., bn)

la distancia entre ellos está dada por la cantidad de unos en el código formado por:

(a0  b0 , a1  b1 , . . . an bn)

donde  representa a la operación O Exclusivo (XOR).

Por ejemplo, los códigos:

01101
10110

tienen una distancia 4 (cuatro)

La "distancia" tal cual la hemos definido tiene las siguientes propiedades (que no
vamos a demostrar):

1) d(a,b) = d(b,a)
2) d(a,b) = 0 si y sólo si a = b
3) d(a,b) + d(b,c)  d(a,c)

Se pueden generar sistemas de codificación binarios que tengan una determinada


distancia. En el caso de un sistema de codificación se llama "distancia" del código (ó del
sistema de codificación) a la mínima distancia que exista entre dos valores válidos del
código.

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

La posibilidad de detectar y corregir errores está fuertemente vinculada, como es de


suponer, a la distancia del código (sistema de codificación) utilizado.

Consideremos un código (sistema de codificación) de distancia "d" y dos objetos


válidos del código A y B. Consideremos el conjunto de valores posibles del sistema de
codificación (no necesariamente válidos) que se obtienen de modificar hasta "e" bits del
valor "A". Idem para los del valor "B". Estos conjuntos se pueden visualizar como "esferas"
en el espacio de "n" dimensiones (siendo n la cantidad de bits del código) rodeando a cada
uno de los valores.

d e
t
A B

Como se puede ver, si estos conjuntos no tienen puntos en común, podemos no


solo detectar la existencia de un error, sino que además podemos reconocer a qué código
correcto corresponde un valor "degenerado" dado, permitiendo por tanto la "corrección" del
error. Si los conjuntos tienen puntos en común no podremos corregir, pero si detectar
errores, siempre y cuando dentro del conjunto de puntos asociado al valor A no se incluya
al valor B, puesto que si no, la alteración de un código válido puede conducir a otro válido,
impidiendo así detectar el error.

Es decir que la condición para que se puedan detectar errores es que:

e<d

la condición para que se puedan corregir es:

d
e<
2

Por ejemplo para poder corregir errores de hasta un bit, hay que utilizar un código de
distancia 3 por lo menos.

2.4 Bits de Redundancia

Se puede demostrar que para generar códigos de distancia 3 para objetos


representables en "k" bits, se necesitan utilizar "p" bits adicionales, llamados bits de
redundancia ó de paridad, tal que se cumpla:

2p  p + k + 1

El razonamiento detrás de esta afirmación es que para poder identificar el bit que
tiene error dipondremos de 2p combinaciones posibles, generadas por los p bits. Con esas
combinaciones debemos poder señalar cual es el bit errado de los p + k bits que tendrá el
código completo (el original más los bits de redundancia agregados). Además precisaremos
tener una combinación para indicar que no hay error y de ahí surge que el lado derecho de
la expresión es p + k + 1.

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Por ejemplo, supongamos que queremos diseñar un sistema de memoria de una


computadora de 16 bits, de manera que sea capaz de corregir errores de hasta 1 bit. De
acuerdo a la expresión necesitamos agregar 5 bits de redundancia para que esto sea
posible.

25 = 32  5 + 16 + 1 = 22

La siguiente tabla muestra los valores de p (bits agregados) para distintos valores de
k (bits del código original).

k p
4 3
8 4
16 5
32 6
64 7
128 8

En la tabla se observa que la cantidad relativa de bits que es necesario agregar


disminuye a medida que aumenta el tamaño del código original. Esta propiedad tiene
impacto sobre el hecho que en las computadoras de hoy en día, que son de 32 ó 64 bits de
tamaño de palabra, sea más frecuente encontrar sistemas de memoria ECC (Error
Correcting Code) que permiten la detección y corrección de un bit fallado.

2.5 Paridad

Uno de los mecanismos para generar sistemas de codificación con capacidad de


detectar errores es el de la paridad, o codificación con bit de paridad.

La idea es agregar a cada código binario de n bits que representan objetos válidos,
un nuevo bit calculado en función de los restantes. La forma en que se calcula el bit de
redundancia (de paridad) es tal que la cantidad de unos en el código completo (original + bit
de paridad) sea par (en cuyo caso hablamos de paridad par) o impar (en cuyo caso se
trata de paridad impar).

Cuando se genera el código (se almacena o se transmite) se calcula este bit


mediante uno de los dos criterios expuestos a partir de los n bits originales. Cuando se
recupera el código (se lee o se recibe) se recalcula el bit y se chequea con el almacenado o
transmitido. En caso de no coincidir estamos ante un error, si el chequeo cierra podemos
decir que para nuestro sistema no hubo errores.

Notemos que no podemos afirmar en forma absoluta la ausencia de error aunque el


bit de paridad recalculado coincida con el recuperado. Esto es una regla general para todo
sistema de codificación con detección de errores, y en este caso se ve claramente: si
cambian a la vez 2 bits del código o, en general, un número par de ellos, el sistema de
detección de errores por paridad no funciona, en el sentido que no reporta el error.

Los sistemas de codificación con capacidad de detección (o detección y corrección)


de errores funcionan correctamente dentro de ciertos límites, si se cumplen ciertas hipótesis
de trabajo. Un conjunto de supuestos que de cumplirse aseguran el buen funcionamiento
de los sistemas que estamos analizando es:

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

(a) La probabilidad de que falle un bit es baja.


(b) Las fallas de bits son sucesos independientes (la posibilidad que un bit falle no
tiene relación alguna con la falla de otro bit del código).

En esta hipótesis la probabilidad de que fallen 2 bits a la vez es igual al cuadrado de


la probabilidad que falle uno (por la segunda hipótesis) que ya era un valor pequeño (por la
primera) por lo que da un valor muy bajo. Por lo tanto en estas hipótesis el sistema de
detección por paridad funciona bien: cuando no detecta error es altamente probable que el
código sea efectivamente el correcto.

Es importante señalar que las hipótesis efectuadas se ajustan al caso de las


memorias de las computadoras modernas. No ocurre lo mismo con los dispositivos de
almacenamiento que graban la información en forma serial (un bit a continuación del otro) ni
con los sistemas de transmisión de datos seriales ya que en estos casos el hecho que falle
un bit está vinculado, en forma no despreciable, a la falla de otro ( en particular del vecino
"anterior"), por lo cual la hipótesis b) no se cumple para estos sistemas, de donde el control
por paridad no sería demasiado efectivo en estos casos.

Volviendo al mecanismo de bit de paridad y recordando la definición de la operación


lógica XOR y su propiedad asociativa es fácil ver que el bit de paridad se puede expresar
como:

P = b0  b1  . . .  bn (paridad par)
ó
P = ( b0  b1  . . .  bn )’ (paridad impar)

El chequeo de la corrección de un código recuperado se puede realizar evaluando la


expresión (para paridad par):

P  b0  b1  . . .  bn

con los valores de P, b0 ... bn recuperados. Si el resultado es 0 "no hubo error", si es 1


entonces se detectó un error.

Una variante de este sistema es el mecanismo de paridad horizontal/vertical. Este


método se puede aplicar cuando se almacenan o transmiten varias palabras de código.
Cada palabra de n bits de código tiene su bit de paridad (que se denomina paridad
horizontal) y cada n palabras almacenadas/transmitidas se agrega una palabra de paridad
generada como el XOR (bit a bit, incluyendo el de paridad horizontal) que recibe el nombre
de paridad vertical. Por ejemplo para n=8 sería algo así:

a0 a1 a2 a3 a4 a5 a6 a7 ah
b0 b1 b2 b3 b4 b5 b6 b7 bh
.............
.............
v0 v1 v 2 v3 v4 v5 v6 v7 vh

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

ah = a0  a1 . . .  a7 (idem para b, c, d, e, f, g, h)

vi = ai  bi  . . .  hi ( i= 0, 1, 2, 3, 4, 5, 6, 7, h)

2.6 2 de 5

Los sistemas de codificación con capacidad de manejar los errores pueden ser
construidos a partir de un sistema de codificación que no tenga esa capacidad (como es el
caso de la “paridad” ya visto) o pueden contruirse desde el comienzo con una distancia
mayor o igual a 2 de forma que tengan incoporada la caractaerística desde el comienzo.

Un ejemplo de esta segunda categoría es el código " 2 de 5", el cuál puede tener la
forma:

01100 - 0
11000 - 1
10100 - 2
10010 - 3
10001 - 4
01010 - 5
01001 - 6
00110 - 7
00101 - 8
00011 - 9

Como vemos este código tiene distancia 2 ya que todos los elementos del código
difieren por lo menos en 2 bits (ej: 11000 y 10100). De los 32 posibles objetos que permiten
representar 5 bits, este código permite representar tan solo 10 objetos.

Una aplicación práctica de un sistema de codificación es el “Entrelazado 2 de 5”


(“Interleaved 2 of 5”) que es un código de barras utilizado para identificar artículos. La
codificación que se utiliza es:
0 ffAAf
1 AfffA
2 fAffA
3 AAfff
4 ffAfA
5 AfAff
6 fAAff
7 fffAA
8 AffAf
9 fAfAf

donde “f” significa una barra fina y “A” una ancha.

El “entrelazado” del nombre se refiere a que la codificación se realiza de a parejas


de dígitos, combinando las barras oscuras con las barras claras. Al comienzo del código se
alternan barras finas oscuras y claras para indicar el comienzo.

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

Notar que luego de la secuencia de inicio fina oscura, fina clara, fina oscura,
fina clara, vienen las siguientes barras oscuras: AfffA, intercaladas con las siguientes
barras claras: fAffA. Esto es porque se toman los dos primeros dígitos (12) y se
representa al 1 con las barras oscuras y al 2 con las claras intercalando oscuras con
claras.

2.7 Códigos de Hamming

Los códigos de Hamming son una forma práctica de generar códigos de distancia 3.
Los veremos a través de un ejemplo en concreto. Supongamos que tenemos 16 objetos
representados, en principio, en binario:

a4 a3 a2 a1

de acuerdo a lo visto antes precisamos 3 bits de redundancia (ya que 2 = 8  3 + 4


3

+ 1 = 8)

p3 p2 p1

Si armamos el código (que tendrá entonces 7 bits) de la siguiente manera:

a4 a3 a2 p3 a1 p2 p1

y convenimos que las representaciones válidas de los 16 objetos a representar son


aquellas en los cuales los bits de redundancia se calculan de la siguiente manera:

p1 = a4  a2  a1

p2 = a4  a3  a1

p3 = a4  a3  a2

podemos al recuperar el código calcular los bits "s" que están vinculados, al igual
que los "p" a la posición de los distintos bits en el código:

a4 a3 a2 p3 a1 p2 p1
S0 x x x x
S1 x x x x
S2 x x x x

s0 = p1  a4  a2  a1

s1 = p2  a4  a3  a1

s2 = p3  a4  a3  a2

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

estos bits "s" representan, en binario, un número " S"

S = S2 S1 S0

Si al calcular "S" se da que es cero no hay errores (por lo menos para nuestro
sistema de codificación). Si " S" da distinto de 0, el número que de me indica el bit que está
errado (siendo el 1 el de más a la derecha, o sea p 1). De esta manera es posible reconstruir
el valor correcto del código, cambiando el bit que identificamos como corrupto (si está en 0
lo pasamos a 1 y viceversa).

La propiedades de este sistema de codificación están determinadas por la elección


de las posiciones de los bits del código original y los bits de paridad en el código resultante.
Como se puede observar la tabla que utilizamos permite reconocer la posición de cada
dígito si reemplazamos las x por 1 y leemos el número S2S1S0 en binario.

2.8 Código de Verificación de Suma

Como fue mencionado los sistemas de detección por paridad son aptos para
trabajar en la hipótesis que la falla de un bit es un suceso probabilísticamente independiente
de la falla de un bit "vecino". Los códigos de Hamming también se apoyan en esta hipótesis
para asegurar eficacia en la detección y corrección del error de un bit.

Esta hipótesis se cumple muy bien en dispositivos como ser las memorias de las
computadoras (RAM). Sin embargo en los sistemas de almacenamiento masivo en base a
discos magnéticos u ópticos, o en sistemas de transmisión serie, la hipótesis no es cierta y
por tanto estos mecanismos de manejo de errores no son del todo efectivos.

Para estos casos se utilizan otros métodos, diseñados para ser capaces de manejar
errores múltiples ó "errores en ráfaga" (un error en ráfaga significa que fallan varios bits
contiguos en forma simultánea).

El más sencillo de estos métodos es el denominado Código de Verificación de


Suma, también conocido por su denominación en inglés “checksum”. El “checksum”
consiste en agregarle a un conjunto de códigos binarios almacenados ó transmitidos un
código adicional consistente en la suma binaria de los mismos, módulo 2n (siendo n la
cantidad de bits del código).

Supongamos un mensaje (Hola!!) formado por 6 caracteres representados en ASCII


de 8 bits. El código binario quedaría:

01001000 01101111 01101100 01100001 00100001 00100001

y el “checksum” a agregar al final se calcula como:

01001000
+01101111
+01101100
+01100001
+00100001
+00100001
---------------
111000110 que si nos quedamos con los 8 bits menos significativos es: 11000110

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

Por lo que el mensaje incluyendo el checksum sería:


01001000 01101111 01101100 01100001 00100001 0010000111000110

Si bien es simple de implementar no es muy efectivo (es fácil ver que hay
combinaciones de bits erróneos que computan el mismo “checksum”).

2.9 Código de Redundancia Cíclica

Un código para errores en ráfaga muy difundido es el Código de Redundancia


Cíclica (CRC), que se basa en la aritmética de módulo aplicada a los polinomios.

Consideremos un "mensaje" a transmitir (o almacenar) de m bits. Llamamos M(x) al


polinomio de grado m-1 cuyos coeficientes coinciden con los bits del mensaje. Se define un
polinomio G(x) de grado r de coeficientes binarios (0 ó 1), que es característico del sistema.

Consideremos el polinomio xrM(x), en otras palabras elevamos el grado del


polinomio M(X) en r. Planteemos la división entera de dicho polinomio entre G(x):

xrM(x) = Q(x)G(x) + R(x) donde Q(x) = cociente y R(x) = resto

Consideremos ahora el polinomio T(x) definido por la expresión:

T(x) = xrM(x) - R(x)

Es sencillo comprobar que T(x) es divisible por G(x). T(x) es el polinomio que se
transmite (o almacena). En realidad los que se transmiten (o almacenan) son los bits
coeficientes de T(x). Notemos que los primeros m bits de T(x) son los mismos que M(x), ya
que R(x) es a lo sumo de grado r-1 y por tanto no afecta ninguno de los coeficientes de
xrM(x). R(x) por tener grado r-1 agrega entonces r coeficientes (bits) al mensaje
representado por T(x) y es, en definitiva, el CRC del mensaje original M(x).

El receptor del mensaje modificado T(x) (o el sistema que lo recupera del


almacenamiento) puede verificar la correctitud del mensaje comprobando que T(x) es
dividible por G(x).

Lo más interesante de este método es que, a pesar de las apariencias, es


sumamente sencillo de implementar, incluso en hardware, por tratarse de coeficientes
binarios.

La elección del polinomio G(x) (denominado "generador") no es un tema menor, ya


que de acuerdo a sus coeficientes tendrá mejores propiedades de detección. Los sistemas
CRC que tienen polinomios G(x) con grado r y contienen término independiente pueden
detectar errores de ráfagas de hasta r bits. Tener en cuenta que estos sistemas son muy
buenos para ráfagas, pero no tanto para errores aislados si estos aparecen más de una vez
en el mensaje.

Un ejemplo de polinomio que se usa es:


16 15 2
CRC-16-IBM -> x +x +x +1

que fue desarrollado originalmente por IBM para su protocolo de comunicaciones


“Bisync”.

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

Otro ejemplo es:


16 12 5
CRC-16-CCITT -> x +x +x +1

desarrollado por la CCITT (actualmente UIT = Unión Internacional de


Telecomunicaciones) para, entre otros, el protocolo de comunicaciones X.25.

También existen polinomios para calcular CRCs de 32 y 64 bits.

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Representación Interna de Datos

Arquitectura de Computadoras
(Versión 4.3c - 2016)
Arquitectura del Computador 1 Notas de Teórico

3 REPRESENTACION INTERNA DE DATOS

3.1 Introducción

Como ya adelantamos en este capítulo analizaremos como se construyen las


representaciones de los distintos tipos de datos en función de los codigos binarios,
formados por estructuras de bits.

3.2 Tipo Carácter

3.2.1 Introducción

Comenzaremos viendo cómo se representan los caracteres mediante códigos


binarios. Entendemos por caracteres los símbolos que se utilizan en el lenguaje natural
escrito: letras, números, símbolos de puntuación, símbolos especiales, etc.

La forma en que se codifican los caracteres ha ido evolucionando con el tiempo y


han existido, y existen actualmente, múltiples formas distintas de hacerlo. Los sistemas de
codificación de caracteres muchas veces dependen de los idiomas y por tanto difieren
según las geografías donde se apliquen y su popularidad depende en parte de la
importancia geopolítica y económica de dichas regiones.

Durante los 80 y los 90 la forma más difundida de representar estos símbolos es la


establecida por el denominado código ISO-8859-1 para los idiomas de Europa Occidental.
Este código fue diseñado por la International Standard Organization en forma original como
ISO/IEC 8859-1 (que tenía menos caracteres definidos), adoptado en forma oficial por la
IANA (Internet Assigned Numbers Authority = organismo que regula actualmente la
actividad en internet) y fue utilizado por los sistemas operativos UNIX (o derivados).
Una variante del ISO/IEC 8859-1 es el Windows-1252, utilizado por el sistema
operativo Windows en sus primeras versiones (hasta Windows 95).

Actualmente la tendencia es hacia la utilización del UCS (Universal Character Set),


que es la parte de especificación de caracteres del proyecto Unicode, el cuál se diseño para
ser un estándar universal de cómo representar texto en múltiples idiomas y de múltiples
tipos (ej: fórmulas matemáticas) en las computadoras. El Unicode fue adoptado por la ISO
bajo la denominación ISO 10646.
Existen distintos sistemas de codificación del Unicode/ISO 10646. El más difundido
es el UTF-8 ya que ha sido adoptado como de soporte obligatorio en sitios y navegadores
de Internet y el UTF-16 usado por las versiones actuales de Windows (de XP en adelante)
en forma nativa. También existe el UTF-32.
El UTF-8 es un sistema de codificación de largo variable, compatible con el ASCII
(American Standard Code for Information Interchange), origen también del ISO-8859 y
muchos otros sistemas de codificación de caracteres.

3.2.2 Representación ASCII

El ASCII es un código de 7 bits que especifica la representación de las letras y


símbolos especiales usados en el idioma Inglés (más exactamente Inglés norteamericano)
además de los números, y es muy similar al alfabeto número 5 del CCITT (Comité
Consultivo Internacional sobre Telefonía y Telecomunicaciones), actualmente ITU
(International Telecomunication Union), organismo que, entre otras funciones, establece
propuestas de estandarización en materia de comunicaciones.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura del Computador 1 Notas de Teórico

De los 128 valores posibles del código (7 bits) 10 se utilizan para los dígitos
decimales (del 30h al 39h), 26 para las letras mayúsculas (del 41h al 5Ah), 26 para letras
minúsculas (del 61h al 7Ah), 34 para símbolos especiales (espacio, !, #,$,%,/,&,+,-,*, etc.) y
los 32 primeros se denominan genéricamente "caracteres de control" y se utilizan
básicamente en la comunicación de datos y con fines de dar formato a los textos en
impresoras y pantallas de video.
Algunos de estos caracteres de control son:
00h  NUL (Null) Es la ausencia de información, se utiliza como carácter de relleno.
02h  STX (Start of Text) Muchos protocolos de comunicación lo utilizan para
indicar el comienzo de un texto.
03h  ETX (End of Text) Idem para fin de texto.
06h  ACK (Acknowledge) Se utiliza en comunicaciones para contestar
afirmativamente la recepción correcta de un mensaje.
15h  NAK (Negative acknowledge) Idem para recepción incorrecta.
0Ah  LF (Line Feed) Indica pasar a la siguiente línea (en una impresora o
pantalla).
0Ch  FF (Form Feed) Indica pasar a página siguiente.
0Dh  CR (Carriage Return) Indica volver a la primera posición dentro de la línea.
11h  DC1 (Data Control 1) Indica dispositivo libre (disponible).
12h  DC2 (Data Control 2) Indica dispositivo ocupado (no disponible).

1Bh  ESC (Escape) Indica el comienzo de una "secuencia de escape". Los


caracteres que vienen a continuación tienen un significado especial. Estas secuencias se
usan típicamente para enviar comandos a las impresoras y/o terminales de visualización.
Por ejemplo, para posicionar el cursor en la pantalla, cambiar el tipo de letra en una
impresora.

La forma más habitual de representar el código ASCII, y en general todos los


sistemas de codificación de caracteres, es a través de una matriz cuyas columnas están
asociadas a los 3 bits más significativos del código, y sus filas a los 4 bits menos
significativos tal como se muestra en la siguiente tabla:

0 1 2 3 4 5 6 7
0 NUL DLE SP 0 @ P ` p
1 SOH DC1 ! 1 A Q a Q
2 STX DC2 " 2 B R b R
3 ETX DC # 3 C S c S
4 EOT DC4 $ 4 D T d T
5 ENQ NAK % 5 E U e U
6 ACK SYN & 6 F V f V
7 BEL ETB ' 7 G W g W
8 BS CAN ( 8 H X h X
9 HT EM ) 9 I Y i Y
A LF SUB * : J Z j Z
B VT ESC + ; K [ k {
C FF FS , < L \ l |
D CR GS - = M ] m }
E SO RS . > N ^ n ~
F SI US / ? O _ o DEL

Tabla 2 - Código ASCII

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura del Computador 1 Notas de Teórico

Como ya hemos establecido, el ASCII codifica los caracteres utilizados para escribir
textos en idioma Inglés y los signos de puntuación y símbolos especiales propios de dicha
lengua. ¿Qué pasa entonces con otras lenguas como el español, en particular?. Cómo se
puede observar, la Ñ, por ejemplo, no está codificada, tampoco las letras acentuadas, así
como signos de puntuación característicos de nuestro idioma como "¿" y "¡". La situación en
este campo fue confusa hasta la última década del pasado siglo y existieron distintas
propuestas de codificación aceptadas.
Se propusieron dos mecanismos básicos para atacar el problema: uno fue modificar
el ASCII de 7 bits adaptándolo a cada lengua; el otro fue utilizar un código de 8 bits, que en
sus primeros 128 valores coincidiera con el ASCII y los restantes utilizarlos para representar
los caracteres propios de un conjunto relativamente grande de idiomas.

Un ejemplo del mecanismo de modificación del ASCII es el que fue utilizado por
EPSON en sus impresoras y que se convirtió en un "estándar de facto" en el mundo de las
computadoras personales al ser aceptado y soportado por la casi totalidad de los otros
fabricantes de impresoras. El mecanismo consiste en sustituir caracteres (en general
símbolos especiales) por los caracteres que le "faltan" al ASCII para adaptarse a cada
lengua en particular. Así tenemos un "ASCII español", un "ASCII francés", un "ASCII inglés
(de Inglaterra)", etc.

3.2.3 Representación IBM437

Un ejemplo de código de 8 bits es el que utilizó por IBM en sus primeras


computadoras personales, el cual puede considerarse también un "estándar de facto".
Utiliza los 128 valores más altos para letras y símbolos de otros idiomas y para caracteres
gráficos (que permiten dibujar recuadros y cosas similares). Posee tambien algunas
versiones adaptadas a distintas regiones del mundo. La utilizada para la mayoría de los
idiomas de Occidente es la IBM437 (o CP437, por Code Page 437). En la tabla 3 se
muestran los caracteres "agregados" al ASCII (incompleta) para esta variante.

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura del Computador 1 Notas de Teórico

Tabla 3 - Código IBM437 de 8 bits (con codigo Unicode asociado).

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura del Computador 1 Notas de Teórico

3.2.4 Representación ISO-8859-1

El código ISO-8859-1 está representado en la tabla 4, incluyendo los caracteres


agregados por la codificación Windows-1252 (también conocida como Windows Latin-1).

Tabla 4 - ISO-8859-1 (en las filas 80 y 90 están los caracteres agregados por
Windows-1252).

3.2.5 Representación ISO 10646

El ISO 10646 es un estándar de representación de caracteres propuesto por la ISO


que coincide con la parte de representación de caracteres del UCS (Universal Code
Character Set) del Proyecto Unicode. El UCS de Unicode pretende codificar texto (no
solamente caracteres) y toda clase de símbolos dando soporte a áreas tales como las
matemáticas, la lingüística y los lenguajes de programación, entre otras. Una de las
ventajas de la representación Unicode es que incluye a todos los lenguajes escritos
conocidos (o al menos a casi todos).

El sistema de representación de caracteres asocia a cada carácter/símbolo un


“punto de código” (“code point”) es decir un valor numérico. En la página unicode.org se
encuentran los “charts” que muestran la expresión gráfica de cada punto de código.

Por ejemplo para la lengua tibetana los caracteres previstos en Unicode/ISO 10646
son:

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura del Computador 1 Notas de Teórico

Nota: la tabla presenta los dígitos más significativos del “punto de código” en las
columnas.

El UCS se definió de tal modo que los primeros 127 caracteres coinciden con los
definidos en el ASCII original.

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura del Computador 1 Notas de Teórico

Los “puntos de código” se codifican de distintas formas. Las más utilizadas con el
UTF-16 y el UTF-8.

El UTF-16 es un sistema de codificación de “puntos de código” del UCS de largo


variable, que utiliza 2 o 4 bytes para representar los “puntos de código”. Es decir que la
mínima cantidad de bits usada para representar un carácter es 16. Es el sistema utilizado
por Windows en sus versiones actuales.

El UTF-8 es también un sistema de codificación de los “puntos de código” del UCS


de largo variable, con la diferencia que utiliza de 1 a 6 bytes (aunque en la práctica se usa
hasta 3 bytes) por lo que el mínimo requerido son 8 bits.

La siguiente tabla muestra los rangos de “puntos de código” (indicados por U-


hhhhhhhh, donde hhhhhhhh son 8 dígitos hexadecimales) y su respectiva codificación
según este algoritmo:

U-00000000 – U-0000007F: 0xxxxxxx

U-00000080 – U-000007FF: 110xxxxx 10xxxxxx

U-00000800 – U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx

U-00010000 – U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

U-00200000 – U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

U-04000000 – U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

El UTF-8 tiene la interesante propiedad que los “puntos de código” correspondientes


al ASCII se codifican en solo 1 byte, con lo que un texto que contenga solamente
caracteres representables en ASCII tendrá la misma representación en ASCII que en UTF-
8.
El UTF-8 es el sistema de codificación del UCS que se está convirtiendo en el
estándar universal, ya que está adoptado en forma obligatoria por los sitios y navegadores
de Internet.

3.3 Tipo String

El tipo STRING es una sucesión de caracteres. Existen varias formas de


representación interna. Lo principal a saber es dónde termina la sucesión.

 Una primera manera es emplear largo fijo. Esta representación es demasiado


rígida.

 Una segunda manera es reservar un código especial para fin de string. Este
código especial no podrá formar parte del string. Por ejemplo, el lenguaje "C"
utiliza el NULL para fin de string. Cuando se utiliza combinado con codificación la
codificación de los caracteres en ASCII (u otro sistema de representación de
caracteres similar). Esta representación recibe el nombre de ASCIIZ.

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura del Computador 1 Notas de Teórico

 Una tercera manera consiste en convertir los strings en un registro donde el


primer campo tiene el largo y el segundo tiene el contenido. En BASIC se
pueden encontrar ejemplos de esta representación.

3.4 Tipo Natural (entero sin signo)

3.4.1 Representación Binaria

Los enteros sin signo (siempre positivos, incluyendo el 0) poseen la representación


más simple: su código binario coincide con su expresión en base 2 restringida a un número
fijo de bits. Se utilizan para contadores, direcciones, punteros y para derivar otros tipos.

Las operaciones elementales de este tipo son las cuatro usuales para los números
enteros (+ - * / ).

Por ejemplo en la suma de 2 enteros sin signo, se aplica el algoritmo usual para los
números binarios. Veamos un par de casos considerando representaciones de 8 bits

Ejemplo 1:

000110000  carry final = 0


25 00011001
+ 74 01001010

99 01100011
Ejemplo 2:

111110000  carry final = 1


25 00011001
+234 11101010

259 00000011  la representación no es correcta

Los bits de carry (acarreo) de las operaciones anteriores (000110000 y 111110000)


se presentan en la primera línea de la operación. Notar que si el ultimo bit de acarreo (es el
denominado bit de acarreo o carry de la operación) es 1, el codigo binario resultante no
representa al resultado de la operación. En ese caso (carry = 1) ha sucedido un overflow,
que significa que nos hemos salido del rango de la representación.

El problema principal en esta representación, que es común a todas las basadas en


un tamaño fijo de palabra, es que estamos restringidos en el tamaño y las operaciones
pueden, por tanto, dar overflow (en este caso indicado por el carry en 1).

Los tamaños usuales para esta representación son: el byte ( 0 a 255 ), la palabra de
2 bytes (16 bits, 0 a (216)-1 ), la palabra de 4 bytes (32 bits, 0 a (2 32)-1) y, actualmente, la
palabra de 8 bytes (64 bits, 0 a (2 64)-1). En general el rango de la representación para n bits
será:

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura del Computador 1 Notas de Teórico

0  N  2n  1

3.5 Tipo Entero (con signo)

3.5.1 Representación Valor Absoluto y Signo

Si tenemos n bits para representar el número, tomamos uno para el signo y el resto
representa el valor absoluto del número en binario (expresión del numero en base 2).

Msb lsb
bn-1 bn-2 ... b1 b0

bn-1 = Signo.
bn-2 ... b1 b0 = Valor absoluto

 Si bn-1 = 1 entonces el número es negativo.

 Si bn-1 = 0 entonces es positivo.

Ejemplo: (en 4 bits)

0110  6
1110  -6

Para n bits el rango del número representado es:

 (2 n1  1)  N  2 n1  1

En esta representación tenemos dos formas de representar el cero, 1000 y 0000


(para n=4). Esto puede verse como un inconveniente. Además las operaciones no trabajan
directamente con la representación sino que deben interpretarse en base a los signos
relativos.

3.5.2 Representación Complemento a Uno

Los números positivos se representan en binario, y los números negativos se


representan como el valor absoluto complementado bit a bit.

Para n bits el rango del número representado es:

 (2 n1  1)  N  2 n1  1

n=8

msb Lsb
5  0000 0101
-5  1111 1010

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura del Computador 1 Notas de Teórico

Ejemplo: (n = 4)

-7 1000
-6 1001
-5 1010
-4 1011
-3 1100
-2 1101
-1 1110
0 0000
0 1111
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111

El orden en binario (interpretando los codigos como si fueran numeros en base 2,


aunque no lo son) no corresponde al orden de los números que representa. Otra
desventaja, es que hay 2 representaciones distintas para el cero ( 0000 y 1111).

3.5.3 Representación Desplazamiento

La representación por desplazamiento supone un corrimiento de los valores a


representar según un valor d (llamado desplazamiento), y posteriormente se la aplica el
módulo para que se pueda almacenar en el tamaño de la representación deseada. Para el
desplazamiento, se supone que el valor codificado (resultado de la operación N + d), es un
número que para n bits es un valor entre 0 y 2n-1, por lo que permite representar valores
desde –d a 2n-d-1.En general para representar 2n números diferentes, se asigna a d el
valor 2n-1, o 2n-1-1.

N  ( N + d ) representado con n bits

Ejemplo: n=4, d= 8

-8 0000
-7  0001
....
-1  0111
0  1000
1  1001
....
7  1111

La propiedad más importante de esta representación es que los códigos conservan


el orden de los números, con o sin signo. En particular, toda representación de un número
negativo es menor que cualquiera de un número positivo. Otra ventaja, es que hay una sola

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura del Computador 1 Notas de Teórico

representación para el cero.


El principal inconveniente de esta representación es que los algoritmos de las
operaciones usuales son más complejos.

3.5.4 Representación Complemento a Dos

Los números positivos se representan directamente en binario y para conseguir el


código de los negativos, se complementa el valor absoluto y se los incrementa en uno.

N  N2 si N  0

N  not (N2 ) + 1 = N si N <0

Por ejemplo, para números de 8 bits se tiene:

Si 70 = 01000110, entonces para lograr -70 hago el complemento a uno (negación


bit a bit) de esta configuración y luego le sumo uno, luego:

01000110 (70)
10111001 (complemento a 1)
1
10111010 (-70)

Las propiedades más importantes de esta representación son:

 Mantiene la suma (la suma con o sin signo es la misma operación, es decir que
el algoritmo es el mismo). Es decir la suma de las representaciones da la
representación de la suma de los números representados, sean estos positivos
o negativos.

 Es coherente la representación del cero:

00000000  0
11111111  not 0
1
00000000

repr( 0 ) = repr( -0 )

 Se pierde la relación de orden. El algoritmo de comparación de A con B depende


de los signos de A y de B.

 La resta se hace sumando el negativo del sustraendo, con lo que tambien se


mantiene.

A - B = A + ( -B ) = A + not B + 1

Al igual que en toda representación de largo fijo las operaciones pueden generar
overflow. Pero a diferencia del caso de la representación binaria (entero sin signo) en este
caso el bit de carry no indica por sí solo esta condición. Veamos algunos ejemplos

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura del Computador 1 Notas de Teórico

ilustrativos de los distintos casos posibles:

Ejemplo 1:
000110000  carry final = 0
25 00011001
+ 74 01001010

99 01100011  representación correcta (overflow = 0)

Ejemplo 2:
111110000  carry final = 1
25 00011001
+ -22 11101010

3 00000011  representación correcta (overflow = 0)

Ejemplo 3:
011100000  carry final = 0
25 00011001
+ 114 01110010

139 10001011  -117 representación incorrecta (overflow = 1)

Ejemplo 4:
100010100  carry final = 1
-120 10001000
+ -22 11101010

-142 01110010  114 representación incorrecta (overflow = 1)

En esta repreentación para saber si hubo overflow al final de la operación hay que
verificar la existencia de acarreo en los dos bits más significativos. Dejamos a cargo del
lector determinar la expresión lógica del overflow en función de dichos acarreos.

Para el caso de la multiplicación sucede algo paradójico: si bien la representación


mantiene también dicha operación, la forma usual de implementar la operación no lo hace.

Veamos primero con ejemplos la primer parte de la afirmación:

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura del Computador 1 Notas de Teórico

Ejemplo 1:

25 00011001
x 3 00000011

15 00011001
6 00011001

75 01001011  representación correcta


Ejemplo 2:

-22 11101010
x 3 00000011

6 11101010
6 11101010

-66 10111110  representación correcta

El problema es que la multiplicación binaria se implementa normalmente dando el


resultado en el doble de bits que los operandos. Esto es: si los operandos son de n bits, el
resultado de la multiplicación se calcula en 2n bits. Esto es porque de otra manera
rápidamente nos iríamos de representación aunque multiplicáramos operandos pequeños.
Al extender el resultado de la operación a 2n bits, la propiedad de mantener la
multiplicación deja de ser cumplida por la representación complemento a 2. De allí es que
se diga habitualmente que la representación complemento a 2 mantiene la suma pero no la
multiplicación (aunque estrictamente no sea correcta la afirmación).

De hecho la propiedad del mantenimiento de ambas operaciones (suma y


multiplicación) se desprende del hecho que en el fondo la aritmética de la representación de
complemento a 2 tiene un vínculo muy estrecho con la aritmética del módulo.
Veamos este punto. Primero observemos que para n bits, el complemento a 1 de un
numero cumple con:

N + N = 2n - 1

Por tanto:

N + N + 1 = 2n

o sea:

N + N = 2n  -N = -1 x 2n + N
dicho de otra manera el complemento a 2 de un número es lo que le falta para llegar
a 2n (por ejemplo en 8 bits, el complemento a 2 de 22 es 234, el complemento a 2 de 117
es 139 y así). La segunda parte es una forma equivalente de plantear la primera, de forma
de evidenciar lo que viene a continuación.

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura del Computador 1 Notas de Teórico

Consideremos ahora la representación de un número N cualquiera. Si N es positivo


se cumple siempre que:

N = 0 x 2n + N

y si fuera negativo se cumplirá que:

-N = -1 x 2n + N

Entonces en ambos casos la representación del número coincide con el resto de la


división entera del numero entre 2n. Es una propiedad conocida que la aritmética del resto
(aritmética de módulo) mantiene las operaciones de suma y multiplicación, siempre que se
tenga la precaución de tomar el módulo (resto de la división entera) de la operación
realizada entre los módulos. Esto equivale a quedarse con los n bits menos significativos
del resultado. Como vimos esto se hace en la práctica con la suma, pero no se hace con la
multiplicación (ya que se extiende a 2n bits), por lo que la propiedad solo se aplica a la
suma en el caso práctico.

3.5.5 Representación Decimal

Se usan para sumar cantidades de muchos dígitos donde no se puede perder


precisión. En aplicaciones comerciales se tiene un caso típico. Pueden ser del largo que se
quiera y se representan internamente en forma similar a un string formado por los dígitos de
su expresión en base 10, incluyendo el signo de “-“ al comienzo si es negativo.

La codificación típica es utilizando ASCII para los dígitos, signo y punto (o cualquier
otro sistema de codificación de caracteres compatible con él):

0 -> 00110000
1 -> 00110001
.........
9 -> 00111001

Observamos que en la representación en 8 bits para dígitos, se usan 10 de los 256


códigos, es decir es muy ineficiente.

Los algoritmos para las operaciones son similares a los empleados en las
operaciones decimales hechas a mano. Para sumar, por ejemplo, primero se deben alinear
los strings de modo que los finales estén enfrentados. Se deben rellenar hacia la izquierda
el mas corto con “0” para que los dos strings tengan el mismo largo. Luego se recorre de
derecha a izquierda dígito a dígito. Se debe obtener el valor del dígito de cada sumando a
partir de su representación como carácter. Si la codificación es ASCII se puede hacer una
operación de “máscara” (AND bit a bit) con 0x0F, ó restar el carácter ‘0’ (si el lenguaje lo
permite) ó utilizar la función “ordinal” o similar que algunos lenguajes poseen (que recibe el
carácter como argumento y devuelve el dígito que representa como número entero).
Luego que se obtiene la pareja de dígitos se realiza la operación (teniendo en
cuenta los signos de los sumandos). Si el resultado es mayor que nueve (para el caso de
suma) se resta 10 y se acarrea 1 para la suma de los próximos dígitos. Si el resultado es
menor que cero (para la resta), se suma 10 y se acarrea un -1 para la resta de la siguiente
pareja de dígitos.
Al finalizar el proceso se deben quitar los 0 a la izquierda del número para terminar
de darle formato al string que representará al resultado de la operación.

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


Arquitectura del Computador 1 Notas de Teórico

3.5.6 Representación Decimal Empaquetado (BCD)

En la representación Decimal se emplean 8 bits para cada lugar, cuando solamente


necesita 4 bits. Por esta razón se define la representación Decimal Empaquetado, en los
cuales se codifica con 4 bits cada dígito, ocupando así un solo “nibble” (“nibble” es el
conjunto de 4 bits). También se les llama Packed BCD (Binary Coded Decimal).

Vemos un ejemplo de codificación:

12345 => 000100100011010001011100

1 2 3 4 5 +
El nibble más a la derecha se utiliza como marca de fin e indica el signo del número.
El código 1100 (C hexadecimal) indica el fin de un positivo, mientras que el 1101 (D) indica
el fin de un negativo. A veces también se utiliza el código 1111 (F) para indicar el fin (sería
sin signo, es decir positivo).

Para operar con estas representaciones es necesario alinear los números (para que
los dígitos del mismo peso queden enfrentados) y luego se suma dígito a dígito teniendo en
cuenta el signo. Para obtener cada dígito recurro a técnicas de “máscara” (AND con 0x0F)
para obtener el dígito del nibble inferior y de desplazamiento (SHIFT) a la derecha (4 bits)
para obtener el dígito del nibble superior. En el resto el algoritmo es como el descripto para
el caso de la representación Decimal. Luego que se tienen los dos digitos de un byte del
resultado se arma el byte desplazando el digito de la parte alta del byte a la izquierda (4 bits)
y haciendo un OR con el dígito de la parte baja del byte.

3.6 Tipo Fraccionario

3.6.1 Representación Decimal con parte fraccional

Es una extensión de la representación Decimal, donde además se representa el


punto decimal con el carácter “.”.

En este caso para sumar primero se deben alinear los strings de modo que los
puntos decimales estén enfrentados. Se deben rellenar hacia la derecha y/o izquierda con
“0” para que los dos strings tengan el mismo largo. Luego el algoritmo es análogo al ya
descripto para la representación Decimal.

3.6.2 Representación Punto Fijo

Para representar numeros con parte fraccional se puede utilizar un número


determinado de bits (ej: 16, 32, 64), asignando un cierto número fijo de bits para representar
la parte entera del número y el resto para la parte fraccional. La parte entera siempre ocupa
los bits más significativos del código.

La representación se obtiene representando en Complemento a 2 el número


resultante de multiplicar N por 2f, siendo f el número de bits dedicados a la parte fraccional.

Para sumar y restar se opera directamente con las representaciones y el resultado


es consistente. Para la multiplicación se requiere corregir el resultado dividiendo entre 2 f.
Para la división se debe multiplicar el resultado por dicho número.

Instituto de Computación - Facultad de Ingeniería - UDELAR 16


Arquitectura del Computador 1 Notas de Teórico

3.6.3 Representación Punto Flotante

En las distintas arquitecturas de computadoras se han utilizado diversas


representaciones para expresar números reales, todas ellas basadas en la siguiente
notación :

N  (1) s .b e .M
donde: s es el signo
e es el exponente
M es la mantisa
b es la base de representación

Las bases utilizadas han sido, normalmente, 10 y 2. Dado que esta representación
es ambigua (existen varias representaciones para un mismo numero) se utiliza una versión
más restringida que se llama normalizada. Los números normalizados son aquellos en que
el bit más significativo de la mantisa es distinto de cero o, lo que es equivalente, son
aquellos en que la mantisa sea máxima.

3.6.3.1 Estándar IEEE 754 de punto flotante

Para que los números representados en punto flotante fueran posibles intercambiar
entre distintas arquitecturas se establece el estándar IEEE 754 que define el formato y las
operaciones con estos. El estándar IEEE 754 usa la base 2 (b = 2) y su mantisa
normalizada es de la forma 1,F. La representación utiliza el signo, el exponente (codificado
usando repreentación desplazamiento) y la parte fraccional de la mantisa (lo que está
después de la “coma binaria”). En definitiva el número se representa por la terna de códigos
binarios S (codificación del signo),E (codificación del exponente en desplazamiento),F
(codificación de la parte fraccional de la mantisa en binario).

El estándar define tres formatos (en función de la cantidad de bits utilizados):

S (bits) E (bits) F (bits) Total (bytes)


Simple Precisión 1 8 23 4
Doble Precisión 1 11 52 8
Precisión Extendida 1 15 64 10

La “Precisión Extendida” se usa para resultados intermedios de operaciones, pero


no para almacenamiento permanente.

Los números se almacenan de la siguiente forma :

Instituto de Computación - Facultad de Ingeniería - UDELAR 17


Arquitectura del Computador 1 Notas de Teórico

En el curso usaremos también la "Media Precisión" (no se usa en la práctica) que


tiene:

S (bits) E (bits) F (bits) Total (bytes)


Media Precisión 1 5 10 2

Los números normalizados son de la forma : (-1)s 1,F 2e, donde el bit más
significativo de la mantisa es un 1. Como todos los números normalizados tienen un uno en
el bit más significativo el estándar define una representación que omite este bit (para
optimizar). Esta consiste en: un 1 implícito, una coma implícita y luego la parte "fraccional"
de la mantisa.

Por lo tanto la representación a utilizar es de la forma :

N  (1) s .2 e127.(1, F ) para números de simple precisión


N  (1) s .2 e1023.(1, F ) para números de doble precisión

El conjunto de valores posibles pueden ser divididos en los siguientes:


 cero
 números normalizados
 números desnormalizados
 infinitos
 NaN (¬E, no es un número, como por ejemplo, la raíz cuadrada de un número
negativo)

Las clases se distinguen principalmente por el valor del campo “E” (exponente),
siendo modificada ésta por el campo “F” (fracción). Cada clase se representa con los
siguientes rangos de valores:

E (Exponente) F (Fracción)
Normalizados 0000….0 < Exp < 1111….1 Cualquier combinación
Desnormalizados 0000………………………..0 0
Cero 0000………………………..0 0
Infinito 1111..................................1 0
Not a Number 1111..................................1 0

Los números desnormalizados sirven para operar con números menores que el
menor número normalizado representable. Estos números asumen un 0 implícito en vez del
1 implícito de los números normalizados. Por lo tanto cuando tenemos un número en
notación punto flotante desnormalizado estamos representando el número (ejemplo para
simple precisión):

(1) s .2 126.(0, F )

donde el exponente coincide con el exponenete del mas negativo normalizado

3.6.3.2 Operaciones en Representación Punto Flotante

Las operaciones (suma, resta, multiplicación) se realizan mediante algoritmos


especializados para la representación.

Instituto de Computación - Facultad de Ingeniería - UDELAR 18


Arquitectura del Computador 1 Notas de Teórico

Para la suma se debe:


- alinear los exponentes (llevando el menor al mayor), adecuando
concordamentemente la mantisa (teniendo en cuenta el 1 omitido)
- sumar las mantisas teniendo en cuenta los signos
- normalizar, acomodando la mantisa y el exponente, si corresponde

Para la multiplicación se debe:


- determinar el signo en base a los signos de los operandos
- sumar los exponentes
- multiplicar las mantisas
- normalizar, acomodando la mantisa y el exponente, si corresponde

3.6.3.3 Normalización y Pérdida de Información

Como vimos los números normalizados son de la forma: 1,F. donde el bit más
significativo de la mantisa es un 1. Todos los números deben ser representados en su
forma normalizada (siempre que se pueda) y los resultados finales de operaciones se
deben normalizar.
El método de normalización utilizado es mover la coma a la parte más significativa
de la cifra, es decir, variando el peso aritmético de los dígitos que lo componen.
Ejemplo: Representación de un decimal a binario en punto flotante (precisión
simple):

Se codificará el número decimal -118,625 usando el sistema de la IEEE 754.

Dado que es un número negativo, el signo es "1".


Primero, hay que escribir el número (sin signo) usando su expresión en base 2. El
resultado es 1110110,101. Luego se mueve la coma “binaria” a la izquierda, dejando sólo
un dígito a su izquierda.
1110110,101 = 1,110110101×26.
Esto es un número en punto flotante normalizado.
La parte fraccional de la mantisa es la parte a la derecha de la coma binaria,
rellenada con ceros a la derecha hasta obtener los 23 bits. Es decir
F = 11011010100000000000000.
El exponente es 6, que debe ser representado en Desplazamiento. Para el formato
IEEE 754 de 32 bits, el desplazamiento es 127, así es que 6 + 127 = 133. En binario, esto
se escribe como 10000101.
E = 10000101

El número queda entonces:

S E F

1 10000101 11011010100000000000000

3.6.3.4 Perdida de Precisión

Una característcia de esta representación es que el conjunto de números


representados no es contínuo, pudiendo existir "huecos" importantes. Esto lleva que en una
suma puede suceder que el resultado coincida con el mayor de los operandos. Es fácil de
ver si se piensa qué pasa si el numero de bits a correr hacia la derecha (para alinear los

Instituto de Computación - Facultad de Ingeniería - UDELAR 19


Arquitectura del Computador 1 Notas de Teórico

exponentes) hace que el bit más significativo sea menos significante que el bit menos
significativo de la otra mantisa: al sumar y tomar los bits mas significativos sólo se estarán
considerando los bits de la mantisa del número mayor.

3.7 Tipo Moneda

Para representar cantidades monetarias se suele utilizar una representación del tipo
"punto fijo", con un numero suficiente de dígitos luego de punto fraccional de forma de darle
cierta precisión a las operaciones financieras hasta el nivel de los "centavos".

Una forma alternativa de verlo es pensar que lo que se almacena es la parte entera
de la cantidad multiplicada por una potencia de 10. Por ejemplo el BASIC de Microsoft
define el tipo "currency" como un entero de 64 bits que resulta de multiplicar la cantidad
original por 10.000.

Es importante tener en cuenta que representaciones con precisión variable, como el


Punto Flotante, no son buenas representaciones para este tipo de información.

Instituto de Computación - Facultad de Ingeniería - UDELAR 20


Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Álgebra de Boole

Arquitectura de Computadoras
(Versión 4.3a - 2016)
Arquitectura de Computadoras Notas de Teórico

4 ALGEBRA DE BOOLE

4.1 Introducción.

El álgebra de Boole es una herramienta de fundamental importancia en el mundo de


la computación. Las propiedades que se verifican en ella sirven de base al diseño y la
construcción de las computadoras que trabajan con objetos cuyos valores son discretos,
es decir las computadoras digitales, en particular las binarias (en las cuales los objetos
básicos tienen solo 2 valores posibles) las que son, en definitiva, la totalidad de las
computadoras de uso corriente.

Desde ya adelantemos que no se verán aquí detalles formales de la construcción


algebraica, ni todas las propiedades que se verifican, así como tampoco todos los métodos
de síntesis de funciones booleanas que habitualmente se incluyen en este tema en cursos
de lógica y/o diseño lógico.

Como toda álgebra, la de Boole parte de un cuerpo axiomático, el cual puede


adquirir diversas formas, variando la cantidad y calidad de los axiomas. Aquí en particular
tomaremos uno: el propuesto por Huntington en 1904 que tiene la ventaja de ser
consistente e independiente.

4.2 Axiomas.

1. Existe un conjunto G de objetos, sujetos a una relación de equivalencia, denotada


por "=" que satisface el principio de sustitución.

Esto significa que si a = b, b puede sustituir a a en cualquier expresión que la


contenga, sin alterar la validez de la expresión.

2. (a) Se define una regla de combinación "+" en tal forma que a + b está en G siempre
que tanto a como b lo estén.
(b) Se define una regla de combinación "" en tal forma que a  b está en G siempre
que tanto a como b lo estén.

3. Neutros.
(a) Existe un elemento 0 en G tal que para cada a de G: a + 0 = a
(b) Existe un elemento 1 en G tal que para cada a de G: a  1 = a

4. Conmutativos.
Para todo par de elementos a y b pertenecientes a G se cumple:

(a) a + b = b + a
(b) a  b = b  a

5. Distributivos.
Para toda terna de elementos a, b, c pertenecientes a G se cumple:

(a) a + (b  c) = (a + b)  (a + c)
(b) a  (b + c) = a . b + a  c

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

6. Complemento.
Para cada elemento a de G existe un elemento a tal que:
aa  0
a  a 1

7. Existen por lo menos dos elementos x, y en G tal que x <> y

Existe similitud de muchos de estos postulados con los del álgebra común. Sin
embargo, la primera de las reglas distributivas (sobre la suma) y la existencia del
complemento diferencian en forma fundamental esta álgebra de la común.

4.3 Modelo aritmético.

El ejemplo más simple del álgebra de Boole se compone de un conjunto G de 2


elementos: "0" y "1". Como es natural estos dos elementos deben coincidir con los neutros
de las reglas de combinación para satisfacer el axioma 3. Las reglas de combinación
debemos definirlas de manera de satisfacer los axiomas.

Así de acuerdo al axioma 3 :


00  0 0 1  0 (a  0)
1 0  1 11  1 (a  1)

de acuerdo al axioma 4
0 1  1 1 0  0
y teniendo presente el axioma 5 :

1  (1  0)  (1  1)  (1  0) (5a con a  1, b  1, c  0)
1  0  (1  1)  1
1  11 (por axioma 3)

0  (0  1)  0  0  0  1 (5b con a  0, b  0, c  1)
0 1  0  0  0
0  00 (por axioma 3)

Por lo tanto las reglas completas son:


00 0 00  0
0 1  1 0 1  0
1 0  1 1 0  0
11  1 11  1

Nosotros usaremos esta versión "binaria" del álgebra de Boole.

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

4.4 Propiedades.

 Dualidad

Si analizamos los postulados veremos que los mismos se presentan de a pares y en


tal forma que uno de la pareja se obtiene de otro cambiando "0" por "1" junto con "+" por ""
(y viceversa). Esto asegura que cada propiedad que se demuestre en esta Álgebra tiene
una "dual" que también es cierta (para demostrar la dual bastaría con repetir la
demostración realizada sustituyendo cada postulado o propiedad utilizada por su dual).

 Asociativa

a) a  (b  c)  (a  b)  c
b) a  (b  c)  (a  b)  c

Si bien las leyes asociativas son muchas veces incluidas dentro del cuerpo
axiomático, de hecho son demostrables a partir de los axiomas aquí presentados
(demostración que no haremos) por lo cual las presentamos como propiedades.

 Idempotencia

Para todo elemento en G se cumple:

aa a
aa  a

Demostración:

a  a  (a  a)  1 (3b)
a  a  (a  a )  (a  a ) (6)
a  a  a  (a  a ) (5a)
aa  a0 (6)
aa a

 aa  a (Dualidad)

 Neutros Cruzados

Para todo elemento en G se cumple

a 1  1
a0  0

Demostración:

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

a  1  a  (a  a ) (6)
a  1  (a  a )  a (asociativa)
a 1  a  a (idempotencia)
 a 1  1

 a0  0 (Dualidad)

Entonces los axiomas 1, 2, 3, 4, 5 y 7 se satisfacen por definición y es fácil


verificar que el G (complemento) también es cierto.

Construimos por lo tanto un modelo "aritmético" de álgebra de Boole que podemos


denominar "binario" y es en definitiva con la que trabajaremos.

Muchas veces las reglas de combinación se presentan como tablas (como las
funciones booleanas más generales que veremos más tarde)

a b a+b a b ab
0 0 0 0 0 0
0 1 1 0 1 0
1 0 1 1 0 0
1 1 1 1 1 1

En general notaremos ab como ab, además la operación “” tendrá mayor
precedencia que la operación “+”.

 Complemento de complemento

Para cada elemento de G se cumple : aa

Para todo par de elementos de G se cumple :

a  ab  a
a ( a  b)  a

Para todo par de elementos de G se cumple :

a  ab  a  b
a(a  b)  ab

 Ley de De Morgan

Para todo par de elementos de G se cumple :

( a  b)  ab
(ab)  a  b

Estas reglas de De Morgan pueden generarse para cualquier número de variables.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

(a1  a 2  ...  a n )  a1 a 2 ...a n


(a1 a 2 ...a n )  a1  a 2  ...  a n

4.5 Modelo lógico.

Los valores que pueden asignarse a un juicio, desde el punto de vista lógico, son
dos: verdadero (V) o falso (F).

Un juicio al cual se le aplica el operador lógico no (negación) forma un nuevo juicio.

Dos juicios pueden combinarse para formar un tercero mediante los operadores
lógicos "o" e "y".

Si vinculamos los valores booleanos 0 y 1 con los valores lógicos F y V


respectivamente, encontramos que las operaciones del álgebra de Boole "binaria" asigna
correctamente los valores lógicos del juicio combinación.

Esto se comprueba observando que:

verdadero o verdadero es verdadero


verdadero o falso es verdadero
falso o verdadero es verdadero
falso o falso es falso

verdadero y verdadero es verdadero


verdadero y falso es falso
falso y verdadero es falso
falso y falso es falso

Por lo cual se puede concluir que el modelo "lógico" es isomorfo con el "aritmético"
(binario) realizando la correspondencia.

F0
V 1

.


Es posiblemente consecuencia de este isomorfismo que las reglas de combinación


"+" y "." del álgebra de Boole reciban los nombres de OR ("o" en inglés) y AND ("y" en
inglés) respectivamente.

4.6 Modelo circuital.

Otro modelo posible es el que surge de considerar llaves eléctricas y asociar el valor
A a la llave abierta (no pasa corriente, circuito abierto) y el valor C con la llave cerrada
(pasa corriente, circuito cerrado).

Es fácil comprobar que la combinación de llaves en paralelo o en serie cumplen las


mismas reglas definidas en el modelo aritmético para "+" y "." respectivamente.

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

paralelo
serie

LL1 LL2 Circuito Paralelo LL1 LL2 Circuito Serie


A A A A A A
A C C A C A
C A C C A A
C C C C C C

Entonces existe también un isomorfismo entre el modelo "circuital" y el "aritmético"


si hacemos la asociación

A0
C 1
paralelo  
serie  

Este isomorfismo es de fundamental importancia para la construcción práctica de las


computadoras binarias.

4.7 Expresiones booleanas.

Llamamos constante a todo elemento del conjunto G que define al álgebra. Las
variables podrán tomar como valor cualquier elemento de G ( 0 o 1 en el caso en que
trabajamos).
Una expresión la podemos definir recursivamente como

1) las constantes y las variables


2) el complemento de una expresión booleana
3) el OR (+) o el AND () de dos expresiones booleanas.

4.8 Funciones booleanas.

Una función "F" de n variables x1 ... x n booleanas es una aplicación del espacio Gn
sobre el espacio G de tal forma que para cada valor posible de la n-upla x 1 ... x n, donde
cada variable puede tomar cualquier valor del conjunto (en nuestro caso {0, 1} ), se asocia
un valor del recorrido G.

Una de las formas de expresar F es a través de las denominadas tablas de


verdad que indican el resultado de F para cada valor posible de la n-upla; por ejemplo :

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

a b c F
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 0
1 1 1 1

Otras formas de representar F incluyen el método de indicar sólo los puntos en los
cuales F vale 1 o sólo los puntos en los cuales vale 0 (representaciones  y 
respectivamente). Para indicar los puntos en que la función vale 1 puede usarse la notación
 en lugar de .

Por ejemplo, la función anterior se puede expresar :

f ( a, b, c )   (1,4,5,7) f ( a, b, c)  (0,2,3,6)

Otra forma de expresar las funciones es a través de expresiones; ejemplo, la función


anterior sería:

f  ac  ab  abc

4.8.1 Conectivas binarias.

Un caso interesante de estudiar es el de las funciones booleanas de 2 variables. Por


ser dos variables las combinaciones posibles son 4, es decir "F" tiene 4 duplas (4 puntos)
por tanto existen 16 funciones booleanas de dos variables posibles. Algunas de ellas no son
de interes, veamos las tablas de verdad de las más útiles.

a b OR AND XOR NOR NAND Equiv. Idemp Tautol.


0 0 0 0 0 1 1 1 0 1
0 1 1 0 1 0 1 0 0 1
1 0 1 0 1 0 1 0 0 1
1 1 1 1 0 0 0 1 0 1

Nota :
la NOR es el complemento de la OR
la NAND es el complemento de AND
la XOR ("O" exclusivo) puede definirse como:
a  b  ab  ab

4.8.2 OR exclusivo.

El XOR es una función muy importante (es la suma aritmética binaria módulo 2) y
cumple las propiedades :
1) Asociativa
2) Conmutativa
3) Distributiva: a(b  c)  ab  ac
4) a  0  a
5) a 1  a

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

6) a  a  0
7) Cancelativa: a  b  a  c  b  c

4.8.3 Suma de productos canónicos.

Desarrollaremos a continuación un método sistemático para encontrar una


expresión algebraica para una función cualquiera dada.

Definamos producto canónico de n variables x1 ... xn al producto de todas ellas en el


cual cada variable aparece una y sólo una vez, en forma simple o complementada.
Una suma de productos canónicos es una expresión formada sumando productos
canónicos.

Existe un teorema (que no demostraremos) que afirma que toda función f de n


variables puede expresarse como:

f x1 , x 2 ,...., x n   x1  x 2  x3  ...  x n  f (1,1,1,...,1) 


x1  x 2  x3  ...  x n  f (0,1,1,...,1) 
x1  x 2  x3  ...  x n  f (1,0,1,...,1) 
.............. 
x1  x 2  x3  ...  xn  f (0,0,0,...,0)

Es decir toda función de n variables puede expresarse como la suma de todos sus
productos canónicos afectado cada producto canónico por un coeficiente. Este coeficiente
es el valor de la función evaluado en el punto tal que las variables que en el producto
canónico asociado aparecen simples tengan el valor 1 y las que aparecen complementadas
el valor 0.

Este teorema, de fundamental importancia nos permite enunciar un método de


construcción de una expresión que represente una función dada. El método es el siguiente:
se tienen en cuenta sólo los puntos en los que la función vale 1 (por el teorema los
productos asociados con los puntos en los que la función vale 0 desaparecen por estar
afectados por un coeficiente nulo: el propio valor de la función); en esos puntos se busca el
producto canónico asociado que es aquel donde la variable aparece simple si en el punto
vale 1 o complementada si vale 0. De esta manera la función puede expresarse como suma
de los productos canónicos así elegidos.

Por ejemplo sea la función de tres variables:

a b c F
0 0 0 0
0 0 1 1  abc
0 1 0 0
0 1 1 1  abc
1 0 0 1  abc
1 0 1 0
1 1 0 0
1 1 1 0

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

Entonces f puede expresarse como f (a, b, c)  a  b  c  a  b  c  a  b  c

4.8.4 Productos de sumas canónicas.

Como todo en el álgebra de Boole, existe un método dual del anterior: el producto
de sumas canónicas. En este caso deben considerarse los puntos en los que la función
vale 0 y buscar las sumas canónicas asociadas que son aquellas en las que la variable
aparece simple si tiene valor 0 y complementada si tiene valor 1.

4.9 Operadores lógicamente completos.

Un conjunto de operadores se llama lógicamente completo si cualquier función


booleana puede expresarse mediante los mismos.

Del teorema de los productos canónicos, ya enunciado, se extrae una conclusión


fundamental tanto del punto de vista lógico como del circuital: el conjunto de operadores +, .
y ' es lógicamente completo.

Otra consecuencia es que para probar que un cierto conjunto de operadores es


lógicamente completo, alcanza con probar que con ellos se pueden implementar el OR, el
AND y el NOT (complemento).

Es fácil probar que el conjunto OR, NOT es lógicamente completo notando que el
AND se puede construir como:

(ab)  a  b (por De Morgan)  a  b  (a  b)

Más interesante aún es mostrar que un solo operador, como el NAND, es


lógicamente completo. Debemos ver como implementar el NOT y el AND y el OR
(representaremos con # el NAND):

a # a  (a.a)  a (complemento)
(a # b)# (a # b)  (a # b)  (a.b)  a.b (AND)
(a # a)# (b# b)  (a.b)  (a  b)  a  b (OR) por De Morgan

Por lo cual el NAND es lógicamente completo.

4.10 Simplificación.

Hasta ahora hemos visto un método sistemático de expresar las funciones


booleanas como expresión de sus variables. Pero este método no asegura que la expresión
lograda sea la más simple posible. El hecho que la expresión de una función sea lo más
simple posible no es algo trivial o caprichoso, es de fundamental importancia en la
construcción práctica de circuitos lógicos, por eso analizaremos algunos métodos para
simplificar expresiones booleanas, de manera de aplicarlos a las expresiones obtenidas
como sumas de productos canónicos.

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

4.10.1 Método algebraico.

El método consiste en la aplicación, más o menos ingeniosa, de transformaciones


algebraicas de manera de lograr expresiones más sencillas. Por supuesto que este no es
un método sistemático, pero es la base, al fin, de los métodos sistemáticos.

Resumamos aquí algunas propiedades vistas del álgebra que serán de utilidad en la
tarea de simplificar:
1) f  f  0
2) f  f 1
3) g  f  g f  f
4) g  f  f  f
5) f  f g  f g

Veamos un par de ejemplos de como se aplican estas propiedades para reducir


expresiones:
a) Sea f1  abc  abc  abc

Por la aplicación de la propiedad 3 a los primeros dos términos y a los dos últimos
queda
f 1  ab  bc

b) Sea f 2  abc  abc  abc  abc

Aplicando la propiedad 3 a los dos primeros términos queda


f 2  bc  abc  abc
f 2  b(c  ac)  abc (por la propiedad distributiva)
f 2  b(c  a)  abc (por la propiedad 5 al paréntesis)
f 2  c(b  ab)  ab (por distributiva aplicada dos veces)
f 2  c(a  b)  ab (por propiedad 5 al paréntesis)

Entonces la expresión de f2 a la que llegamos es:

f 2  ab  ac  bc

Esta sin embargo no es la expresión más reducida de f 2. Vemos como hubiera


quedado aplicando la propiedad 3 al primer y cuarto miembro y al segundo y tercero

f 2  ac  ab

siendo esta sí, la expresión más reducida.

Como vemos entonces el procedimiento descrito no asegura reducir la expresión a


un mínimo ya que depende de como se elijan las propiedades a aplicar y los términos sobre
los que se aplican.

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

4.10.2 Métodos sistemáticos.

Los modelos sistemáticos se basan en la propiedad 3 g  f  g f  f y son


básicamente uno "gráfico" (Diagrama de Karnaugh) y otro "algorítmico" o "numérico"
(Método de Quine-McKlusky)
A continuación veremos una introducción al método gráfico.

4.10.3 Diagrama de Karnaugh.

Este método consiste en representar en forma gráfica una función como suma de
productos canónicos y hacerlo de tal forma que sea sencillo establecer procedimientos
sistemáticos para hallar las agrupaciones de términos más convenientes para simplificar la
expresión. Esto se logra utilizando una cuadrícula en la cual a cada cuadrado elemental
corresponde un producto canónico posible y tal que al pasar de uno a otro cualquiera de
sus cuatro adyacentes solo cambie el valor de una de las variables en juego. Por ejemplo
para tres variables la cuadrícula es:

c\ab 00 01 11 10
0
1

Para cuatro variables:

cd\ab 00 01 11 10
00
01
11
10

Para cinco variables:

e=0 e=1
cd\ab 00 01 11 10 cd\ab 00 01 11 10
00 00
01 01
11 11
10 10

En esta cuadrícula se marcan con "1" los lugares para los cuales la combinación de
valores de las variables hace que la función valga 1 y el método consiste en buscar agrupar
los "unos" formando los rectángulos más grandes posibles (que tengan todos 1 en su
interior), repitiendo este proceso hasta que todos los puntos donde la función vale "1" estén
comprendidos en algún rectángulo (siendo la cantidad total de rectángulos utilizados la
menor posible). Es necesario aclarar que la cantidad de elementos agrupados debe ser una
potencia de 2.

Nota: el diagrama es circular (los elementos de cada borde son adyacentes con los
del borde simétrico)

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

Ejemplos:

cd\ab 00 01 11 10
00 1 1
01 1 1 1
11
10

cd\ab 00 01 11 10
00 1 1 1
01 1 1
11
10 1 1

Una vez realizado el proceso anterior la mínima expresión de la función se obtiene


sumando los términos asociados a cada rectángulo los cuales son el producto de las
variables (simples o complementadas) cuyo valor no cambia en él.

Por ejemplo en los diagramas anteriores sería

1) f 3  ac  bcd
2) f 4  ad  abc  acd

Para finalizar veamos como se aplica el método al caso ya visto de la función:

f 2  abc  abc  abc  abc

El diagrama de Karnaugh correspondiente es

c\ab 00 01 11 10
0 1
1 1 1 1

Entonces la función queda f 2  ac  ab la cual coincide, como era de esperar, con


la expresión más reducida hallada por el método "algebraico".

La primer expresión de f2 hallada con dicho método tenía además el término bc que
corresponde al rectángulo formado por los dos extremos inferiores del diagrama que aquí
queda evidente que no era necesario puesto que con los otros dos términos cubrimos
todos los puntos donde la función vale "1".

4.10.4 Uso de “comodines” (“don’t care” ó “X”)

Cuando la función booleana que se desea minimizar tiene puntos en los cuáles no
está definida, es decir que no importa el valos que toma para ciertas combinaciones
específicas de sus variable de entrada, se puede utilizar esta propiedad para eventualmente
lograr una minimización más importante de la expresión algebraica.
Para ello se colocan “x” en el diagrama de Karnaugh correspondiente a esos puntos
no definidos y las “x” se podrán tomar como 1 en caso que permitan lograr un rectángulo de

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

mayor tamaño y 0 en caso contrario. De esta manera al lograr rectángulos de mayor


tamaño minimizo los términos de la expresión y eventualmente también la cantidad de los
mismos.
Cabe aclarar que no siempre se logra una mayor minimización porque existen casos
donde no es posible asignarle 1 a la “x” para lograr rectángulos más grandes. Notar
además que no tiene sentido alguno agrupas solamente “x” (porque así estaríamos
agregando términos, cuando la idea de usar las “x” es lograr una mayor minimización).

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Circuitos Combinatorios

Arquitectura de Computadoras
(Versión 4.3b - 2016)
Arquitectura de Computadoras Notas de Teórico

5 CIRCUITOS COMBINATORIOS

5.1 Introducción

En este capítulo presentaremos los elementos básicos para la implementación en


hardware de las funciones lógicas y ejemplos de cómo se pueden sintetizar funciones más
complejas en base a operaciones más simples disponibles como "bloques".

En general trabajaremos con los "Circuitos Combinatorios", que los definimos como
aquellos cuya salida está determinada, en todo instante, por el valor actual de sus entradas.

Antes de presentar la forma de representar las funciones lógicas básicas, veremos


brevemente como se implementan las mismas en términos electrónicos.

5.2 Transistores

Ya dijimos que el Modelo Circuital del Álgebra de Boole permite la construcción


mediante "llaves eléctricas" de un álgebra isomórfica con el Modelo Binario. Para ello
necesitamos que estas llaves puedan ser controladas (es decir accionadas) por los valores
que adoptan las variables (que en el modelo están representados por 0 = no circula
corriente y 1 = circula corriente).

Para ello el primer mecanismo que se usó (de hecho en la computadora MARK I en
la década del 40) fue el relé (llave electromagnética). El diagrama de un dispositivo de
estas características es:

I
i

Al circular una corriente i por el circuito de la izquierda la bobina genera un campo


electromagnético que acciona el interruptor, el cuál permite el pasaje de la corriente I por
el circuito de la derecha. Este esquema corresponde a un relé "normalmente abierto".
Existen también los relés "normalmente cerrados", en los cuales el mecanismo
electromagnético funciona a la inversa: la inducción de la bobina provoca la apertura del
interruptor.

Si en un sistema con relés tomamos el estado "circula corriente" como 1 y "no


circula corriente" como 0, es directo observar que un relé normalmente cerrado implementa
la función NOT.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

En ese modelo también es sencillo de observar que el siguiente circuito implementa


la función AND entre dos corrientes ia e ib:

ia I

ib

Los relés fueron luego reemplazados por las válvulas de vacío. Estos dispositivos
fueron los primeros completamente electrónicos utilizados en una computadora: la ENIAC.

Tomado de Virtual Valve Museum Tomado de Wikipedia


(http://en.wikipedia.org/wiki/Image:Triode.jpg)

En el caso de la válvula de vacío tipo "Triodo" (como la mostrada en el diagrama) la


diferencia de potencial entre la "rejilla" y el "cátodo" controlan el pasaje de electrones entre
el "ánodo" y el "cátodo", con lo cual el triodo es una llave controlada por diferencia de
potencial (ó "tensión", ó "voltaje").

A fines de la década del 50 se inventa el transistor, el cuál, con algunas variantes,


es el que se utiliza hasta ahora y que ha permitido alcanzar densidades de miles de
millones de unidades por centímetro cuadrado.

Tomado de Wikipedia (http://es.wikipedia.org/wiki/Imagen:Transistor-photo.jpg)

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

El funcionamiento de un transistor bipolar aplicado a la lógica digital es básicamente


el de una llave electrónica muy similar a un relé.

C
B
I
i
E

Los transistores se pueden definir, en principio, como "amplificadores de corriente"


ya que al circular una corriente i entre la base (B) y el emisor (E) del transistor se produce
la circulación de una corriente I entre el colector (C) y el emisor (E), cumpliendo la
relación:

I = hFE * i

siendo hFE una constante típica de cada modelo de transistor. Esta relación de
proporcionalidad es válida en el denominado modo de funcionamiento "lineal" y es utilizada
por ejemplo en los dispositivos que trabajan con señales analógicas, como equipos de
audio, televisores, etc. El funcionamiento en modo "lineal" depende, básicamente, del
circuito donde el transistor se coloca.
Sin embargo en las aplicaciones de lógica digital a los transistores se los hace
trabajar en el modo de funcionamiento "saturación", donde la corriente I alcanza su valor
máximo (determinado por otros parámetros del circuito).
Por otra parte, y al igual que en las aplicaciones analógicas, la magnitud eléctrica
que se considera es la diferencia de potencial eléctrico (o "voltaje") en lugar de la corriente.
Dada la conocida relación entre diferencia de potencial y corriente eléctrica dada por la Ley
de Ohm:

ΔV = R * I
Como muchas veces se consideran las diferencias de potencial ΔV con respecto a
una referencia común (denominada "tierra lógica") es que se aplica la relación anterior en la
forma:

V = R * I
Entonces veamos como queda el transistor cuando agregamos resistencias en su
base y en su colector:

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

El modo de funcionamiento de saturación se alcanza cuando el valor de Ve


(diferencia de potencial o voltaje de entrada) es tal que la corriente entre base y emisor
(IBE) genera una corriente entre colector y emisor (ICE) tal que la caída de potencial en la
resistencia RC colocada entre el colector y la fuente de alimentación coincide con la
diferencia de potencial de ésta. Esto equivale a decir que la diferencia de potencial entre
colector y emisor es 0. En realidad en la práctica dicha diferencia nunca puede llegar a ser
menor que un cierto valor denominado "voltaje de saturación colector emisor" (VCEsat),
por lo que la condición de saturación se da cuando se cumple la relación:

VCC - VCEsat = RC * hFE * IBE

El valor de VCEsat es aproximadamente 0,2 Volts, pero a los efectos se toma como
0.

Por su lado la corriente IBE circula cuando Ve > VBE siendo VBE una diferencia de
potencial que se produce entre base y emisor de un transistor y cuyo valor un parámetro
característico de los mismos y vale aproximadamente 0,6 Volts. Por ley de Ohm la corriente
de base cumple:

Ve - VBE = RB * IBE

despejando IBE y sustituyendo resulta:

VCC - VCEsat = RC * hFE * (Ve - VBE) / RB


En definitiva si se eligen correctamente los valores de las resistencias de base y
colector para que el sistema funcione en saturación para cuando el valor de la entrada sea
Ve = VCC se cumplirá que:
si Ve = VCC entonces Vs = 0

Por otra parte si no circula corriente entre base y emisor tampoco circulará corriente
entre colector y emisor. Esto significa que no circulará corriente por la resistencia de
colector y, de acuerdo a la ley de Ohm, no habrá entonces caída de potencial entre los
extremos de la misma, por lo que se cumplirá que:

si Ve = 0 entonces Vs = VCC

Si consideramos que el voltaje 0 corresponde a un 0 lógico y el voltaje igual al de la


fuente VCC corresponde a un 1 entonces vemos que el circuito anterior implementa la
operación NOT.

5.3 Lógicas

5.3.1 Lógica RTL

En base a las ideas manejadas en el circuito del NOT hecho en base a un transistor
y resistencias se pueden construir las demás conectivas binarias. En particular dado que el
NOR es un operador lógicamente completo alcanza con mostrar como se puede construir
con transistores y resistencias para poder afirmar que es posible construir cualquier función

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

lógica binaria de esta forma.

La construcción de funciones lógicas con esta técnica, empleando transistores y


resistencias, se denomina RTL (Resistor Transistor Logic).

Veamos el siguiente circuito en RTL:


Es simple de verificar que el circuito cumple que:

si Va = 0 y Vb = 0 entonces Vs = VCC
si Va = 0 y Vb = VCC entonces Vs = 0
si Va = VCC y Vb = 0 entonces Vs = 0
si Va = VCC y Vb = VCC entonces Vs = 0

ya que la conducción de cualquiera de los dos transistores provocará que la caída


de potencial en la resistencia de colector lleve el voltaje de salida a 0.

Dicho comportamiento en voltajes equivale a la tabla de verdad del NOR. Por tanto
hemos logrado mostrar que es posible construir cualquier función lógica en base a un
diseño RTL.

5.3.2 Lógica TTL

En la práctica la lógica RTL no se usa porque la utilización de las resistencias en la


forma que aparecen en el circuito genera una disipación de calor muy grande (la energía
disipada por una resistencia es proporcional al valor de ésta y al cuadrado de la corriente
que circula por ella de acuerdo a la Ley de Joule).

Para mejorar la situación se busca agregar transistores de forma de utilizar la


capacidad de amplificar corriente que poseen para disminuir la corriente circulante por las
resistencias. Esta técnica si bien sigue empleando resistencias, tiene una fuerte
dependencia de los transistores para lograr su cometido por lo que se denomina tecnología
TTL (Transistor Transistor Logic).

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

El circuito del NOR queda de la siguiente manera en TTL:

Tomado de Hoja de Datos de SN7402 de Texas Instruments

La más famosa familia de circuitos integrados construidos con lógica TTL se


identificó con números de 4 ó 5 dígitos que comienzan con 74.
Ejemplos:
7400 -> circuito integrado con 4 circuitos NAND de dos entradas
7402 -> circuito integrado con 4 circuitos NOR de dos entradas
7406 -> circuito integrado con 6 circuitos NOT
7408 -> circuito integrado con 4 circuitos AND de dos entradas
7432 -> circuito integrado con 4 circuitos OR de dos entradas
74193 -> circuito contador sincrónico de 4 bits

5.3.3 Lógicas TTL S/LS/ALS

Uno de los problemas de la lógica TTL sigue siendo el relativo alto consumo de
energía y su relativa baja performance en alta frecuencia. Esto se mejoró con la utilización
de transistores de mejores prestaciones, denominados Schottky (en honor a su inventor).
Esto dio lugar a variantes de la familia 74, conocidas como 74S, 74LS y 74ALS. Las letras
adicionales significan:
 S = Schottky
 LS = Low power Schottky
 ALS = Advanced Low power Schottky

5.3.4 Tecnología CMOS

La tecnología Schottky no modificó el hecho que siguieran siendo transistores


bipolares, los cuales tienen una característica inherente de consumir energía aún cuando
están en reposo (sus corrientes de "fuga" son relativamente elevadas). También el hecho
de poseer una resistencia interna equivalente cuando está en modo conducción genera una
disipación de calor alta dependiendo del estado de la salida (es decir cuando conducen no
son un conductor perfecto y presentan una resistencia significativa al pasaje de corriente).
Por eso luego de algunas décadas de predominancia de este tipo de transistores en
los circuitos integrados, los mismos fueron reemplazados por transistores FET (Field Effect
Transistor) construidos en base a tecnología CMOS (Complementary Metal Oxide
Semiconductor).
Los transistores construidos con esta tecnología tienen corrientes de fuga
prácticamente nulas por lo que su consumo es despreciable en reposo, y por la forma que

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

se construyen los circuitos con ellos sólo disipan energía cuando conmutan (sus salidas
pasan de un valor a otro respondiendo al cambio de sus entradas). Por otro lado su
resistencia interna es prácticamente nula en modo de conducción. La desventaja inicial que
tenían de mala respuesta a cambios rápidos de sus entradas (o sea mala respuesta en
frecuencia) fue superada con el tiempo con lo que han terminado por reemplazar totalmente
a los transistores bipolares.

Un transistor IGFET (Insulated Gate Field Effect Transistor, también conocido como
MOSFET) se puede considerar como una llave electrónica controlada por voltaje casi
perfecta, cuyo símbolo es:

Otros símbolos posibles son:

Tomado de www.learnabout-electronics.org

Los MOSFET de canal-n tienen "lógica positiva", mientras que los canal-p tienen
"lógica negativa", ya que funcionan de acuerdo al siguiente esquema:

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

Con esta tecnología el circuito del NOT se construye de la siguiente manera:

La característica señalada de disipar energía solamente en la conmutación (cambio


de estado) se puede observar analizando en el circuito del NOT. Como el voltaje de entrada
no cambia inmediatamente de 0 a Vcc o viceversa, hay una fracción de tiempo durante la
cual el voltaje está en valores intermedios que hacen conducir simultáneamente a ambos
transistores. Ese estado de conducción intermedio presenta valores de resistencia interna
bajos (aunque superiores a la resistencia casi nula de la conducción plena). Este fenómeno
genera picos importantes de corriente, los cuales circulan por los transistores en un modo
de conducción intermedio, lo que representa, en definitiva, la generación de calor. Este
fenómeno hace que los circuitos integrados fabricados con CMOS tengan una disipación de
calor proporcional a la frecuencia de trabajo del circuito.

Por su lado el circuito del NOR es:

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

5.4 Compuertas

La implementación en circuitos de las conectivas binarias básicas se denominan


habitualmente "compuertas". Así tendremos compuertas AND, OR, NAND, NOR, XOR y
NOT.
Las compuertas se representan por símbolos gráficos. Existen dos grandes familias
de símbolos, los tradicionales (símbolos "redondeados") y los propuestos por el estándar
ANSI/IEEE 91-1984 / IEC Publication 617-12 (símbolos "rectangulares").

5.5 Circuitos Lógicos Combinatorios

Los circuitos lógicos combinatorios, o simplemente circuitos combinatorios, son


circuitos elaborados a partir de compuertas o de otros circuitos del mismo tipo (usados
como "bloque constructivo") cuya salida es una función lógica de sus entradas y por tanto
las salidas actuales sólo dependen del valor actual de las entradas.

Los circuitos combinatorios son, en definitiva, la implementación en hardware de


funciones lógicas (funciones booleanas). Los circuitos se representan como "cajas negras"
de las cuales se especifican las entradas, las salidas y la función booleana que las vincula.

5.6 Síntesis de Circuitos Combinatorios

Una forma siempre aplicable (aunque en algunos casos más trabajosa) para
construir un circuito lógico parte de la función booleana a implementar representada, por
ejemplo, mediante su tabla de verdad. A partir de ella y mediante Diagramás de Karnaugh
(u otro método) se realiza la minimización (en dos niveles) de la misma. De esa forma se

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

llega a una expresión de la función en base a operaciones NOT y ANDs y ORs


(multipuerta).

Una alternativa es identificar partes del circuito que se puedan realizar con otros
"bloques constructivos" de mayor nivel, tales como sumadores de n bits, multiplexores,
decodificadores, comparadores, selectores, etc. Luego se reúnen y conectan
adecuadamente estos bloques minimizando, de ser necesario, la lógica de dichas
conexiones mediante Diagramás de Karnaugh.

Veremos a continuación un par de ejemplos de aplicación de la metodología.

5.6.1 Circuito Mayoría

Consideremos la función booleana determinada por la tabla de verdad:

a b c M
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1

El diagrama de Karnaugh correspondiente resulta:

c\ab 00 01 11 10
0 1
1 1 1 1

La función minimizada queda:

M = ab + ac + bc

Entonces el circuito en base a compuertas AND, OR y NOT tiene la forma:

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

5.6.2 Circuito Semi-sumador de 2 bits

Consideremos ahora la función booleana determinada por la tabla de verdad, donde


s1s0 representa la suma en binario de las entradas a1a0 y b1b0. La salida c es el Carry
(acarreo):

a1 a0 b1 b0 s1 s0 c
0 0 0 0 0 0 0
0 0 0 1 0 1 0
0 0 1 0 1 0 0
0 0 1 1 1 1 0
0 1 0 0 0 1 0
0 1 0 1 1 0 0
0 1 1 0 1 1 0
0 1 1 1 0 0 1

a1 a0 b1 b0 s1 s0 c
1 0 0 0 1 0 0
1 0 0 1 1 1 0
1 0 1 0 0 0 1
1 0 1 1 0 1 1
1 1 0 0 1 1 0
1 1 0 1 0 0 1
1 1 1 0 0 1 1
1 1 1 1 1 0 1

Los diagramas de Karnaugh correspondientes con:

s1

b1b0\ a1a0 00 01 11 10
00 1 1
01 1 1
11 1 1
10 1 1

s0

b1b0\ a1a0 00 01 11 10
00 1 1
01 1 1
11 1 1
10 1 1

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

b1b0\ a1a0 00 01 11 10
00
01 1
11 1 1 1
10 1 1

Por lo que las expresiones mínimas de las salidas son:


b v
s1 = a1b1b0 + a1a0b1 + a1a0b1b0 + a1a0b1b0 + a1a0b1 + a1b1b0
s0 = a0 0 + 0b0
s0 = a0b0 + a0b0

c = a1a0b0 + a0b1b0 + a1b1

Los esquemas de los circuitos basados en compuertas para las tres salidas en
función de sus expresiones mínimas se presentan a continuación.

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

Dado que los tres circuitos corresponden al mismo sistema y tienen las mismas
entradas, también puede considerarse un circuito que reutiliza las compuertas NOT y
genera las tres salidas como en el siguiente esquema.

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura de Computadoras Notas de Teórico

5.7 Bloques Constructivos

A continuación veremos algunos ejemplos de circuitos combinatorios útiles para ser


utilizados como parte de diseños más complejos. De hecho estos circuitos, o algunas
variantes de ellos, están disponibles como circuitos integrados independientes, pensando
en dicho propósito. Conforman la base del concepto de re-utilización que introdujo la
electrónica digital hace más de 4 décadas y que la industria del software imitó con los
conceptos de modularidad, re-usabilidad de código y orientación a objetos.

5.7.1 Circuito Decodificador

El circuito decodificador es un circuito con N entradas y 2N salidas. Para el caso de


N = 3 tiene el siguiente símbolo:

Su tabla de verdad es:

A B C Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
0 0 0 0 0 0 0 0 0 0 1
0 0 1 0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0 1 0 0
0 1 1 0 0 0 0 1 0 0 0
1 0 0 0 0 0 1 0 0 0 0
1 0 1 0 0 1 0 0 0 0 0
1 1 0 0 1 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0 0

es decir dada una combinación de unos y ceros a la entrada todas las salidas
estarán en 0 salvo la que corresponda al número binario coincidente con la combinación de
entradas.

En la práctica este circuito está disponible con lógica negativa (las salidas son 1
salvo la seleccionada) y con entradas adicionales funcionando como un demultiplexor
(circuito que veremos más adelante).

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


Arquitectura de Computadoras Notas de Teórico

El circuito "interno" de un decodificador es simple:

5.7.2 Circuito Multiplexor

El circuito multiplexor es un circuito con N + 2N entradas y 1 salida. Para el caso de


N = 3 tiene el siguiente símbolo:

Su tabla de verdad es:

A B C Y
0 0 0 D0
0 0 1 D1
0 1 0 D2
0 1 1 D3
1 0 0 D4
1 0 1 D5
1 1 0 D6
1 1 1 D7

Instituto de Computación - Facultad de Ingeniería - UDELAR 16


Arquitectura de Computadoras Notas de Teórico

es decir que la salida Y toma el valor de la entrada D cuyo índice coincida con el
número binario representado por las entradas A, B y C. Las entradas A, B y C se llaman
entradas de "control" y las entradas D se llaman de "datos".

Se denomina multiplexor porque es capaz de presentar en una sola variable Y


cualquiera de las 2N entradas. Esto tiene aplicaciones cuando la salida Y es un "canal
principal de comunicación", mientras que las entradas D son "sub-canales de
comunicación". Este circuito permite que variando en el tiempo las entradas de control
logremos dividir la utilización del canal principal entre los sub-canales. Esta técnica se
denomina TDM (Time Division Multiplexing). De allí que el circuito se denomine multiplexor.

Una característica distintiva del circuito multiplexor es su aplicabilidad para la


realización de funciones lógicas. Consideremos el siguiente circuito basado en un multilexor
8 a 1:

Si escribimos la tabla de verdad de este circuito nos queda:

a b c M
0 0 0 0
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 1

que coincide con la tabla de verdad del circuito Mayoría (a, b, c).

Si observamos nuevamente la tabla de verdad resumida del circuito multiplexor


constataremos que asignando un valor apropiado a cada una de las entradas del datos D,
estamos en condiciones de generar el valor 0 ó 1 correspondiente a cada una de las
combinaciones de los bits de control (entradas A, B, C). Esto permite construir cualquier
función lógica de n variables con un multiplexor de n entradas de control.

Los circuitos integrados disponibles (como el 74251) disponen de salida "tri-state" (el
concepto de tri-state se verá más adelante) controlada por una entrada adicional G y una
salida de lógica invertida W:

Instituto de Computación - Facultad de Ingeniería - UDELAR 17


Arquitectura de Computadoras Notas de Teórico

Por más información ver el documento:


http://www.fairchildsemi.com/ds/DM/DM74ALS251.pdf

5.7.3 Circuito Demultiplexor

El circuito demultiplexor realiza la tarea inversa al multiplexor. Posee 1 entrada de


datos, N entradas de control y 2N salidas, según el símbolo:

Su tabla de verdad es muy similar a la del decodificador, con la diferencia que el


valor de la salida seleccionada depende de la entrada G:

A B C Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
0 0 0 0 0 0 0 0 0 0 G
0 0 1 0 0 0 0 0 0 G 0
0 1 0 0 0 0 0 0 G 0 0
0 1 1 0 0 0 0 G 0 0 0
1 0 0 0 0 0 G 0 0 0 0
1 0 1 0 0 G 0 0 0 0 0
1 1 0 0 G 0 0 0 0 0 0
1 1 1 G 0 0 0 0 0 0 0

Instituto de Computación - Facultad de Ingeniería - UDELAR 18


Arquitectura de Computadoras Notas de Teórico

El circuito interno equivalente de un demultiplexor es:

En la práctica solamente se consiguen circuitos integrados demultiplexores y no


existen decodificadores "puros", ya que con ellos es muy simple construir un decodificador
(basta poner la entrada G en 1). Es el caso, por ejemplo, del circuito 74138, el cual tiene las
salidas con lógica negada y además posee dos entradas adicionales de lógica negada (que
están en AND con la entrada de lógica directa):

Por más información ver el documento:


http://www.fairchildsemi.com/ds/DM/DM74ALS138.pdf

Instituto de Computación - Facultad de Ingeniería - UDELAR 19


Arquitectura de Computadoras Notas de Teórico

5.7.4 Circuito Sumador Completo de 1 bit

Veremos a continuación un circuito que puede ser utilizado para construir


sumadores de n bits, mediante su conexión en "cascada". Para ello deberemos construir un
sumador de dos números de 1 bit cada uno con entrada y salida de acarreo (carry).

La tabla de verdad de este circuito es:

a b cin S cout
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1

Minimizando usando Diagrama de Karnaugh:

cin \ab 00 01 11 10
0 1 1
1 1 1

cout

cin \ab 00 01 11 10
0 1
1 1 1 1

(Nota: observar que cout tiene el mismo diagrama que el circuito Mayoría)

Con esto quedan las ecuaciones:


S = cin + b in + abcin + a in v
S = abcin + abcin + abcin + abcin

cout = ab + acin + bcin

Instituto de Computación - Facultad de Ingeniería - UDELAR 20


Arquitectura de Computadoras Notas de Teórico

El circuito que se obtiene sería entonces:

Este es un caso donde se puede observar que el método de Karnaugh permite


hallar un circuito mínimo en dos niveles, pero no necesariamente el circuito que tenga el
menor número de compuertas.
Si observamos la expresión de S:
S = cin + b in + abcin + a in v
S = abcin + abcin + abcin + abcin

y trabajamos con ella resulta:


S = cin + b i in v
S = (ab+ab)cin + (ab+ab)cin

El segundo paréntesis corresponde a la expresión del xor entre a y b. El primero a la


negación de dicho exor:
S = b in v
S = (ab)cin + (ab)cin

Podemos observar en la expresión anterior que ahora queda el exor entre el exor de
a y b con cin.

S = (ab)cin

Por otra parte la expresión del carry de salida es:

cout = ab + acin + bcin

que podemos agrupar como:

cout = ab + (a+b)cin

y esto es equivalente a:

cout = ab + (ab)cin

Instituto de Computación - Facultad de Ingeniería - UDELAR 21


Arquitectura de Computadoras Notas de Teórico

(esto se debe a que el único caso donde a+b es distinto de ab es cuando a y b son
1 simultáneamente y allí ab es 1 y por tanto el or general da 1 de todos modos).

El circuito que resulta de estas nuevas expresiones es:

que, como se puede observar directamente, posee muchas menos compuertas que
la versión anterior. Como nada es "gratis" también se observa que el circuito tiene un nivel
más de compuertas (normalmente el nivel de compuertas "not" no se cuenta, por lo que el
circuito original tiene 2 niveles y este tiene 3).

Esto desde el punto de vista lógico no presenta dificultades. Pero en la práctica


existe un fenómeno (tiempo de setup o propagación) que desaconseja el incorporar más
niveles de compuertas en los circuitos. Este fenómeno lo estudiaremos más detenidamente
en el siguiente punto.

Antes de pasar a él veamos como quedaría un sumador de 4 bits en base a


sumadores de 1 bit:

Instituto de Computación - Facultad de Ingeniería - UDELAR 22


Arquitectura de Computadoras Notas de Teórico

5.8 Tiempo (Retardo) de Propagación

Desde el punto de vista lógico el siguiente circuito:

tiene su salida siempre en 0.

Sin embargo dicho comportamiento teórico no se cumple en la realidad, ya que los


circuitos electrónicos que implementan las distintas compuertas (y en el caso particular el
NOT) no cambian su salida en forma instantánea frente a un cambio en su(s) entrada(s).
Existe un cierto tiempo que se requiere para que las distintas etapas del circuito se
acomoden al nuevo estado de conducción y generen las magnitudes (voltaje, corriente)
necesarias para llevar la salida al nivel lógico acorde a la expresión lógica.
Este tiempo recibe distintos nombres, tales como "tiempo de propagación", "retardo
de propagación", "retardo de conmutación" o "tiempo de setup". Este tiempo puede ir de
menos de 1 ns (nanosegundo, 1 ns = 10E-9 segundos) a más de 1 μs (microsegundo, 1μs
= 10E-6 segundos), dependiendo de la tecnología y características de los circuitos de las
compuertas.

El efecto que produce el fenómeno se puede visualizar en el siguiente diagrama de


tiempo:
Tp

t
E

t
En el diagrama se ha omitido considerar el retardo de propagación de la compuerta
AND, porque de hecho no interesa a los efectos de analizar el problema. El retardo de
propagación en la compuerta NOT produce que cuando la entrada E cambia a 1, la salida
del NOT demora en pasar a 0 un cierto tiempo Tp. Durante ese tiempo ambas entradas del
AND están en 1 con lo cual su salida pasará a 1 (en vez de quedarse en 0 que sería su
estado lógico de acuerdo al circuito, si éste fuera ideal). Recién cuando la salida del NOT
cambie la salida del AND irá a su valor correcto. El fenómeno produjo un "pulso" a la salida
que no debería haber existido. El fenómeno se puede compensar con técnicas apropiadas
de diseño de los circuitos lógicos, las que se basan en compensación de recorridos de las
distintas señales y en agregar compuertas, asociadas a rectángulos redundantes en los
diagramas de Karnaugh, de modo de evitar la generación de estas salidas espúreas. Estos
fenómenos se denominan genéricamente "azares estáticos".

Instituto de Computación - Facultad de Ingeniería - UDELAR 23


Arquitectura de Computadoras Notas de Teórico

Por este fenómeno es que normalmente se prefieren circuitos con pocos niveles de
compuertas entre sus entradas y sus salidas. Si pensamos que el circuito de sumador
completo de 1 bit que usamos para generar el circuito sumador de 4 bits tiene un retardo
Tp, entonces el sumador de 4 bits tendrá 4xTp, o en general NxTp, siendo N el número de
bloques en cascada que se conecten. Al crecer el retardo de propagación, las salidas
demoran más en ser válidas y poder ser consideradas como entradas para etapas
siguientes. Además la velocidad a la que podemos cambiar las señales (frecuencia de
conmutación) estará en relación inversa al tiempo de propagación, ya que cuanto más alto
este tiempo menor será la velocidad a la que podré cambiar las entradas (para darle tiempo
a que las salidas se estabilicen antes de cambiar nuevamente las entradas).

Instituto de Computación - Facultad de Ingeniería - UDELAR 24


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Memorias ROM

Arquitectura de Computadoras
(Versión 4.3a - 2016)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

6 MEMORIAS ROM

6.1 Introducción

En este capítulo analizaremos un circuito combinatorio especial, que por su variedad


de aplicaciones merece un tratamiento diferenciado del resto.
Este circuito tiene m entradas y n salidas. Para el caso de m = 14 y n = 8 el símbolo
que lo representa es:

Las entradas se identifican por A0 a A13 y las salidas por D0 a D7 (en este caso).
Para un caso genérico sería: A0 a Am-1 y D0 a Dn-1. Más adelante veremos que son y para
qué se usan las entradas CS y OE.

6.2 Características

La tabla de verdad de un circuito ROM está formado por 2m filas y n columnas:

Entradas Salidas
Am-1 Am-2 Am-3 …. …. A2 A1 A0 Dn-1 Dn-2 … D1 D0
0 0 0 …. …. 0 0 0 0 0 …. 0 0
0 0 0 …. …. 0 0 1 1 0 …. 1 0
0 0 0 …. …. 0 1 0 0 0 …. 0 0
…. …. …. …. …. …. …. …. …. …. …. …. ….
…. …. …. …. …. …. …. …. …. …. …. …. ….
1 1 1 …. …. 1 0 1 1 1 …. 1 1
1 1 1 …. …. 1 1 0 0 1 …. 0 1
1 1 1 …. …. 1 1 1 1 1 …. 1 1

La colección de 0 y 1 que hemos colocado en las salidas es una cualquiera de las


posibles. De hecho podemos representar genéricamente una de las salidas como:

Dij
siendo
0 < i < 2m - 1
0<j<n-1

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Esta tabla de verdad puede verse como la descripción del contenido de un "array"
de 2m elementos que tienen n bits cada uno. Como es un circuito combinatorio, los valores
concretos de los bits de los elementos (los Dij) son fijos, predeterminados. Por estas dos
características a estos circuitos se los llama Read Only Memory (Memoria de Solo Lectura),
o, más brevemente, ROM.

Es fácil observar que con una ROM se puede implementar cualquier función lógica
de m variables de entrada y n salidas. Basta con especificar el "contenido" de la ROM de
manera que los n bits de cada palabra (posición del array) correspondan al valor de la
función en el punto (que coincide con el índice del array).

6.3 Circuito Interno

El circuito interno de una ROM tiene, para cada bit de salida, la siguiente forma:

El fabricante de la ROM coloca la entrada de la AND asociada a Dij en 0 ó en 1, en


función de la tabla de verdad que le especifiquemos. Para ello conecta la entrada a "tierra"
o a "Vcc".

6.4 Variantes Tecnológicas

Las ROMs así construidas tienen el inconveniente que una vez que se fabrican no
es posible cambiar su contenido.

Esto no sería un problema significativo cuando usamos las ROMs como circuito
combinatorio. Sin embargo el uso habitual de las ROMs es el de almacenar programas fijos
(ej: las rutinas de inicio de un computador, el programa almacenado de un controlador de
un semáforo, un ascensor, un lavarropas, etc). Los programas tienen correcciones y

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

mejoras constantes, por lo que es poco práctico (y poco rentable) tener que producir
nuevas ROMs cada vez que hay un cambio.

Por ello se fueron desarrollando con el tiempo nuevos circuitos que dieran respuesta
a esta situación: por un lado fueran memorias permanentes (no perdieran su contenido al
quedar sin energía eléctrica) y por otro pudiera ser modificado su contenido de alguna
forma.

6.4.1 PROM

Las PROM son Programmable ROM. Una PROM es una ROM cuyo contenido
puede ser definido a posteriori de construida, mediante una actividad de programación que
se realiza utilizando un circuito electrónico especial (un Programador de PROMs).

En esencia son ROMs que tienen en su entrada Dij a las ANDs de selección una
conexión tanto a ground (0) como a Vcc (1). Esta conexión está realizada mediante un
fusible, el cual se quema al momento de "programar" el contenido de la PROM. Si quiero
grabar un 0 quemo el fusible de la conexión a Vcc y si quiero grabar un 1 quemo el fusible
de la conexión a tierra.

Estos fusibles no pueden reconstruirse. Cuando se graba una PROM con un cierto
contenido no hay marcha atrás.

6.4.2 EPROM

Si bien las PROMs significaron un avance, el hecho de no tener "vuelta atrás" aún
significaba una restricción para el uso intensivo de PROMs en el almacenamiento de
programas. De esa necesidad no del todo satisfecha surgió la tecnología de las EPROM
(Erasable PROM).

Una EPROM es una ROM que puede ser borrada. El mecanismo de borrado es
totalmente distinto al de programación e implica un proceso de exposición del circuito a luz
ultravioleta por varios minutos. La gran ventaja es que puede reutilizar las EPROMs muchas
veces borrando su contenido y grabando uno nuevo.

Para ello las EPROM disponen de una ventana transparente en el encapsulado


cerámico ó plástico del circuito integrado.

Tomado de Wikipedia © Bill Bertram 2006

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Esa ventana expone el propio chip de silicio, de forma de poder irradiar


adecuadamente el material con luz ultravioleta de forma de revertir las modificaciones
físico-químicas producidas por el proceso de grabación por impulsos eléctricos, mediante
un dispositivo específico: Programador de EPROMs.

Esta ventana está normalmente tapada de forma de evitar exponer el silicio a la luz
normal (que contiene componentes ultravioletas) para que el contenido de la EPROM no se
altere.

De todos modos como el fenómeno también se produce ante la presencia de otro


tipo de radiaciones (como los rayos cósmicos) que no pueden detenerse con una etiqueta,
el contenido de las EPROMs termina alterándose con el tiempo (aunque, por suerte, este
tiempo es sumamente largo, de varias decenas de años).

Como se dijo su principal uso es el almacenamiento de los programas permanentes


de un sistema. Su capacidad de desde algunos kilobits hasta del orden de 8 Megabits.
Muchas veces están organizadas en palabras de 8 bits (byte).

6.4.3 EEPROM

Las EPROM si bien solucionan el problema de la re-usabilidad de este tipo de


memorias, todavía tienen el inconveniente que este proceso es sumamente lento, complejo
y requiere retirar la EPROM del sistema para realizar el borrado.

Es así que surgieron las EEPROM (Electrical EPROM), o sea una EPROM cuyo
proceso de borrado se hace eléctricamente y puede efectuarse sin retirar el circuito
integrado del sistema. Posee otra diferencia importante con la EPROM: una EEPROM
normalmente tiene la capacidad de borrar cada bit en forma individual (también hay
implementaciones que borran una palabra completa en cada operación de borrado).

Típicamente se utilizan para almacenar los datos de configuración de un sistema.


Tienen una capacidad de hasta del orden de 128 kbits. Es frecuente que estén organizadas
en palabras de un solo bit.

6.4.4 Flash EEPROM / Flash EPROM / Flash Memory

Este tipo de memoria es una variante de las EEPROM que se desarrolló con el
objetivo de mejorar el tiempo de borrado, de forma de habilitar su uso para aplicaciones de
almacenamiento masivo.
Si bien el nombre está asociado al concepto de velocidad (lo que se corresponde
con lo antedicho), el nombre se origina en la similitud que uno de sus creadores veía entre
el proceso de borrado y el destello del flash de una cámara de fotos.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Su aplicación más difundida es la de almacenamiento masivo (reemplazo de discos


duros o disquetes), ya que su tiempo de acceso es varios órdenes de magnitud menor que
la de dichos dispositivos. Las capacidades de los chips llegan en la actualidad a del orden
de 6 Tbits, y están organizados en palabras de 8 ó, más habitualmente, 16 bits.

En la foto siguiente se puede ver la parte interna de una Memoria USB, que
actualmente se usa para almacenar información en forma transportable (lo que antes se
hacía con disquetes).

6.5 Capacidad y Organización

Las memorias ROM están caracterizadas por una cierta capacidad, que se mide en
bits (ó Kilobits, Megabits ó Gigabits) y una determinada organización, que se expresa en
cantidad de palabras de tantos bits.
Ejemplos:
- ROM de 8 Kbits, con organización de 1Kx8 (1 Kilo palabras de 8 bits)
- ROM de 8 Kbits, con organización de 4Kx2 (4 Kilo palabras de 2 bits)
- ROM de 1 Kbits, con organización de 1Kx1 (1 Kilo palabras de 1 bit)

6.6 Arreglos de Memorias

Las memorias se utilizan en combinaciones (arreglos) normalmente denominados


"bancos de memoria". Estos bancos permiten la construcción de memorias del tamaño
requerido por el sistema en base a circuitos integrados disponibles (es habitual que se
requiera más memoria de la que puede suministrar un único circuito integrado, o que el
tamaño de palabra necesario sea otro).

Es de destacar que estas ideas que estamos desarrollando en el contexto de


memorias ROM también se aplican a otro tipo de memorias (RAM) que veremos en otro
capítulo y, en particular, a los modulos de memoria (tipo SIMM, DIMM o similar).

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

En los próximos diagramas circuitales aparecerán las entradas CS y OE. Como ya


hemos mencionado el significado y utilización de dichas entradas se verá más adelante en
este mismo capítulo. Por ahora consideremos que son entradas que existen en todas las
ROMs y deben, por tanto, existir en las ROMs "compuestas" que vamos a diseñar.

6.6.1 Memoria de mayor tamaño de Palabra

En este caso el objetivo es lograr una memoria ROM de n bits de salida a partir de
memorias de menor cantidad de bits (su tamaño de palabra es menor que el requerido).

Veamos como se construye un banco así utilizando un ejemplo: supongamos que


queremos construir una ROM de 1Kx8 y disponemos solamente de ROMs de 1Kx4.

Lo primero es determinar la cantidad de memorias requeridas. En este caso vemos


que la memoria solicitada tiene una capacidad de 8 Kbits y las disponibles de 4 Kbits. Esto
da que se necesitarían 2. Por otro lado el análisis de la organización solicitada y la
disponible, confirma esta cantidad.

No es difícil concluir que el circuito de la ROM de 1Kx8 equivalente es el


representado por el diagrama esquemático a continuación:

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

6.6.2 Memoria de mayor cantidad de Palabras

En este caso el objetivo es lograr una memoria ROM de m bits de entrada a partir
de memorias de menor cantidad de bits de dirección.

Veamos como se construye un banco así utilizando un ejemplo: supongamos que


queremos construir una ROM de 2Kx8 y disponemos solamente de ROMs de 1Kx8.

Al igual que en caso anterior lo primero es determinar la cantidad de memorias


requeridas. En este caso vemos que la memoria solicitada tiene una capacidad de 16 Kbits
y las disponibles de 8 Kbits. Esto da que se necesitarían 2 al igual que en el ejemplo
anterior. Por otro lado el análisis de la organización solicitada y la disponible, confirma esta
cantidad.

En el caso anterior cada ROM contribuía con una parte de los bits de salida. En este
caso cada ROM contribuirá con una parte del rango de direcciones. La ROM a construir
tiene 11 bits de entrada, con un rango de direcciones de 0 a 2047. Cada ROM disponible
tiene 10 bits de entrada, con un rango de direcciones de 0 a 1023. Por tanto cada ROM
contribuirá con la mitad de las posiciones: una de ellas aportará las posiciones de 0 a 1023
y la otra las posiciones de 1024 a 2047. Para seleccionar qué ROM se conecta a la salida
utilizamos multiplexores de 2x1, controlados por el bit más significativo de las entradas de
dirección.

El circuito que implementa este funcionamiento es:

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

En el siguiente diagrama los multiplexores se han explicitado en sus equivalentes


AND y OR (se ha omitido la repetición de la estructura de compuertas de forma de no
sobrecargar el dibujo):

6.7 Chip Select

La entrada CS (Chip Select) permite ahorrar en la implementación la estructura de


ANDs que estamos colocando a la salida de las ROMs para elegir cual de ellas conecta a la
salida en función del bit más significativo de la dirección.

En otras palabras las compuertas ANDs están incluidas dentro del chip de la ROM y
el selector es la entrada CS.

Si CS = 0 todas las salidas de la ROM están en 0, con independencia de las


entradas de dirección y del "valor" almacenado en la "posición" de la ROM indicada por
dicha dirección y si CS = 1 las salidas presentan el contenido de la ROM en la posición
señalada por la dirección.

En las ROMs más modernas la entrada CS en 0 tiene un efecto un poco distinto por
el cual el circuito interno de la ROM pasa a un estado de bajo consumo de energía y el
estado de sus salidas tiene un comportamiento similar al "tri-state" que veremos en el
próximo punto.
A los efectos del curso consideraremos que el comportamiento es el primero de los
descriptos (las salidas pasan a estado lógico 0).

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

6.7.1 Aplicación del Chip Select (CS) a Arreglos de Memorias

El circuito de la ROM de 2Kx8 queda simplificado por el uso del CS de esta manera:

6.8 Lógica de Tercer Estado (Tri-state)

En el ejemplo anterior se ve que las ORs que se colocan a la salida en realidad


siempre tienen una de sus entradas en 0. Esto es por la forma de funcionamiento del
circuito en donde se utilizan como salida lógica de un selector.

Dada esa propiedad alguien podría verse tentado de quitar las OR y unir las salidas.
Eso desde el punto de vista lógico no es posible porque sería equivalente a igualar dos
variables de valor en principio distinto (una de ellas con valor 0 y la otra con 0 ó 1). Desde el
punto de vista del circuito provocaría un cortocircuito que posiblemente dañe las salidas que
se unieran de esa forma.

Para poder implementar ORs "cableadas" (sin necesidad de utilizar compuertas) se


diseñaron los circuitos de manera que tuvieran salidas con tres estados posibles (en lugar
de los 2 estados lógicos habituales): 0, 1 y Z. El estado Z se denomina también "tercer
estado", "estado de alta impedancia", "estado indiferente" ó "tri-state".

Los circuitos que tienen este tipo de salida disponen también de una entrada
denominada OE (Output Enable) o similar. Cuando dicha entrada de control está en 0, la
salida pasa al "estado de alta impedancia" y cuando la entrada de control está en 1, la
salida está en estado lógico 0 ó 1.

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

Un caso típico de uso de esta tecnología es en los "buffers", ya sean directos o


inversores:

6.8.1 Aplicación de Lógica Tri-state con Output Enable (OE) a Arreglos de Memorias

Veamos a continuación como queda del circuito de la ROM de 2Kx8 simplificado por
el uso de la lógica de tres estados a través de la entrada de control OE:

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Flip-Flops

Arquitectura de Computadoras
(Versión 4.3b - 2023)
Arquitectura de Computadoras Notas de Teórico

7 FLIP-FLOPS

7.1 Introducción

En este capítulo comenzaremos a analizar los circuitos secuenciales, circuitos


que, a diferencia de los combinatorios, determinan el valor de sus salidas no solo en función
del valor actual de sus entradas sino que también en función de los valores anteriores de las
mismas.

Comenzaremos por estudiar un caso particular de circuitos secuenciales: los Flip-


Flops, para luego introducirnos al diseño de circuitos secuenciales con el caso particular de
los circuitos contadores, para finalmente incursionar en el tema de Máquinas de Estado
como herramienta de especificación y síntesis de circuitos secuenciales generales.

7.2 Flip-Flop

Como ya se adelantó el Flip-Flop es un caso particular de circuito secuencial y se lo


puede ver como un "elemento de memoria", un circuito que tiene la capacidad de "recordar"
un valor de la entrada previo al actual.
Existen distintos tipos de flip-flops como veremos a continuación.

7.2.1 Flip-Flop R-S Asíncrono (Latch)

El Flip-Flop (FF) R-S Asíncrono (también denominado Latch) es un circuito que tiene
la forma:

_
Tiene dos salidas que se denominan Q y Q (que anotaremos en adelante Q'), y dos
entradas R y S (nombres determinados por sus características, que veremos al analizar el
comportamiento del circuito).

Es sencillo comprobar que si los valores a la entrada son R=1 y S=0, entonces las
salidas serán Q=0 y Q'=1. Esto es porque R=1 fuerza la salida del NOR de arriba a 0 y
entonces ambas entradas del NOR de abajo serán 0 y su salida quedará en 1.
Por un razonamiento análogo se puede ver que si R=0 y S=1, entonces las salidas
serán inversas, Q=1 y Q'=0.
Ahora si las entradas son R=0 y S=0, resulta que los valores de las salidas no
quedan totalmente determinados, ya que tanto Q=0 y Q'=1 como Q=1 y Q'=0 son
combinaciones válidas (notar que no son válidas Q=Q', ya sea ambos 0 ó ambos 1, porque
al ser R=S=0 las salidas quedan obligadas a ser complementarias por la topología del
circuito). Para saber cual de las combinaciones de salidas se produce debemos analizar
cuales eran los valores anteriores de R y S.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Si se llega a R=S=0 desde R=1 y S=0 resulta que las salidas serán Q=0 y Q'=1, pero
si antes las entradas estaban en R=0 y S=1 al pasar a R=S=0 las salidas serán Q=1 y Q'=0.
Esta propiedad permite afirmar que al pasar sus entradas a 0 el circuito "recuerda" cual fue
la ultima entrada en 1. Este es el concepto de memoria asociado al hecho que la salida del
circuito no depende solamente del valor actual de las entradas sino que también de los
valores anteriores.

Queda por analizar el caso de las entradas R=S=1. En este caso las salidas son
ambas 0 (Q=Q'=0) ya que ambos NORs tienen al menos una entrada en 1. Esto en principio
no es problema. Pero si analizamos que pasa cuando las entradas dejan de ser ambas 1
veremos que aparece un problema con el comportamiento del circuito. Si R pasa de 1 a 0,
mientras S permanece en 1, el circuito pasará a tener salidas Q=1, Q'=0. Si la que pasa a 0
es la entrada S, entonces las salidas pasan a Q=0, Q'=1. Pero, ¿qué pasa si ambas pasan
simultáneamente a 0?. En ese caso el valor de las salidas no quedan determinados, pueden
ser indistintamente Q=1, Q'=0 ó Q=0 y Q'=1 (notar que otra combinación es inválida para la
topología del circuito). ¿Cuál de las dos combinaciones posibles será la que adopte el
circuito?. En principio no se sabe, se trata de una indeterminación. En la práctica lo que
sucede es que una de las entradas cambiará antes que la otra (aunque sea por un tiempo
sumamente pequeño de diferencia), por lo que estaremos en uno de los casos anteriores.

El problema es que a todos los efectos el comportamiento en este caso sigue siendo
indeterminístico y por tanto la combinación R=S=1 es "prohibida" (se debe evitar su
aparición a la entrada de un latch tipo R-S).

La tabla de verdad de este circuito se representa de la siguiente forma:

R S Qn+1
0 0 Qn
0 1 1
1 0 0
1 1 -

Por su parte el símbolo que se utiliza para representar el bloque de circuito es:

7.2.2 Flip-Flop R-S Sincrónico

Uno de los problemas que se presentan al intentar utilizar este tipo de circuitos como
elementos de memoria es el hecho que las funciones que generan los valores de las
señales R y S pueden variar en momentos no deseados y el flip-flop responderá a esos
cambios según su tabla de verdad.

Para evitar esta situación se introduce una señal de sincronismo para el circuito (la
habilitación ó el reloj) que indicará cuando son válidos los valores de R y S y cualquier otra
señal significativa para el circuito completo. Esta entrada de control puede actuar de

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

distintas maneras como veremos más adelante.

El circuito interno de un flip-flop R-S sincrónico es:

Cuando la entrada de control (G en el esquema) está en 1, las entradas R y S


aparecen a la entrada de los NOR, pero si la entrada de control está en 0 entonces las
entradas asociadas en los NOR serán 0, lo que asegura que las salidas del flip-flop se
mantendrán incambiadas por más que los valores de R y/o S puedan cambiar.

En este caso donde las entradas se consideran mientras la entrada de control esté
en 1, se dice que el sistema trabaja "por nivel", ya que lo que interesa es el estado de la
señal de control: si vale 1 entonces el resto de las señales serán válidas y si vale 0 no lo
serán. Esta modalidad de funcionamiento se denomina "control por compuerta", "control por
habilitación" ó "control por nivel".

El otro caso corresponde a un circuito donde lo que interesa es la transición de 0 a 1


de la entrada de control. En este caso se dice que se trabaja con un "reloj (clock) por
flanco".

Normalmente en el curso trabajaremos con flip-flops R-S que funcionan en la


modalidad "por nivel" (habilitación, señal G), mientras que en los restantes flip-flops lo
habitual será trabajar con los dispositivos que funcionan en modalidad "por flanco" (reloj ó
clock, señal CLK).

Los símbolos de este flip-flop son:

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

7.2.3 Flip-Flop D

Este flip-flop puede verse como una variante del flip-flop R-S, que tiene el siguiente
circuito interno (en la modalidad de control por nivel):

Este circuito se comporta como el R-S para cuando sistemáticamente R y S toman


los valores opuestos. Es decir que las únicas combinaciones válidas son R=D’=1 y S=D=0 ó
R=D’=0 y S=D=1.

Esto lleva a que la tabla de verdad de un flip-flop de este tipo es:

D Qn+1
0 0
1 1

Y su ecuación característica es:

Qn+1 = Dn
En otras palabras lo que indica la ecuación característica o su tabla de verdad
equivalente es que el nuevo valor de la salida Q (identificado con el subíndice n+1)
corresponde al valor actual de la entrada D (identificado con el subíndice n).

Para ser más precisos: en el caso de los flip-flops con entrada de control por nivel, el
nuevo valor de la salida corresponde al valor de la entrada D mientras la señal de control
(G) está en 1. Mientras la señal de control G está en 0 la salida mantiene el valor de la
entrada D inmediatamente antes de la transición de 1 a 0 de la entrada G.

En el caso de los flip-flops con entrada de control por flanco, el nuevo valor de la
salida corresponde al valor de la entrada D al momento de la transición de la entrada de
reloj (CLK) de 0 a 1 (es decir el "flanco ascendente"). Este nuevo valor de la salida es
adoptado inmediatamente después de ocurrido dicho flanco.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Los símbolos de este flip-flop son:

7.2.4 Flip-Flop T

Este flip-flop tiene el siguiente símbolo:

y la siguiente ecuación característica:

Qn+1 = QnT' + Qn' T


que corresponde a la siguiente tabla de verdad reducida:

T Qn+1
0 Qn
1 Q'n

Notar que tanto la tabla como la ecuación describen un circuito que o bien mantiene
su salida incambiada en el tiempo (cuando T = 0) o bien la invierte en cada flanco
(ascendente) de su entrada de control (cuando T = 1).

7.2.5 Flip-Flop J-K

Este flip-flop busca resolver definitivamente el problema del flip-flop R-S. Consiste en
dos flip-flops R-S sincrónicos por nivel conectados en "cascada" y realimentados de la
siguiente manera:

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

Analicemos el comportamiento de este circuito para deducir tabla de verdad y su


ecuación característica.

Lo primero a resaltar del circuito es que la entrada de habilitación del segundo FF es


negada respecto al primero. Esto implica que las entradas al segundo FF no cambiarán
mientras su entrada de control esté en 1, ya que son las salidas del primer FF cuya entrada
de habilitación está, por consiguiente, en 0.

Veamos ahora el comportamiento de las distintas combinaciones de valores de las


entradas J y K.

Si las entradas J y K están ambas en 0 el primer FF tendrá sus entradas R y S en 0.


Esto significa que dicho FF mantendrá sus salidas incambiadas. Por tanto las entradas al
segundo FF se mantendrán o bien en R = 0, S = 1 ó bien en R = 1, S = 0, forzando en
ambos casos la salida a un valor determinado y que, por tanto, también permanece
incambiado.

Si la entrada J está en 0 y la entrada K está en 1 resulta que la entrada R del primer


FF está en 0 y la entrada S coincide con el valor de la salida Q del segundo FF.
Notar que esto produce el siguiente efecto: si Q (segundo FF) = 0, entonces S
(primer FF) = 0 y por tanto se mantiene el valor y nada cambia por lo que Q (segundo FF)
queda en 0. Pero si Q (segundo FF) = 1, entonces S (primer FF) = 1, lo que provoca que Q
(primer FF) pase a 1 y esto represente un 1 en la entrada R (segundo FF) lo que lleva la
salida Q (segundo FF) a 0.

Ahora si suponemos J en 1 y K en 0, resulta que la entrada S del primer FF está en


0 y la entrada R coincide con el valor de la salida Q' (Q negada) del segundo FF.
Esto produce el siguiente efecto: si Q (segundo FF) = 1 entonces Q' (segundo FF) =
0 y por tanto R (primer FF) = 0 y entonces se mantienen todos los valores. Pero si Q
(segundo FF) = 0 entonces Q' (segundo FF) = 1 y por tanto la entrada R (primer FF) queda
en 1 provocando un "Reset" que lleva Q (primer FF) a 0, Q' (primer FF) a 1 y como
consecuencia la salida Q (segundo FF) pasará a 1.

Finalmente si consideramos el caso J = K = 1 resulta que las entradas R y S del


primer FF serán coincidentes con Q' y Q del segundo FF. Notar que esto implica que R y S
del primer FF son opuestas y, por tanto, tampoco en este caso pueden llegar a adoptar la
combinación prohibida de ambos valores en 1.
Si Q (segundo FF) = 0, con lo que Q' (segundo FF) = 1, resulta R (primer FF) = 1 y S
(primer FF) = 0 por lo que la salida Q (primer FF) pasa a 0, lo que hace que las entradas R y
S del segundo FF queden en R = 0, S = 1 y esto produce que Q (segundo FF) pase a 1. Si

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

por el contrario Q (segundo FF) = 1, y por tanto Q' (segundo FF) = 0, resulta R (primer FF) =
0 y S (primer FF) = 1 y esto lleva Q (primer FF) a 1, lo que a su vez implica R (segundo FF)
= 1 y S (segundo FF) = 0, que termina generando una salida Q (segundo FF) = 0.
Por tanto el efecto neto cuando J = K = 1 es que el flip-flop complementa su salida.

Si escribimos todas estas relaciones en una tabla de verdad resulta:

J K Q Qn+
n 1
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 1
1 0 1 1
1 1 0 1
1 1 1 0

Si minimizamos Qn+1 queda:

Qn \JK 00 01 11 10
0 1 1
1 1 1

Por lo que la ecuación característica del flip-flop J-K es:

Qn+1 = JQ'n + K'Qn


Así mismo se puede escribir su tabla de verdad en forma reducida de la siguiente
forma:

J K Qn+
1
0 0 Qn
0 1 0
1 0 1
1 1 Q'n

Notemos que en este caso el funcionamiento del flip-flop respecto a su entrada de


control es siempre del tipo "sincrónico por flanco", ya que por más que CLK esté en 1 y las
entradas cambien, las salidas no acompañan ese cambio. Las salidas sólo responden al
valor de las entradas al momento del flanco descendente de la entrada de control (cuando
pasa de 1 a 0, en realidad el valor existente inmediatamente antes de iniciar el cambio). Si
quisiéramos tener un flip-flop J-K con control por flanco ascendente (transición de 0 a 1 de
la entrada de reloj) bastaría con agregar una compuerta NOT a la entrada CLK).

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

El símbolo de este flip-flop es:

El flip-flop J-K es denominado muchas veces el flip-flop universal, ya que con él se


pueden "emular" los demás flip-flops:

➢ R-S: si hacemos J = S y K = R resulta un R-S con la ventaja de aceptar la


combinación R=S = 1.
➢ D: si hacemos K' = J = D, se comporta como un D (verificarlo en la tabla de
verdad reducida)
➢ T: si hacemos K = J = T, se comporta como un T

7.2.6 Entradas de Set y Clear

Las implementaciones prácticas de los flip-flops sincrónicos con activación por flanco
usualmente disponen de dos entradas de control adicionales las cuales actúan en forma
asíncrona (actúan por nivel) y sirven para poner a 1 (Set ó Preset) ó a 0 (Clear) el circuito.

Los símbolos de estos flip-flops con entradas asíncronas son:

7.2.7 Entrada de Clock Enable

Especialmente para el caso de los flip-flops D usados como "bits de memoria" surge el
problema de cómo almacenar en el FF solamente cuando interesa y no cada vez que el
reloj genera un flanco, ya que normalmente se usa un reloj de onda cuadrada que cambia
constantemente.
Una solución posible sería hacer un AND a la entrada de CLK del FF entre el reloj del
sistema y una señal de activación que pase a "alto" cuando interesa escribir el valor en el
flip-flop. Esto potencialmente genera problemas de falsos pulso de reloj aplicados al flip-flop
si esta señal de activación no está perfectamente sincronizada con el reloj general. Para ello
algunos flip-flops implementan una entrada adicional llamada Clock Enable, que funciona
como un habilitador de la señal del clock hacia dentro del flip-flop, aunque en realidad la
implementación interna más común está esquematizada por el circuito:

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

Los símbolos que se utilizan para este tipo de flip-flops son:

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Contadores

Arquitectura de Computadoras
(Versión 4.3 - 2016)
Arquitectura de Computadoras Notas de Teórico

8 CONTADORES

8.1 Contadores

Ahora nos concentraremos en un caso particular de circuito secuencial: el contador.


El contador es un circuito cuyas salidas representan, en un código binario dado, la cuenta
de la cantidad de cambios en su entrada, módulo su capacidad.
Usualmente se utilizan contadores binarios (que usan el código binario para
representar números naturales) aunque se pueden diseñar contadores que utilicen el
código Gray, el entrelazado 2 de 5, el decimal empaquetado o cualquier otro que se pueda
considerar. Normalmente cuentan las transiciones de la entrada de 0 a 1 (flancos
ascendentes). No tienen que empezar en 0, ni su módulo tiene porqué ser una potencia de
2.

8.1.1 Contador en base a Flip-Flops T

La manera más simple de construir un contador es a partir de flip-flops T, de la


siguiente manera:

Para analizar el comportamiento del circuito supongamos que inicialmente todas las
salidas de los FF están en 0.

Al pasar la entrada ENT de 0 a 1 generará un flanco ascendente en la entrada de


reloj del primer flip-flop por lo que su salida Q0 pasará a 1. Esto a su vez generará un
flanco ascendente en la entrada de reloj del segundo flip-flop, llevando su salida Q1 a 1, lo
que genera otro flanco en el tercer flip-flop y algo análogo ocurre con el cuarto flip-flop. Esto
quiere decir que la situación luego del primer flanco es:

Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1

Al ocurrir el segundo flanco el primer flip-flop vuelve a cambiar, pero no genera un


flanco ascendente en la entrada de reloj del segundo, por lo que éste queda incambiado, lo
mismo que el resto de la cascada.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Hasta entonces la secuencia es:

Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0

Al llegar el tercer flanco en la entrada ENT el primer flip-flop vuelve a cambiar su


salida, la que pasa a 1. Esto sí genera un nuevo flanco ascendente en el segundo flip-flop
que lleva a cambiar su salida Q1 de 1 a 0. Como esto no genera un flanco ascendente, el
resto de los flip-flops permanece igual:

Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1

En el siguiente flanco ascendente (cuarto) de la entrada ENT vuelve a cambiar Q0,


pero como pasa de 1 a 0 el resto sigue igual. Pero al próximo (quinto) Q0 pasa de 0 a 1,
generando un flanco a la entrada del segundo flip-flop, lo que mueve a Q1 de 0 a 1 y esto
representa un flanco ascendente en la entrada del tercer flip-flop que, entonces, cambia de
1 a 0. Notar que el cuarto flip-flop no se modifica:

Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1
Cuarto flanco 1 1 0 0
Quinto flanco 1 0 1 1

El análisis continúa de la misma manera hasta llegar al dieciseisavo flanco quedando:

Q3 Q2 Q1 Q0
Inicial 0 0 0 0
Primer flanco 1 1 1 1
Segundo flanco 1 1 1 0
Tercer flanco 1 1 0 1
Cuarto flanco 1 1 0 0
Quinto flanco 1 0 1 1
Sexto flanco 1 0 1 0
Séptimo flanco 1 0 0 1
Octavo flanco 1 0 0 0
Noveno flanco 0 1 1 1
Décimo flanco 0 1 1 0
Onceavo flanco 0 1 0 1
Doceavo flanco 0 1 0 0
Treceavo flanco 0 0 1 1
Catorceavo flanco 0 0 1 0
Quinceavo flanco 0 0 0 1
Dieciseisavo flanco 0 0 0 0

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

Notemos que al cabo de 16 flancos llegamos a la misma condición inicial, por lo que
a partir de ese momento la secuencia se repetirá.

Si observamos la tabla que quedó notamos enseguida que las salidas Q3, Q2, Q1,
Q0 forman un numero en binario de 4 bits que va disminuyendo desde 1111 (15) hasta
0000 (0) en forma cíclica (llegado a 0 luego vuelve a 15 y comienza de nuevo a disminuir)
Por tanto el circuito formado por los flip-flops T conectados de esa manera se
comporta como un contador binario descendente de 4 bits.

Para tener un número mayor de bits (y por tanto mayor capacidad de cuenta) basta
con agregar más flip-flops T conectados de manera análoga. Por cada flip-flop que se
agrega se duplica la capacidad de cuenta.

Si quisiéramos que la cuenta fuera ascendente deberíamos usar el siguiente


esquema de conexión de los flip-flops:

8.1.2 Contador en base a Flip-Flops D

Para analizar como diseñar un contador en base a flip-flops tipo D vamos a


proponernos construir un contador ascendente que cuente en código Gray entre 1 y 10. Si
bien es un ejemplo particular la metodología que desarrollaremos se puede aplicar al
diseño de cualquier otro contador. Como usaremos flip-flops tipo D sincrónicos por flanco,
el contador será un contador de flancos (transiciones de 0 a 1) de la entrada.

Dada la especificación lo primero a determinar es la cantidad de flip-flops necesarios.


Para ello veamos como se va construyendo un código Gray:

0
1
----
11
10
----
110
111
101
100
----
1100
1101
1111

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

1110
1010
1011
1001
1000

Notar que el código se genera espejando lo ya hecho hasta los lugares potencia de
dos (indicados por las líneas punteadas) agregándole un 1 delante.
Si tomamos, arbitrariamente, que el primer código representa el 0, nos queda la
siguiente tabla de codificación:

0 0000
1 0001
2 0011
3 0010
4 0110
5 0111
6 0101
7 0100
8 1100
9 1101
10 1111
11 1110
12 1010
13 1011
14 1001
15 1000

Para el caso que nos ocupa tomamos los códigos binarios desde el 1 al 10.
Obviamente, y como era de esperar, precisamos 4 dígitos para representar los códigos
Gray de estos números, por lo que nuestro contador requiere de 4 flip-flops.

El siguiente paso en escribir una tabla que nos indique en función del valor actual de
las salidas Q3, Q2, Q1, Q0, cuál deben ser los nuevos valores de forma que el circuito se
comporte como deseamos (notar que por haber elegido un numero de cuenta que no es
potencia de 2, el código no queda "perfectamente" cíclico en Gray):

Actuales Nuevos
Q3Q2Q1Q0 Q3Q2Q1Q0
1 0 0 0 1 0 0 1 1
2 0 0 1 1 0 0 1 0
3 0 0 1 0 0 1 1 0
4 0 1 1 0 0 1 1 1
5 0 1 1 1 0 1 0 1
6 0 1 0 1 0 1 0 0
7 0 1 0 0 1 1 0 0
8 1 1 0 0 1 1 0 1
9 1 1 0 1 1 1 1 1
10 1 1 1 1 0 0 0 1

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Recordando que la ecuación característica de los flip-flops tipo D es:


Qn+1 = Dn
esto es que el nuevo valor de la salida del flip-flop corresponde al valor actual de la
entrada, para lograr los nuevos valores indicados en la tabla para los Qj, basta con colocar
en su entrada actual esos valores.

De esta manera nos queda una tabla de verdad de un circuito combinatorio, cuyas
entradas son los valores actuales de los Qj y sus salidas son los valores actuales de Dj
necesarios para lograr la transición deseada.
Tenemos entonces la siguiente tabla de verdad del circuito combinatorio:

Q3 Q2 Q1 Q0 D3 D2 D1 D0
0 0 0 1 0 0 1 1
0 0 1 1 0 0 1 0
0 0 1 0 0 1 1 0
0 1 1 0 0 1 1 1
0 1 1 1 0 1 0 1
0 1 0 1 0 1 0 0
0 1 0 0 1 1 0 0
1 1 0 0 1 1 0 1
1 1 0 1 1 1 1 1
1 1 1 1 0 0 0 1

El siguiente paso consiste en minimizar las expresiones de las ecuaciones de los Dj


utilizando Karnaugh. Usaremos comodines ("don't care") en las cuentas que no son
alcanzadas (0, y 11 a 15).

D3
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 1 X
01 1 X
11 X
10 X X

D2
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 1 X
01 1 1 X
11 1 X
10 1 1 X X

D1
Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X X
01 1 1 X
11 1 X
10 1 1 X X

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

D0

Q 3Q 2 / 00 01 11 10
Q 1Q 0
00 X 1 X
01 1 1 X
11 1 1 X
10 1 X X

Las ecuaciones resultantes son:

D3 = Q1'Q0' + Q3Q1' D2 = Q0' + Q3'Q2 + Q2Q1'

D1 = Q2' + Q1Q0' + Q3Q1'Q0 D0 = Q3 + Q2'Q1' + Q2Q1

El circuito completo queda como se muestra en la próxima página:

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Memorias RAM

Arquitectura de Computadoras
(Versión 4.3b - 2016)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

9 MEMORIAS RAM

9.1 Introducción

Una característica distintiva de los flip-flops es su capacidad de recordar el valor


anterior de una entrada, o lo que es lo mismo: tienen memoria.

Esta capacidad de memoria es fundamental no solo para la construcción de circuitos


secuenciales, sino que también es la base para el almacenamiento de la información a ser
procesada en las computadoras en la forma en que éstas están organizadas en la
actualidad (arquitecturas de programa almacenado), como se verá mas adelante.

La base de la memoria es el flip-flop que es capaz, como vimos, de almacenar un bit.


Lo normal es utilizar conjuntos de bits, organizados en palabras de n bits. Cuando la
memoria es de una sola palabra recibe el nombre de Registro (también puede recibir el
nombre de Latch) cuando tiene múltiples recibe la denominación genérica de RAM.

En general una memoria RAM es un array de 2m palabras de n bits, de forma similar


a lo que ya analizamos para las ROMs, salvo que en esta oportunidad se comportan como
un arreglo (array) tal como los conocemos en las materias de programación (si escribo un
valor en una posición y leo esa posición el valor que leo es el que escribí).

El nombre RAM es una sigla que corresponde a Random Access Memory. Este
nombre no es del todo feliz y seguramente fue elegido históricamente por tres causas:
- para diferenciar estos dispositivos de las primeras memorias que funcionaban de
modo "secuencial" (para leer una posición había que leer previamente todas las
anteriores). Lo de Random estaría apuntando al tipo de acceso "directo" a la
posición requerida.
- para que se pareciera a la sigla de la "memoria" ROM, lo que seguramente llevó a
Random (por la R) en vez de Direct, que sería lo correcto. Pensemos que nadie
querría almacenar información en un dispositivo que la devolvería en forma
aleatoria, por lo que definitivamente las memorias RAM no son Random.
- por esa manía existente en la industria informática de nombrar a las cosas
utilizando tres letras.
Nota: en francés a las memorias RAM se las llama "memoire vivre" (memoria viva) y a las
ROM se las llama "memoire morte" (memoria muerta), términos que parecen mucho mas
apropiados a las características de estos dispositivos.

9.2 Tipos de Memoria

Hay distintos tipos de organizaciones de memorias del tipo RAM. Los elementos que
determinan estas variantes son:
- si los datos de entrada (lo que se va a escribir) y de salida (lo que se lee)
comparten los mismos caminos físicos o están separados.
- si tienen mas de una única palabra de n bits.
- si requieren de circuitos de "refresco" (veremos qué significa esto mas adelante).

Cuando se tiene una memoria de una única palabra, con entradas y salidas
diferenciadas se habla de Latch o Registro, cuando se tienen multiples palabras y no se
requiere de circuitos de "refresco", se habla en general de SRAM, por Static RAM (otro
nombre para la polémica, ¿cómo algo que puede ser modificado recibe el nombre de
"estático"?). Lo normal son las SRAM que tienen la entrada y salida coincidentes en las
conexiones, mientras que las de múltiples palabras con entradas y salidas diferenciadas, si

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

bien existen, están reservadas a aplicaciones específicas (ej: memorias para tarjetas de
video). Finalmente las memorias de multiples palabras que necesitan circuito de refresco,
reciben el nombre de DRAM por Dynamic RAM (no existen memorias tipo Registro que
sean a su vez Dinámicas).

Nota: la denominación "Static" se comenzó a utilizar para diferenciar a las memorias


clásicas a partir del momento en que aparecieron las memorias "Dynamic", término que
hace referencia a su necesidad de contar con un circuito de "refresh" (refresco).

Los símbolos de los distintos tipos de memoria son:

Registro (ó Latch):

Static RAM:

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

Dynamic RAM:

9.3 Circuito Interno

Los distintos tipos de memoria están implementados por circuitos característicos.

Registro ó Latch:

Tienen el circuito mas simple. Son un conjunto de flip-flops tipo D, sincrónicos (flanco
ascendente) conectados con su entrada de reloj en común y un control de tercer estado,
también común, en sus salidas.

Static RAM (SRAM):

Están construidas en base a flip-flops tipo D, los cuales tienen sus entradas de
habilitación controladas por un circuito de selección en base a la decodificación de las
entradas de direción (Am).
Veamos como es el circuito asociado al bit Dij (bit j-ésimo de los n de la palabra i-
ésima de las 2m palabras de la memoria), para una memoria SRAM con entrada y salida
independiente:

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

En el caso que fuera una memoria SRAM con entrada y salida combinadas, el circuito
del elemento de memoria sería de la forma:

El circuito de selección está formado por un decodificador y lógica de control asociada


(para hacer intervenir el CS). A su vez a la salida se requiere de lógica (compuertas OR) y
de buffers de tercer estado para implementar el OE general de la memoria.

El siguiente es un diagrama de bloques de un circuito SRAM real (el chip AS7C3256A


de 32 K x 8 de Alliance Semiconductor):

Dynamic RAM (DRAM):

Aunque en la práctica se realiza una optimización a nivel del circuito con transistores
que implementa el circuito lógico mostrado para el elemento de memoria, se requieren al
menos 6 transistores para construir cada bit de una memoria del tipo SRAM. Dado que en
cada momento de la evolución de la tecnología la cantidad de transistores que se pueden
colocar en un mismo chip está limitada por la tecnología disponible en ese momento, es un
dato muy importante el número de transistores que se requieren para cada bit, ya que una
disminución en ese número tiene un inmediato impacto en la capacidad del chip de
memoria obtenido.

A este punto se dirige el diseño de las DRAM. Estas memorias utilizan una propiedad
de los transistores: la existencia de la junta entre la base y el emisor (o entre el gate y el
source) produce como efecto lateral la formación de un condensador (capacidad parásita).

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Normalmente la existencia de este condensador es un efecto no deseado, ya que la


acumulación de carga eléctrica que se produce en él perjudica la velocidad de conmutación
del transistor (ya que para cambiar su estado de conducción hay que desalojar la carga
acumulada en este condensador parásito y eso lleva su tiempo). Sin embargo los
inventores de las DRAM utilizaron esa propiedad para "guardar" un bit en forma de carga
acumulada en ese capacitor "parásito".

Esto lleva a que en este tipo de memorias se requiera solamente un transistor por
cada bit a almacenar. Este hecho ha resultado determinante para el éxito de este diseño, ya
que permite hasta 6 veces mayores capacidades de almacenamiento para cada estadio
tecnológico de la fabricación de chips y ha disimulado las notorias complicaciones de la
circuitería auxiliar requerida por estas memorias para funcionar.

La particular forma de almacenar la información le dan ciertas características propias


a estos dispositivos.
Por un lado la lectura es destructiva: al "leer" se quita la carga almacenada lo que
genera una corriente por el transistor que es lo que en definitiva se detecta. La forma de
mantener la información que contenía la memoria es grabando nuevamente el mismo valor.
Por suerte para los diseñadores de sistemas que quieran utilizar estas memorias el propio
circuito interno de los chips de este tipo se encarga de este trabajo (cada vez que se lee se
hace simultáneamente una operación de escritura).
Por otro lado la carga almacenada se va perdiendo con el tiempo. Dado que ningún
dispositivo es perfectamente no conductor, siempre existen las denominadas "corrientes de
fuga" que hacen que luego de un cierto período de tiempo la carga acumulada desaparezca
(y con ella la información almacenada). Para remediar esto las memorias deben ser
"refrescadas", es decir se debe periódicamente grabar nuevamente la información para que
ésta no se pierda. Dada la naturaleza del procedimiento de lectura de la memoria, esta "re-
grabación" se logra simplemente leyendo la memoria. Esta lectura periódica debe ser
realizada con un período menor al tiempo de pérdida de la carga (tiempo de descarga del
"capacitor parásito" que almacena la información).

Teniendo como objetivo primario minimizar el tiempo requerido para refrescar un chip
completo de DRAM, y de paso disminuir la cantidad de "patitas" necesarias para el circuito
integrado (en el pasado este fue un problema técnico a resolver, dado que los primeros
encapsulamientos disponibles tenían un número acotado de pinos), estas memorias están
organizadas en forma matricial y la dirección se presenta separada en fila (row) y columna
(column).

El siguiente es un diagrama de bloques de una DRAM de 4 Mbits (en particular la


MSM514100D de OKI Semiconductor):

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

El circuito integrado tiene el siguiente "pinout" (disposición de las entradas y salidas


en las conexiones del encapsulado):

Como vemos tanto en el diagrama de bloques como en el pinout, esta DRAM tiene 11
bits de entrada de dirección. Es claro que con 11 bits de dirección no es posible direccionar
directamente los 4 Mbits que dispone la memoria (para ello se requerirían el doble, o sea
22).
El punto es que, como se dijo, estos chips no reciben la información de dirección toda
junta sino que reciben primero la información de la fila y luego la información de columna,
usando los mismos bits de entrada de dirección en momentos distintos. Para ello poseen
los registros internos RAB (Row Address Buffer), también denominado RAR (Row Address
Register) y CAB (Column Address Buffer), también denominado CAR (Column Address
Register), los cuales son cargados con la dirección presente en los bits An en el flanco de
las señales RAS (Row Address Strobe) y CAS (Column Address Strobe).

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

La gran ventaja de este diseño es que manteniendo un valor de columna (CAB)


incambiado y cambiando sucesivamente todos los valores de fila (RAB) se consigue
refrescar toda la memoria. Esto es porque cada vez que se accede a una fila en realidad se
están "leyendo" todos los bits de la fila simultáneamente (luego el circuito selecciona el
correcto usando la información de columna). Con esto se reduce drásticamente el tiempo
necesario para hacer el "refresh". Para m bits de dirección en vez de hacer 2 m lecturas
hacemos 2m/2. Para el ejemplo donde 2m = 11, resulta que en lugar de hacer 2 22 (4.194.304)
hacemos solamente 211 (2.048)
En el caso particular del chip mostrado se dispone de una facilidad adicional de RAS-
refresh, en el cual alcanza con activar el RAS para que el circuito interno incremente
automáticamente la fila de forma de ir haciendo el refresh.

9.4 Parámetros

En las memorias RAM hay distintos aspectos que caracterizan el comportamiento de


la misma, su aplicabilidad a una función específica y la posibilidad de ser insertada en
determinado circuito. Los más importantes son:
- capacidad (en bits)
- organización (cuantas palabras de qué tamaño)
- tiempo de acceso en lectura (cuanto tiempo pasa desde que se le presenta una
dirección y las señales de control que correspondan hasta que presenta el
contenido en la salida)
- tiempo de acceso de escritura (cuanto tiempo pasa desde que se le presenta una
dirección, el dato a escribir y las señales de control que correspondan hasta que le
memoria adopta el nuevo valor y está en condiciones de iniciar un nuevo ciclo de
escritura)
- tipo de tecnología (estática ó dinámica, en definitiva si requieren o no de un
circuito de refresco)
- capacidad de retener la información sin estar alimentadas de energía

Los tiempos de acceso en algunos casos son presentados en base a la frecuencia de


reloj a la que pueden trabajar. La frecuencia de reloj está muy ligada a la velocidad de
transferencia de información que puede tener una memoria sincrónica (aunque, como
veremos, no siempre la relación es lineal ya que juegan otros factores arquitectónicos de la
solución).

9.5 Variantes Tecnológicas

A continuación veremos algunas variantes tecnológicas que existen de los tipos de


memoria básicos vistos.

9.5.1 SRAM

Es la tradicional memoria basada en flip-flops ya mencionada. Tiene menores tiempos


de acceso (en general) que la memoria basada en tecnología dinámica. Tiene el
inconveniente de ocupar mas espacio (requiere más transistores) y ser más cara.

9.5.2 DRAM

Es la memoria dinámica original. Hoy en día ya no se construyen chips DRAM


"clásicos", ya que hay sido superados por distintas mejoras al diseño. Son más económicas
que las SRAM, pero más lentas, en particular por el uso de la técnica de direccionamiento
matricial en base al CAS y al RAS (columna y fila por separado).

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

9.5.3 FPM DRAM

Una de las primeras mejoras al diseño DRAM fue el denominado Fast Page Mode,
donde se optimizaba al acceso, permitiendo múltiples CAS para el mismo RAS. De esta
forma se mejoraba sensiblemente el tiempo de acceso. El nombre se debe a que cada fila
se puede asociar a una página de un libro: una vez que encontré una "palabra" (un bit) en
una "pagina" (fila del chip) las siguientes palabras (bits) las encontraré más rápido si están
en la misma página (fila).

9.5.4 EDO DRAM

Las DRAM Enhanced Data Out son una mejora sobre las FPM, consistente en
acelerar el acceso al próximo bit, iniciando una lectura por adelantado al bit contiguo al
accedido en un momento dado. De esta forma se ahorra la espera por la circuitería interna
de detección de la carga de almacenamiento.

9.5.5 BEDO DRAM

Las Burst EDO son una mejora, relativamente menor, sobre las EDO, para cuando
las lecturas son en modo de ráfaga (burst).

9.5.6 SDRAM

Las Synchronous DRAM utilizan un reloj para marcar los tiempos de los ciclos de
lectura o escritura y mantener en sincronismo la memoria con el resto del sistema (en
particular con la CPU). Este sincronismo le permite mejorar los tiempos de acceso respecto
a las memorias EDO. En la actualidad todas las memorias DRAM son del tipo sincrónico.
Las SDRAM se sub-clasifican en función de la frecuencia del reloj para la que están
diseñadas, para lo que se utiliza una clasificación propuesta por Intel en su especificación
del computador tipo PC:

PC-66: reloj de 66 MHz

PC-100: reloj de 100 MHz

PC-133: reloj de 133 MHz

9.5.7 RDRAM

Las Rambus DRAM son la propuesta de un fabricante para diseños de DRAM de alta
frecuencia (y por lo tanto altas velocidades de transferencia). Los chips de memoria están
implementados de forma de utilizar ambos flancos del reloj a los efectos de sincronizar las
transferencias. Las frecuencias de reloj disponibles van desde 300 MHz (equivalentes a 600
MHz), 350 MHz (equivalentes a 700 MHz), 400 MHz (equivalentes a 800 MHz), 533 MHz
(equivalente a 1066 MHz) hasta 600 MHz (equivalente a 1200 MHz).
La tecnología que utilizan estas memorias fue diseñada por la empresa Rambus que
licenció sus patentes a distintos fabricantes, entre ellos Intel. Los problemas legales y los
juicios que inició contra distintos fabricantes de memorias (reclamando que la tecnología
DDR desarrollada mas tarde por otros "copia" conceptos de su diseño y por tanto infringen

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

sus patentes) son tan o incluso más conocidos que sus productos.

9.5.8 DDR SDRAM

Estas memorias utilizan ambos flancos del reloj para realizar las operaciones, de allí
que reciben el nombre de Double Data Rate (Transferencia de Datos Doble). Son un
desarrollo estándar realizado por un conjunto de fabricantes para enfrentar el diseño
patentado de Rambus.
Por razones de mercadeo los nombres comerciales de este tipo de memorias han
sido bastante confusos, en particular porque hacen mención a la "frecuencia equivalente"
que tendría una memoria SDRAM "clásica" que solo hiciera una operación por ciclo.

Las versiones disponibles comercialmente son:

DDR-200: reloj de 100 MHz (equivale a 200 MHz, también denominada PC-200)

DDR-266: reloj de 133 MHz (equivale a 266 MHz, también denominada PC-266)

DDR-333: reloj de 167 MHz (equivale a 333 MHz, también denominada PC-333)

DDR-400: reloj de 200 MHz (equivale a 400 MHz, también denominada PC-400)

9.5.9 DDR2 SDRAM

Son la evolución tecnológica de las DDR, con un diseño pensado en aumentar la


frecuencia de trabajo. Son técnicamente incompatibles (trabajan a otro voltaje de
alimentación y poseen un encapsulado totalmente distinto).
Las variantes disponibles son:

DDR2-400: reloj de 200 MHz (equivale a 400 MHz, también denominada PC2-3200)

DDR2-533: reloj de 266 MHz (equivale a 533 MHz, también denominada PC2-4200)

DDR2-667: reloj de 333 MHz (equivale a 667 MHz, también denominada PC2-5300)

DDR2-800: reloj de 400 MHz (equivale a 800 MHz, también denominada PC2-6400)

DDR2-1066: reloj de 533 MHz (equivale a 1066 MHz, también denominada PC2-
5300)

DDR2-1200: reloj de 600 MHz (equivale a 1200 MHz, también denominada PC2-
9000)

9.5.10 DDR3 SDRAM

Son el siguiente paso en la evolución tecnológica de las DDR, con mayor la


frecuencia de trabajo y menor consumo (basado en un voltaje de trabajo menor). También
son técnicamente incompatibles con las DDR2 y las DDR.
Históricamente las variantes disponibles eran:

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

DDR3-800: reloj de 400 MHz (equivale a 800 MHz, también denominada PC3-6400)

DDR3-1066: reloj de 533 MHz (equivale a 1066 MHz, también denominada PC3-
8500)

DDR3-1333: reloj de 667 MHz (equivale a 1333 MHz, también denominada PC3-
10600)

DDR3-1600: reloj de 800 MHz (equivale a 1600 MHz, también denominada PC3-
12800)

Actualmente se construyen con frecuencias equivalentes de 1866 MHz, 2133 MHz,


2400 MHz, 2666 MHz, 2800 MHz, 2933MHz, 3000 MHz, 3100 MHz y 3200 MHz.

9.5.11 DDR4 SDRAM

Son un paso más en la evolución de las SDRAM, con un voltaje de trabajo menor y
frecuencias mayores a las DDR3, que permiten un menor consumo y una mayor
performance, llegando a frecuencias equivalentes de 4000 MHz.

9.5.12 VRAM

Para los controladores de video de los computadores hasta hace un tiempo se solía
utilizar un tipo especial de memoria (ya sea basada en tecnología SRAM o DRAM), que se
denomina Video RAM y cuya característica principal es contar con "doble puerta". Es decir
son dispositivos que pueden ser leídos a la misma vez que escritos (en direcciones
distintas). Esto es útil para poder mantener el refresco de la información en el monitor a una
velocidad constante (leyendo) a la misma vez que el programa actualiza la información a
desplegar en la pantalla (escribiendo).
Este tipo de memoria son como los "latch" pero organizados en múltiples palabras. En
la actualidad la tendencia es a utilizar memorias GDDR4 / GDDR5 (GDDR = Graphics
DDR), basadas en memorias DDR3, con un sistema de acceso simultáneo a dos páginas,
con lo que simula ser “dual port” como la VRAM.

9.5.13 NVRAM

La Non Volatile RAM es una memoria del tipo RAM que puede conservar su
información aún cuando el sistema donde está insertada queda sin alimentación eléctrica.
La forma tradicional de implementar este tipo de memorias es con un SRAM de bajo
consumo y una batería (ó pila) que le dé alimentación mientras no se dispone de la
alimentación eléctrica general del sistema.

9.5.14 CMOS RAM

Estas memorias en realidad son un nombre que popularizó la arquitectura PC para un


tipo de NVRAMs construidas con chips de bajo consumo basados en tecnología CMOS
(Complementary Metal Oxide Semiconductor). En los PCs esta memoria no volátil se usa
para almacenar la configuración básica del computador.

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

9.6 Módulos de Memoria

Los computadores modernos implementan sus sistemas de memoria principal en


base a módulos de memoria. Estos módulos son pequeñas tarjetas de circuito impreso que
disponen de los chips de memoria en cantidad y organización adecuada para el tamaño de
palabra soportado por la arquitectura del procesador utilizado. Estas tarjetas de circuito se
insertan en zócalos (memory sockets) previstos en las placas principales (motherboards) de
los computadores a tales efectos.

Algunos ejemplos de estos módulos son:

SIMM:

Estos fueron los primeros módulos en imponerse en la industria del PC. La sigla
significa Single In-line Memory Module, ya que si bien la placa de circuito tenía contactos en
ambas caras estos eran en realidad redundantes. Existieron en dos variantes:

- 30 contactos ó pines (para buses de memoria de 8 bits)

- 72 contactos ó pines (para buses de memoria de 32 bits)

DIMM:

Fueron la evolución de los SIMM asociados con la aparición de las SDRAM y las
arquitecturas de memoria de 64 bits (aun para procesadores de 32 bits). La sigla significa
Dual In-line Memory Module.

Existen variantes con distinta cantidad de contactos.

- 168 contactos ó pines (utilizado con memorias SDRAM)

- 184 contactos ó pines (utilizado con memorias DDR)

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

- 240 contactos ó pines (utilizado con memorias DDR2)

Los módulos DDR3 también utilizan 240 contactos, aunque como son incompatibles
eléctricamente, tiene la "mueca" de identificación (cortes en forma de "media luna" que
poseen en ambos extremos y en el medio) en otro lugar para evitar confusiones, mientras
que los DDR4 utilizan 288 contactos.

También existen alternativas a cada uno de los tipos anteriores con menor cantidad
de contactos (logrando módulos más pequeños físicamente) diseñados para equipos
portátiles (Notebooks, Palms, etc.).

A su vez existen distintas denominaciones de acuerdo al tipo de chip SDRAM que


utilicen y en particular a la velocidad de transferencia que poseen (expresada en
Mbytes/seg.), por ejemplo PC3-12800 (construidas con chips DDR3-1600)

También existen variantes respecto al voltaje de alimentación (5 Volts, 3.3 Volts, 1.5
Volts) y respecto a si son "buffereados" (también se los denomina "registrados") ó no. Los
módulos "registrados" disponen de circuitería adicional que amplifica las señales entre el
modulo de memoria y el controlador de memoria de la placa principal, dotando de mayor
estabilidad y confiabilidad al circuito. Ambas características se reconocen por la posición de
las muecas de codificación.

RIMM:

Son los módulos utilizados para memorias con tecnología Rambus. También hay
variantes con distinta cantidad de contactos.

- 184 contactos ó pines (utilizado en sistemas de memoria con buses de 16 bits)

- 232 contactos ó pines (utilizado en sistemas de memoria con buses de 32 bits)

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Máquinas de Estado

Arquitectura de Computadoras
(Versión 4.3 - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

10 MAQUINAS DE ESTADO

10.1 Introducción

En este capítulo retomaremos el tema de los circuitos secuenciales y, en particular,


veremos como la metodología de Máquinas de Estado permite especificar y deducir a partir
de la especificación cuál sería un circuito lógico, combinación de flip-flops y lógica
combinatoria, que implemente un circuito secuencial dado.

Como dijimos antes un circuito secuencial es aquél en el cual la(s) salida(s)


actual(es) depende(n) no solo del valor actual de la(s) entrada(s), sino también de la
historia pasada de esa(s) entrada(s). La denominación de “secuencial” que recibe este tipo
de circuitos hace referencia justamente al hecho que su comportamiento depende de cual
ha sido la secuencia de valores de la(s) entrada(s).

Dado que puede haber infinitas secuencias de entrada(s) que, a su vez, pueden ser
de largo infinito resulta muy útil introducir una regla que las agrupe y que permita encarar el
problema con un conjunto finito de elementos: los estados.

10.2 Estado

Vamos de definir una relación de equivalencia entre dos secuencias de valores de


entrada(s) de un circuito secuencial dado. Esta relación establece que dos secuencias
serán equivalentes si cumplen con dos condiciones: coinciden a partir de cierto punto y a
partir de dicho punto la salida del circuito es la misma para ambas secuencias.

Ejemplo: las secuencias A y B son equivalentes

Secuencia A: 011100110101111001101111000000110101011100....
Salida: 000000000000010101010000001000000000001000....
Secuencia B: 101010111001100000000110101011100....
Salida: 000010101010000001000000000001000....

y que a partir del lugar indicado cumplen ambas condiciones.

A partir de la regla de equivalencia podemos separar el conjunto de infinitas


secuencias de entrada(s) en clases de equivalencia. A cada clase de equivalencia le
corresponde un estado del circuito secuencial. Notemos que esta idea se corresponde con
el concepto intuitivo de “haber llegado a un cierto estado” luego de recorrer cierto camino.
Si bien esta clasificación se puede hacer siempre y la asociación con los estados también,
solo nos interesarán los casos donde el número de clases de equivalencia distintas sea
finito, ya que de otra forma no sería posible construir un circuito secuencial que tuviera ese
comportamiento (resultado que no vamos a demostrar ya que se ve en las asignaturas de
Ciencia de la Computación). Un circuito secuencial que se analiza en base a la idea de
estado recibe el nombre de Máquina de Estado (ó Máquina de Estados).

10.3 Autómatas Finitos Deterministas

Las máquinas de estado son, en definitiva, un caso particular de Autómatas Finitos


Deterministas (AFD). Los AFD son un modelo matemático de un sistema con entradas y
salidas discretas. Dicho sistema pude estar en cualquiera de un número finito de
configuraciones o estados. El estado del sistema resume, como vimos, la información
concerniente a entradas anteriores, y que es necesaria para determinar el comportamiento

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

del sistema para entradas posteriores, ya que dicho comportamiento es siempre el mismo
para la misma combinación estado – entrada. De esta característica viene el término de
determinista.

En las materias de Ciencia de la Computación encontraremos muchos ejemplos de


sistemas de estado finito, y la teoría de autómatas finitos es una herramienta útil para el
diseño de tales sistemas. También es una herramienta útil para el diseño de programas, en
particular los que implementan protocolos de algún tipo, incluyendo las interfaces hombre-
máquina. En nuestra asignatura veremos como un circuito secuencial puede ser modelado
mediante un AFD de forma de separar el diseño lógico de la implementación electrónica.

Formalmente, los autómatas finitos o máquinas de estado, son cuaternas M = (E, Σ,


δ, e0), donde E es un conjunto finito de estados, e0 ∈ E es el estado inicial, Σ es el alfabeto
de entrada, y δ:ExΣ → E es la función de transición.

A continuación veremos un caso especial de AFDs, los AFD con salida: las
máquinas secuenciales.

10.4 Autómatas Finitos con Salida

Existen dos planteamientos distintos para este tipo de autómata, la salida puede
estar asociada con el estado (máquina de Moore), ó con la transición (máquina de Mealy).

10.4.1 Máquina de Mealy

Una máquina de Mealy es una t-upla M = (E, Σ, ∆, δ, λ, e0), donde E es un conjunto


finito de estados, e0 ∈ E es el estado inicial, Σ es el alfabeto de entrada, ∆ es el alfabeto de
salida, δ : ExΣ → E es la función de transición y λ : ExΣ → ∆ es la función de salida (o
transferencia).

Consideremos ahora el siguiente ejemplo M = ({e0, e1, e2}, {0, 1}, {y, n}, δ, λ, e0),
donde δ y λ vienen dadas por la siguientes tablas.

δ 0 1
e0 e1 e2
e1 e1 e2
e2 e1 e2

λ 0 1
e0 n n
e1 y n
e2 n y

A la primera de las tablas (que especifica la función δ) se la conoce como Tabla de


Transición (ó Tabla de Transiciones) y a la segunda (que especifica la función λ) como
Tabla de Salida (ó Tabla de Transferencia).
Si bien la representación tabular es suficiente para especificar el autómata existe
otra forma, utilizada con mayor frecuencia debido a su carácter gráfico que permite una
mejor visualización del comportamiento de la máquina.

Dicha representación gráfica recibe el nombre de Diagrama de Estados, siendo un


grafo orientado, representando con círculos los estados y con arcos orientados las
transiciones de estado (la función de transición) y anotando xx...x/yy....y sobre cada

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

transición los valores de la(s) entrada(s) que provocan la transición y el valor


correspondiente de la(s) salida(s) (la función de salida).

El diagrama para este ejemplo quedaría así:

0/y

e1
0/n

e0 1/n 0/n

1/n
e2

1/y

En el autómata anterior, dada una entrada 01100 genera como salida nnyny. De
esta forma podemos ver como un autómata con salida, computa una función con dominio
tiras del alfabeto Σ, y genera como salida una tira del alfabeto ∆, formada por la
concatenación de los símbolos asociados a cada transición, por la que pasó el autómata al
procesar la tira de entrada.

10.4.2 Maquina de Moore

Una maquina de Moore es una tupla M = (E, Σ, ∆, δ, λ, e0), donde E es un conjunto


de estados finito, e0 ∈ E es el estado inicial, Σ es el alfabeto de entrada, ∆ es el alfabeto de
salida, δ : ExΣ → E es la función de transición y λ : E → ∆ es la función de salida.

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Podemos ver una versión similar al ejemplo visto para Mealy, pero con las salidas
ahora asociadas a los estados.

e0-/-

1 0
0

e1y/y
0
1

e2n/n e1n/n

1
e2y/y 0

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Circuitos Secuenciales

Arquitectura de Computadoras
(Versión 4.3 - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

7 CIRCUITOS SECUENCIALES

7.1 Definición

Un circuito secuencial es un sistema en el cual la salida depende de la entrada y del


valor de las entradas anteriores. Un ejemplo ya visto de estos circuitos son los flip-flops.

Los sistemas secuenciales se caracterizan por tener “memoria”, la que se puede


asociar a la existencia de “estados” internos. Estos estados son los que determinan, junto a
la entrada actual, el comportamiento futuro del sistema. Como vimos los estados de alguna
forman “memorizan” la evolución en el tiempo que tuvieron las entradas y por ende el
sistema en su conjunto.

Un sistema secuencial se describe por las ecuaciones:

Y = G(X, E)
E' = H (X, E)

siendo Y la salida, X la entrada, E el estado interno y E’ el nuevo valor del estado luego de
la transición provocada por la presencia de una nueva entrada.

X
G Y

E Memoria E'

Esto significa que la salida no depende solo de las entradas (como en los sistemas
combinatorios) sino también del llamado vector de estado E.

Los estados internos se describen por un grafo denominado Diagrama de Estados,


que no es más que un AFD con salida o máquina secuencial como las ya vistas, donde los
círculos representan los estados (que a nivel circuital se almacenan en flip-flops) y los arcos
representan las transiciones.

Los rótulos de los arcos indican los eventos que generan cambios de estado, que
corresponden a los posibles valores del vector de entrada para un nuevo vector de entrada.
Notemos que decir “nuevo vector de entrada” no implica que exista un “nuevo valor del
vector de entrada” (el valor puede ser el mismo que el anterior). Por esto es necesario que
el sistema tenga una forma de reconocer que debe procesar una nueva entrada (aunque el

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

valor no haya cambiado). Esto se logra típicamente por un reloj de sincronismo y es la


forma que utilizaremos en este curso.

Notemos que las ecuaciones características de los circuitos secuenciales que


presentamos al principio del capítulo:

Y = G(X, E)
E' = H (X, E)

formalmente corresponden a los circuitos que se diseñen en base a la Máquina de Mealy.

Si el diseño fuera hecho en base a la Máquina de Moore, las ecuaciones deberían lucir así:

Y = G(E)
E' = H (X, E)

ya que en el caso de Moore la salida depende solamente del estado actual de la máquina,
mientras que el nuevo estado nuevo sí depende del estado actual y la entrada.

7.2 Diseño de Circuitos Secuenciales

El diseño de un circuito secuencial en base a las máquinas de estado (en particular


en el curso utilizaremos la de Mealy) se realiza en base a la especificación del AFD que
define el comportamiento esperado del circuito. Los estados se almacenan en flip-flops (tipo
D ó J-K, sincrónicos por flanco) y las funciones G (de salida ó transferencia) y H (de
transición) se implementan en lógica combinatoria.

En base a estos principios de diseño, se pueden establecer las siguientes etapas,


las que deben ser ejecutadas para obtener el diseño del circuito:

• Modelado del sistema a implementar mediante la especificación del AFD


correspondiente mediante un Diagrama de Estados (este es un paso no
obligatorio, que conviene realizar por razones de claridad de visualización del
comportamiento que se especifica).
• Deducir la “Tabla de Estados” (tabla que establece para cada estado cual es el
próximo estado y cuáles las salidas en función de las entradas) a partir del
Diagrama de Estados (o especificarla directamente en base al comportamiento
esperado del AFD, si es que no se hizo el paso anterior).
• Determinar cantidad de bits y sistema de codificación para la(s) entrada(s) y
la(s) salida(s).
• Determinar el número de flip-flops necesarios para codificar todos los estados
posibles del sistema y determinar la codificación a utilizar.
• Incorporar la codificación de los estados, entradas y salidas a la Tabla de
Estados para obtener la “Tabla de Transiciones y Salidas”.
• Seleccionar los flip-flops a utilizar y en base a las ecuaciones de los mismos
pasar de la Tabla de Transiciones y Salidas a las tablas de verdad de las
funciones lógicas que permitirán determinar el valor de la(s) salida(s) en base a
la(s) entrada(s) y las salidas de los flip-flops, y el valor a presentar en las
entradas de los flip-flops para almacenar el nuevo estado en ellos.
• Minimizar las expresiones lógicas en dos niveles mediante un método
sistemático (en el curso utilizamos Diagramas de Karnaugh).
• Dibujar el circuito lógico resultante en base a los flip-flops y compuertas básicas
(AND, OR y NOT).

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

A continuación veremos ejemplos de cómo aplicar esta metodología de diseño de


circuitos secuenciales.

7.3 Ejemplos

7.3.1 Contador Binario (modulo cuatro)

En este primer ejemplo vamos a diseñar un contador de módulo 4 (de 0 a 3). Este
circuito es bastante particular ya que no tiene entrada, por lo que el cambio de estado es
incondicional y ocurre en cada flanco ascendente del reloj. Si se quiere contar los cambios
de nivel (flanco ascendente) de una señal cualquiera, basta utilizar esa señal como reloj del
contador. Si, en cambio, se desea contar las transiciones de 0 a 1 de una señal en forma
sincrónica respecto a un reloj general del sistema, entonces se debe utilizar el contador que
veremos en el próximo punto.

Para construir el contador binario, de acuerdo al método propuesto, primero


debemos especificar el problema mediante un AFD con salida (máquina de estado de
Mealy), para lo que vamos a dibujar su diagrama de estados:

x/0 e0 x/3

e1 e3

x/1 e2 x/2

El siguiente paso es obtener la Tabla de Estados:

En En+1 Salida
e0 e1 0
e1 e2 1
e2 e3 2
e3 e0 3

Tengamos presente que esta tabla no hace otra cosa que mostrar la información de
las funciones de transición δ y de salida λ, resumidas en el comúnmente llamado “Diagrama
de Estados” del AFD M = ({e0, e1, e2, e3}, {}, {0, 1, 2, 3}, δ, λ, e0) con salida dibujado.

El diagrama de estados tiene cuatro estados por lo que necesitamos dos flip-flops
para poder representarlos (cuyas salidas anotaremos q1 y q0).

A continuación debemos asignar la codificación a cada estado. En este caso parece


natural codificar en base al subíndice utilizado en la denominación de los estados
expresado en binario. Lo mismo para la salida (el valor expresado en binario en 2 bits)

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

La Tabla de Transiciones y Salidas queda entonces así:

En En+1 Salida
q1 q0 q1 q0 s1s0
00 01 00
01 10 01
10 11 10
11 00 11

Usaremos flip-flops tipo D, por lo que de la tabla anterior podemos pasar a la Tabla
de Verdad, usando la ecuación del flip-flop tipo D:
Qn+1 = Dn
y queda:

q1 q0 d1 d0 s1 s0
00 0 1 0 0
01 1 0 0 1
10 1 1 1 0
11 0 0 1 1

Ahora lo que resta es hacer los diagramas de Karnaugh que minimicen los circuitos
combinatorios que implementarán la función de transición y la función de salida, en base a
las tablas de verdad obtenidas. Dichos circuitos tienen como entrada la(s) entrada(s) del
circuito secuencial, y el valor del estado anterior y como salidas deben dar el próximo
estado (que oficiarán como entradas de los flip-flops tipo D) y la(s) salida(s) esperada(s) del
circuito secuencial en su conjunto, respectivamente.

Dado que la codificación elegida para los estados coincide exactamente con la
salida, resulta que el circuito combinatorio que implementa la función de salida es la
identidad sobre salidas q de los FF. Por esto sólo nos resta minimizar el circuito
combinatorio para la función de transición.

d1

q1 \ q0 0 1
0 0 1
1 1 0

d1 = q1’. q0 + q1. q0’


d0

q1 \ q0 0 1
0 1 0
1 1 0

d0 = q0’

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Quedando entonces el siguiente circuito secuencial:

7.3.2 Contador de Transiciones Binario (modulo cuatro)

En este ejemplo veremos el caso ya adelantado en el cual el interés es contar


transiciones de una señal (de 0 a 1, es decir flancos ascendentes) en forma sincrónica con
un reloj. Al igual que en el caso anterior vamos a diseñar un contador de módulo 4 (de 0 a
3). A diferencia con el contador del ejemplo anterior este circuito sí tiene entrada, y los
cambios de estado se producirán cuando la entrada sea 1 al momento del flanco del reloj
de sincronismo. Notar que en este caso solamente se tendrá en cuenta los valores de la
señal de entrada al momento del flanco del reloj (si cambia durante el período del reloj el
contador construido de esta forma no lo detectará).

Siguiendo nuevamente los pasos de diseño del método propuesto primero


especificaremos el problema mediante un AFD con salida (máquina de estado de Mealy),
que en este caso tendrá el siguiente diagrama de estados:

0/3

1/0 e0 1/3

0/0 e1 e3 0/2

1/1 e2 1/2

0/1

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

El siguiente paso es obtener la Tabla de Estados, en la que en este caso sí se debe


tener en cuenta la entrada, por lo que la cantidad de filas se duplica, aunque para el caso
de la entrada = 1 es igual a la anterior:

En Entrada En+1 Salida


e0 0 e0 3
e0 1 e1 0
e1 0 e1 0
e1 1 e2 1
e2 0 e2 1
e2 1 e3 2
e3 0 e3 2
e3 1 e0 3

Al igual que en el caso anterior tenemos cuatro estados por lo que necesitamos dos
flip-flops para poder representarlos. Haremos la misma codificación de los estados en base
al subíndice en binario. La Tabla de Transiciones y Salidas queda de la siguiente forma:

En Entrada En+1 Salida


q1 q0 e q1 q0 s1 s0
00 0 00 11
00 1 01 00
01 0 01 00
01 1 10 01
10 0 10 01
10 1 11 10
11 0 11 10
11 1 00 11

En este caso también usaremos flip-flops tipo D, con lo que pasamos a las
siguientes tablas de verdad:

q1 q0 e d1 d0 s1 s0
000 0 0 1 1
001 0 1 0 0
010 0 1 0 0
011 1 0 0 1
100 1 0 0 1
101 1 1 1 0
110 1 1 1 0
111 0 0 1 1

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

Los diagramas de Karnaugh tienen ahora tres variables y resultan así:

d1
q1 q0 \ e 0 1
00
01 1
11 1
10 1 1

d1 = q1.e’ + q1.q0’ + q1'.q0.e

d0

q1 q0 \ e 0 1
00 1
01 1
11 1
10 1

d0 = q0.e’ + q0’.e

s1

q1 q0 \ e 0 1
00 1
01
11 1 1
10 1

s1 = q1.q0+ q1.e + q1'.q0'.e'

s0

q1 q0 \ e 0 1
00 1
01 1
11 1
10 1

s0 = q0'.e’ + q0.e
El circuito queda entonces:

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

Las funciones de salida están directamente vinculadas al diagrama de estados que


especificamos para el contador, y dependen también de la codificación elegida para los
estados. Notemos que en el diagrama que hicimos la salida quedó vinculada al identificador
del estado hacia el que vamos. Si en cambio especificáramos que la salida coincida con el
estado que abandonamos quedaría el diagrama de estados siguiente:

0/0

1/0 e0 1/3

0/1 e1 e3 0/3

1/1 e2 1/2

0/2

Notemos que el efecto que tiene este cambio sobre el comportamiento del circuito
es que provoca que los cambios en el valor de las salidas del contador ocurren en el flanco
descendente de la entrada (cuando cambia de 1 a 0), en vez del flanco ascendente (cambio
de 0 a 1) como ocurría en el diseño original. Si mantenemos la codificación de los estados
este diagrama se traduce en la siguiente Tabla de Transición y Salida:

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

En Entrada En+1 Salida


q1 q0 e q1 q0 s1 s0
00 0 00 00
00 1 01 00
01 0 01 01
01 1 10 01
10 0 10 10
10 1 11 10
11 0 11 11
11 1 00 11

Usando la ecuación del flip-flop D pasamos a las tablas de verdad:

q1 q0 e d1 d0 s1 s0
000 0 0 0 0
001 0 1 0 0
010 0 1 0 1
011 1 0 0 1
100 1 0 1 0
101 1 1 1 0
110 1 1 1 1
111 0 0 1 1

Como la tabla de transición (cambio de estado) no cambió, tampoco cambiarán las


expresiones lógicas minimizadas de las entradas de los flip-flops (d1 y d0). Pero sí hay un
cambio significativo en las funciones de salida. Es fácil ver que ahora s1 = q1 y s0 = q0. Por
lo que el circuito se simplifica significativamente y queda:

7.3.3 Reconocedor de Secuencia

En este ejemplo construiremos un circuito que reconozca la secuencia 11011 en su


único bit de entrada. La salida será Falsa (F) mientras la secuencia no sea reconocida.
Será Verdadera (V) al momento de reconocerla y volverá a Falsa (F) para esperar una

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

nueva secuencia correcta.

Comencemos por plantear el diagrama de estados de la máquina. Para ello


consideramos un estado inicial E1 (espero 1) en el cuál la máquina estará hasta que llegue
el primer "1" de la secuencia a reconocer. Cuando llega el primer "1" pasamos al estado V1
(vino 1). Estando en V1, si llega otro "1" pasamos al estado V11 (vino 1 y luego 1), pero si
llega 0 volvemos al anterior (la secuencia debe comenzar de nuevo, ya que "10" no forma
de la secuencia válida). En el estado V11 en caso que llegue un "0" entonces pasamos a un
nuevo estado V110 (vino 1, luego 1 y luego 0). Si en cambio llega un "1" entonces debemos
quedarnos en el mismo estado, porque significa que llegaron hasta ahora "111", lo que
significa que también vino un "1" y luego otro "1". El próximo paso es analizar si estando en
V110 llega un "1": hay que pasar al estado V1101 (ya que por ahora la secuencia puede ser
válida), en cambio si llega un "0" debemos volver al inicio (E1) ya que la posible secuencia
válida se frustró. Finalmente si estando en el estado V1101 viene un "0" entonces la salida
será Falsa y pasaremos al estado E1 a esperar el primer "1" de una nueva posible
secuencia válida. Si en cambio llega un "1" entonces la salida será Verdadera. Queda por
definir a qué estado vamos. De hecho existen dos alternativas: si consideramos el "1" que
llegó como fin de una secuencia válida y como posible comienzo de una nueva secuencia
válida, entonces debemos pasar al estado V11 (ya que habrían llegado dos "1" seguidos de
una posible nueva secuencia válida). En caso contrario debemos ir al estado E1.
Notar que en cualquier máquina secuencial para diseñar correctamente el diagrama
de estados es necesario analizar qué sucede a partir de cada estado con todos y cada uno
de los posibles valores de la entrada (en este caso se reduce a "0" ó "1", en otro caso
podrían haber más posibilidades).

Alternativa 1:

V1 1/F
1/F

0/F
0/F E1 V11 1/F

0/F 1/V 0/F


0/F

V1101 V110

1/F
Alternativa 2:

V1 1/F
1/F

0/F
0/F E1 V11 1/F
0/F
0/F 1/V 0/F

V1101 V110

1/F

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

Vamos a continuar con la implementación de la alternativa 1. La tabla de salidas y


transiciones unificada para este caso queda:
En Entrada En+1 Salida
E1 0 E1 F
E1 1 V1 F
V1 0 E1 F
V1 1 V11 F
V11 0 V110 F
V11 1 V11 F
V110 0 E1 F
V110 1 V1101 V
V1101 0 E1 F
V1101 1 V11 V

En este caso tenemos 5 estados, por lo que requerimos 3 flip-flops para almacenar
la codificación de los mismos.

Debemos ahora codificar los estados, la entrada y la salida. La entrada ya está en


booleano (0 ó 1) y la salida parece natural codificarla F → 0 y V → 1. Los estados los
codificamos de 000 a 100 en el orden presentado en la tabla. Con estas codificaciones la
Tabla de Transiciones y Salidas queda:

En Entrada En+1 Salida


q2 q1 q0 e q2 q1 q0 s
000 0 000 0
000 1 001 0
001 0 000 0
001 1 010 0
010 0 011 0
010 1 010 0
011 0 000 0
011 1 100 0
100 0 000 0
100 1 010 1

Usando flip-flops tipo D pasamos de la Tabla de Transiciones y Salidas a las tablas


de verdad de las funciones de transición y salida. Notemos que en este caso hay más
códigos binarios de estados que estados reales, con lo que las tablas de verdad incluirán
“X” (don’t care) en los lugares que correspondan a las codificaciones que no representan
ningún estado de la máquina. Esto es así porque estas codificaciones pueden considerarse
como estados "inalcanzables", ya que ninguna evolución de la máquina secuencial pasará
por ellos. Por esta razón las funciones de transición y de salida para esos estados
inalcanzables no importa qué valor toman (ya que nunca sucederán), por lo que puede
usarse como valores "comodín" (X) a los efectos de lograr una mayor minimización de los
circuitos.

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

q2 q1 q0 e q2 q1 q0 s
0000 0 0 0 0
0001 0 0 1 0
0010 0 0 0 0
0011 0 1 0 0
0100 0 1 1 0
0101 0 1 0 0
0110 0 0 0 0
0111 1 0 0 0
1000 0 0 0 0
1001 0 1 0 1
1010 X X X X
1011 X X X X
1100 X X X X
1101 X X X X
1110 X X X X
1111 X X X X

A continuación realizaremos la minimización de las funciones, utilizando los


diagramas de Karnaugh:

d2

q 0e \ q 2q 1 00 01 11 10
00 X
01 X
11 1 X X
10 X X

d2 = q1.q0.e

d1

q 0e \ q 2q 1 00 01 11 10
00 1 X
01 1 X 1
11 1 X X
10 X X

d1 = q'1.q0.e + q2.e + q1.q'0

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

d0

q 0e \ q 2q 1 00 01 11 10
00 1 X
01 1 X
11 X X
10 X X

d0 = q'2.q'1.q'0.e + q1.q'0.e'

q 0e \ q 2q 1 00 01 11 10
00 X
01 X 1
11 X X
10 X X

s = q2.e
El circuito queda entonces de la siguiente forma:

7.3.4 Control de Ascensor

Como forma de ejemplificar que los circuitos secuenciales no solamente son


apropiados para generar o reconocer secuencias, como lo podría estar indicando su
denominación y los ejemplos vistos hasta ahora, vamos a encarar el diseño de un circuito
para controlar un modelo simplificado de un ascensor.

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura de Computadoras Notas de Teórico

Este ascensor atenderá tres pisos: PB, 1° y 2°. Con sideraremos solamente la
botonera interna en la caja como entrada (botones PB, 1° y 2°) y como salida deberemos
controlar el encendido del motor (ON/OFF) y el sentido de marcha (SUBE/BAJA). No nos
preocuparemos de cómo es que se detiene el motor al llegar al piso (obviamente en un
control de ascensor real esto debería ser tenido en cuenta).

Comencemos con el diagrama de estados. Los estados "naturales" de este sistema


parecen ser los pisos en los que está el ascensor (dado que hemos simplificado el modelo y
no tenemos en cuenta el "viaje" de un piso a otro, no hay estados que no sean estar en un
piso). En función del piso actual (estado) y de qué botón pulse el usuario (entrada) quedará
determinado si el ascensor debe moverse (encendido del motor) y con qué sentido. No es
difícil arribar al siguiente diagrama de estados, siendo la única consideración especial el
hecho de utilizar la salida "X" (indiferente) en "sentido" en el caso que el motor esté
detenido (ya que en ese caso no importa si sube o baja ya que no se mueve):
1°/OFF, X

1°/ON, SUBE 1° 2°/ON, SUBE

PB/OFF,X PB 2° 2°/OFF, X
PB/ON, BAJA 1°/ON, BAJA

PB/ON, BAJA

2°/ON, SUBE

El próximo paso es escribir, a partir del diagrama de estados, la Tabla de Estados:

En Entrada En+1 Salidas


Motor Sentido
PB PB PB OFF X
PB 1° 1° ON SUBE
PB 2° 2° ON SUBE
1° PB PB ON BAJA
1° 1° 1° OFF X
1° 2° 2° ON SUBE
2° PB PB ON BAJA
2° 1° 1° ON BAJA
2° 2° 2° OFF X

En este caso tenemos 3 estados por lo que precisamos 2 bits para representarlos
(PB → 00, 1° → 01, 2° → 10). Por su lado vamos a codificar la entrada también en 2 bits
(usaremos la misma codificación que para los estados), mientras que para las salidas
tomaremos 1 bit para cada una (OFF → 0, ON → 1, BAJA → 0, SUBE → 1).

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


Arquitectura de Computadoras Notas de Teórico

Con estas codificaciones la tabla anterior se transforma en la siguiente Tabla de


Transiciones y Salidas:
n n+1
E Entrada E Salidas
q1 q0 e1 e0 q1 q0 motor sentido
00 00 00 0 X
00 01 01 1 1
00 10 10 1 1
01 00 00 1 0
01 01 01 0 X
01 10 10 1 1
10 00 00 1 0
10 01 01 1 0
10 10 10 0 X

Si usamos flip-flops tipo D y aplicamos su ecuación, agregando los códigos de


estados inalcanzables (como en el ejemplo anterior) y aprovechando también que hay
entradas "inexistentes" (codificaciones que no corresponden a entradas reales), podemos
pasar a las tablas de verdad de las funciones de transición y salida:

q1 q0 e1 e0 q1 q0 m s
0000 0 0 0 X
0001 0 1 1 1
0010 1 0 1 1
0011 X X X X
0100 0 0 1 0
0101 0 1 0 X
0110 1 0 1 1
0111 X X X X
1000 0 0 1 0
1001 0 1 1 0
1010 1 0 0 X
1011 X X X X
1100 X X X X
1101 X X X X
1110 X X X X
1111 X X X X

El próximo paso es la minimización de las tablas de verdad de las entradas de los


flip-flops y las salidas:

Instituto de Computación - Facultad de Ingeniería - UDELAR 16


Arquitectura de Computadoras Notas de Teórico

d1
e1e0 \ q1q0 00 01 11 10
00 X
01 X
11 X X X X
10 1 1 X 1

d1 = e1

d0
e1e0 \ q1q0 00 01 11 10
00 X
01 1 1 X 1
11 X X X X
10 X

d0 = e0

m
e1e0 \ q1q0 00 01 11 10
00 1 X 1
01 1 X 1
11 X X X X
10 1 1 X

m = q'1.e1 + q1.e'1 + q0.e'0 + q'0.e0

s
E1e0 \ q1q0 00 01 11 10
00 X X
01 1 X X
11 X X X X
10 1 1 X X

s = e1 + q'1.e0

El circuito queda como se ve en la figura siguiente:

Instituto de Computación - Facultad de Ingeniería - UDELAR 17


Arquitectura de Computadoras Notas de Teórico

Instituto de Computación - Facultad de Ingeniería - UDELAR 18


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Máquina Lógica General

Arquitectura de Computadoras
(Versión 4.3 - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

12 MAQUINA LOGICA GENERAL

12.1 Introducción

En este capítulo veremos el esquema general de una máquina lógica capaz de


implementar cualquier máquina lógica particular e introduciremos el concepto de
computadora, para en los capítulos siguientes concentrarnos en la forma de construirlas (su
arquitectura).

En los cursos de Teoría de Computación se analiza la teoría general de los


autómatas y, en particular, se analiza el hecho que todo problema resoluble mediante un
algoritmo (o sea "computable") se puede reducir al problema de traducir símbolos y/o
reconocer secuencias. En nuestra materia tomaremos esos elementos como un dato y
veremos la aplicabilidad de esos conceptos a las máquinas lógicas y sus implicancias.

12.2 Máquina Lógica General

En el capítulo de Máquinas de Estado, ya vimos que los circuitos secuenciales


implementados a partir de las máquinas de estado, en particular las que obedecen al
esquema de Mealy, tienen un comportamiento que puede expresarse matemáticamente
mediante las expresiones:

Y = G (X, E)
E' = H (X, E)
siendo:
Y = salida actual
E' = próximo estado
X = entrada actual
E = estado actual
G = función de salida
H = función de estado

La primera observación a realizar es que una máquina combinatoria es un caso


particular de máquina secuencial (dónde la función de estado es la identidad y la función de
salida solo depende de la entrada X). Por tanto una máquina secuencial se puede
comportar tanto como un reconocedor de secuencias (en definitiva de esa característica fue
que partimos para modelizarlas como máquinas de estado), como un traductor de símbolos
(una máquina combinatoria me devuelve un "símbolo de salida" como resultado de una
transformación de un "símbolo de entrada").

Por tanto una máquina de estados es una máquina lógica general, en el sentido que
puede actuar reconociendo secuencias como traduciendo símbolos. De acuerdo a lo
expresado en la introducción de este capítulo esto significa que una máquina de estas
características es capaz de resolver cualquier problema computable que pueda
presentarse.

La segunda observación es que una máquina como ésta puede implementarse


utilizando el siguiente esquema de bloques:

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

X
ROM Y

ROM

E RAM E'

donde la ROM de más arriba implementa la función G, la ROM de abajo la función H


y la RAM es del tipo "registro" para almacenar el estado.

Es fácil ver que el diagrama anterior es equivalente a:

X Y
ROM

E RAM E'

donde hemos juntado las dos ROMs que implementan las funciones G y H en una
sola.

El esquema anterior, que representa una máquina de estados, recibe la


denominación de Máquina Lógica General, ya que con una ROM de tamaño adecuado
(que permita implementar las funciones G y H requeridas) y una RAM ("latch" ó registro)
con la cantidad de bits adecuada, se puede construir la máquina que resuelva cualquier
problema computable específico que se plantee. En otras palabras: dado un problema
existe una ROM y una RAM que permiten implementar la máquina que resuelve dicho
problema, con la única condición que el mismo sea resoluble por un autómata finito. La
condición de "resoluble por un autómata" está dada porque una máquina así resuelve
problemas reducibles al reconocimiento de secuencias y/o la traducción de símbolos. La
condición de "finito" está vinculada al hecho que la ROM y la RAM pueden tener, al menos
desde el punto de vista teórico, el número de bits que se desee, siempre que éste sea
finito.

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

La última observación es que, aunque en principio sorprenda, todo problema


"algoritmizable", desde multiplicar números ó calcular raíces cúbicas, hasta la liquidación de
sueldos y el diseño asistido por computadora (CAD), puede ser reducido a su mínima
expresión abstracta como una combinación de reconocimiento de secuencias y/o traducción
de símbolos.

Por tanto la anterior aseveración sobre la máquina lógica general se puede traducir
en que dado un problema cualquiera "resoluble" (multiplicar números o liquidar sueldos, por
decir dos ejemplos) puedo construir una máquina que lo haga.

12.3 Máquina Lógica General Programable

Si damos un paso más y sustituimos la ROM que implementa las funciones de


salida y estado por RAM, nos queda el esquema:

X Y
RAM

E RAM E'

Podemos decir que si construyo una máquina de estas características, la misma


podrá resolver todos los problemas tales que sus funciones de salida y estado puedan
implementarse con la cantidad de bits disponibles en la RAM superior y los bits de
almacenamiento de la RAM inferior alcancen para el número de estados requeridos para
esos problemas. Para resolver un problema específico alcanzará con "programar" las
funciones G y H en la RAM, almacenando los contenidos apropiados en la misma.

12.4 Computadora

Una computadora, tal como la conocemos hoy, en definitiva es una máquina


lógica universal programable. Por tanto el esquema anterior es el de mayor nivel de
abstracción y generalidad que podemos proponer para representar una computadora (ó
computador, ú ordenador, aquí no vamos a entrar a dirimir ni el posible sexo de estos
sistemas ni la vieja disputa entre España y América Latina sobre cuál es su nombre
correcto, para este último tema existe un interesante artículo accesible en
http://www.elcastellano.org/ordenado.html).

Notemos que en este contexto "programar" significa determinar los contenidos de la


RAM que implementa las funciones de salida y estado.

Para ser más precisos en el esquema presentado, deberíamos separar la RAM


superior en una RAM (grande) más una ROM (pequeña). Esto porque todo computador
necesita tener implementado al menos un "programa" básico en ROM, que permita ingresar
las funciones G y H (específicas para el problema concreto a resolver) en la RAM, porque
recordemos que el contenido de las RAMs se borra al quitarle la energía. Pero en definitiva

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

es un detalle que no es trascendente en este momento.

12.5 Arquitectura de una Computadora

El esquema anterior si bien es, como dijimos, el más general que podemos utilizar
para representar una computadora, dista bastante de lo que conocemos cotidianamente por
estos equipos. No es sencillo ni directo reconocer en él al "Pentium", el “Core Duo” (o al
"procesador" que sea), ni el disco duro; apenas la memoria parece estar asociada de
alguna manera a la RAM. Ni hablemos del teclado, el mouse y el monitor de video…….

La razón última de esta aparente inconsistencia está en que el anterior esquema, si


bien abstracto y general, es normalmente impracticable, en el sentido que rápidamente se
llega a tamaños de RAM requeridos para las funciones G y H y los estados que no son
posibles de conseguir con circuitos de memoria reales. Entonces si bien teóricamente el
esquema es correcto, en la práctica no es aplicable.

Para ejemplificar este concepto pensemos simplemente el problema de sumar


números muy grandes (supongamos representables en 32 bits), sin acarreo. Es un simple
problema de traducción de símbolos (traduzco el "símbolo" formado por la yuxtaposición de
la pareja de operadores por el "símbolo" que es su suma de 32 bits). Para la máquina que
implemente esta solución se requiere una RAM de 64 bits de entrada y 32 bits de salida.
Una RAM así tendría una capacidad de 264 x 22 bytes = 26 x 260 bytes = 64 Exabytes (1
Exabyte es un Gigabyte de Gigabytes) o sea algo así como el equivalente de 1000 millones
de discos duros de un PC moderno.

Es así que surge el concepto de la arquitectura de las computadoras, que consiste


en un conjunto de técnicas que permiten construir máquinas lógicas generales
programables en forma práctica. En materia terminológica se distingue la "arquitectura" de
un computador de la "organización" de un computador. Se puede decir que la arquitectura
es la visión funcional (el conjunto de recursos que "ve" el programador), mientras que la
organización es la forma en que se construye una cierta arquitectura en base a circuitos
lógicos.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Arquitectura de von Neumann

Arquitectura de Computadoras
(Versión 4.2 - 2011)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

13 ARQUITECTURA DE VON NEUMANN

13.1 Introducción

Esta arquitectura fue la propuesta por el matemático John von Neumann para la
construcción de la computadora EDVAC en 1945 (la máquina se terminó de construir en
1949), sucesora de la que se considera la primer computadora electrónica, la ENIAC
(1946).
Los conceptos que propuso von Neumann han tenido una vigencia mucho más allá
de la esperada en una industria como la de las tecnologías de la información. Por más que
llame la atención todos los computadores modernos disponibles comercialmente poseen en
el fondo la misma arquitectura que la EDVAC, definida en 1945. Mucho se ha adelantado
en materia de los circuitos lógicos (la organización) que implementan la arquitectura, pero
casi nada en los principios de diseño que planteó von Neumann hace más de 60 años (que
en materia tecnológica representan más de una decena de generaciones completas).

Se puede decir que la idea fundamental de von Neumann se apoya en el hecho que
una operación compleja normalmente se puede dividir como una secuencia ordenada de
operaciones más simples. En otras palabras lo que propuso fue construir una máquina
capaz de ejecutar algoritmos en forma explícita. Para ello introdujo el concepto de
"programa almacenado" como una "secuencia lógicamente ordenada de instrucciones",
siendo las "instrucciones" las operaciones básicas que implementa el hardware a través de
sus circuitos lógicos.

Una Arquitectura de von Neumann tiene tres bloques constructivos básicos: la


Unidad Central de Proceso (ó CPU por su sigla en inglés), la Memoria y la Entrada/Salida.

Las funciones de cada bloque son:

- CPU: se encarga de ejecutar los programas.


- Memoria: almacena el programa (conjunto de instrucciones ordenado
lógicamente) y los datos (operadores y resultados de la ejecución de las
instrucciones).
- Entrada/Salida: comunica el computador con el mundo exterior, permitiendo la
interacción con los usuarios y con otras computadoras.

CPU MEM

E/S

La Memoria se implementa como ya hemos visto en los capítulos anteriores. En un


próximo capítulo veremos en detalle el sub-sistema de Entrada/Salida. En este capítulo
nos concentraremos, entonces, en analizar la CPU.
Estos tres sub-sistemas se interconectan por medio de un bus, que contiene líneas
de datos, de dirección y de control.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

13.2 CPU

La Unidad Central de Proceso es la encargada de la ejecución de las


instrucciones.

Para ello la arquitectura de von Neumann propone que la misma cuente con los
siguientes elementos básicos:

- Unidad Aritmética-Lógica (ALU): circuito lógico que implementa operaciones


de aritmética binaria (típicamente la operaciones básicas para representaciones
"binario" y "complemento a 2" y lógicas (típicamente AND, OR, EXOR y NOT bit
a bit). También es habitual que implemente operaciones de desplazamiento y/o
rotación de bits.
- Unidad de Control: circuito secuencial que implementa el denominado "ciclo de
instrucción", permitiendo acceder a la siguiente instrucción de un programa, leer
sus operandos, efectuar la operación indicada en la ALU y guardar el resultado
de la misma.
- Banco (Set / Conjunto) de Registros: una serie de posiciones especiales de
memoria, ubicadas físicamente dentro de la propia CPU, que permiten un
acceso a operandos y lugares de almacenamiento de resultados mucho más
veloz que si estuvieran en el sistema de memoria normal. Algunos de estos
registros son de uso interno de la propia CPU (más precisamente de su Unidad
de Control) y otros son accesibles y utilizables por el programador.

Notemos que el Banco (Set / Conjunto) de Registros no es un elemento esencial de


la arquitectura. Es un elemento de carácter tecnológico que tiene que ver con dos aspectos:
- - por razones vinculadas a la electrónica, la velocidad de transferencia de
información entre dos circuitos está limitada por la distancia geográfica entre los
mismos
- la memoria rápida (usada en los pocos registros de la CPU) es más cara que la
memoria más lenta (usada en las mucho más abundantes posiciones del
sistema de memoria principal).

De allí que se utilice poca memoria rápida (por el costo) y que se ubique en las
cercanías de donde se va a utilizar (dentro de la CPU) para minimizar su tiempo de acceso.

13.3 Caracterización de una Arquitectura von Neumann

Como ya expresamos todas las computadoras actuales tienen en esencia la misma


arquitectura. Sin embargo dentro de la idea general de von Neumann que todas respetan,
se diferencian entre sí por decisiones de diseño que afectan la cantidad y cualidad de sus
elementos componentes.

Así una arquitectura particular (ej: Intel x86, PowerPC, SPARC, MIPS, etc) establece
en forma diferenciada los siguientes elementos característicos, los que deben ser
conocidos por los programadores "de bajo nivel" para poder escribir programas para una de
esas arquitecturas:

- Set de Instrucciones: la cantidad de instrucciones disponibles y la calidad y


complejidad de las operaciones implementadas en el hardware de la CPU.
- Formato de Instrucción: la forma en que se codifican las instrucciones.
- Set de Registros: la cantidad de registros disponibles al programador, así como
la función que pueden cumplir (ej: origen o destino de operaciones,
almacenamiento de direcciones de operandos).

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

- Modos de Direccionamiento: formas de generar las direcciones para hallar los


operandos o almacenar los resultados de las operaciones.
- Manejo de la Entrada/Salida: forma de comunicación con los "periféricos"
(dispositivos que implementan la interacción con el mundo exterior).
- Manejo de Interrupciones: manejo de una forma particular de invocar a ciertas
sub-rutinas de los programas que estudiaremos mas adelante.

13.3.1 Set de Instrucciones


Históricamente desde la EDVAC hasta principios de la década del 80 la tendencia
fue ir, progresivamente, aumentando la cantidad de instrucciones disponibles en el
hardware y su complejidad. Es así que las arquitecturas más difundidas a fines de los 70
(Intel 8080, Motorola 6800, Digital VAX, IBM 370) disponían de cientos de instrucciones y
soportaban por hardware operaciones complejas tales como la comparación de strings y la
búsqueda de un elemento en un array.
En ese momento se pensaba que cuanto más "potente" era el hardware (en cuanto
a la variedad de operaciones disponibles), más eficientemente se podrían ejecutar los
programas, logrando una mayor "performance" del sistema.

Sin embargo en 1980 se publicaron, casi simultáneamente, trabajos de investigación


de las universidades de Berkeley y Stanford (ambas en California, EE.UU.) que proponían
un enfoque radicalmente distinto: lo mejor era disponer de un conjunto mínimo de
instrucciones que estuvieran implementadas en forma óptima. Estos trabajos acuñaron el
término RISC (Reduced Instruction Set Computer) para referirse a los diseños basados en
este concepto. A partir de ese momento el resto de las arquitecturas pasaron a
denominarse, por contraposición, CISC (Complex Instruction Set Computer).
Durante muchos meses corrieron ríos de tinta en publicaciones de todo tipo
discutiendo cuáles arquitecturas eran mejor: si las basadas en la filosofía RISC o las CISC.
La historia de esta batalla "tecnológica" tiene aspectos muy interesantes y un resultado
doblemente paradójico: si bien las primeras implementaciones prácticas de RISC
(incluyendo un chip diseñado por un grupo de estudiantes de Berkeley) demostraron que
las RISC eran mucho mas eficientes (considerando su desempeño en relación con la
frecuencia del reloj utilizado), el mercado siguió siendo de las CISC, en particular de la que
se convirtió en un estándar de facto: la arquitectura x86 de Intel (la de los actuales
procesadores “Pentium” y “Core”). La segunda paradoja es que para lograr los niveles
actuales de desempeño, Intel debió incorporar conceptos de RISC en su diseño. Hoy se
puede decir que un procesador Pentium es, en el fondo, una máquina RISC que ejecuta un
conjunto de "micro-rutinas" que "emulan" las instrucciones de una máquina de arquitectura
x86.

13.3.2 Formato de Instrucciones


El formato de las instrucciones refiere a la codificación de las distintas instrucciones
para su almacenamiento en la memoria del sistema.

Al igual que para los demás tipos de datos manipulados que vimos (caracteres,
números) los computadores trabajan con una representación de las instrucciones mediante
un código binario.
El código binario reserva una serie de bits para identificar la operación realizada por
la instrucción, otros indican los operandos a utilizar y sus direcciones, así como la
indicación de dónde se almacena el resultado.

Los atributos que definen el formato de las instrucciones incluyen aspectos tales
como si los códigos binarios asociados son de largo fijo o variable y si las instrucciones
tienen operandos y destino independientes (en cuyo caso se habla de "arquitectura de 3
direcciones") ó solapados (correspondiente a "arquitectura de 2 direcciones").

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Las arquitecturas RISC promocionaron la utilización de formatos de instrucción de


largo fijo, como forma de simplificar la circuitería de decodificación y permitir la utilización
eficaz de técnicas de optimización (pipeline, superescalaridad) que se verán más adelante.
Las arquitecturas CISC normalmente tienen instrucciones de largo variable.
Las arquitecturas RISC también utilizan formatos de “3 direcciones”, mientras que
en las CISC es más común encontrar implementaciones de “2 direcciones” (como es el
caso de Intel x86).

13.3.3 Set de Registros


Los registros son, como mencionamos, posiciones "especializadas" de memoria,
ubicadas dentro de la propia CPU y que poseen una manera de direccionarlas distinta de la
memoria "normal" del sistema.
Los primeros diseños siguieron el ejemplo de la EDVAC de von Neumann y
utilizaron registros "con personalidad". En la propuesta original de von Neumann la
computadora poseía, entre otros, un registro Acumulador para las operaciones aritméticas,
un registro Contador para operaciones que implicaran contar y un registro Indice para ser
utilizado para contener direcciones de operandos en memoria. Esas ideas son las que
llevaron a Intel a nombrar los registros de su primer microprocesador 8080 con letras: A
(Acumulador), B (Base, para direcciones), C (Contador, en instrucciones de string), D
(Data, para almacenar datos, es decir operandos en general) y así sucesivamente. Luego la
arquitectura x86 de 16 bits tomó esos nombres y le agregó una X (de eXtended, en
referencia a que pasaron de ser de 8 bits a 16 bits), quedando AX, BX, CX y DX, a los que
se agregaron SI (Source Index) y DI (Destination Index) entre otros.
La característica de los registros "con personalidad" es que su función dentro de las
instrucciones (como operandos fuente, operandos destino, contadores o parte del
direccionamiento de los operandos) está condicionada y no todos sirven para cualquier
función. Su aplicabilidad es restringida y específica.

Las arquitecturas RISC promovieron desde el comienzo el uso de registros


"despersonalizados", de uso general, aplicables todos y cada uno a cualquiera de las
funciones antedichas. Intel incorporó la idea a partir del procesador 80386, primer
representante de 32 bits de su familia arquitectónica. Los registros de 32 bits de la
arquitectura x86 se denominan EAX, EBX, ECX, EDX, ESI, EDI, etc (la "E" significa
"Enhanced") y pueden intercambiarse casi completamente en su uso en las instrucciones.

13.3.4 Modos de Direccionamiento


Los modos de direccionamiento establecen las formas en que se puede, a nivel de
las instrucciones, especificar la dirección de un operando o del lugar donde colocar el
resultado de la operación correspondiente a la instrucción.

Existen tres modos de direccionamiento básicos: Inmediato, Directo e Indirecto. A


continuación presentaremos las características de cada uno:

- Inmediato: en este modo en la instrucción se encuentra el propio operando (su


valor). Se utiliza típicamente para constantes (ya que las instrucciones no se
pueden modificar).
- Directo: en este modo en la instrucción se encuentra la dirección del operando.
Se pueden distinguir dos tipos:
- Directo a Registro: el operando está almacenado en un registro y la
instrucción contiene el identificador del registro
- Directo a Memoria: el operando está almacenado en memoria y la instrucción
contiene la dirección donde se encuentra
- Indirecto: en este modo en la instrucción se encuentra la dirección del lugar

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

donde se encuentra la dirección del operando. También se pueden distinguir dos


tipos:
- Indirecto por Registro: el operando está almacenado en una posición de
memoria cuya dirección se encuentra en un registro y la instrucción contiene
el identificador del registro. De los dos tipos de indirecto éste es el
habitualmente implementado, utilizando mas de un registro (sumando sus
contenidos) para formar la dirección. En algunos casos la arquitectura prevé
multiplicar el contenido del registro por el tamaño en bytes del operando. En
ese caso se habla de direccionamiento indizado.
- Indirecto por Memoria: el operando está almacenado en una posición de
memoria cuya dirección está en otra posición de memoria y la instrucción
contiene la dirección de esta última. Esta variante no es implementada en las
arquitecturas prácticas disponibles.

Los modos Directo e Indirecto (especialmente en su modalidad Indizado) se suelen


combinar para establecer la dirección de un operando o de un destino. La dirección se
forma sumando el contenido de uno o mas registros identificados en la instrucción con la
"dirección base" contenida en la misma. Esto permite implementar fácilmente el acceso a
estructuras tipo array. Se coloca la dirección de comienzo de la estructura en la instrucción
(modo directo) y se cambia el contenido de un registro "índice" (que también debe estar
referenciado en la instrucción) para ir recorriendo el array haciendo un "loop" y reutilizando
la misma instrucción.

13.3.5 Manejo de Entrada/Salida


Más adelante veremos un capítulo completo dedicado a este tema. Por ahora
interesa marcar que las distintas arquitecturas se distinguen en este punto básicamente por
el hecho de tener o no instrucciones específicas, con su propio espacio de
direccionamiento, para la comunicación con los dispositivos que permiten la interacción con
el "mundo exterior".

13.3.6 Manejo de Interrupciones


Nos referiremos a este tema en un capítulo específico.

13.4 Arquitectura Harvard

La arquitectura Harvard se caracteriza porque existen, a diferencia de la von


Neumann, dos unidades de memoria separadas: una para los datos y otra para las
instrucciones:

MEM
DATOS
E/S CPU
MEM
PROG

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

Muchas veces se presenta la arquitectura Harvard como algo diferente de la


arquitectura von Neumann. Sin embargo en el fondo no cambia la esencia de la von
Neumann: siguen existiendo “programas” formados por una secuencia lógica de
“instrucciones” las que son ejecutadas por una “CPU”.

Actualmente muchos procesadores implementan una arquitectura Harvard


modificada, que consiste en mantener ciertos caminos separados y paralelos para acceder
a las instrucciones en forma simultánea con los datos, pero permitiendo que los datos y las
instrucciones están almacenados en una memoria común. Los detalles de estas
implementaciones se verán más adelante en el curso.

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Organización del CPU

Arquitectura de Computadoras
(Versión 4.3a - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

14 ORGANIZACIÓN DE LA UNIDAD CENTRAL DE PROCESO (CPU)

14.1 Introducción

En este capítulo veremos un posible diseño interno de una unidad central de


proceso de una arquitectura de von Neumann, incluyendo sus variaciones de "lógica
cableada" y "lógica microprogramada".

Presentaremos como ejemplo la organización del procesador de la arquitectura


MIC-1, desarrollada por Andrew S. Tanenbaum con fines didácticos en su libro Structured
Computer Organization (Organización de Computadoras, un Enfoque Estructurado), en
particular para su 3ra Edición.

14.2 Componentes Básicos de la CPU

Como ya dijimos antes una CPU (Centrol Processor Unit) está conformada por tres
sub-sistemas fundamentales: la ALU (Arithmetic Logic Unit, Unidad Aritmética y Lógica), la
CU (Control Unit, Unidad de Control) y el Register Set (también denominado Register Bank)
ó sea Conjunto (o Banco) de Registros.

ALU

Banco de
Registros

Unidad
de
Control

El Banco de Registros contiene registros de tres categorías desde el punto de vista


de su función en relación con los programas y el funcionamiento interno de la CPU:
- Totalmente visibles: estos son los ya mencionados registros de uso general ó
personalizados que contienen operandos o direcciones para su utilización en las
instrucciones. El programador de “bajo nivel” los manipula directamente en los
programas.
- Parcialmente visibles: son registros que tienen funciones especiales pero
participan de algún modo indirecto en las instrucciones. El programador los
manipula indirectamente en determinadas instrucciones específicas. Ejemplos
de este tipo de registros son el IP (Instruction Pointer), también denominado PC
(Program Counter) que contiene la dirección de la próxima instrucción a
ejecutarse (en algunas arquitecturas almacena la dirección de la que se está
ejecutando en este momento), el SP (Stack Pointer) que contiene el puntero al
primer lugar de la pila en las arquitecturas “de stack” y el PS (Processor Status)
también denominado registro de FLAGS (en el caso de Intel) que contiene el
estado del procesador incluyendo el valor que tomaron los bits de condición
(Negative, Zero, Carry, Overflow) en función del resultado de la última operación
realizada por la ALU.
- Internos: son registros que utiliza la Unidad de Control de la CPU para poder

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

ejecutar las instrucciones. Almacenan constantes, el estado de la CU, la


instrucción en ejecución (su código binario), resultados intermedios de cálculos
de direcciones, etc. No son visibles de ninguna manera al programador.

La Unidad de Control es, en definitiva, una máquina secuencial que realiza el “ciclo
de instrucción”: conjunto de acciones ordenado y secuencial que interconectan
adecuadamente los distintos elementos en el tiempo, para lograr el objetivo de ejecutar la
instrucción realizando la operación indicada sobre los operandos correspondientes y
almacenando el resultado en el lugar indicado. Esta máquina secuencial funciona
sincronizada por un reloj, el cual también es utilizado para sincronizar todas las actividades
de los otros elementos del sistema (memoria y entrada/salida). En las primeras
computadoras el reloj era el mismo para todos los elementos. Últimamente se utilizan
relojes independientes (aunque vinculados) para cada sub-sistema. En muchos diseños se
utilizan más de un reloj para la CPU, con la misma frecuencia, pero desfasados (0º, 90º,
180º y 270º, por ejemplo) a los efectos de ser utilizados para sincronizar distintas partes del
circuito compensando los diferentes retardos de propagación de las señales en los circuitos
internos de la CPU.

La Unidad Aritmética y Lógica es un conjunto de circuitos (típicamente


combinatorios) que implementan un conjunto de operaciones, que incluyen suma y resta
(en aritmética complemento a 2), operaciones lógicas bit a bit (AND, OR, EXOR, NOT) y
operaciones de desplazamiento (shift). Las ALUs más avanzadas incluyen operaciones de
multiplicación y división (aunque en este caso se implementan como una máquina
secuencial que implementa algún algoritmo para estas operaciones).

14.3 Ciclo de Instrucción

Se denomina ciclo de instrucción a la secuencia de acciones que realiza la CPU


(más específicamente la Unidad de Control) para lograr ejecutar una instrucción del
programa almacenado en memoria.

Un ciclo de instrucción típico tiene 5 pasos característicos:


- Fetch: este paso consiste en leer la próxima instrucción a ejecutarse desde la
memoria.
- Decode: en este paso se analiza el código binario de la instrucción para
determinar qué se debe realizar (cuál operación, con qué operandos y donde
guardar el resultado)
- Read: en este paso se accede a memoria para traer los operandos
- Execute: es la ejecución de la operación por parte de la ALU sobre los
operandos
- Write: en el último paso se escribe el resultado en el destino indicado en la
instrucción.

Notemos que no todas las instrucciones requieren de todos los pasos indicados
para su ejecución. Por ejemplo las instrucciones que tienen sus operandos en registros, no
requieren del paso “read”, mientras que las que no guardan un resultado no requieren del
paso “write”.

Para realizar estos pasos la unidad de control maneja un conjunto de señales de


control interno a la CPU y otras de control externo (en la interfaz con la memoria y con el
sistema de entrada/salida), las que habilitan las conexiones apropiadas entre los distintos
elementos de forma que el respectivo paso del ciclo se cumpla. Por ejemplo: para hacer el
“fetch” conecta el bus de direcciones de memoria con el registro PC (que contiene la
dirección de la próxima instrucción a ejecutarse), conecta el bus de datos de memoria con

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

el registro interno IR (Instruction Register) y coloca en el bus de control de la memoria las


señales apropiadas para realizar una lectura.

14.4 Estructura de la CPU

En el siguiente diagrama se muestra la estructura de una CPU MIC-1.

A0, A1, A2, A3


B0, B1, B2, B3
C0, C1, C2, C3 ENC

Bus C Bus A Bus B

PC

AC

SP

IR

TIR

+1

-1

AMASK

SMASK

M0
F
Bus Direcciones
L0 A Latch B Latch L1

MAR

MBR

Bus Datos X0 A Mux

RD M1, M2, M3

N
F0, F1 Z
WR ALU

S0, S1 Shifter

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

En esta propuesta de organización interna se dispone de los siguientes recursos (es


una arquitectura de 16 bits):

• Registro PC: contiene el puntero de instrucción (“Program Counter”)


• Registro AC: es el registro ACumulador
• Registro SP: contiene el puntero a la pila (“Stack Pointer”)
• Registro IR: almacena la instrucción leída desde memoria
• Registro TIR: almacena temporalmente copias de la instrucción
• Registro 0: contiene la constante 0
• Regsitro +1: contiene la constante 1 (positiva)
• Registro -1: contiene la constante -1 (negativa en complemento a 2)
• Registros AMASK: contiene el valor binario 0000111111111111 (0x0fff)
• Registros SMASK: 000000001111111 (0x00ff)
• Registros A a F: para uso interno de la Unidad de Control
• Registro MAR (Memory Address Register): almacena la dirección de memoria
que se presenta en el bus de direcciones de la memoria durante una operación
de lectura o escritura de la misma.
• Registro MBR (Memory Buffer Register): almacena el dato leído de la memoria
(en una operación de lectura) o el dato a escribir en la memoria (durante una
operación de escritura).
• AMux: multiplexor que elige entre dos entradas posibles.
• ALU: Unidad Aritmética y Lógica, capaz de ejecutar 4 operaciones: suma A+B, A
and B identidad A (la salida es igual a su entrada A), not A.
• Shifter: unidad encargada de realizar la operación de desplazamiento: 0 bit (no
desplaza nada), 1 bit a la derecha, 1 bit a la izquierda.
• ALatch/BLatch: son registros intermedios utilizados para simplificar los aspectos
de sincronismo de las señales, requeridos porque el diseño original de
Tanenbaum prevé la construcción del banco de registros con Flip-Flops
asíncronos (un diseño basado en FF con reloj por flanco podría evitar el uso de
estos registros intermedios).

Notas:
- La interfaz con la memoria y la E/S se realiza a través del bus de datos, el bus
de direcciones y el bus de control (formado por las señales RD y WR).
- Los registros, la ALU y la unidad de Shift son de 16 bits de tamaño de palabra.
- La unidad de desplazamiento no siempre se explicita como en el ejemplo ya que
se puede considerar que forma parte de la ALU.
- Normalmente las ALUs calculan también las salidas C (Carry) y V (oVerflow).
- Los valores de las constantes de los distintos registros está vinculada con las
necesidades de la “macroarquitectura” asociada a la MIC-1 y no constituyen un
requisito en otras microarquitecturas.
- Tener presente que este es tan solo un ejemplo de cómo se puede construir
internamente una CPU y ni siquiera es uno que pueda considerarse óptimo.

Por razones de simplicidad se ha omitido dibujar la Unidad de Control en el


diagrama anterior. Esta es, como dijimos, una máquina secuencial. Las salidas de este
circuito secuencial son todas las señales de control indicadas en el diagrama, que actúan
sobre los distintos recursos internos y el bus de control externo de manera de completar los
distintos pasos del ciclo de instrucción visto.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Las funciones que cumplirían las distintas señales de control son:

- A3, A2, A1, A0: seleccionan un registro y conectan su salida al bus A (ej:
0000/PC, 0001/AC, 0010/SP, 0010/IR, 0100/TIR, 0101/0, 0110/+1, 0111/-1,
1000/AMASK, 1001/SMASK, 1010/A, 1011/B … 1111/F)
- B3, B2, B1, B0: seleccionan un registro y conectan su salida al bus B (ej: idem a
la codificación para A)
- C3, C2, C1, C0: seleccionan un registro y conectan su entrada al bus C (ej: idem
a la codificación para A)
- ENC: habilita el bus C para que se guarde el valor en el registro seleccionado
- X0: selecciona si conecta a su salida la entrada que viene desde el MBR o
desde el bus A (ej: 0 – MBR, 1 – Bus A)
- F1, F0: codifican la operación a realizar por la ALU (ej: 00 – A+B, 01 – A and B,
10 – A, 11 – not A)
- S1, S0: codifican la operación de desplazamiento (ej: 00 – no desplaza, 01 – un
bit a la derecha, 10 – un bit a la izquierda)
- L1, L0: controlan la carga de los registros intermedios del bus B y el bus A
respectivamente.
- M0: controla la carga en el MAR (ej: 1 – carga)
- M1, M2, M3: controlan la forma que se cargan los datos en el MBR, cuando y
desde donde se produce. M1 activa la carga (ej: 1 – carga). M2 es la señal de
lectura de memoria RD (ej: 1 – lee la memoria). M3 es la señal de escritura de
memoria (eg: 1 – escribe la memorias).

Veamos como manejaría la Unidad de Control estas señales de control para lograr
ejecutar el ciclo de instrucción. Consideremos el ejemplo en el que se va a ejecutar una
suma entre un operando en memoria y el acumulador, con modo de direccionamiento
directo (la dirección está en los últimos 12 bits de la instrucción).

El primer paso es el fetch. Para leer la instrucción de memoria se debe cargar el


contenido del registro PC en el MAR, realizar una operación de lectura desde memoria y se
debe conectar el bus de datos con el registro IR, de forma de cargar en él la instrucción.
Para ello hay que:
- conectar la salida del registro PC al bus B (B3 = 0, B2 = 0, B1 = 0, B0 = 0)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar cargar MAR (M0 = 1)
- seleccionar cargar el MBR (M1 = 1)
- seleccionar lectura de memoria (M2 = 1)
- seleccionar MBR en el AMux (X0 = 0)
- seleccionar la operación identidad-A en la ALU (F1 = 1, F0 = 0)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro IR al bus C (C3 = 0, C2 = 0, C1 = 1, C0 = 0)
- habilitar el bus C (ENC = 1)

Al colocar todas estas señales en los valores indicados se procederá a la lectura de


la instrucción contenida en la posición PC de la memoria. Notemos que de acuerdo a los
tiempos de acceso de la memoria se pueden llegar a necesitar mantener las señales por
más de un ciclo de reloj a los efectos de tener en cuenta las latencias (tiempos de
propagación) de la circuitería involucrada.
Para completar el paso de fetch es necesario actualizar el valor de PC, para lo que
se requiere las siguientes señales (en el siguiente ciclo de reloj):
- conectar la salida del registro PC al bus B (B3 = 0, B2 = 0, B1 = 0, B0 = 0)
- conectar la salida del registro +1 al bus A (A3 = 0, A2 = 1, A1 = 1, A0 = 0)
- seleccionar cargar el ALatch (L1 = 1)

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

- seleccionar cargar el BLatch (L0 = 1)


- seleccionar Bus A en el A Mux (X0 = 1)
- seleccionar A + B en la ALU (F1 = 0, F0 = 0)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro PC al bus C (C3 = 0, C2 = 0, C1 = 0, C0 = 0)
- habilitar bus C (ENC = 1)

El siguiente paso del ciclo de instrucción es el decode. La decodificación se realiza


analizando el código binario de la instrucción. Para ello se implementa en la CU una función
mediante un circuito combinatorio que toma como entrada el contenido del IR y da como
salida los valores apropiados de las señales de control, condicionando también el próximo
estado de la máquina secuencial, como en el caso del ejemplo ya que al reconocer el modo
de direccionamiento directo debe realizarse el paso de read.

Para realizar el paso de read se debe cargar la dirección del operando (contenida en
los últimos 12 bits de la instrucción) en el MAR, para luego realizar una operación de lectura
desde memoria, cargando el MBR desde el bus de datos, de forma de almacenar en él el
operando. Para ello hay que:
- conectar la salida del registro IR al bus B (B3 = 0, B2 = 0, B1 = 1, B0 = 0)
- conectar la salida del registro AMASK al bus A (A3 = 1, A2 = 0, A1 = 0, A0 = 0)
- seleccionar cargar el ALatch (L1 = 1)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar Bus A en el A Mux (X0 = 1)
- seleccionar A and B en la ALU (F1 = 0, F0 = 1)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro A al bus C (C3 = 1, C2 = 0, C1 = 1, C0 = 0)
- habilitar bus C (ENC = 1)
con estas señales y sincronizado por el reloj se guarda la dirección contenida en la
instrucción en el registro A. A continuación (próximo ciclo de reloj) se colocan las señales:
- conectar la salida del registro A al bus B (B3 = 1, B2 = 0, B1 = 1, B0 = 0)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar cargar MAR (M0 = 1)
- seleccionar cargar el MBR (M1 = 1)
- seleccionar lectura de memoria (M2 = 1)

En el paso siguiente se realiza el execute. Para ello se deben activar las siguientes
señales:
- conectar la salida del registro AC al bus B (B3 = 0, B2 = 0, B1 = 0, B0 =1)
- seleccionar cargar el BLatch (L0 = 1)
- seleccionar MBR en el A Mux (X0 = 0)
- seleccionar la operación A + B en la ALU (F0 = 0, F1 = 0)
- seleccionar no desplazamiento en el Shifter (S0 = 0, S1 = 0)
- conectar la entrada del registro AC al bus C (C0 = 1, C1 = 1, C2 = 0, C3 =1)
- habilitar bus C (ENC = 1)

Sincronizado por el reloj se realiza la operación en la ALU y se guarda el resultado en el


registro AC.

Cabe destacar que al ser una instrucción cuyo resultado se almacena en un registro,
no corresponde que exista un paso de write.

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

14.5 Lógica Cableada vs Lógica Microprogramada

Hay dos filosofías de diseño claramente diferenciadas para la Unidad de


Control: la “lógica cableada” y la “lógica microprogramada”.

El diseño de la CU en base a la filosofía de “lógica cableada” se hace como


cualquier circuito secuencial: en base a un diagrama de estados (que contemple todas las
situaciones posibles y por tanto todos los estados posibles en función de las distintas
instrucciones y sus variantes) traduciéndola a una máquina de Mealy (por ej.). Para el
ejemplo anterior deberíamos tomar como salidas todas las señales de control necesarias y
como entradas los bits del código binario de las instrucciones.
En este caso el resultado es óptimo desde el punto de vista de la velocidad de los
circuitos, pero tiene poca flexibilidad ya que cualquier cambio en el diseño del set de
instrucciones de la CPU genera la necesidad de re-escribir el diagrama de estados y, por
ende, cambiar todo el circuito lógico que lo implementa.

En cambio la filosofía de “lógica microprogramada” propone que la CU se construya


en base a un autómata más sencillo que “ejecute” el ciclo de instrucción de cada instrucción
de la CPU siguiendo en secuencia un conjunto de “microinstrucciones” que contienen los
valores de las señales apropiados para esa instrucción particular. Es decir que para cada
instrucción a nivel de la CPU existirá un “microprograma”, consistente en una secuencia
lógica de microinstrucciones que establecerán el orden de los eventos necesarios para
lograr la ejecución de la instrucción en la CPU, incluyendo todas las “bifurcaciones” de la
secuencia que se requieran en base a los distintos tipos de direccionamiento y cualquier
otra variante que admita la instrucción específica. En este caso hay una penalización en la
velocidad de proceso porque el microprograma se almacena en una ROM interna de la
CPU y cada microinstrucción debe ser leída de ella, pero simplifica enormemente la tarea
de modificar el set de instrucciones, ya que simplemente alcanza con cambiar el contenido
de la ROM del microprograma. También las máquinas microprogramadas permiten
fácilmente implementar instrucciones complejas, tales como la búsqueda de un elemento
en un array, ó la copia o la comparación de arrays, etc.

La tendencia en materia de diseño de CPUs era, hasta la década de 1980, utilizar


lógica microprogramada. La aparición de las arquitecturas RISCs puso en cuestión esa
tendencia, ya que dichas propuestas promovían el uso de lógica cableada, en particular
asociado al concepto de optimizar la velocidad de proceso. De todos modos es probable
que la ventaja que esos diseños obtuvieron en materia de rendimiento se deba
principalmente al uso óptimo de técnicas tales como el “pipelining” (que se verá más
adelante) permitido por las características de su set de instrucciones. El punto es que si se
usa un set “reducido” con fines de optimización, también resulta más sencillo implementar
la CPU en “lógica cableada”.

14.6 Microprogramación Horizontal y Vertical

Si quisiéramos implementar en microcódigo (microprogramación) la Unidad de


Control del ejemplo tendríamos que cada microinstrucción debería contener los bits
codificados de las señales de control de lo distintos caminos de las señales de datos, como
ocurre con el acceso al banco de registros. Este es uno de los enfoques posibles y de
hecho tiene la ventaja de reducir la cantidad de bits necesarios para codificar cada
microinstrucción. Recibe el nombre de microprogramación vertical.

Por el contrario la microprogramación horizontal utiliza microinstrucciones con los


bits de control sin codificar. Para el caso del ejemplo se requerirían 16 bits de control para

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

cada bus (1 bit para cada uno de los registros) en vez de los 4 utilizados en forma
codificada.

La microprogramación vertical supone que determinados conjuntos de recursos solo


pueden ser utilizados de a uno por vez en cada función y de allí que pueden ser
codificados. Esto permite ahorrar bits (y por tanto espacio en la ROM de microprograma),
pero queda firme esa restricción que puede ser perjudicial a la hora de generar altos niveles
de paralelismo, en especial en arquitecturas más complejas que la del ejemplo.

14.7 Microinstrucciones

La microarquitectura MIC-1 que hemos tomado como ejemplo propone una


implementación mediante microprogramación. Para ello cuenta con una ROM para
microprogramas (denominada “Control Store”), interna a la CPU, que permite almacenar un
total de 256 microinstrucciones. Cada microinstrucción es codificada con un código binario
de 32 bits.

Cada microinstrucción deberá tener bits disponibles para indicar los valores (0/1) de
las señales que controlan los distintos elementos, a saber:
4 bits para control de bus A
4 bits para control de bus B
4 bits para control de bus C
1 bit para habilitar el bus C
2 bits para control de latches de bus
2 bits para control de la ALU
2 bits para control del Shifter
1 bit para control de AMux
1 bit para control del MAR
3 bits para control del MBR

El control de los latches en realidad es necesario en prácticamente todos los casos,


por lo que se lo realizará directamente mediante el reloj, con lo que se requieren 22
señales. Dado que se utilizan 32 bits para codificar las microinstrucciones, los restantes 10
bits se utilizan para manejar la secuenciación del microprograma, como se explicará a
continuación. Antes veamos el formato de las microinstrucciones:

Para secuenciar las microinstrucciones del microprograma se procede de la siguiente


manera. En función de lo que esté codificado en los bits COND la siguiente microinstrucción
será:
00: la ubicada a continuación en la memoria ROM de microprograma
01: si la salida N de la ALU es 1 la ubicada en la dirección de la ROM ADDR
10: si la salida Z de la ALU es 1 la ubicada en la dirección de la ROM ADDR
11: siempre la ubicada en la dirección de la ROM ADDR

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

14.8 Unidad de Control Microprogramada

En general una implementación de una unidad de control microprogramada dispone


de una ROM para almacenar las microinstrucciones de los microprogramas que
implementan el ciclo de instrucción de las instrucciones de la CPU, y de una máquina
secuencial que ejecuta la secuenciación de las microinstrucciones de acuerdo a la lógica
que se haya codificado.
El esquema general es:

La implementación de MIC-1 utiliza para su sincronismo interno la técnica de relojes


desfasados, que son señales de reloj obtenidas de un reloj “padre” mediante la utilización
de “líneas de retardo” (dispositivos electrónicos que provocan un cierto retraso en la
propagación de la señal):

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

Incorporando la parte de sincronismo y los elementos de la unidad de control


microprogramada al esquema de la MIC-1, ésta queda:

Los elementos de la unidad de control microprogramada de la MIC-1 son:


- MPC (Micro Program Counter): es un registro que almacena la dirección (8 bits)
de la microinstrucción que se va a ejecutar
- Increment: circuito combinatorio que suma uno
- Mmux: es un multiplexor que selecciona entre la salida del Increment y los
últimos 8 bits del MIR para determinar la dirección de la ROM
- Control Store: memoria ROM de 256 palabras de 32 bits donde se almacenan
las microinstrucciones
- MIR (Micro Instruction Register): registro que almacena la microinstrucción leída
desde la Control Store y desde el cuál se conectan las distintas señales de
control al resto de los elementos de la microarquitectura

Notar que este diseño no responde estrictamente al esquema general presentado,


porque busca la máxima simplicidad en su implementación. Esto lleva a realizar la
decodificación en base a operaciones realizadas por la ALU (como se verá más adelante).
Esto no es lo habitual en diseños comerciales de unidades de control.

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

14.9 Micro Ensamblador

Un microprograma será una colección de códigos binarios que representen a las


microinstrucciones necesarias para controlar las señales deseadas.

Por ejemplo:
AMUX
COND

ADDR
ALU

MBR
MAR

ENC
SH

RD
WR

A
0 00 10 00 0 1 1 0 0 0000 0000 0000 00000000 0x10c00000
0 00 10 00 0 0 1 0 0 0000 0000 0000 00000000 0x10400000
1 00 10 00 0 0 0 0 1 0011 0000 0000 00000000 0x90130000
0 00 00 00 0 0 0 0 1 0000 0110 0000 00000000 0x00106000

Al igual que para el caso de las instrucciones, “programar” en códigos binarios es un


tanto engorroso. Por eso se desarrollan lenguajes “ensambladores” que permiten utilizar
una nomenclatura bastante más amigable para representar las microinstrucciones.

Para el caso veremos el MAL (Micro Assembler Language) propuesto por


Tanenbaum para su MIC-1.

Este micro-ensamblador tiene una notación basada en identificar en cada


“sentencia” a todas las señales que deben estar en 1 (no aparecen las que van en 0). Para
señalar las asignaciones de los buses A, B y C usa una notación similar a la asignación
utilizada en los lenguajes de alto nivel como el Pascal.
Así por ejemplo:
ac:=d
indica que se desea copiar el contenido del registro D en el AC, para lo cual el bus C se
conecta al registro AC, se activa ENC, el registro D se conecta al bus A, la ALU realiza la
función identidad y el Shifter no desplaza.
La codificación de esta microinstrucción sería:
AMUX
COND

ADDR
ALU

MBR
MAR

ENC
SH

RD
WR

0 00 10 00 0 0 0 0 1 0000 0000 1101 00000000 0x10100d00

Las cuatro operaciones de la ALU se representan así (los registros usados son a
modo de ejemplo):
ac:=ac + d ac:=band(ir, smask) f:=ac c:=inv(a)
los registros destino pueden ser cualquiera (incluyendo el MAR y el MBR), pero el MAR no
puede ser operando.

Las dos operaciones efectivas de la unidad de desplazamiento se representan así:


lshift(ac) rshift(ir)

Las operaciones de desplazamiento también aceptan como argumento una


operación de ALU:
lshift(tir + tir)
(por ejemplo la microinstrucción anterior hace un shift de dos bits a la izquierda)

La activación de las señales RD y WR se realiza colocando rd ó wr en la expresión.

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

La secuenciación de las microinstrucciones se realiza mediante la expresión:


if n then goto XXXX if z then goto XXXX
donde XXXX es la dirección (de 8 bits) de la memoria ROM donde se almacena la
microinstrucción del microprograma a la que se quiere ir (se puede asumir que es el
“numero” de la microinstrucción si se asume que la primera es la de número 0).

Las distintas expresiones pueden ser combinadas en una misma microinstrucción (la
misma “sentencia”):
tir:=lshift(tir + tir); if n then goto 33
el efecto de esta microinstrucción es guardar en el registro TIR el resultado de realizar un
desplazamiento a la izquierda de 2 bits del propio registro TIR y saltar a la microinstrucción
33 si es que el segundo bit más significativo del valor original del TIR es 1 (notar que la
ALU hace solo la suma que representa el desplazamiento a la izquierda de un bit y por
tanto allí el bit más significativo del resultado es el segundo bit más significativo del
original).

Hay un caso particular de sentencias, donde solo nos interesa determinar un salto
en alguna condición de los bits de un registro, pero no queremos asignarlo a ningún otro
registro. Para ese caso se dispone del “registro virtual” denominado “alu”, que se usa así:
alu:=lshift(tir + tir); if n then goto 33
en este caso el resultado de la operación sobre TIR no afecta a ningún registro, pero la
ALU actúa y computa el valor de la salida N según el resultado de la operación.

Por ejemplo: las codificaciones del primer ejemplo mostrado corresponden a las
siguientes microinstrucciones:
mar:=pc; rd
rd
ir:=mbr
pc:=pc + 1
secuencia que analizada implica que el registro PC (Program Counter) se carga en el MAR
y se activa la señal RD para realizar una lectura de memoria. Luego en la segunda
microinstrucción se mantiene RD activa (esto es porque se está asumiendo que la lectura
de la memoria demora dos ciclos de reloj). La siguiente microinstrucción mueve el
contenido del MBR (lo que fue leído de memoria) al registro IR y finalmente la última
microinstrucción le suma uno al PC. No es difícil identificar esta sucesión de eventos con la
etapa de fetch del ciclo instrucción.

14.10 Microprograma de la MIC-1

En una máquina de estas características (microprogramada) típicamente el


microprograma siempre empieza en la dirección 0, con las microinstrucciones necesarias
para hacer el fetch. Luego siguen las requeridas para el decode. A partir del decode se
producen saltos hacia las secuencias de microinstrucciones que implementan las etapas
que sean requeridas (read, execute y write) según el tipo de instrucción y finalmente se
vuelve a la dirección 0 para comenzar un nuevo fetch.

La etapa de decode de este ejemplo de microarquitectura es bastante trabajosa, por


la escasez de recursos que su diseñador incluyó. Los recursos disponibles son los
estrictamente necesarios para implementar las instrucciones de su macroarquitectura (el
set de instrucciones), la cual recibe el nombre de MAC-1. Este conjunto de instrucciones
tiene el formato de instrucción que está representado en la siguiente tabla:

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

Tomado de “The Microarchitecture/Microprogramming Level” de la Universidad de Maryland

Notar que las instrucciones que tienen operandos directos a memoria contienen una
dirección de 12 bits. Por su lado las operaciones “insp” y “desp” usan un operando
inmediato de 8 bits. Justamente para poder manipular estos valores es que existen los
registros AMASK (máscara de 12 bits) y SMASK (máscara de 8 bits).
Tener en cuenta que esta opción de diseño del formato de instrucción condiciona la
capacidad de direccionamiento de esta CPU (un máximo de 4096 palabras de 16 bits).
También condiciona los modos de direccionamiento de los operandos (solo directo para las
operaciones aritméticas), la disponibilidad de registros (solo se dispone del AC como
registro para operaciones) y los tipos de salto (son todos absolutos).

Notar también que los códigos de operación que definen de qué instrucción se trata
están armados como un “árbol” (a medida que se avanza hacia la derecha aparecen más
opciones según los valores de los bits anteriores). Este diseño determina la forma en que
se puede hacer la decodificación (básicamente a fuerza de desplazamientos sucesivos y
verificación del valor del bit más significativo resultante), aunque la misma es realmente
poco eficiente realizada de esta forma.

En la tabla de la próxima página se puede observar un posible microprograma


completo para la implementación de la macroarquitectura MAC-1 en la microarquitectura
MIC-1.

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura de Computadoras Notas de Teórico

Tomado de “The Microarchitecture/Microprogramming Level” de la Universidad de Maryland

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


MICROPOCESADOR 8086

NOTAS DE CURSO
(Versión 2.2)

Arquitectura de Computadores Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

ÍNDICE
DIRECCIONAMIENTO DE MEMORIA............................................................................................................. 2
MODOS DE DIRECCIONAMIENTO................................................................................................................. 3
REGISTRO.......................................................................................................................................................................................3
VALOR o INMEDIATO.....................................................................................................................................................................3
DIRECTO..........................................................................................................................................................................................3
INDIRECTO......................................................................................................................................................................................3
INSTRUCCIONES............................................................................................................................................ 5
CÓDIGO.................................................................................5
ARITMÉTICAS..................................................................................................................................................................................6
ADD....................................................................................6
ADC....................................................................................6
SUB ...................................................................................6
SBB....................................................................................6
MUL....................................................................................7
DIV....................................................................................8
NEG....................................................................................9
CBW....................................................................................9
INC....................................................................................9
DEC...................................................................................10
LÓGICAS........................................................................................................................................................................................11
AND...................................................................................11
OR....................................................................................11
XOR...................................................................................11
NOT...................................................................................12
CMP...................................................................................12
DESPLAZAMIENTO.......................................................................................................................................................................13
SAL/SHL...............................................................................13
SHR...................................................................................14
SAR...................................................................................14
ROL...................................................................................15
ROR...................................................................................16
MOVIMIENTO e I/O........................................................................................................................................................................17
MOV...................................................................................17
IN....................................................................................17
OUT...................................................................................18
MANEJO DE FLAGS......................................................................................................................................................................19
CLC...................................................................................19
STC...................................................................................19
CLI...................................................................................19
STI...................................................................................20
BIFURCACIÓN INCONDICIONAL.................................................................................................................................................21
CALL..................................................................................21
JMP...................................................................................22
RET...................................................................................22
BIFURCACIÓN CONDICIONAL.....................................................................................................................................................23
JA / JNBE (no considera signo)........................................................23
JB / JNAE / JC (no considera signo)...................................................24
JNB / JAE / JNC (no considera signo)..................................................24
JBE/JNA (no considera signo)..........................................................25
JE/JZ ................................................................................25
JG/JNLE (considera signo).............................................................26
JNG/JLE (considera signo).............................................................26
JNE/JNZ...............................................................................27
JNO...................................................................................27
JNS...................................................................................28
JO....................................................................................28
JS....................................................................................29
MANEJO DE STACK......................................................................................................................................................................30
PUSH..................................................................................30
POP...................................................................................30
PUSHF.................................................................................30
POPF..................................................................................31
INTERRUPCIONES.......................................................................................................................................................................32
INT...................................................................................32
IRET..................................................................................32

Arquitectura de Computadores 1 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

DIRECCIONAMIENTO DE MEMORIA
Los registros del 8086 son de 16 bits, por lo tanto el número de direcciones posibles a
direccionar con 1 solo registro es:
216 = 6553610 = 1000016
lo cual representa un total de 64 Kbytes y los valores de direcciones se encuentran en el
rango de 0 a FFFF.
Para superar este límite se utilizan 2 registros para direccionar memoria: Uno de
SEGMENTO y otro de DESPLAZAMIENTO (offset) dentro del segmento. La notación
utilizada para una dirección segmentada es:
SEGMENTO:DESPLAZAMIENTO
La relación entre la dirección de memoria real y la dirección segmentada es:
DIR = SEGMENTO * 16 + DESPLAZAMIENTO
Al multiplicar por 16 se obtienen 4 bits más con lo que ahora se tiene:
2 20 = 104857610 = 10000016
con lo cual tenemos un total de 1024Kb = 1Mb de memoria direccionable. Los valores para
las direcciones reales se encuentran en el rango 0 a FFFFFh.
Es importante hacer notar que una misma dirección de memoria puede ser direccionada
con distintos valores de segmento y desplazamiento
Ej:
100:50 = 105:0 =0:1050, trabajando en base 16.

Arquitectura de Computadores 2 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

MODOS DE DIRECCIONAMIENTO
Se entiende por modos de direccionamiento a las diferentes formas que pueden tomar los
parámetros de las instrucciones del procesador.
Diferentes autores clasifican en forma distinta los modos de direccionamiento del 8086.
Nosotros distinguiremos fundamentalmente cuatro modos diferentes:
REGISTRO
Un parámetro que direcciona a un registro está utilizando el modo de direccionamiento
REGISTRO.
Ej: MOV Ax,Bx
En este ejemplo los dos parámetros direccionan un registro.

VALOR o INMEDIATO
El modo de direccionamiento INMEDIATO es utilizado cuando se hace referencia a un valor
constante. Este se codifica junto con la instrucción. Es decir dicho parámetro representa a su
valor y no a una dirección de memoria o un registro que lo contiene.
Ej: MOV Ax,500
En este ejemplo el número 500 es un parámetro inmediato.

DIRECTO
Se utiliza el modo directo cuando se referencia a una dirección de memoria y la misma esta
codificada junto con la instrucción.
Ej:
MOV Al,[127]
En este ejemplo el desplazamiento de la dirección de memoria se codifica junto con la
instrucción y el segmento se asume a DS.
Si MEMORIA es un array de bytes que representa a la memoria la instrucción anterior se
puede poner como:
Al := MEMORIA[ DS:127 ]

INDIRECTO
Se utiliza el modo directo cuando se referencia a una dirección de memoria a través de uno
o varios registros
Ej: MOV Al,[Bx]
Aquí el offset de la dirección de memoria está contenido en el registro Bx y al igual que el
caso anterior como no se especifica el segmento se asume DS.
Si MEMORIA es un array de bytes que representa a la memoria la instrucción anterior se
puede poner como:
Al := MEMORIA[ DS:Bx ]
La especificación completa de las expresiones que van dentro de los paréntesis rectos es:

{ Bx | Bp } [ + { Si | Di } ] [ + desplazamiento ] |
{ Si | Di } [ + desplazamiento ] |
desplazamiento

Arquitectura de Computadores 3 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

Donde la expresión entre {} es obligatoria, la expresión entre [] es opcional y el signo |


implica opción entre dos expresiones.
Fuera del paréntesis recto se puede indicar cual es el registro de segmento usado para
completar la dirección de memoria. En caso que este no se especifique siempre se asume
uno por defecto.
Ejemplos:
Mov Ax, [Bp + 3]
Add [Bx + Si ], 4
Sub Es:[Bx + Di + 5],Dx

En la Tabla 1 se indican las combinaciones posibles entre registros índice y los segmentos
así como las asignaciones por defecto.
Tabla 1.Combinación entre registros de segmento e indices.

CS SS DS ES
IP Si
SP si
BP Prefijo por defecto prefijo prefijo
BX Prefijo prefijo por defecto prefijo
SI Prefijo prefijo por defecto prefijo
DI Prefijo prefijo por defecto por defecto
(cadenas)

Arquitectura de Computadores 4 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

INSTRUCCIONES
Para describir a cada una de las instrucciones usaremos el siguiente formato:
CÓDIGO
Formato: CÓDIGO op1 , op2
Tipo Args: Se indica qué forma puede tomar cada parámetro poniendo debajo del
mismo una lista de códigos entre paréntesis que definimos así:
A dirección absoluta inmediata ( 4 bytes )
a dirección absoluta inmediata ( 2 bytes )
i operando inmediato ( 1 o 2 bytes )
d desplazamiento inmediato ( 1 byte )
r registro de uso general ( 8 o 16 bits )
R registro de uso general ( 16 bits )
m palabra de memoria ( 1 o 2 bytes )
M palabra de memoria ( 2 bytes )
W doble palabra de memoria ( 4 bytes )
CL el nombre de un registro en particular

Lógica: Se indica usando pseudo código cual es


la lógica de la instrucción.
Descripción: Descripción de la semántica de la instrucción.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - ? X X X X
En la tabla de Banderas se indica cómo afecta a las flags del procesador la
ejecución de la instrucción, usando el siguiente código:
X → afecta siempre el valor de la flag colocando el valor apropiado
según corresponda.
? → el valor de la flag luego de la ejecución de la instrucción es
indeterminado
- → la ejecución de la instrucción no afecta el valor de flag

Arquitectura de Computadores 5 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

ARITMÉTICAS
ADD
Formato: ADD op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 + op2
Descripción: Suma los dos operandos y almacena el resultado en op1 , por lo tanto
ambos deben tener el mismo tipo
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X

ADC
Formato: ADC op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 + op2 + c
Descripción: Idem a ADD pero además suma el valor del carry.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X

SUB
Formato: SUB op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 − op2
Descripción: Idem a ADD pero realiza la resta en lugar de la suma.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X

SBB
Formato: SBB op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op1 − op2 − c
Descripción: Idem a SUB pero además resta el carry.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X

Arquitectura de Computadores 6 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

MUL
Formato: MUL op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
Ax = Al *op
sino si op es de tipo palabra ⇒
Dx, Ax = Ax* op
fin si
si la mitad superior del resultado es 0
CF = 0
sino
CF = 1
fin si
OF = CF
Descripción: Multiplica sin considerar el signo, el acumulador ( Ax o Ax) por el
operando op según este último sea de tipo byte o palabra.
En caso que op sea de tipo byte ls resultado se almacena en Ax si es de
tipo palabra se almacena en el par de registros Ax , Dx colocando la parte
más significativa en Dx .
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - ? ? ? ? X

Arquitectura de Computadores 7 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

DIV
Formato: DIV op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
si Ax div op > FFh ⇒
INT 0
else
Al = Ax div op
Ah = Ax mod op
fin si

fin si
sino si op es de tipo palabra ⇒
si Dx: Ax div op > FFh ⇒
INT 0
else
Ax = Dx: Ax div op
Dx = Ax mod op
fin si

Descripción: Divide sin considerar el signo, el acumulador Ax por el operando op si


este último es de tipo byte. Si op es de tipo palabra el número dividido por
éste es Dx: Ax .
En caso que op sea de tipo byte el cociente se almacena en Al y el resto
en Ah . Si es de tipo palabra el cociente se almacena en Ax y el resto en
Dx
Si el cociente es mayor que el número máximo representable (FFh o FFFFh
según sea el caso), el resultado queda indefinido y se genera una
interrupción tipo 0.
Banderas
OF DF IF TF SF ZF AF PF CF
? - - - ? ? ? ? ?

Arquitectura de Computadores 8 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

NEG
Formato: NEG op
Tipo Args: ( r,m)
Lógica:
si op es de tipo byte ⇒
op = FFh − op
op = op + 1
sino si op es de tipo palabra ⇒
op = FFFFh− op
op = op + 1
fin si
Descripción: Calcula el complemento a 2 de op
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X
CBW
Formato: CBW
Lógica:
siAl < 80h
Ah = 00h
sino
Ah = FFh
fin si
Descripción: Copia el bit 7 del registro AL en todos los bits del registro AH; es decir
expande el bit de signo de AL
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -
INC
Formato: INC op
Tipo Args: ( r,m)
Lógica: op = op + 1
Descripción: Incrementa el operando destino.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X -

Arquitectura de Computadores 9 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

DEC
Formato: DEC op
Tipo Args: ( r,m)
Lógica: op = op − 1
Descripción: Decrementa el operando destino.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X -

Arquitectura de Computadores 10 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

LÓGICAS
AND
Formato: AND op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ∧ op2
CF = OF = 0
Descripción: Calcula el "y" lógico bit a bit entre op1 y op2 .
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0

OR
Formato: OR op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ∨ op2
CF = OF = 0
Descripción: Calcula el "o" lógico inclusivo bit a bit entre op1 y op2
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0

XOR
Formato: XOR op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica:
op1 ← op1 ⊗ op2
CF = OF = 0
Descripción: Calcula el "o" lógico exclusivo bit a bit entre op1 y op2 .
Banderas:
OF DF IF TF SF ZF AF PF CF
0 - - - X X ? X 0

Arquitectura de Computadores 11 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

NOT
Formato: NOT op
Tipo Args: ( r,m)
Lógica: op ← ¬op

Descripción: Calcula el complemento a 1 de op . Es decir, cambia unos por cero y ceros


por unos.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

CMP
Formato: CMP op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 − op2
Descripción: Resta op1 de op2 pero solo afecta las flags ignorando el resultado. Los
operandos quedan inalterados pudiéndose consultar las flags mediante una
operación de bifurcación condicional.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X X X X

Arquitectura de Computadores 12 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

DESPLAZAMIENTO
SAL/SHL
Formato: SAL op1 , op2
SHL op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la izq.
Ej: SAL Al,1

CF Al
Antes ? a b c d e f g h

Al
Despues h b c d e f g h 0
Descripción: Desplaza a la izquierda los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con ceros.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X

Arquitectura de Computadores 13 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

SHR
Formato: SHR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la der.
Ej: SHR Al,1
Al CF
Antes a b c d e f g h ?

Al
Despues 0 a b c d e f g h
Descripción: Desplaza a la derecha los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con ceros.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X
SAR
Formato: SAR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: corre op1 , op2 lugares a la derecha expandiendo el signo.
Ej: SAR Al,1
Al CF
Antes a b c d e f g h ?

Al
Despues a a b c d e f g h
Descripción: Desplaza a la derecha los bits de op1 el nro. de bits especificado por op2 .
Los bits a la derecha se rellenan con el signo del primero operando.
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - X X ? X X

Arquitectura de Computadores 14 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

ROL
Formato: ROL op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: rota op1 , op2 lugares a la izquierda.
Ej: ROL Al,1
CF Al
Antes ? a b c d e f g h

Al
Despues a b c d e f g h a

Descripción: Rota a la izquierda los bits de op1 el numero de bits especificado por op2
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
OF contiene el xor del CF con el bit más significativo del resultado.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - - - - - X

Arquitectura de Computadores 15 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

ROR
Formato: ROR op1 , op2
Tipo Args: ( r,m) (1, CL)
Lógica: rota op1 , op2 lugares a la izquierda.
Ej: ROR Al,1
Al CF
Antes a b c d e f g h ?

Al
Despues h a b c d e f g h

Descripción: Rota a la derecha los bits de op1 el numero de bits especificado por op2
Si el nro. de bits a desplazar es 1, se puede especificar directamente. Si es
mayor que 1 debe cargarse en CL.
CF contiene luego de la ejecución el ultimo bit de op1 en ser desplazado
"fuera" de la representación.
OF contiene el xor del CF con el bit menos significativo del resultado.
Banderas:
OF DF IF TF SF ZF AF PF CF
X - - - - - - - X

Arquitectura de Computadores 16 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

MOVIMIENTO e I/O
MOV
Formato: MOV op1 , op2
Tipo Args: ( r,m) (r,m,i)
Lógica: op1 ← op2
Descripción: Transfiere un byte o una palabra desde el operando fuente al operando
destino.
Ambos operandos deben ser del mismo tipo (byte o palabra).
El contenido especificado por el elemento fuente se copia sobre el
elemento destino, quedando inalterado el elemento fuente.
Atención: No se puede mover memoria a memoria.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

IN
Formato: IN op1 , op2
Tipo Args: (AL, AX) (i,DX)
Lógica:
si op1 = Al
Al = I/ O(op 2 )
sino si op1 = AX
Ax = I/ O(op 2 )
fin si
Descripción: Transfiere un byte o una palabra de una puerta de entrada del procesador
al registro Al o Ax, respectivamente.
El nro. de la puerta se puede especificar mediante:
• Un valor fijo (de o a 255).
• Un valor variable, el contenido en el registro Dx (de 0 a 65535),
pudiéndose acceder a 64K puertas de entrada.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 17 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

OUT
Formato: OUT op1 , op2
Tipo Args: (i,DX) (Al, Ax)
Lógica:
si op1 = Al
I/ O(op 2 ) = Al
sino si op1 = Ax
I/ O(op 2 ) = Ax
fin si
Descripción: Transfiere un byte o una palabra desde el registro Al o Ax a una puerta de
salida del procesador
El nro. de la puerta se puede especificar mediante:
• Un valor fijo (de o a 255).
• Un valor variable, el contenido en el registro Dx ( de 0 a 65535),
pudiéndose acceder a 64K puertas de salida.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 18 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

MANEJO DE FLAGS
CLC
Formato: CLC
Lógica: CF := 0
Descripción: Borra la bandera de acarreo (CF) sin afectar a ninguna otra bandera.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - 0

STC
Formato: STC
Lógica: CF := 1
Descripción: Pone en 1 la bandera de acarreo (CF) sin afectar a ninguna otra bandera.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - 1

CLI
Formato: CLI
Lógica: IF := 0
Descripción: Borra la bandera de activación de interrupciones (IF) y desactiva las
interrupciones enmascarables (las que aparecen sobre la linea INTR del
procesador).
• Las interrupciones enmascarables se pueden activar o desactivar.
• Las interrupciones no enmascarables (las que aparecen sobre la
linea NMI) no se pueden desactivar.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - 0 - - - - - -

Arquitectura de Computadores 19 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

STI
Formato: STI
Lógica: IF := 1
Descripción: Pone en 1 la bandera de activación de interrupciones (IF) y activa las
interrupciones enmascarables (las que aparecen sobre la linea INTR del
procesador)
Una interrupción pendiente no será reconocida hasta que no se haya
ejecutado la instrucción que sigue a STI.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - 1 - - - - - -

Arquitectura de Computadores 20 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

BIFURCACIÓN INCONDICIONAL
CALL
Formato: CALL op1
Tipo Args: (R,M,a,A,W)
Lógica:
Si llamada FAR
PUSH CS
PUSH IP
CS := segmento op1
IP := offset op1
sino { llamada NEAR }
PUSH IP
IP := op1
fin si
Descripción: Modifica el flujo de control, cambiando el puntero de programa (CS:IP) a la
dirección indicada por op1 , guardando previamente en la pila la dirección
de la instrucción siguiente, para volver a esta instrucción una vez ejecutado
el procedimiento.
El procedimiento llamado puede estar:
• Dentro del mismo segmento (llamada NEAR). En este caso, se
almacena en la pila el desplazamiento de la instrucción siguiente.
• En otro segmento (llamada FAR). En este caso se almacena en la
pila primero el segmento y segundo el desplazamiento de la
instrucción siguiente.
La llamada puede ser a su vez:

• Directa, es decir op1 es el valor a asignar a el puntero de


instrucción. Se supone siempre un salto NEAR a menos que se
indique lo contrario.

• Indirecta, es decir op1 contiene la dirección de memoria donde se


encuentra el valor a asignar al puntero de instrucción. Si se utiliza
WORD PTR, el contenido es la nueva dirección o desplazamiento.
Si en cambio se utiliza DWORD PTR la primera palabra contiene el
desplazamiento y la segunda el segmento. De esta forma se
pueden hacer llamadas NEAR o FAR, respectivamente.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 21 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JMP
Formato: JMP op1
Tipo Args: (R,M,a,A,W)
Lógica:
Si llamada FAR
CS := segmento op1
IP := offset op1
sino
IP := op1
fin si
Descripción: Igual al CALL sin guardar la dirección de retorno en el stack:
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

RET
Formato: RET
Lógica:
POP IP
si procedimiento FAR
POP CS
fin si
Descripción: Retorna de un procedimiento invocado por un CALL, utilizando como
dirección de retorno el valor almacenado en el tope del stack.
El ensamblador genera un RET distinto según el procedimiento sea NEAR
o FAR:
• SI es NEAR se asume que en el tope del STACK contiene el nuevo
valor de IP.
• SI es FAR se asume que en el tope del STACK contiene el nuevo
valor de IP y luego esta el nuevo valor de CS.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 22 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

BIFURCACIÓN CONDICIONAL
Este conjunto de instrucciones se utilizan para efectuar un salto CONDICIONAL a una
dirección de memoria ubicada en el segmento CS a una distancia menor a 128 bytes de la
instrucción actual.
Todas verifican cierta condición que deben cumplir algunos bits del registro de flags para
realizar la transferencia de control. Si dicha condición no se cumple entonces el salto no se
realiza.

JA / JNBE (no considera signo)


Formato: JA op1 (Jump Above)

JNBE op1 (Jump Not Below or Equal)


Tipo Args: (d)
Lógica:
Si CF = 0 y ZF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
CF=0 y ZF=0.
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JA DIR. ; saltar a DIR si a > b
; sin considerar signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 23 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JB / JNAE / JC (no considera signo)


Formato: JB op1
JNAE op1
JC op1
Tipo Args: (d)
Lógica:
Si CF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
CF=1 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JC DIR. ; saltar a DIR si a < b ; sin considerar signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

JNB / JAE / JNC (no considera signo)


Formato: JNB op1
JAE op1
Tipo Args: (d)
Lógica:
Si CF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
CF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNB DIR. ; saltar a DIR si a ≥b
; sin considerar signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 24 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JBE/JNA (no considera signo)


Formato: JBE op1
JNA op1
Tipo Args: (d)
Lógica:
Si CF = 1 o ZF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
CF=1 o ZF=1.
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNA DIR. ; saltar a DIR si a ≤b
; sin considerar signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

JE/JZ
Formato: JE op1
JZ op1
Tipo Args: (d)
Lógica:
Si ZF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=1 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JC DIR. ; saltar a DIR si a = b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 25 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JG/JNLE (considera signo)


Formato: JG op1
JNLE op1
Tipo Args: (d)
Lógica:
Si ZF = 0 y SF = OF
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=0 y SF=OF .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JG DIR. ; saltar a DIR si a > b
; considerando el signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

JNG/JLE (considera signo)


Formato: JNG op1
JLE op1
Tipo Args: (d)
Lógica:
Si ZF = 1 o SF ≠ OF
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=1 y SF ≠ OF .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNG DIR. ; saltar a DIR si a ≤b
; considerando el signo
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 26 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JNE/JNZ
Formato: JNE op1
JNZ op1
Tipo Args: (d)
Lógica:
Si ZF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
ZF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNE DIR. ; saltar a DIR si a ≠b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

JNO
Formato: JNO op1
Tipo Args: (d)
Lógica:
Si OF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
OF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
ADD a,b ; a=a+b
JNO DIR. ; saltar a DIR si no hubo overflow
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 27 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JNS
Formato: JNS op1
Tipo Args: (d)
Lógica:
Si SF = 0
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
SF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNS DIR. ; saltar a DIR si a ≥b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

JO
Formato: JO op1
Tipo Args: (d)
Lógica:
Si OF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
OF=1.
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
ADD a,b ; a=a+b
JO DIR. ; saltar a DIR si hubo overflow
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 28 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

JS
Formato: JS op1
Tipo Args: (d)
Lógica:
Si SF = 1
IP ← op1 + IP
Descripción: Transfiere el control a la instrucción (IP + op1 ) si se cumple la condición
SF=0 .
El desplazamiento es un valor con signo de 8 bits, es decir esta
comprendido entre -128 y 127.
Ej:
CMP a,b ; comparar a y b
JNS DIR. ; saltar a DIR si a < b
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 29 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

MANEJO DE STACK
El stack del 8086 está implementado utilizando fundamentalmente las operaciones PUSH
y POP conjuntamente con los registros SS y SP.
El tope del stack está apuntado por SS:SP y las operaciones PUSH y POP los actualizan
de forma de obtener la semántica de stack como veremos más adelante.

PUSH
Formato: PUSH op1
Tipo Args: (R,M)
Lógica:
SP=SP-2
MOV SS:[SP], op1
Descripción: Decrementa el puntero del stack, SP y transfiere la palabra especificada
por op1 a la dirección SS:SP
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

POP
Formato: POP op1
Tipo Args: (R,M)
Lógica:
MOV op1 ,SS:[SP]
SP=SP+2
Descripción: Transfiere la palabra en tope del stack al operando op1 y luego incrementa
el puntero del stack, SP.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

PUSHF
Formato: PUSHF
Lógica:
SP=SP-2
MOV SS:[SP],FLAGS
Descripción: Coloca el registro de flags en al tope del stack.
Banderas:
OF DF IF TF SF ZF AF PF CF
- - - - - - - - -

Arquitectura de Computadores 30 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

POPF
Formato: POPF
Lógica:
SP=SP-2
MOV FLAGS, SS:[SP]
Descripción: Restaura los registros de flags desde el tope del stack.
Banderas:
OF DF IF TF SF ZF AF PF CF
X X X X X X X X X

Arquitectura de Computadores 31 Facultad de Ingeniería


Microprocesador 8086 Notas del Curso

INTERRUPCIONES
La tabla de interrupciones del 8086 se encuentra en la dirección absoluta 0 y ocupa el
primer kilobyte de memoria.
Dicha tabla posee 256 entradas de 4 bytes cada una. La entrada i-ésima de esta tabla
posee la dirección de memoria del manejador de la interrupción i. Los primeros 2 bytes
corresponden al offset del manejador y los últimos 2 corresponden al segmento del mismo.

INT
Formato: INT op1
Tipo Args: (i)
Lógica:
PUSHF
IF=0
TF=0
CALL FAR tabla_int( op1 )
Descripción: Genera una interrupción software tipo op1 .
Banderas:
OF DF IF TF SF ZF AF PF CF
- - x x - - - - -

IRET
Formato: IRET
Lógica:
RET
POPF
Descripción: Retorna de una interrupción. Funciona en forma equivalente al RET
utilizado para retornar de una llamada CALL con la diferencia que esta
instrucción restaura las flags del stack antes de retornar.
Banderas:
OF DF IF TF SF ZF AF PF CF
X x x x x x x x x

Arquitectura de Computadores 32 Facultad de Ingeniería


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Entrada / Salida

Arquitectura de Computadoras
(Versión 4.4 - 2024)

Instituto de Computación - Facultad de Ingeniería - UDELAR


1
Arquitectura de Computadoras Notas de Teórico

15 ENTRADA/SALIDA

15.1 Introducción

En este capítulo vamos a completar la presentación de la arquitectura von Neuman,


introduciendo la parte de entrada y salida, encargada de vincular a la computadora (hasta
ahora conjunto CPU+Memoria) con el mundo exterior.

La entrada/salida (habitualmente anotada E/S) actúa como interfaz entre los


programas que ejecuta la CPU en base a las instrucciones y los datos almacenados en la
memoria, con los dispositivos que permitirán interactuar con el mundo físico, permitiendo
así por un lado introducir la información a procesar en el sistema (entrada) y por otro
presentar el resultado de ese proceso de modo inteligible para el ser humano (o al menos
de manera más amigable que la de medir diferencias de potencial en los circuitos).

Los dispositivos que permiten la interacción de los usuarios con el sistema se


denominan periféricos. Esta denominación obedece a razones históricas, que se remontan
a la época en que un computador ocupaba una sala entera, donde la capacidad de proceso
se ubicaba en el centro (de allí Unidad Central de Proceso) y los dispositivos de interacción
con el usuario estaban a su alrededor (en la periferia).

15.2 Buses

La conexión de la CPU, la Memoria y la Entrada/Salida, se realiza mediante grupos


de "líneas" que comunican tres tipos de información: dirección, datos y control. Esta
agrupación se denomina bus (su nombre hace alusión al hecho que recorre todos los sub-
sistemas a conectar).

CPU MEM

E/S

Por lo indicado en este bus principal pueden distinguirse a su vez tres buses
secundarios:

 bus de direcciones:
 formado por las líneas de conexión que transportan las direcciones de
memoria o E/S a ser accedidas durante la transferencia
 bus de datos:
 formado por las líneas de conexión que transportan la información que es
transferida sobre el bus entre los distintos componentes conectados
 bus de control:
 formado por las líneas de conexión que transportan señales que controlan el
uso del bus y la comunicación sobre el mismo. Algunas de las señales típicas
presentes en este bus son:
 Memory_Read (indica una operación de lectura sobre la memoria)
 Memory_Write (indica una operación de escritura sobre la memoria)

Instituto de Computación - Facultad de Ingeniería - UDELAR


2
Arquitectura de Computadoras Notas de Teórico

 I/O_Read (indica una operación de lectura sobre la entrada/salida)


 I/O_Write (indica una operación de escritura sobre la entrada/salida)
 Bus_Request (indica que un sub-sistema desea tomar control del bus
para iniciar una transferencia)
 Bus_Grant (confirma que el bus está disponible para quien lo solicitó)
 Transfer_ACK (confirma la recepción de una transferencia de
información)
 Interrupt_Request (indica un pedido de interrupción hacia un sus-sistema)
 Interrupt_ACK (confirma la aceptación del pedido de interrupción)
 Clock (sincroniza las actividades del bus y sus señales)
 Reset (fuerza el reset de todos los componentes conectados al bus)

El bus de direcciones transporta información que permite identificar y seleccionar las


posiciones de memoria a leer ó escribir y/o las entidades de E/S con las que se va a
interactuar. El bus de datos transporta los datos leídos o a escribir ya sea en la memoria o
en los dispositivos de E/S (traspaso de información entre los sub-sistemas). El bus de
control permite la administración de la comunicación entre la CPU, la Memoria y la E/S.

En general un bus está definido por un conjunto de características que incluyen:


 especificaciones mecánicas (conectores)
 especificaciones eléctricas (niveles de voltajes y/o corriente), bits de dirección y
de datos y consideraciones de "timing" (tiempo) de las señales involucradas
incluyendo el reloj de sincronismo
 protocolo de comunicaciones

En particular cuando hablamos del "protocolo de comunicaciones" nos estamos


refiriendo al conjunto de reglas que debe seguir cualquier entidad conectada al bus para
hacer uso del mismo a los efectos de realizar un intercambio de información con otra
entidad.

Según sea el tamaño del sub-bus de datos se habla de buses de 16, 32 o 64 bits
(estos son los tamaños habituales al presente). También caracteriza a un bus si el sub-bus
de datos es separado del sub-bus de direcciones o está multiplexado en el tiempo con él.
En particular estas dos características, unidas a la frecuencia del reloj utilizado para el
sincronismo, determinan la capacidad de transferencia de información del bus.

Según sean las características del protocolo de comunicaciones se distinguen


distintos tipos de buses. Una primera clasificación posible es en base a su complejidad:

 Bus Simple
Este tipo de buses se implementan en una filosofía "Master-Slave" ("Maestro-
Esclavo"). Existe una sola entidad que controla el uso del bus en todo momento (el
"Master"), típicamente la CPU, quien inicia, controla y participa de todas las
transferencias que se realizan en el bus. Todas las transacciones sobre el bus se
realizan bajo su supervisión. Las entidades "esclavas" que deseen utilizar el bus
tienen que esperar ser habilitados por el "maestro", el cual o bien utiliza técnicas de
"polling" (consulta) para determinar si una entidad esclava desea hacer una
transferencia o bien dispone de algún mecanismo por el cual la entidad interesada
en realizar una transferencia le avisa de este interés (ej: por un pedido de
interrupción).

Instituto de Computación - Facultad de Ingeniería - UDELAR


3
Arquitectura de Computadoras Notas de Teórico

 Bus Inteligente
En estos buses cualquier entidad conectada puede tener, al menos potencialmente,
la capacidad de convertirse en el "Master" del bus (se dice que tiene la capacidad de
"bus mastering") y comandar una transferencia. Al momento que una o varias
entidades requieren hacer uso del bus ocurre una competencia por el uso del
mismo, la cual es resuelta por un mecanismo de arbitraje que determina cuál de los
contendientes pasa a ser el "master", mientras que el resto permanecerá como
"slave" hasta que se termine la transacción.

En función de cómo sea este mecanismo de arbitraje se distinguen, a su vez, las


siguientes categorías de bus:

 Bus con Arbitraje Centralizado


Un bus con este tipo de arbitraje se denomina Jerárquico. En estos buses
hay una entidad que tiene mayor jerarquía que las demás (típicamente la
CPU) y es la responsable de entregar el control del bus a las entidades que
lo requieran. La entidad interesada en utilizar el bus le avisa de este interés
("bus request") y el árbitro la habilita a utilizarlo ("bus grant").

 Bus con Arbitraje Distribuido


Un bus con este tipo de arbitraje es denominado Equitativo. En estos buses
todas las entidades conectadas tienen el mismo "rango" y no existe un árbitro
central, sino que el mecanismo de asignación del bus tiene su inteligencia
distribuida entre todas las entidades con capacidad de "bus mastering".
Cuando dos o más entidades requieren simultáneamente del bus se aplica
un mecanismo de arbitraje que determina cuál de los contendientes por el
uso del bus tendrá el control del mismo en ese momento y cuál(es) tendrá(n)
que esperar hasta que quede liberado nuevamente. Este arbitraje, a
diferencia del caso anterior, se resuelve por una especie de votación entre
los distintos contendientes, sin la necesidad de contar con un árbitro fijo y
central.

Existe otra clasificación de los buses que apunta a categorizarlos según sea la
aplicación a la que se destinan, en función de la ubicación de las entidades a conectar en
relación a lo que se podría definir como "frontera" del sistema. Si bien esta clasificación es
discutible y eventualmente varía con el tiempo ó con el alcance de lo que consideremos
"sistema", los buses se suelen distinguir entre:

 Internos cuando se utilizan para conectar sub-sistemas dentro de la "frontera"


del sistema. El caso más típico e indiscutible de un bus interno es el "bus de
memoria" (que conecta la CPU con los bancos de memoria)

 Externos cuando se utilizan para conectar sub-sistemas fuera de dicha frontera.


Los casos más típicos y claros de este tipo de buses lo constituyen el bus SCSI
(Small Computer System Interface) que se puede utilizar para conectar
básicamente dispositivos de almacenamiento masivo (discos rígidos y unidades
de cinta), y el bus USB (Universal Serial Bus) que se puede utilizar para conectar
una variedad muy amplia de dispositivos (discos, impresoras, "mouses",
escáners, etc).

15.3 Buses de Expansión

Por otra parte están los que podemos denominar buses de expansión, que se

Instituto de Computación - Facultad de Ingeniería - UDELAR


4
Arquitectura de Computadoras Notas de Teórico

utilizan para conectar placas de circuito adicionales (tarjetas de expansión ó expansion


boards ó expansion cards) a la placa de circuito principal del sistema (placa madre o
motherboard). En la casi totalidad de las computadoras actuales estos buses de expansión
están contenidos dentro del chasis del equipo por lo que podríamos considerarlos internos,
aunque si el "sistema" que consideráramos fuera la placa principal, entonces habría que
clasificarlos como externos.

Los buses de expansión se identifican claramente en un sistema porque poseen un


conector "hembra" característico, normalmente diseñado para insertar en él una placa de
circuito con sus contactos en la propia placa, sin necesidad de un conector "macho"
(aunque hay buses que utilizan conectores tanto en la placa madre como en la de
expansión).

Es destacable el hecho que, si bien como concepto arquitectónico el bus de


expansión estuvo presente en la mayoría de los diseños de computadoras desde los inicios
de la industria, es a partir de la mitad de la década de los '70 que toma un interés especial.
A partir de la microcomputadora Altair 8000, pero en especial a partir de la Apple II, el bus
de expansión se convierte en un actor clave en la industria de la computación, ya que al
poner en "dominio público" la especificación del mismo, se abre la posibilidad que
fabricantes distintos del diseñador original del computador puedan producir "tarjetas de
expansión" compatibles con dicho sistema, formándose una industria completa que gira
alrededor de las ampliaciones y opciones para los sistemas básicos. Entre otras cosas el
éxito de la estrategia de Apple y su "diseño de bus abierto" forzó a IBM a incursionar en la
misma senda al lanzar su PC en 1980, lo que terminó de cambiar las reglas de una industria
que, hasta ese momento, basaba la diferenciación de su oferta y la competitividad en
diseños propietarios y cerrados a otros actores.

A continuación veremos algunos ejemplos de buses de expansión.

Buses de Expansión en los PCs

 ISA (Industry Standard Architecture)


Este bus corresponde al incorporado por IBM en su modelo PC-AT en 1984. Es un
bus de 16 bits de datos y 24 bits de direcciones no multiplexados, del tipo "maestro-
esclavo". Básicamente es una extensión del bus del microprocesador 80286 utilizado
en esos sistemas, con poca inteligencia y un reloj de sincronismo de 8 MHz, con una
tasa de transferencia máxima de 16 MBps.

La siguiente fotografía muestra los conectores de la placa madre de un computador


con bus ISA.

Tomado de Wikipedia - Foto tomada por Jorge González

Instituto de Computación - Facultad de Ingeniería - UDELAR


5
Arquitectura de Computadoras Notas de Teórico

 MCA (Micro Channel Architecture)


Este bus fue incorporado por IBM en su frustrada línea de computadoras PS/2 en
1987, en un intento de retomar el control de la industria de tarjetas de expansión y,
en especial, de frenar el fenómeno de los sistemas "clone" (clonado). En un bus
inteligente con capacidad de "bus mastering" y arbitraje centralizado, de 32 bits de
datos y 32 bits de direcciones, no multiplexados, independiente del tipo de
procesador de la placa madre y un reloj inicial de 10 MHz (tasa de transferencia de
20 MBps a 40 MBps).

 EISA (Extended Industry Standard Architecture)


Este bus fue diseñado por los distintos fabricantes de PCs "compatibles" en reacción
al Microcanal de IBM. Es una extensión del bus ISA a 32 bits (32 bits de datos y 32
bits de direcciones no multiplexados), con dos modalidades de funcionamiento: una
con capacidad de "bus mastering" (arbitraje centralizado) y otra del tipo master-slave
para funcionar como un ISA. El diseño de su conector, así como la posibilidad de
trabajar en las dos modalidades, le permitió soportar tarjetas ISA al mismo tiempo
que las "nuevas" tarjetas EISA (aunque sacrificando prestaciones). Si bien esto no
fue suficiente para sobrevivir al paso del tiempo, logró su objetivo inmediato:
destruyó totalmente la estrategia de IBM y la obligó a abandonar la MCA. El reloj del
bus era de 8 MHz (como el ISA), con una tasa de transferencia máxima de 32 MBps.

 VLB (VESA Local Bus - VESA = Video Electronics Standards Association)


Este bus fue una propuesta impulsada por los fabricantes de tarjetas de video que
necesitaban de un mayor ancho de banda de transferencia que el ofrecido por el bus
EISA, principalmente para la conexión de la tarjeta de video gráfica. Consistió
básicamente en volver a la idea de "amplificar" el bus interno del microprocesador,
en este caso del 80486. Es de 32 bits y trabaja a 33 MHz (igual que dicho micro).

 PCI (Peripheral Component Interconnect)


Este bus fue desarrollado inicialmente por Intel y apareció por 1993 (su versión
inicial fue la 2.0). Actualmente sus especificaciones son mantenidas por PCI-SIG
(PCI Special Interest Group) un consorcio de empresas entre las que, naturalmente,
está Intel. Es un bus que acepta configuraciones de 32 bits de datos y 32 bits de
direcciones ó, con un conector más grande de 64 bits, multiplexados. Su primera
versión fue con un reloj de 33.33 MHz, para una tasa de transferencia de 133 MBps
(266 MBps cuando se implementaba en 64 bits). Al igual que el MCA y el EISA es un
bus con capacidad de "bus mastering" y arbitraje centralizado. La versión 2.1 de la
especificación pasó a soportar un reloj de 66.67 MHz, con una tasa de transferencia
de 266 MBps y comenzó a soportar tarjetas con voltajes de 3.3 Volts, además de los
tradicionales 5 Volts. La especificación 3.0 pasó a usar solamente 3.3 Volts.
Su evolución, el PCI-X (propuesto por Compaq, IBM y HP en 1998), utiliza un reloj
de 133 MHz, lleva la tasa de transferencia a 1014 MBps y el PCI-X 2.0 utiliza un reloj
de 266 MHz para una tasa de transferencia de 2035 MBps.
A fines de la década de los '90 y comienzos de este siglo, el bus PCI terminó por
desplazar completamente a los buses MCA y EISA, convirtiéndose en el único
estándar en materia de buses de expansión de la arquitectura PC, con la excepción
del bus AGP.

Instituto de Computación - Facultad de Ingeniería - UDELAR


6
Arquitectura de Computadoras Notas de Teórico

La siguiente fotografía muestra los conectores de la placa madre de un computador


con bus PCI.

Tomado de Wikipedia - Foto tomada por Jorge González

 AGP (Accelerated Graphic Port - Advanced Graphic Port)


Este bus fue diseñado por Intel teniendo en mente la conexión de tarjetas gráficas
de video (como su nombre lo indica). Desde 1997 se sucedieron las especificaciones
AGP 1.0 de 32 bits y 66 MHz para una tasa de transferencia de 266 MBps, el AGP
2.0 de 32 bits y 133 MHz, llevando la tasa de transferencia a 533 MBps, el AGP 4x
con 32 bits y 133 MHz pero utilizando la técnica de "double pump" (utiliza ambos
flancos del reloj para transferir datos) lleva la tasa de transferencia a 1066 MBps y
finalmente la AGP 8x que utiliza la técnica "quad pump" (utiliza flancos desfasados
del reloj principal) y alcanza 2133 MBps.

 PCI Express (PCIe)


Este bus fue desarrollado por el consorcio PCI-SIG como evolución del PCI. Tiene
un diseño radicalmente distinto: es un bus de múltiples conexiones serie en lugar de
ser un bus paralelo como el PCI y sus antecesores. Esta condición le permite dos
características interesantes al momento de evaluar rendimientos: puede transmitir
en forma “full-duplex” en cada conexión (“lane” en la terminología PCIe) es decir los
dos nodos que se comunican pueden transmitir simultáneamente, y puede utilizar
velocidades de reloj muy altas. Tener presente que los buses paralelo tienen una
limitante en la velocidad de reloj porque padecen el fenómeno del “skew” que
consiste en que las señales transmitidas por conductores paralelos pueden llegar
desfasados en el tiempo si los conductores tienen distinto largo, llevando a confundir
bits de una palabra con bits de la siguiente. A medida que la frecuencia sube las
diferencias de largo de los conductores se hace cada vez más crítica e imposibles
de resolver en la práctica. Usando técnicas de paralelismo asíncrono el PCIe puede
transmitir por varias conexiones en forma simultánea, multiplicando la capacidad de
transferencia de información por la cantidad de conexiones (“lanes”) disponibles. Es
así que surgen las variantes x1, x2, x4, x8, x16 y x32 del bus, en función de la
cantidad de conexiones serie en paralelo que posee el bus. Las implementaciones
actuales no incluyen la x32 (aunque sí está en la especificación). Una tarjeta PCIe
puede insertarse en un slot de mayor paralelismo (ej: una x1 se puede colocar en

Instituto de Computación - Facultad de Ingeniería - UDELAR


7
Arquitectura de Computadoras Notas de Teórico

una ranura x4). Lo inverso también es cierto, ya que el protocolo negocia el


funcionamiento en función de las conexiones eléctricas disponibles, pero para esto
el conector del slot debe tener un diseño especial (abierto en un extremo).
La siguiente foto muestra distintos tipos de slots PCIe (de arriba hacia abajo: x4,
x16, x1, x16 y un PCI estándar de 32 bits):

Tomado de Wikipedia - Foto tomada por Snickerdo

Otros Buses de Expansión

Obviamente los buses de expansión que se han utilizado y se utilizan en los


computadores personales no son los únicos existentes. De hecho no fueron los PCs
los primeros sistemas en contar con esta forma de conectar tarjetas de circuito
adicionales y hay buses que perduran hasta hoy en día, aunque opacados por la
difusión de los vinculados al mundo del PC.

Veamos un par de ejemplos relevantes:

 VMEbus (VERSA Module Eurocard Bus)

Es un bus histórico que tiene sus orígenes en la década del 70. Fue diseñado por
Motorola, originalmente para su familia de microprocesadores 68000. Mantiene su
aplicabilidad en sistemas embebidos y sistemas de control en general. Es un bus
inteligente con arbitraje centralizado, realizado por la tarjeta que se inserte en la
primera ranura, con prioridad jerárquica o circular. Utiliza conectores (formato DIN
europeo) tanto en la tarjeta de expansión como en el “backplane” (conjunto de
conectores “macho” con alimentación que implementa el bus). Un sistema construido
con VMEbus dispone de un chasis con el “backplane” y la fuente de alimentación en
el cual se insertan las tarjetas. El procesador (tarjeta que contiene el
microprocesador y la memoria) es una tarjeta que se inserta como cualquier otra de
expansión (normalmente en el primer slot para oficiar como árbitro del bus).

La siguiente fotografía muestra un chasis con bus VME y una tarjeta para el mismo.

Instituto de Computación - Facultad de Ingeniería - UDELAR


8
Arquitectura de Computadoras Notas de Teórico

Tomado de la página web de ITCN

 NuBus

Este bus fue originalmente desarrollado por el MIT (Massachussets Institute of


Technology) como parte de un proyecto de un sistema denominado NuMachine que
nunca fue completado. El diseño fue tomado primeramente por Texas Instruments
para su sistema TI Explorer (una máquina diseñada para trabajar en lenguaje LISP)
y su sistema S1500 (un multiprocesador basado en UNIX). Luego Apple adoptó una
versión modificada (con un solo conector) para su familia de computadores
Macintosh (luego Apple adoptó el bus PCI y abandonó el NuBus).
Es un bus inteligente, de 32 bits, con capacidad de bus mastering, con arbitraje
distribuido. Utiliza conectores tanto en la tarjeta como en la placa principal. Texas
Instruments lo implementó en formato Eurocard (similar al VMEbus) con backplane
pasivo, mientras que Apple lo implementó con un único conector por tarjeta (en vez
de tres) y sobre la placa principal de las Macs.

La siguiente fotografía muestra una tarjeta de expansión para una computadora


Apple Macintosh basada en este bus:

Tomado de Wikipedia - Foto tomada por Danamania

Instituto de Computación - Facultad de Ingeniería - UDELAR


9
Arquitectura de Computadoras Notas de Teórico

El siguiente esquema muestra la especificación mecánica del NuBus original de TI:

Tomado del manual de Texas Instruments 2242825-0001 NuBus Specifications

15.4 Periféricos de Entrada/Salida

Los dispositivos periféricos de entrada/salida son los que realizan el vínculo del
computador con el mundo exterior. A través de ellos se realiza el ingreso de programas y
datos a procesar (mediante teclados, lectores de distinto tipo, etc) y se obtienen los
resultados del proceso de la información en un formato que sea "legible" para el ser humano
(impreso en papel, desplegado en una pantalla, etc) ó se provoca alguna alteración del
mundo físico circundante (ej: encendido de una luz). A este tipo de periféricos a veces se
los denomina "de interfaz" o "transductores".

Si bien no son estrictamente dispositivos de "entrada/salida" también se incluyen


entre ellos a los dispositivos de almacenamiento masivo de información (discos, cintas).
También están los dispositivos de comunicación, que permiten intercambiar información con
otros sistemas.

Algunos ejemplos de estos dispositivos son:

Transductores:
 Teclado
 Apuntador (más conocido como Ratón)
 Impresora (Matriz, Chorro de Tinta, Laser)
 Monitor (CRT, LCD, Plasma)

Instituto de Computación - Facultad de Ingeniería - UDELAR


10
Arquitectura de Computadoras Notas de Teórico

 Escáner
 Tableta de Digitalización

Almacenamiento:
 Diskettera
 Disco Magnético
 Disco Optico (CD, DVD)
 Cinta (QIC, DAT, DLT)

Comunicación:
 Modem (Analógico, RDSI, ADSL)
 Red Ethernet

15.5 Controladores de E/S

La arquitectura de E/S maneja el concepto de “controlador de E/S”. Un controlador


de E/S es la parte del periférico que contiene su inteligencia y por tanto lo “controla”. La
denominación es heredada del pasado cuando una impresora o una unidad de cinta tenían
por un lado un “armario” que contenía el mecanismo (martillos de impresión, motores de
arrastre, cabezas magnéticas, etc) y por otro lado otro armario que contenía los circuitos
que manejaban esos mecanismos, accionando los martillos, los motores, decodificando
señales, etc. Este último “armario” era el “controlador”.

En la actualidad la parte mecánica del dispositivo y la inteligencia que lo controla


están en el mismo gabinete, o al menos la inteligencia está distribuida entre el gabinete del
periférico y el gabinete de la computadora. Dos ejemplos de casos extremos pueden ser por
un lado un monitor gráfico (la caja del periférico tiene casi ninguna inteligencia vinculada a
la generación de las imágenes que muestra y toda la inteligencia se concentra en el
“controlador de video gráfico” que reside en el computador) y por el otro lado una impresora
láser (que incluye una verdadera computadora interna para generar las imágenes que debe
imprimir y manejar todo el complejo mecanismo de impresión y en el computador solo
reside una “interfaz” para comunicar los datos a imprimir).

15.5.1 Conexión de los Controladores de E/S

Existen distintas variedades en la forma que un controlador se conecta con un


computador, en particular teniendo en cuenta su lugar de residencia: si en el gabinete del
periférico, si en el gabinete del computador o distribuido entre ambos.

Veremos a continuación la representación esquemática de algunos de estos casos:

1) El controlador de E/S está contenido en el gabinete del computador

a) El controlador de E/S está conectado directamente al bus interno del


sistema

Este es el caso del controlador de video de un computador personal basado


en bus ISA (Nota: en estos ejemplos estamos teniendo en cuenta que el bus
ISA es prácticamente el bus interno con sus señales amplificadas).

Instituto de Computación - Facultad de Ingeniería - UDELAR


11
Arquitectura de Computadoras Notas de Teórico

CPU MEM

Cont. Perif.

b) El controlador de E/S está conectado a un bus distinto al bus interno del


sistema, el cual se conecta al bus interno a través de un adaptador

Es el caso de un controlador de video en un computador personal con bus


PCI ó AGP. Es de notar que es habitual en la terminología asociada a la
tecnología PCI denominar “bridge” (puente) a este adaptador.

CPU MEM

Bridge

Cont. Perif.

2) El controlador de E/S está contenido en el gabinete del periférico

En este caso no se da la situación que el controlador de E/S pueda estar


conectado directamente al bus interno del sistema porque dicho bus no está
diseñado para soportar largos recorridos de la señal. Por eso se requiere una
interfaz ó un bus del tipo externo que habilite la conexión. La diferencia entre interfaz
y bus es que la interfaz permite la conexión de un único dispositivo, por lo que su
protocolo de comunicaciones es más sencillo y no necesita de un algoritmo de
administración del uso compartido.

Podemos distinguir las situaciones:

a) Se utiliza una interfaz conectada directamente al bus interno del sistema

Es el caso de una impresora conectada por un puerto paralelo a un


computador personal con bus ISA.

Instituto de Computación - Facultad de Ingeniería - UDELAR


12
Arquitectura de Computadoras Notas de Teórico

CPU MEM

Interf. Cont. Perif.

b) Se utiliza un adaptador de bus conectado directamente al bus interno del


sistema

Es el caso de un disco SCSI (Small Computer System Interface) en un


computador con bus ISA.

Estamos considerando que el hecho que el disco de un computador personal


está contenido en el gabinete esto no modifica el hecho que también puede estar
fuera, cuando se utiliza el estándar SCSI. En este caso la ubicación tiene que ver
con aspectos mas vinculados a la comodidad y a la economía que a requerimientos
técnicos.

CPU MEM

Adap. Cont. Perif.

Cont. Perif.

Instituto de Computación - Facultad de Ingeniería - UDELAR


13
Arquitectura de Computadoras Notas de Teórico

c) Se utiliza un adaptador de bus conectado a un bus distinto del bus interno

Es el caso de un disco SCSI (Small Computer System Interface) en un


computador con bus PCI.

CPU MEM

Bridge

Adap. Cont. Perif.

Cont. Perif.

3) El controlador de E/S está distribuido entre el gabinete del computador y el del


periférico

Es el caso del teclado de un computador personal, donde parte de la inteligencia


reside en el propio teclado (posee un microcontrolador que realiza el barrido de
las teclas para determinar si hay alguna presionada) y parte en la placa principal
del computador (donde otro microcontrolador realiza algunas funciones de
conversión de códigos y repetición de teclas).

CPU MEM

Cont. Cont. Perif.

Instituto de Computación - Facultad de Ingeniería - UDELAR


14
Arquitectura de Computadoras Notas de Teórico

15.5.2 Acceso a los Controladores de E/S

La comunicación de la CPU con los controladores de E/S se realiza a través de


posiciones de memoria especiales de estos dispositivos, las que son accesibles también
para la CPU. Existen dos tipos de arquitecturas de E/S respecto a la forma de acceso desde
la CPU:

1) Direccionamiento aisalado de E/S: La CPU dispone de un espacio de direcciones


reservado para la E/S, el cuál es accedido por instrucciones especialmente
destinadas para ese fin (típicamente identificadas como in y out). Un ejemplo de
este enfoque es la familia de procesadores Intel.

2) E/S mapeada a memoria: La CPU accede a los controladores de E/S como si se


trataran de posiciones normales de memoria, utilizando para tales fines cualquier
instrucción que acceda a memoria. Un ejemplo de este diseño es la familia de
procesadores SPARC de Sun Microsystems (y en general todos los diseños
RISC).

Estas memorias especiales de los controladores de E/S se llaman genéricamente


registros. Normalmente un controlador de E/S tiene un conjunto relativamente pequeño de
registros para implementar el intercambio de información con la CPU. Una excepción a esta
regla la constituyen los controladores de video que por requerir grandes volúmenes de
información necesitan espacios de direcciones amplios. Esto representa alguna dificultad de
implementación en las arquitecturas Intel (porque el espacio de direcciones reservado a E/S
es pequeño) por lo que en los PCs se adoptó una estrategia de mapeo de las memorias de
video en el espacio de direcciones de memoria de la CPU (en vez de utilizar el espacio de
E/S).

Una propiedad interesante de los registros de E/S es que aún en el caso que se
accedan como memoria, no se comportan como memoria, pudiendo tener comportamientos
bien diferentes tales como:

sólo lectura:
el registro solo puede ser leído y si se escribe en él no se logra ningún efecto
(es decir si luego de escribir se lee, lo que se lee no es lo que se escribió).

sólo escritura:
el registro solo puede ser escrito y si se lee se obtiene un resultado
impredecible (los datos que se leen pueden ser cualquier cosa).

lectura/escritura independiente:
en este caso se tienen dos registros diferentes, uno de sólo lectura y otro de
sólo escritura accesibles en la misma dirección de E/S. Por lo que si bien se
puede escribir y leer en la misma dirección, las posiciones de memoria
accedidas son separadas e independientes, por lo que, obviamente, lo que
se escribe no puede ser leído posteriormente.

lectura/escritura normal:
estos registros de E/S se comportan como una posición de memoria normal,
lo que se escribe puede ser leído más tarde

Otra característica importante a tener en cuenta cuando se accede a E/S es que


muchas veces hay bits que no están definidos, por lo que al leerlos juntos en un byte o una

Instituto de Computación - Facultad de Ingeniería - UDELAR


15
Arquitectura de Computadoras Notas de Teórico

palabra pueden tomar cualquier valor, con lo que la comparación del contenido del byte ó
palabra con valores debe hacerse mediante el uso de máscaras (haciendo el AND bit a bit
con un valor que tenga en uno aquellos bits que nos interesan, de forma que el resultado
tenga únicamente en cuenta los bits que sí están definidos ó aquellos que nos interesan en
cada momento). Algo similar ocurre al escribir, en algunos registros determinados bits que
no están definidos deben, de todos modos, escribirse en un valor determinado (0 ó 1).

La cantidad de registros y su función dependen fuertemente de cada controlador y


de la aplicación que tenga el mismo (no es igual un controlador de comunicaciones que uno
de video). De todos modos hay algunos registros característicos que están presentes en
muchos de ellos:

Datos Entrada:
este registro contiene un dato destinado a la CPU, proveniente del periférico,
del propio controlador o de la línea de comunicaciones.

Datos Salida:
este registro contiene un dato proveniente de la CPU y destinado al
periférico, al propio controlador o a la línea de comunicaciones.

Estado:
este registro contiene bits que indican el estado del controlador en sí mismo
o del periférico que controla (ej; si hay un dato en el registro de entrada, si
está libre el registro de salida, si hay un pedido de interrupción pendiente, si
hay alguna condición de error en el controlador ó el periférico, etc).

Control:
este registro contiene bits que le indican al controlador de E/S ó al periférico
realizar determinada acción (ej: ponerse en línea, reiniciarse, que lea el dato
del registro de salida, etc). En algunos controladores de E/S antiguos
también se controlaban qué registros eran accesible en cada momento en
una dirección de E/S específica (por ejemplo se implementaban stacks de
registros y con un bit del registro de control se hacía el “push” y con otro el
“pop”).

15.6 Arquitectura de E/S y Buses de un PC

La arquitectura de buses de los Computadores Personales (PCs) ha evolucionado


con el tiempo. En un inicio (etapa del Bus ISA) el esquema era básicamente el que hemos
venido considerando: la CPU directamente conectada a la memoria y a la E/S.

Con la aparición del bus PCI en 1993 y el bus AGP en 1997 la topología cambió y la
mayor complejidad del sistema de memoria y la necesidad de un mejor manejo del DMA
(Direct Memory Access) llevó a la aparición de dos controladores con funciones
especializadas: el “Northbridge” que se encarga del control de los accesos a la memoria y
de los buses especializados (como el AGP) y el “Souhbridge” responsable del control de los
demás buses y periféricos.

Instituto de Computación - Facultad de Ingeniería - UDELAR


16
Arquitectura de Computadoras Notas de Teórico

El esquema es:

A partir del año 2000, Intel introduce cambios y deja de utilizar el PCI como “bus
central” del sistema, buscando lograr mejores velocidades de transferencia entre los
distintos componentes. De allí que reemplaza la terminología “northbidge” y “southbridge”
por la de “hubs”: MCH (Memory Controller Hub = Northbridge) y ICH (IO Controller Hub =
Southbridge).

Estos dos controladores están inicialmente unidos por el “Hub Link Bus”,
actualmente reemplazado por el DMI (Direct Memory Interface). Otra característica
importante de este re-diseño es que desaparece el ISA Bus, y las conexiones con
dispositivos de baja velocidad (el Super IO y el Firmware = BIOS) se hace a través de un
nuevo bus: el LPC (Low Pin Count).

Instituto de Computación - Facultad de Ingeniería - UDELAR


17
Arquitectura de Computadoras Notas de Teórico

Instituto de Computación - Facultad de Ingeniería - UDELAR


18
Arquitectura de Computadoras Notas de Teórico

La tendencia a partir de 2007 fue eliminar el uso de los buses AGP y PCI y basar
toda la E/S en el bus PCI-Express (PCI-e). Esta tendencia aparece asociada al desarrollo
de los “chipsets” vinculados a los procesadores “Core 2” de Intel.

Por ejemplo en la figura siguiente se observa el esquema de bloques del “chipset”


P45 de Intel.

Instituto de Computación - Facultad de Ingeniería - UDELAR


19
Arquitectura de Computadoras Notas de Teórico

A su vez en la arquitectura de los procesadores “Core i5/i7” se coloca el MCH dentro


de la CPU.

En el caso del Core i5 se busca un diseño simple de bajo costo, realizable con
básicamente dos chips: la CPU y un PCH (Peripheral Controller Hub) que reemplaza al ICH.

Para el Core i7 se busca un diseño de alta performance con un IOH (Input Output
Hub) destinado en exclusivo para los dispositivos de muy altos requerimientos de
transferencia de datos, como los controladores gráficos.

Instituto de Computación - Facultad de Ingeniería - UDELAR


20
Arquitectura de Computadoras Notas de Teórico

Instituto de Computación - Facultad de Ingeniería - UDELAR


21
Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Interrupciones

Arquitectura de Computadoras
(Versión 4.3 - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

16 INTERRUPCIONES

16.1 Introducción

En este capítulo veremos el último de los componentes esenciales de la arquitectura


von Neuman: el manejo de interrupciones.

Este concepto es habitualmente difícil de entender en los cursos básicos de


computación porque se aparta de lo que “intuitivamente” pensamos de la ejecución de un
programa: siempre pensamos que la próxima instrucción (o sentencia) que se ejecuta de un
programa es la que está escrita a continuación en el código, o siendo más precisos (para
contemplar los saltos) la que está a continuación en la lógica de ejecución del programa.
Esto, que parece hasta de perogrullo, sin embargo no es cierto debido justamente al
mecanismo de interrupciones que se utiliza en todos los sistemas que se basan en los
conceptos de programa almacenado.

Primeramente veremos una justificación de porqué es conveniente utilizar un


mecanismo de este tipo, para luego presentar una definición de lo que es una interrupción.

16.2 Justificación del Manejo de E/S por Interrupciones

16.2.1 Técnica de “Poleo”

Imaginemos la siguiente situación: tenemos un computador al que se le conecta una


“terminal tonta” mediante un puerto de comunicaciones serial. Una terminal de este tipo
consiste en una pantalla capaz de desplegar caracteres y un teclado. En la pantalla se
despliegan los caracteres recibidos por la conexión serial, mientras que las teclas digitadas
en el teclado son enviadas como caracteres por dicha conexión.

Complementemos el cuadro diciendo que en el computador se ejecuta un programa


de edición básica de texto (que va mostrando en la pantalla de la terminal el texto que va
digitando el usuario en el teclado de la misma).

Una forma de diseño de este programa implica que el programa esté en un “loop”
(con una estructura tipo while) esperando por la aparición de un carácter en el puerto serie
del computador al que está conectado el terminal. Cuando éste aparece lo procesa para
desplegarlo en la pantalla, mueve el cursor un lugar hacia delante (eventualmente
cambiando de línea) y vuelve al bucle de espera por un nuevo carácter.

Supongamos por un momento que se necesitan 1000 instrucciones de máquina


para procesar un carácter recibido en el puerto serie. Si tenemos en cuenta que un hábil
digitador es capaz de teclear del orden de 60 palabras por minuto y considerando que una
palabra promedio tiene del orden de 5 letras, concluimos que la tasa de ingreso de
caracteres es:
60 palabras / minuto * 5 letras / palabra = 300 letras / minuto = 5 letras /
segundo

Esto significa que el tiempo entre que el usuario digita una letra y la siguiente es del
orden de 0,2 segundos (200 ms).

Supongamos que el procesador de este computador tiene una capacidad de


proceso de 1 MIPS (Millón de Instrucciones Por Segundo). Esto significa que en 200 ms
puede ejecutar 200.000 instrucciones. De ellas requiere 1000 para procesar la tecla,
mientras que las restantes 199.000 se desperdician en el “loop” de espera.

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Una idea que surge casi enseguida es: ¿porqué no utilizar esas “instrucciones
muertas” para atender los requerimientos de otros usuarios?. Podríamos, por ejemplo,
conectar múltiples terminales “tontas” con un programa de edición de texto que fuera
consultando los distintos puertos de comunicación serie de forma de detectar los caracteres
que vayan llegando y procesando los mismos.

Si bien esto es posible surge el inconveniente que el programa de edición de texto


debería ser adaptado (modificado) cada vez que se agrega o se quita una conexión de
terminal y aún en el caso que pensáramos en un mecanismo mas dinámico que la re-
compilación (ej: un array dinámico de direcciones de puertos serie "activos" parametrizable
en tiempo de ejecución) tendríamos la restricción que el programa cumpliría la misma
función para todos los usuarios conectados.

Obviamente que esta restricción también podríamos levantarla haciendo programas


"combinados" que atendieran múltiples tipos de requerimientos (editores de texto,
compiladores, planillas de cálculo, procesadores de imágenes, etc, etc) pero es evidente
que las combinaciones serían muchas y el código sería cada vez mas complicado para
poder "polear" distintos puertos de comunicación serie e invocar los módulos apropiados en
cada caso.

La solución que se encontró a este problema es, en definitiva, la existencia de un


programa (denominado Sistema Operativo) que se encarga del manejo de los
controladores de comunicación y le pasa los caracteres a los programas apropiados. Y para
no desperdiciar instrucciones en bucles ociosos se recurre a la técnica que el controlador
de E/S que maneja la comunicación tenga la capacidad de "avisar" cuando dispone de un
carácter para ser procesado. El mecanismo de aviso es justamente a través de las
interrupciones.

16.2.2 Sincronización con la E/S

Otra razón por la cual se utiliza este mecanismo tiene que ver con la eficiencia del
acceso a los dispositivos de entrada/salida y, en particular, a los dispositivos de
almacenamiento masivo.

Una gran proporción de los programas utiliza las unidades de disco para almacenar
la información que requieren procesar y para guardar el resultado de ese proceso en los
denominados sistemas de archivos. Estos dispositivos involucran habitualmente
elementos mecánicos en su construcción (ej: discos que giran y que son leídos por una
cabeza que se desplaza movida por un "actuador"). Los "tiempos de respuesta" de los
dispositivos mecánicos son siempre varios órdenes de magnitud más lentos que los
electrónicos. Por ejemplo un disco moderno tiene un muy buen tiempo de acceso (se
denomina así al tiempo promedio para acceder al bloque de información grabado en alguna
de sus pistas) respecto a los diseños originales, estando actualmente por debajo de los 10
ms. Sin embargo ese tiempo es "una eternidad" si lo comparamos con el tiempo de acceso
de una memoria electrónica (entre 10 ns y 100 ns).

Esta situación lleva al hecho que si un programa requiere un dato de un disco debe
esperar del orden de 10 ms para poder disponer de él. Aún si tomamos el ejemplo del
procesador de 1 MIPS (en la práctica hoy se utilizan procesadores capaces de ejecutar
cientos de MIPS) vemos que durante ese tiempo de espera el procesador podría haber
ejecutado del orden de 10.000 instrucciones. Por esto realizar la sincronización de la
entrada/salida mediante la técnica de enviar el comando correspondiente y quedarse a
esperar la respuesta resulta en algo sumamente ineficiente.

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

Al igual que en el caso de las terminales tontas, aquí conviene utilizar el procesador
para ejecutar otros programas mientras los controladores de E/S, con su inteligencia propia,
realizan la operación requerida y cuando terminan "avisan" que los datos ya están
disponibles en algún lugar accesible a tiempos "electrónicos" (ej: un "buffer" en el
controlador de E/S ó incluso en la propia memoria del sistema).

Al igual que en el caso anterior la solución pasa por un programa especial (el
Sistema Operativo) que se encargue de la E/S y por el mecanismo de interrupciones que
habilite la posibilidad de avisar de la culminación de la operación de E/S solicitada.

16.3 Definición

Una definición de interrupción puede ser:

Una interrupción consiste en un mecanismo que provoca la alteración del


orden lógico de ejecución de instrucciones como respuesta a un evento externo,
generado por el hardware de entrada/salida en forma asincrónica al programa que
está siendo ejecutado y fuera de su control.

En forma alternativa se puede decir que:

Una interrupción consiste en un mecanismo que le permite al hardware la


invocación de una rutina fuera del control del programa que está siendo ejecutado.

Analicemos el contenido de la primer definición que hemos dado. Por un lado


decimos que se trata de un mecanismo, cuyos detalles veremos mas adelante, que provoca
la alteración del orden lógico de ejecución de instrucciones. Esto significa que cuando
ocurre una interrupción la próxima instrucción a ser ejecutada no es la que corresponde a la
secuencia lógica de instrucciones del programa que se está ejecutando, que vendría a ser
la apuntada por el IP (Instruction Pointer), sino que dicha secuencia se modifica y se pasa a
ejecutar otra instrucción (concretamente la primera de la rutina de servicio de la
interrupción correspondiente al pedido atendido).

Por otro lado nos referimos a que es en respuesta a un evento externo, que está
generado por el hardware de entrada/salida, es decir que no es el programa que lo genera
(al menos no en forma directa), siendo provocado por el hardware, en particular el asociado
a los dispositivos de entrada/salida, más concretamente: los controladores de E/S.

Y finalmente se menciona que es asincrónico y fuera de su control, lo que significa


que el programa que está siendo ejecutado no tiene control sobre el momento en que este
mecanismo se dispara, ni sobre la propia ocurrencia del fenómeno. Es decir que, en
particular, no hay sincronismo entre la ejecución del programa y la, eventual, invocación a
esa rutina "especial" disparada por la interrupción.

16.4 Pedido de Interrupción

El mecanismo de interrupción comienza con el pedido de interrupción ("interupt


request") generado por un controlador de entrada/salida.

Este pedido se genera a raíz de alguna condición detectada por el controlador (ej:
dispone de un dato para ser leído por la CPU, terminó de ejecutar la lectura del sector de
disco solicitada, hay una condición de error en el byte recibido por la línea de
comunicaciones, etc, etc).

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Las condiciones que generan el pedido varían de acuerdo al tipo de controlador que
se trate y de acuerdo a como esté configurado el mismo. Hay controladores capaces de
solicitar interrupciones ante determinadas y diferentes condiciones de error, pero que
pueden ser programados para no hacerlo a través de bits que habilitan/deshablitan la
posibilidad que una situación particular pueda generar, o no, una interrupción.

Los controladores de E/S disponen de una señal de salida (habitualmente


denominada INT ó INTR ó IRQ) que toma el valor "1" cuando el controlador interrumpe.
Normalmente esa salida es el reflejo hardware de un bit del registro de ESTADO. Es decir
que el nivel actual (0 ó 1) de la señal INT del controlador de E/S puede leerse en un bit de
dicho registro. Este bit de "pedido de interrupción pendiente" y su correspondiente reflejo en
el hardware permanece en nivel alto hasta que la rutina de atención de la interrupción
realice alguna operación sobre los registros del controlador de E/S que satisfaga el pedido,
con lo cual el controlador procederá a pasar ese bit (y su salida INT) a 0. Cuál es esa
acción dependerá del controlador y, posiblemente, de la condición que provocó el pedido.
Algunos pedidos de interrupción se satisfacen con la lectura del registro de estado, otros
requieren de la lectura de algún registro adicional, otras requieren de la escritura de un
registro, etc.

En las CPUs también existe esta señal, que recibe denominaciones similares (INT,
IRQ, etc), pero que es de entrada. Esta entrada es la que el hardware de la CPU consulta
para determinar si hay algún pedido de interrupción por parte de algún controlador de E/S.

Luego lo veremos en mayor detalle pero adelantemos que la CPU chequea la


existencia de un pedido de interrupción al finalizar la ejecución de cada instrucción. Si
detecta una solicitud, procede a desencadenar el mecanismo que desemboca en la
ejecución de la rutina de servicio de la interrupción, luego de la cual se pasa a ejecutar la
próxima instrucción del programa interrumpido (la que se hubiera ejecutado si no hubiera
existido la interrupción), siempre que no existe un nuevo pedido de interrupción, en cuyo
caso se desencadenará un nuevo proceso de invocación a la rutina de servicio que
corresponda.

De acuerdo a la forma que la CPU detecta que hay un pedido de interrupción se


distinguen dos casos: detección por nivel y detección por flanco.

16.4.1 Detección por Nivel

En este caso la CPU reconocerá que hay un pedido de interrupción pendiente


mientras su entrada INT esté en el nivel lógico alto ("1").
Esto significa que toda vez que la CPU detecte esa entrada en alto, desencadenará
la invocación a la rutina de atención, incluso cuando haya terminado recién de ejecutar una
rutina de interrupción.

16.4.2 Detección por Flanco

En este caso lo que interesa a los efectos de determinar que existe un


requerimiento de interrupción es la existencia de un cambio de nivel bajo ("0") a alto ("1"),
es decir un flanco, en la entrada INT.
Es decir que no importa el valor absoluto actual de la entrada INT, lo que se tiene en
cuenta es si existió un cambio de 0 a 1. Si hubo un flanco y aún no ha sido invocada la
rutina de atención, la CPU lo hace y da por cumplido el pedido.

Luego veremos que esto tiene sus implicancias en el diseño de las rutinas de
servicio a las interrupciones.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

16.4.3 Circuito Equivalente de la entrada INT

La entrada INT tiene el siguiente circuito lógico equivalente:

La entrada INT a la CPU alimenta la entrada de reloj de un flip-flop D cuya entrada


D está en nivel lógico alto ("1"). Esto hace que en cada flanco ascendente de INT el flip-flop
adopta el valor "1" en su salida Q. La salida del FF y la propia entrada INT se presentan a
un multiplexor cuya entrada de control selecciona si la salida INT-Interno corresponde
directamente a la señal INT (cuando es por nivel) ó a la señal Q (cuando es por flanco).
Esta entrada de control del multiplexor permite configurar si la CPU va a trabajar por nivel o
por flanco en su entrada de pedido de interrupción. Finalmente la CPU activa la señal
Borro-Pedido-Int cada vez que invoca a la rutina de servicio de la interrupción de forma de
pasar el FF a 0. La señal INT-Interno es la que la CPU consulta para determinar si hay un
pedido de interrupción pendiente.

16.5 Atención del Pedido de Interrupción

Cuando la CPU reconoce que hay un pedido de interrupción desencadena el


mecanismo de atención a dicha solicitud. Por ahora vamos a considerar que la CPU acepta
la interrupción, dejando para más adelante la consideración de en qué casos esto ocurre.

Para atender una solicitud de interrupción, la CPU realiza los siguientes pasos:

• "termina" de ejecutar la instrucción actual. Notemos que utilizamos las comillas


para señalar que, en realidad, lo que ocurre es que la CPU consulta si hay un
pedido de interrupción al final del ciclo de instrucción, luego de la etapa de
"write" y antes del siguiente "fetch". Esto se traduce en que el pedido de
interrupción debe esperar hasta el final de la ejecución de la instrucción para que
sea efectivamente detectado como tal.

• salva el valor actual del puntero de instrucción (IP), como forma de poder
regresar a ejecutar la siguiente instrucción del programa que fue interrumpido,
luego de la ejecución de la rutina de servicio a la interrupción.
Es de destacar que las distintas arquitecturas realizan esta actividad de
diferentes formas. Podemos distinguir básicamente dos:
- utilizando un stack. Esta vía es la habitual en las arquitecturas que
implementan un stack por hardware, como es el caso de los
procesadores Intel.
- utilizando un registro. Esta vía es la habitual de las arquitecturas RISC,
en particular la SPARC.

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

También es de destacar que hay arquitecturas que salvan adicionalmente otros


registros. Por ejemplo los procesadores Intel salvan el registro que contiene el
estado del CPU (el registro de FLAGS) incluyendo los bits de condición (Zero,
Negative, Carry, oVerflow) que generó la ALU en la última instrucción ejecutada.
En el mismo caso de Intel x86 además, como consecuencia de utilizar un
modelo de direccionamiento de memoria segmentado, salvan el registro que
contiene el identificador del segmento de código del programa que fue
interrumpido.

• identifica el controlador de E/S que realizó el pedido de interrupción. Veremos


este tema en el siguiente punto.

• obtiene la dirección de la rutina de servicio de la interrupción correspondiente al


controlador identificado. También hay distintas formas de implementar esto,
aunque la mayoría son variaciones sobre el concepto de vector de
interrupciones.
- la arquitectura Intel x86 utiliza un identificador de 8 bits del pedido de
interrupción como índice a una tabla (el vector de interrupciones) que en
cada entrada tiene la dirección absoluta de la rutina de interrupción
asociada, formada por el segmento (valor a cargar en el registro de
segmento de código) y el desplazamiento dentro del segmento (valor a
cargar en el puntero de instrucción) de la dirección de memoria de la
primer instrucción de la rutina de interrupción.
- la arquitectura SPARC utiliza también un identificador de 8 bits para el
pedido de interrupción, el cuál multiplica por 16 antes de sumarle el valor
contenido en un registro especial (el Trap Base Register, ó registro base
de "traps", nombre que le da SPARC a las interrupciones) para formar la
dirección a la cuál se va a pasar el control. De esta forma tenemos una
especie de tabla que almacena las primeras 4 instrucciones (SPARC
tiene instrucciones de largo fijo de 4 bytes) de cada rutina de
interrupción.

• enmascara las interrupciones. Esto significa que inhibe la aceptación de nuevos


pedidos de interrupción hasta tanto ocurran uno de los siguientes eventos: se
retorne de la rutina de servicio de la interrupción (todas las arquitecturas tienen
una instrucción específica para hacer esto) ó el código de la rutina de servicio
habilite en forma explícita (a través de una instrucción) la posibilidad de aceptar
nuevas interrupciones.
Esto lo hace con el fin de que múltiples interrupciones simultáneas (desde el
punto de vista del mecanismo de detección) no sobre-escriban los lugares que
se están utilizando para salvar el puntero de instrucción ú otros registros vitales
para poder retornar sin inconvenientes al programa originalmente interrumpido.
De esta forma le permiten a la rutina de interrupción tomar los recaudos
apropiados para evitar esto y recién luego, si corresponde y tiene sentido para el
sistema en su globalidad, proceder a habilitar nuevamente las interrupciones.

• pasa a ejecutar la rutina de servicio a la interrupción (ó rutina de interrupción a


secas), cargando en el puntero de instrucción la dirección de la primer
instrucción de dicha rutina.

16.6 Identificación del Controlador que solicita la Interrupción

Es normal que un sistema tenga múltiples controladores de E/S. Por tanto hay que
tener un mecanismo que permita saber cuál controlador de E/S generó un pedido concreto

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

de atención mediante el mecanismo de interrupción.

Las soluciones a este problema son variadas y pueden estar basadas en el


hardware o en el software.

16.6.1 Identificación por Hardware

16.6.1.1 Líneas INT/IRQ independientes en la CPU

En este caso el propio CPU tiene múltiples entradas INT (numeradas, por ej: INT0,
INT1, INT2, etc) y la idea es conectar un controlador de E/S a cada una de ellas. La
identificación es entonces por hardware y directa: el controlador que está pidiendo la
interrupción es el que está conectado a la entrada INTn donde se detecta la solicitud. En
este caso hay una dirección de la rutina de servicio a la interrupción por cada línea de
pedido disponible.

En algunos casos, como en el ejemplo de la arquitectura SPARC, las entradas de


solicitud de interrupción están codificadas. Esto quiere decir que el SPARC en vez de tener
16 entradas de solicitud independientes, tiene 4 entradas en las cuáles se presenta el
código binario del pedido de interrupción. Esto exige la inclusión de un hardware de
codificación externo a la CPU de forma de convertir las entradas de solicitud individual a las
entradas codificadas de la CPU.

16.6.1.2 Mecanismo INT/INTA

En mecanismo fue diseñado por Intel para sus primeros microprocesadores de 8


bits (8080 y 8085) y luego mantenido en las sucesivas familias arquitectónicas que los
sucedieron. La idea es que el CPU dispone de una única entrada de pedido de interrupción
INT, a la cuál se conectan en modalidad OR-cableado todos los pedidos de interrupción de
los distintos controladores de E/S. También dispone de una salida denominada INTA
(Interrupt Acknowledge) que le avisa al controlador de E/S que ha sido aceptado su
solicitud de interrupción y le indica con esa señal que coloque en el bus de datos su
identificación. La CPU entonces realiza una lectura del bus de datos y obtiene el
identificador.
Este procedimiento se extiende para el caso de múltiples controladores mediante el
encadenamiento de las señales INTA (los controladores de E/S que soportan este
mecanismo tienen una entrada y una salida INTA) según el siguiente esquema:

CPU MEM

INT

INTA Cont. Cont. Cont.

De esta manera cuando la CPU inicia el ciclo de atención a un pedido de


interrupción y levanta su señal de salida INTA, la misma se va propagando por los distintos

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

controladores en forma encadenada. De esta forma el primer controlador de la cadena que


tenga un pedido de interrupción pendiente procederá a no continuar con la propagación de
la señal INTA hacia los restantes controladores y será él quien coloque en el bus de datos
su identificador.

Esto establece una prioridad implícita en la forma de interconectar los controladores,


ya que los que estén mas cerca de la CPU tendrán la posibilidad de ser atendidos antes en
caso de coincidir en el tiempo con un pedido de otro controlador que esté más distante (en
"saltos de INTA") de la CPU.

Este mecanismo, si bien técnicamente es viable, parte del supuesto que cada
controlador de E/S existente tendrá su propio identificador (fijado en el hardware). Esto
sumado al hecho que inicialmente se reservaron solamente 8 bits para dicho identificador
llevó a que no fuera posible acomodar las distintas variantes de controladores que los
distintos fabricantes diseñaban. Esto sumado al hecho que solamente los
microprocesadores de Intel tenían este mecanismo, llevó esta propuesta al fracaso
comercial y en poco tiempo la propia Intel debió reconocer que no podía imponer a la
industria su idea y generó el concepto de controlador de interrupciones como forma de
permitir que un controlador de E/S que no estuviera diseñado para usar este mecanismo
pudiera de todos modos conectarse a un sistema con INTA.

16.6.1.3 Controlador de Interrupciones

En particular se utiliza en la arquitectura x86 como forma de compatibilizar el


mecanismo INT/INTA con controladores de E/S que no lo utilicen. La idea es que un
controlador de interrupciones posee múltiples líneas de entrada de solicitud INT (en el caso
del 8259 de Intel se denominan IRQ) para la conexión de los pedidos de interrupción de los
diferentes controladores de E/S. Tiene, a su vez, una única salida de pedido de interrupción
INT con su correspondiente INTA para implementar el mecanismo de identificación por
hardware.

CPU MEM

INT IRQ0

Cont. Cont.
INTA Int.
IRQ7

Cont.

Cuando un controlador de E/S solicita una interrupción, el controlador de


interrupciones genera el pedido a la CPU a través de la señal INT. La CPU cuando acepta
la interrupción activa la señal INTA y en ese momento es el controlador de interrupciones
quién coloca en el bus de datos la identificación que está asociada a la entrada IRQ por la
que llegó el pedido. El controlador de interrupciones es configurable y tiene registros en los
cuales se puede almacenar cuál es la identificación que presentará para cada una de las
líneas IRQ. De esta forma al inicializar los contenidos de estos registros se puede

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

configurar dinámicamente cuáles identificadores se utilizarán para los distintos


controladores de E/S que se conecten en las distintas entradas de requerimiento de
interrupción.

16.6.2 Identificación por Software

Esta categoría aplica cuando todos los controladores de E/S conecten su salida de
pedido de interrupción en OR-Cableado a la única entrada INT de la CPU. Más
genéricamente aplica cuando hay múltiples controladores conectados en OR a la misma
entrada de INT, sea ésta única o no. En esta situación la rutina de servicio de la
interrupción debe tener una parte inicial que consista en el recorrido de los distintos
controladores de E/S, leyendo los registros de estado hasta encontrar aquél que tenga su
bit de "pedido de interrupción" en "1". En ese caso se invocará a la sub-rutina asociada a
ese controlador específico.

Como la entrada de INT es el OR de todos los pedidos de los controladores, para el


caso de que la CPU detecte por nivel no corro el riesgo de dejar de atender a algún
controlador, aún en el caso que la estrategia de la rutina de atención sea del estilo
"encuentro el primer controlador con solicitud pendiente, lo atiendo y salgo de la rutina de
servicio de interrupción". Pero en el caso de la detección por flanco existe ese riesgo como
vamos a analizar a continuación.

Para entender el problema analicemos el siguiente diagrama de tiempos, donde se


muestra por un lado las salidas de pedidos de interrupción de dos controladores A y B y por
otro el OR de ambas (que es lo que la CPU ve a su entrada de pedido de interrupción).

INT CPU

INT-B

INT-A

En el diagrama se muestra que primero ocurre el pedido de interrupción del


controlador A, el cual provoca que la entrada a la CPU pase también a 1 (esto es porque es
el OR cableado). Antes que la rutina de servicio a la interrupción llegue a ejecutar la acción
que satisface el requerimiento del controlador A, el controlador B pasa su salida a 1,
indicando que también tiene un pedido de interrupción para ser procesado. En la entrada a
la CPU ese cambio no se ve reflejado porque al ser un OR, resulta que 1 OR 0, ó 1 OR 1
da el mismo resultado. Luego en el diagrama de tiempo se muestra que la salida del
controlador A pasa a 0, en el momento que la CPU, luego de haber identificado que el
controlador A está solicitando interrupción, ejecuta la instrucción que corresponde a lo que
el controlador de E/S entiende como condición para dar por satisfecho su requerimiento.
Notemos que si bien INT-A pasa a 0, la entrada de pedido de interrupción a la CPU sigue
en 1 (porque INT-B sigue en ese valor).

Analicemos que pasaría si en este momento y en esta situación, enseguida después


de haber detectado y procesado el pedido del controlador A, la rutina de servicio de la

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

interrupción termina su ejecución y el control retorna al programa que fue interrumpido.

Si la detección es por nivel esto no representa un problema, porque de darse esta


situación el pedido de interrupción del controlador B sigue vigente y el mecanismo de
atención al pedido de interrupción se disparará inmediatamente de nuevo.

Pero en cambio si la detección es por flanco y sucede la situación descripta, la


rutina de servicio de la interrupción no será invocada nuevamente porque a los efectos de
la CPU la solicitud del controlador B no existió, ya que el flanco que hubiera generado en la
entrada INT quedó "enmascarado" por el nivel alto que ya existía en ese momento como
consecuencia del pedido, aún no satisfecho, del controlador A. En otras palabras: el
controlador B queda sin ser atendido. Y lo que es peor, si el controlador A (o cualquier otro
controlador que estuviera conectado a esa línea de entrada) pide una nueva interrupción,
ésta tampoco sería detectada. Es más: todo el mecanismo de interrupciones queda
bloqueado.

Enfrentado a este problema una primer solución que viene a la mente es que la
rutina de servicio de la interrupción consulte el estado del controlador B antes de terminar
su ejecución. Si el controlador B tiene un pedido pendiente se lo atiende y entonces su
salida baja a 0 y se resuelve el tema. ¿Se resuelve?. Falso. Porque si bien resolvimos la
situación concreta analizada, es fácil ver que si mientras estoy atendiendo al controlador B,
el controlador A vuelve a pedir interrupción y al terminar de procesar el B la rutina de
servicio termina, estaremos en un problema similar (sólo que esta vez será el A el que
bloquea el mecanismo). Esta situación podría repetirse múltiples veces, con lo que
parecería no haber solución al problema. Sin embargo existe una estrategia de diseño de la
rutina de servicio que permite que el sistema de pedidos de interrupción no se tranque al
utilizar detección por flanco con múltiples controladores en la misma línea de solicitud. Esta
estrategia será motivo de un ejercicio práctico, aunque se puede adelantar que la misma
tiene que ver con asegurarse de alguna forma que la entrada INT estuvo en algún momento
en 0, con lo que no interesa el estado de dicha entrada al momento de salir de la rutina de
servicio de la interrupción. Si esto ocurrió (INT estuvo en 0 en algún momento), entonces se
habrá detectado un nuevo flanco y por tanto si el flanco existió la rutina de atención será
invocada nuevamente.

16.7 Habilitación de Interrupciones

La CPU tiene la capacidad de aceptar o no los pedidos de interrupción de los


controladores de E/S. Esta capacidad está implementada de dos maneras, una general y
otra selectiva, a las que denominaremos enmascaramiento y deshabilitación, sólo a los
efectos de distinguirlas en la denominación.

• enmascaramiento: en este caso la CPU posee la propiedad de poder inhibir la


aceptación de todas las solicitudes de interrupción, sin importar de cuál
controlador provengan. Esto se realiza a través del valor de un bit de máscara
de interrupción (que recibe el nombre de IM = Interrupt Mask, EI = Enable
Interrupt, ET = Enable Traps, etc, dependiendo de la arquitectura), normalmente
perteneciente al registro de estado de la CPU (denominado registro de FLAGS,
o regitro PS por Processor Status). La CPU para determinar si hay un pedido
efectivo de interrupción hace el AND de la señal de pedido interno de INT con el
valor de este bit y utiliza este resultado para tomar la decisión. Si el bit está en 0
no existirá un pedido efectivo (por más que haya controladores de E/S
solicitando interrupción). Si está en 1 los requerimientos de interrupción que
hubiera serán procesados.

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

El valor de este bit se cambia mediante instrucciones específicas del set de


instrucciones del procesador. A estas instrucciones las denominaremos enable y
disable. En un lenguaje de alto nivel las representaremos por los
procedimientos enable() y disable().
La CPU pone automáticamente a 0 este bit al invocar a la rutina de servicio de la
interrupción. Por ello una rutina de interrupción comienza su ejecución con
las interrupciones deshabilitadas y así continuarán a menos que
explícitamente sean habilitadas por el código de la propia rutina. La instrucción
que provoca la finalización de la rutina de interrupción y el retorno a la ejecución
del programa interrumpido vuelve a recuperar el valor anterior del bit (el cuál
obviamente era 1 porque sino no se hubiera invocado).
También es de señalar que cuando una CPU comienza a funcionar (se le aplica
energía por primera vez) también arranca con las interrupciones enmascaradas
(deshabilitadas).

En todas las CPUs existe una entrada, independiente de la INT, denominada


NMI (por Non Maskable Interrupt) que trabaja en forma independiente de la
máscara de inhibición y un pedido de interrupción que por ella sea presentado
será siempre procesado. La idea de esta entrada es conectar a ella pedidos de
interrupción críticos (tales como la falla de la fuente de alimentación ó la
detección de un error de paridad en la memoria). En la práctica la arquitectura
de los computadores tipo PC no la utilizan.

• deshabilitación: en este caso se actúa sobre los controladores de E/S en forma


individual, de forma de inhibir su eventual pedido de interrupción. Los
controladores de E/S tienen habitualmente un bit en su registro de CONTROL
que actúa como máscara para su salida de pedido de interrupción. De hecho la
salida tendrá el valor resultante de la ecuación:
salida INT = bit INT registro de ESTADO AND bit MASK_INT registro de
CONTROL
Notemos que el bit que refleja la condición de "pedido de interrupción pendiente"
del registro ESTADO sigue reflejando si el controlador requiere de la
intervención de la CPU. Lo que sucede es que la salida de hardware hacia la
CPU queda condicionada al valor del bit de habilitación del registro CONTROL.
Este mecanismo permite al programador tener poder de decisión selectivo sobre
qué controladores de E/S podrán generar pedidos de interrupción y cuáles no.

El bit MASK_INT descripto inhibe totalmente la generación de interrupciones por


parte del controlador de E/S. Algunos controladores de E/S disponen también de
otros bits de máscara que actúan a nivel diferenciado sobre las distintas posibles
condiciones que generan interrupciones. Por ejemplo en un controlador de
comunicaciones se pueden generar interrupciones por distintos motivos:
recepción de un carácter, error en la línea de comunicaciones, carácter
transmitido, cambio en las líneas de control de la comunicación, etc. y el
controlador puede tener bits que inhiban en forma individual la generación de
solicitudes de interrupción asociadas a cada condición.

16.8 Prioridades

Existen dos situaciones que pueden llevar al mecanismo de interrupciones a tener


que tomar una decisión acerca de cómo proceder:
- hay dos (o más) solicitudes de interrupción simultáneas
- hay una (o más) solicitud de interrupción mientras se está ejecutando
una rutina de servicio de una interrupción previa y las interrupciones han

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

sido habilitadas.

En cualquiera de ellas la decisión dependerá de la existencia de prioridades entre


los distintos requerimientos.

16.8.1 Interrupciones Simultáneas

Cuando una CPU o un controlador de interrupciones implementa un mecanismo de


prioridades, éste determinará cuál de múltiples solicitudes que ocurran a la misma vez será
atendida.
Es de notar que el concepto de simultaneidad no implica que los pedidos de
interrupción lleguen exactamente en el mismo instante del tiempo, sino que lleguen durante
el período entre una verificación y otra por parte de la CPU, la cuál puede estar postergada
en el tiempo si las interrupciones están deshabilitadas.

El mecanismo de prioridades puede adoptar distintas estrategias: prioridad fija,


prioridad configurable o sin prioridad.
Cuando la prioridad es fija siempre será atendida primero la solicitud que provenga
de una línea de pedido que tenga mayor jerarquía. Normalmente se utiliza la numeración de
las entradas para fijar su prioridad.
Cuando la prioridad es configurable, la misma se puede cambiar en función de las
condiciones del sistema en general.
Cuando el sistema es sin prioridad debe implementar un sistema de selección de
la solicitud a atender que asegure la equitatividad en selección de las distintas entradas.

El mecanismo de prioridades puede estar implementado por hardware o por


software. Cuando es por hardware se puede realizar a nivel de la CPU (si tiene múltiples
entradas de interrupción, ya sean directas o codificadas) ó a nivel del controlador de
interrupciones. Cuando es por software el mecanismo se implementa como un algoritmo en
la rutina de atención a la interrupción (notemos que esta vía es la única para el caso de
CPUs con una única entrada INT y sin controlador de interrupciones). El algoritmo puede
implementar cualquiera de las estrategias vistas, mediante un apropiado recorrido de los
controladores de E/S para averiguar cuál fue el que interrumpió, como ser:
- recorido lineal: siempre comenzando por el mismo y con un orden pre-
establecido (prioridad fija)
- recorrido programable: utilizando una tabla que establece el orden a
seguir (prioridad configurable)
- recorrido "round-robin": comenzando cada vez en el siguiente al último
atendido, en forma circular.

16.8.2 Interrupción de Interrupción

Suponiendo que las interrupciones no están enmascaradas durante la ejecución de


la rutina de interrupción (recordar que para que esto ocurra la rutina debe explícitamente
ejecutar la instrucción que desenmascara las interrupciones) y ocurre un pedido de
interrupción, la atención o no de dicha solicitud dependerá del esquema de
jerarquías/prioridades que tenga implementada la CPU y/o el controlador de interrupciones.

Como regla general sólo se aceptará una interrupción de un nivel igual o superior
(en algunas arquitecturas puede ser solamente si es superior en sentido estricto) al de la
interrupción que está siendo actualmente atendida.

Para esto el mecanismo de interrupciones mantiene en algún registro el "nivel actual


de interrupción" que refleja la prioridad de la interrupción que está siendo servida. Al ocurrir

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

una nueva solicitud, se compara el nivel de la interrupción asociado al nuevo pedido con el
actual y sólo se procede si es mayor ó igual (ó mayor estricto) al actual. Ese valor es
actualizado al momento de invocar la rutina de interrupción.

Las distintas propuestas arquitectónicas resuelven esto de distintas formas. La


propuesta Intel lo hace en el controlador de interrupciones a través del registro ISR (In
Service Register), mientras que SPARC lo hace en el procesador a través de los bits de IPL
(Interrupt Processor Level) del registro PS (Processor Status).

16.9 Rutinas de Interrupción

16.9.1 Preservación del Contexto

Las rutinas de interrupción (también denominadas de servicio a la interrupción ó de


atención a la interrupción) son la pieza de código que se ejecuta como resultado del
mecanismo que desencadena la CPU al procesar un pedido de interrupción.

Como esta pieza de código se ejecuta en forma asincrónica a la ejecución del


programa que es interrumpido y sin conocimiento de parte de éste, hay que tener ciertas
precauciones al escribir este tipo de rutinas.

La consideración fundamental es que las rutinas de interrupción deben preservar el


contexto del programa interrumpido.

Se entiende por contexto de un programa a su estado completo, el cuál incluye


todas sus variables y estructuras de memoria, incluyendo las que están almacenadas en
forma transitoria en los registros de la CPU y alcanzando al valor de los registros especiales
de la misma, en particular el registro de banderas o bits de condición (los bits Z, N, C y V).

Parte de este contexto es salvado por el hardware quién, además del puntero de
instrucción, en algunas arquitecturas salva el registro de estado del procesador (o registro
de banderas o flags) como es el caso de Intel x86. Pero el resto debe ser salvado (o no
alterado) por la propia rutina de interrupción, con las consideraciones correspondientes a
dos situaciones distintas: no es lo mismo si la máquina es no dedicada que si es
dedicada.

16.9.1.1 Máquina No Dedicada

En este caso en la máquina donde se ejecuta la rutina de interrupción existen


múltiples programas en ejecución, con distintos propósitos, los cuáles han sido
programados por distintos equipos de programadores, sin coordinación alguna.
En este caso hay que respetar a rajatabla la regla que la rutina de interrupción no
puede modificar ninguna parte del contexto del programa interrumpido y si requiere del uso
de algún registro de la CPU (cosa harto probable) deberá previamente salvarlo. Los lugares
y procedimientos paa hacerlo dependerá del tipo de arquitectura (stack, array de memoria
local, etc).

16.9.1.2 Máquina Dedicada

En este caso la máquina está completamente dedicada a una función específica y


todos los programas y rutinas que en ella se ejecutan están desarrollados por el mismo
equipo de programadores o por equipos fuertemente coordinados.
En este caso los equipos de programadores pueden establecer reglas de uso de los

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura de Computadoras Notas de Teórico

recursos compartidos del sistema (típicamente los registros de la CPU) de forma que se
evite la necesidad de tener que salvarlos en la rutina de interrupción e incluso puede existir
la necesidad de que la rutina de interrupción modifique alguna variable del programa
interrumpido (típicamente el programa principal) de forma de alertarlo de alguna condición
ocurrida en la E/S y comunicada por este mecanismo.

16.9.2 Estrategias de Programación

Para programar sistemas que contengan rutinas de interrupción existen multiplicidad


de estrategias y estilos. Normalmente constarán de un programa principal y una o más
rutinas de interrupción asociadas a los dispositivos de E/S que deben ser considerados por
el sistema.
Se pueden distinguir los siguientes casos en cuanto a la decisión de dónde colocar
la lógica del sistema (la parte del código que implementa el núcleo de su comportamiento):

• toda la lógica del sistema se implementa en el programa principal y las rutinas


de interrupción solamente modifican banderas indicando que se ejecutaron.

• toda la lógica se implementa en las rutinas de interrupción y el programa


principal o bien está en loop infinito (máquina dedicada) o bien instala e inicializa
las rutinas de interrupción y termina (máquina no dedicada).

• la lógica se implementa en parte en el programa principal y en parte en las


rutinas de interrupción.

No hay una regla general que indique cuál de las estrategias es la más apropiada.
Quizás lo que sí se pueda decir es que conviene alguno de los casos extremos, porque la
distribución de la lógica entre el programa principal y las rutinas vuelve bastante engorroso
el análisis y la depuración (debug) del código resultante.

En particular la estrategia de poner toda la lógica en el programa principal es la que


permite mayor facilidad a la hora de las tareas de depuración (aunque no implica
necesariamente que el código resultante sea el más sencillo siempre).

También se debe tener en cuenta que en las máquinas no dedicadas no se debe


dejar en loop infinito un programa (porque lleva el consumo de CPU al 100% en forma
permanente, lo que no es adecuado en un ambiente multitarea / multiusuario). Por lo tanto
en este caso la estrategia apropiada es la de implementar la lógica totalmente en las rutinas
de interrupción.

La otra consideración a tener en cuenta es como implementar técnicas de polling


(para controladores sin capacidad de interrumpir) en sistemas con interrupciones. En este
sentido hay dos formas posibles:
- se dispone de un timer (reloj) que genera una interrupción periódica y en
la rutina de atención asociada se realiza la consulta al controlador de
E/S. Esta variante tiene la característica de poseer cierto retardo de
reacción frente a un cambio en la E/S, ya que depende del período del
timer, porque éste determinará cada cuanto tiempo, como máximo, se
producirá una interrupción.
- se realiza el "polling" en el programa principal. Es de notar que esta
variante es la que asegura que la reacción frente a un cambio en la E/S
sea instantánea.

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Jerarquía de Memoria

Arquitectura de Computadoras
(Versión 4.3 - 2012)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

19 JERARQUIA DE MEMORIA

19.1 Introducción

Este capítulo está dedicado al análisis de los distintos niveles de memoria existentes
en un computador, con especial énfasis en los sistemas de “cache”.

19.2 Justificación Tecnológica

Históricamente siempre existió un compromiso de diseño en los sistemas de


memoria: las memorias rápidas son más costosas que las memorias más lentas. Por tanto
un diseño equilibrado es aquel que combina en su justa medida memorias de un tipo y de
otro. Este diseño debe, además, lograr la mejor relación entre el coste del sistema y su
rendimiento (capacidad de proceso).

La solución a este problema es el concepto de jerarquía de memoria. Esta jerarquía


básicamente establece un orden en función de la capacidad de memoria y su velocidad. La
mayor jerarquía la tiene la memoria más rápida (y por tanto menor en tamaño, para
mantener el coste acotado) y la menor la memoria más lenta (y por tanto más económica)
pero por tanto más abundante.

Velocidad Tamaño (Bytes)

1ns Registros 100s

1ns Cache L1 Ks

10ns Cache L2 Ms

100ns Memoria Principal (RAM) Gs

10ms Memoria Secundaria (Disco) 100Gs

10s Memoria Terciaria (Cinta) Ts

Cuanto más descendemos en la jerarquía de memoria, más económica (y por tanto


más abundante) es la memoria. Por ejemplo en la actualidad una memoria RAM de 4
GBytes cuesta unos U$S 40, es decir unos 10 U$S / GByte. Un disco de 500 GBytes cuesta
del orden de U$S 100, es decir unos 0,2 U$S / GByte. Aquí vemos que en materia de
precio por capacidad de almacenamiento el disco le lleva una ventaja de 50 a 1 a la
memoria RAM. Si lo miramos velocidad de acceso el disco es 100000 veces más lento.

Por su lado un chip de memoria SRAM (construido con tecnología de flip-flops) de 4

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

Mb cuesta unos U$S 8, mientras que un chip DRAM (construido con tecnología de
memorias dinámicas) de 2 Gb sale U$S 1. Esto significa que la memoria SRAM cuesta
4000 veces más que la memoria DRAM !!. Esto lleva a la inviabilidad económica de
construir computadoras con memoria principal basada en tecnología SRAM.

Por otra parte en la década de los 90 del siglo pasado las tecnologías utilizadas para
implementar tanto la lógica de los procesadores como la de las memorias era bastante
similar en materia de la frecuencia de trabajo. Sin embargo la frecuencia de trabajo de la
lógica empezó a aumentar a un ritmo mayor que la de la memoria (en particular los circuitos
de memoria utilizados para la memoria RAM principal).

Memoria Logica

6000

5000

4000
MHz

3000

2000

1000

0
1992 1994 1996 1998 2000 2002 2004 2006 2008 2010

Si bien en la última década la tecnología de memoria logró, por lo menos, no seguir


perdiendo terreno, esto se debió básicamente a una ralentización del crecimiento de la
frecuencia de trabajo de la lógica de los procesadores, motivada por ciertas barreras físicas
difíciles de pasar con la tecnología de fabricación de circuitos integrados actualmente
utilizada.

Este fenómeno de diferencia notoria en las frecuencias de trabajo fue la que llevó a
la necesidad de mejorar y ampliar el uso de las memorias cache (tipo de memoria que
desarrollaremos más adelante) y de hecho se pasó de una sola memoria de este tipo a
tener dos (L1 y L2) y hasta tres niveles (L1, L2 y L3), como forma de mejorar el rendimiento
de las computadoras sin elevar excesivamente el costo.

19.3 Principio de Localidad

La organización jerárquica de la memoria se basa en una característica que poseen


la mayoría de los programas (al menos dentro de ciertos límites). Esta propiedad se
denomina principio de localidad.
El principio de localidad establece que los programas acceden a una porción

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

relativamente reducida del espacio de direcciones en un determinado lapso de tiempo.

El principio tiene dos variantes:

• Localidad temporal: si un ítem es referenciado en determinado momento, es


común que vuelva a ser referenciado poco tiempo después.

• Localidad espacial: cuando un ítem es referenciado en determinado momento,


es común que los ítems con direcciones “cercanas” también sea accedidos poco
tiempo después.

Pensemos en las estructuras de control tipo bucle ó en el procesamiento de


estructuras vectoriales o matriciales y veremos enseguida como se aplican estos principios.
Por ejemplo en un “for” que recorra los elementos de un array tenemos por un lado que las
instrucciones dentro del bucle del “for” van a ser referenciadas una y otra vez, cada cierto
tiempo, mientras la cuenta no llegue el límite. Del mismo modo el dato que está a
continuación del actual será utilizado luego (suponiendo que el array se recorre de a un
elemento por vez). En este ejemplo se cumplen ambas variantes del principio de localidad.

¿Cómo aprovechamos el principio de localidad en la jerarquía de memoria?. Lo


hacemos manteniendo los datos “recientemente accedidos” en las jerarquías altas, más
cerca de quien lo consume (la CPU). También moviendo bloques de memoria contiguos
hacia las jerarquías más altas. Con lo primero se apuesta a la localidad temporal, con lo
segundo a la localidad espacial.

El principio de localidad es aplicado por distintos actores dentro de un sistema:

• registros <> memoria: lo aplica el compilador ó el programador de bajo nivel


• memoria cache <> memoria: lo aplica el hardware
• memoria <> disco: lo aplica el sistema operativo (memoria virtual) ó el
programador (archivos)

19.4 Términos utilizados en Jerarquía de Memoria

Hay una serie de términos que se utilizan cuando se habla de jerarquía de memoria.

Hit

Se dice que ocurre un hit cuando un objeto de información se encuentra en el lugar


de la jerarquía donde se lo está buscando.

Miss

Se dice que ocurre un miss cuando el elemento de información no es encontrado en


el lugar de la jerarquía donde se lo está buscando. En este caso es necesario ir a buscar el
objeto a un nivel de jerarquía inferior.

Hit Rate

Es la tasa de acierto de encontrar un elemento de información en el lugar de la


jerarquía en que se lo busca.

Miss Rate

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

Es la tasa de fallos en encontrar un elemento de información en el lugar buscado (y


coincide con1 – Hit Rate).

Hit Time

Tiempo de acceso promedio en el nivel de jerarquía considerado (donde se da el


hit).

Miss Penalty

Tiempo de acceso promedio adicional requerido para acceder al elemento de


información en el nivel de jerarquía inferior. Típicamente ocurre que Hit Time << Miss
Penalty.

Tiempo promedio de acceso a memoria

Si consideramos el nivel de jerarquía “memoria cahé” podemos establecer que el


tiempo promedio de acceso a memoria (es decir a elementos de información almacenados
en la memoria principal de la computadora) cumple la relación:

Tiempo promedio de acceso a memoria = Hit Time + Miss Rate * Miss Penalty

19.5 Rendimiento de la Memoria

La velocidad de acceso a los elementos de información, incluyendo las instrucciones


de los programas condiciona la capacidad de proceso de las computadoras. Es por esto
que es el rendimiento del sistema de memoria tiene un impacto significativo sobre el
rendimiento general.
Los sistemas de memoria tienen distintos parámetros que tienen relación con su
capacidad de movilizar elementos de información:

Tiempo de Acceso: es el tiempo que transcurre entre que la dirección se presenta


estable y los datos pueden ser manipulados en forma confiable. Puede haber diferencias
entre el tiempo de acceso de lectura y el de escritura.

Tiempo de Ciclo: es el tiempo mínimo que debe pasar entre un acceso y el siguiente
(las memorias requieren de un cierto tiempo de recuperación antes de poder iniciar un
nuevo ciclo de acceso). Es la suma del tiempo de acceso más el de recuperación.

Tasa de Transferencia: es la velocidad de movimiento de datos de la memoria.

La tasa de transferencia está afectada por el tiempo de acceso y por el tiempo de


ciclo, ya que ambos condicionan la velocidad con que los datos pueden ser obtenidos. Para
mejorar la tasa se puede trabajar sobre la arquitectura del sistema de memoria.

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

Si partimos de la configuración básica:

CPU

Memoria

Una primera aproximación al problema de mejorar la tasa de transferencia es


aumentar la cantidad de bits que se pueden transferir en cada momento. La tasa de
transferencia en definitiva es la cantidad de palabras por segundo que se puede transferir.
Cuanto más grande sea la palabra (en bits) mayor será la tasa de transferencia.

CPU

Memoria

Otra aproximación ataca el problema del tiempo de recuperación de la memoria


(que forma parte del tiempo de ciclo), solapándolo con el tiempo de acceso, utilizando la
técnica denominada de “entrelazado” (interleaved) que consiste en separar la memoria en
bancos que puedan ser accedidos en forma independientes.

CPU

0
0

Memoria 1 Memoria 2

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

En este caso se muestra un entrelazado con dos bancos de memoria. El número de


bancos de memoria puede ser mayor.
En el entrelazado se organizan los bancos de memoria de modo que tengan un
ancho similar a la unidad de transferencia entre la CPU y la memoria y de modo que dos
unidades de transferencia contiguas a nivel de direcciones estén en bancos
independientes.
De esta manera se pueden iniciar operaciones de lectura ó escritura sobre
direcciones contiguas sin necesidad de esperar el tiempo de recuperación de la memoria,
como muestra el siguiente diagrama:

En el ejemplo supusimos que el tiempo de recuperación coincide con el tiempo de


acceso, con lo que el entrelazado cumple el objetivo en forma óptima. Naturalmente esto no
tiene porqué ser así, en cuyo caso tendríamos penalizaciones provocadas por el tiempo de
recuperación como se muestra en el siguiente diagrama:

En general lo que debemos hacer para diseñar un buen sistema de entrelazado es


la relación entre los tiempos. Para el caso de este segundo ejemplo, el óptimo se logra con
un entrelazado con 4 (cuatro) bancos:

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

19.6 Memoria Caché

19.6.1 Introducción

La memoria caché es una memoria de tamaño reducido, de alta velocidad, que se


coloca entre la memoria principal y la CPU. Utilizando el principio de localidad mantiene
copias de los bloques de memoria principal más accedidos, de manera que cuando la CPU
requiere una palabra que está en uno de los bloques almacenados en la memoria caché, el
requerimiento es satisfecho desde la memoria caché, con un tiempo de acceso mucho
menor que si debiera ser satisfecho desde la memoria principal.

CPU

Transferencia de Palabras

Memoria
Cache

Transferencia de Bloques

Memoria
Principal

Desde la memoria cache se accede a la memoria principal en bloques de k palabras


(normalmente k > 1). Cuando un bloque es leído desde memoria se almacena en una línea
de la cache.

La lógica de funcionamiento de la memoria cache es la que se esquematiza en el


siguiente diagrama de flujo:

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

Comienzo

Se recibe
pedido de
lectura de
una palabra

La
palabra No
está en
cache? Se lee el
bloque de
Si memoria que
tiene la palabra

Se elige una
linea de la
cache para
alojar el bloque

Se entrega la Se transfiere
Se entrega la
palabra a la el bloque
palabra a la
CPU desde la hacia la
CPU
cache cache

Fin

En definitiva si cuando la CPU requiere una palabra de memoria (para lectura)


ocurre un “hit” en la memoria de mayor jerarquía (la cache) entonces el requerimiento se
satisface desde dicha memoria, con un menor tiempo de acceso. Si por el contrario ocurre
un “miss”, se dispara un mecanismo por el cual se trae desde la memoria el bloque que
contiene la palabra buscada para simultáneamente escribirlo en la línea de la memoria
cache que corresponda y entregar la palabra solicitada a la CPU.

En realidad luego veremos que es un poco más complejo el algoritmo, ya que al


seleccionar una línea de la memoria cache para almacenar el bloque leído desde la
memoria principal, puede significar la necesidad de escribir el contenido actual de la línea
en el bloque de memoria principal correspondiente, dependiendo de la estrategia de “write”
que se siga.

Notemos que cuando ocurre un “miss” (la palabra buscada no está en la memoria
cahce) al realizar la transferencia desde memoria principal del bloque entero que contiene
la palabra buscada hacia la memoria cache, estamos aprovechando el principio de localidad
ya que lo mas probable es que el próximo requerimiento de acceso a la memoria sea una
palabra próxima (seguramente la de la dirección siguiente), por lo que probablemente
estará contenida en el bloque recién leído desde memoria. Es decir, luego de un “miss” lo
más probable es que ocurra un “hit” por la estrategia de mover bloques (y no palabras)

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

desde la memoria principal a la memoria cache.

19.6.2 Diseño de la Cache

En el diseño de un sistema de memoria cache hay que tomar una serie de


decisiones sobre distintos aspectos que tienen impacto sobre su rendimiento, entendido
como el porcentaje de “hits” respecto al total de accesos.

Primero haremos un repaso de todos estos aspectos para luego detenernos en


aquellos que merecen una explicación con mayor detalle.

Tamaño

Uno de los elementos a considerar es el tamaño de la memoria cache. Ya sabemos


que la memoria utilizada para este subsistema es un elemento comparativamente muy
caro, por lo que siempre deberemos lograr un compromiso entre la cantidad de memoria
cache y la cantidad de memoria principal.

Si bien el punto de equilibrio depende fuertemente del tipo de programas que se


ejecuten en el sistema, existirá una cierta cantidad de memoria a partir de la cual el
incremento del rendimiento obtenido no compensa el costo adicional de agregar más
memoria cache. Actualmente la memoria cache se coloca en el propio “chip” del
procesador, por lo cual también existe una limitante adicional: la cantidad de transistores
disponibles en el circuito integrado es finita y compite con todos los demás sub-sistemas
que deben ser construidos.

El estado del arte actual de los procesadores comerciales disponibles indican que se
utilizan 3 niveles de cache: el L1 de unos 10KB a 20KB, el L2 de 128KB a 512 KB y el L3 de
4MB a 12MB. Si consideramos que una computadora actual puede tener 4GB y más de
memoria, vemos que la relación entre el tamaño de la memoria principal y la cache (L3) es
de 1000 a 1.

Función de Correspondencia (Mapping)

Este elemento de diseño determina como se asocia una cierta posición de memoria
con su posible ubicación en la memoria cache. La memoria cache está formada por un
cierto conjunto de líneas. En cada línea se puede almacenar un bloque de memoria. Por
tanto la función de correspondencia establece para cada bloque de memoria cuales son las
líneas posibles de ser utilizadas en la cache para almacenarlo. La relación puede ser desde
que cualquier línea de la cache puede recibir a un bloque dado de memoria (denominada
correspondencia “completamente asociativa”) hasta que solo una línea determinada puede
recibir un bloque dado (denominada correspondencia “directa”), pasando por que cierto
conjunto de n líneas puede alojar un bloque dado (es la correspondencia “asociativa por
conjuntos de n vías”).

Algoritmo de Sustitución

Al momento que ocurre un “miss” es necesario traer un nuevo bloque de la memoria


principal a la cache. Para los casos en que hay más de un lugar posible de colocación del
bloque (casos de correspondencia “totalmente asociativa” o “asociativa por conjuntos”) es
necesario tener un algoritmo para seleccionar cual de las líneas utilizar (y por tanto
reemplazar su contenido en caso que no haya lugares libres, lo que va a ser la situación
habitual).

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

Política de Escritura

Hasta ahora hemos analizado como se comporta la memoria cache en la operación


de lectura, pero también debemos analizar qué pasa cuando la CPU escribe en la memoria.
En las operaciones de escritura (write) existen dos grandes estrategias write
through y write back. La primera (write through) implica que, de existir un hit, la operación
de escritura se hace en la memoria cache y también en la memoria principal. En la segunda
en el caso del hit la escritura se realiza solamente en la memoria cache.
Naturalmente la estrategia write back permite un mejor desempeño del sistema en
escritura, pero tiene la complejidad adicional de determinar si es necesario actualizar la
memoria principal con el contenido de una línea de cahe que va a ser reemplazada como
consecuencia de un miss, si es que el bloque tuvo algún cambio desde que se trajo a la
cache. También tiene la tarea adicional de velar por la coherencia de la cache, aspecto
que veremos más adelante.

Tamaño del bloque

Un aspecto que debe analizarse es el tamaño del bloque (y por tanto de la línea del
cache). Para un tamaño de memoria cache dado, ¿qué conviene más? ¿una línea más
grande o más cantidad de líneas?.
En el primer caso por el principio de localidad la probabilidad de un hit luego de un
miss aumenta, pero se puede sufrir ante cambios de contexto en ambientes de
multiprogramación.

19.6.3 Función de Correspondencia Directa

Para ejemplificar los distintos tipos de función de correspondencia usaremos en


todos los casos una memoria cache con un tamaño de 64 KBytes, con un tamaño de
bloque de 4 Bytes, en una CPU de 24 bits de dirección (16 MBytes).

Como dijimos en la función de correspondencia directa (Direct Mapping) a cada


bloque de memoria se le asocia una única línea de cache. Dado que tenemos 16 MBytes de
22
memoria, tenemos 16 MBytes / 4 Bytes = 4 M bloques (4 M = 2 ). Por su parte tenemos 64
KBytes / 4 Bytes = 16 K líneas (16 K = 2 ). Esto significa que hay 28 bloques de memoria
14

que tienen la misma línea de cache asignada en la función de correspondencia.

Para implementar la función se distinguen tres campos en una dirección dada:

Tag: es el campo que identifica cual de los posibles bloques está en cada línea. Son
los bits más significativos de la dirección Tiene 8 bits de largo para el ejemplo propuesto.
Línea ó Slot: son los bits que identifica la línea asociada con el bloque. En el caso
del ejemplo son 14 bits (que identificaremos con la letra r).
Byte o Palabra: son los bits menos significativos de la dirección e identifican al byte
o a la palabra individual dentro de la línea de cache o el bloque de memoria. Para el caso
son 2 bits (en general w bits).

TAG LINEA BYTE


23 16 15 2 1 0

Un bloque de memoria está identificado por el TAG y la LINEA (22 bits en el


ejemplo, que identificaremos con la letra s). Dada una Dirección se determina el Bloque
como Dirección / Tamaño de Línea. A partir del Bloque se determina la Línea del cache

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

con la fórmula Bloque % Cantidad de Líneas de la cache. El Tag se calcula como Bloque /
Cantidad de Líneas de cache.

Por tanto la correspondencia directa determina en que línea del cache se puede
almacenar cada bloque de memoria, Si m = cantidad de líneas de cache y B = número total
s
de bloques de memoria (que es 2 ), queda:

Línea de Cache Bloque contenido


0 0, m, 2m, 3m…B-m
1 1,m+1, 2m+1…B-m+1
………. ……………………………………
m-1 m-1, 2m-1,3m-1…B-1

Como vemos en la tabla, dado un bloque de memoria cualquiera existe solamente


una línea de cache en la que puede almacenarse. Para mayor claridad veamos un
esquema:

Con los r bits selecciono la única línea de la memoria cache en que puede estar el
bloque de memoria. En esa línea además del bloque está almacenado el tag
correspondiente al bloque. Entonces para determinar si hay un hit, comparo el tag
almacenado con los bits de tag de la dirección. Si coinciden tengo un hit y la lectura la hago
desde la memoria cache, usando los bits w para seleccionar la palabra dentro del bloque.
En caso contrario debo ir a la memoria principal.

En la figura siguiente se muestra un ejemplo, mostrando los contenidos de la


memoria principal y las líneas de la memoria cache:

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

Una forma de ver esta forma de correspondencia es que cada región de memoria
principal de tamaño igual a la memoria cache puede estar contenida completamente en la
memoria cache. Pero dos bloques ubicados en regiones distintas, separados un múltiplo del
tamaño de la memoria cache competirán por la misma linea de la cache.

La principal ventaja de esta función de correspondencia es su simplicidad y por tanto


su bajo costo de implementación. La desventaja es que un programa que se mueva por
regiones de memoria muy distantes, posiblemente genere una gran cantidad de misses
repercutiendo negativamente en el rendimiento de la memoria.

19.6.4 Función de Correspondencia Completamente Asociativa

En este caso la función de correspondencia (denominada Fully Associative en


inglés) vincula un bloque de memoria con cualquier línea de la memoria cache. Es decir
que un bloque dado puede estar en cualquier lugar de la cache.

Básicamente cada dirección de memoria se interpreta como un TAG y un BYTE o


WORD. Cada TAG identifica en forma unívoca a un bloque de memoria dentro de la cache.

TAG BYTE
23 2 1 0

Para saber si un cierto bloque está o no en la memoria cache es necesario

Instituto de Computación - Facultad de Ingeniería - UDELAR 13


Arquitectura de Computadoras Notas de Teórico

comparar los tags correspondientes a los bloques almacenados en todas las líneas de la
cache. Y esto se debe hacer lo más rápido posible. De hecho en el mismo ciclo de reloj del
acceso de memoria, ya que no tendría sentido implementar una memoria cache rápida que
luego perdiera varios ciclos de reloj en la búsqueda del tag por cada acceso.

Para lograr esto se utilizan memorias especiales, denominadas memorias


asociativas. Este tipo particular de memorias funcionan de esta manera: si se le presenta
un cierto dato a la entrada, devuelven a su salida el lugar de la memoria donde se
encuentra almacenado ese dato (si es que está, naturalmente), o un dato asociado.
Entonces en la memoria asociativa guardo el tag asociado con el contenido del bloque. Al
“leer” la memoria asociativa presento el tag y la memoria me devuelve el bloque. También
podría hacerlo con una memoria asociativa que me devuelva la dirección donde se
encuentra el bloque dentro de otra parte de la memoria cache (en este caso “normal”).

El principal problema de este tipo de memorias es su alto costo de implementación.

Un esquema de funcionamiento de esta función de correspondencia se puede ver


en la siguiente ilustración:

Los bits de tag de la dirección deben compararse al unísono con todos los tags
almacenados en la memoria cache. Esto se hace a través de la memoria asociativa
descripta. Si hay un hit la palabra se lee desde la memoria cache, usando los bits w para
seleccionar la palabra dentro del bloque.

En el siguiente ejemplo se ve el funcionamiento de la correspondencia totalmente


asociativa con contenidos de la memoria principal y la memoria cache:

Instituto de Computación - Facultad de Ingeniería - UDELAR 14


Arquitectura de Computadoras Notas de Teórico

19.6.5 Función de Correspondencia Asociativa por Conjunto de N Vías

En este caso la función de correspondencia (N-way Set Associative en inglés)


establece que cada bloque de memoria tiene asociado un conjunto de líneas de la memoria
cache y puede estar almacenado en cualquiera de las líneas del conjunto. La cantidad de
vías es la cantidad de líneas contenida en un conjunto. Ejemplo: una memoria cache
asociativa por conjuntos de 4 vías tiene 4 líneas en cada conjunto. Un bloque dado podrá
estar en cualquiera de las 4 líneas de su correspondiente conjunto.

En este caso para implementar la función de correspondencia se distinguen los


siguientes campos en una dirección dada, suponiendo 2 vías:

Tag: es el campo que identifica cual de los posibles bloques está en cada línea. Son
los bits más significativos de la dirección Tiene 9 bits de largo para el ejemplo propuesto.
Conjunto: son los bits que identifica al conjunto de líneas asociado con el bloque.
En el caso del ejemplo son 13 bits (que identificaremos con la letra d).
Byte o Palabra: son los bits menos significativos de la dirección e identifican al byte
o a la palabra individual dentro de la línea de cache o el bloque de memoria. Para el caso
son 2 bits (en general w bits).

TAG CONJUNTO BYTE


23 15 14 2 1 0

Instituto de Computación - Facultad de Ingeniería - UDELAR 15


Arquitectura de Computadoras Notas de Teórico

El esquema de funcionamiento de la memoria cahé en este caso es:

Y el ejemplo con datos queda:

Instituto de Computación - Facultad de Ingeniería - UDELAR 16


Arquitectura de Computadoras Notas de Teórico

En este tipo de función de correspondencia, con los bits d selecciono el conjunto de


líneas donde podría estar almacenado el bloque. Una vez determinado el conjunto,
entonces debo comparar al unísono todos los tags almacenados en ese conjunto de líneas
con los bits de tag de la dirección (se hace por una memoria asociativa o por un circuito de
comparación múltiple) Si hay coincidencia hay un hit y se lee desde la memoria cache.

19.6.6 Algoritmos de Sustitución

Cuando ocurre un miss y es necesario leer un nuevo bloque a la memoria cache,


será necesario determinar cual línea ocupar, en caso que exista más de una posibilidad.

Para el caso de la función de correspondencia directa hay una sola línea posible por
lo que este problema no existe. Pero para los casos de correspondencia totalmente
asociativa o asociativa por conjuntos de n vías hay más de una posibilidad y se requiere
definir la manera en que se determinará la selección.

Un aspecto a tener en cuenta cuando se piensan en estos algoritmos es que los


mismos deben ser posibles de ser implementados en hardware, porque no pueden
significar un impacto negativo en el rendimiento del sistema. Los algoritmos más utilizados
son los siguientes:

Menos Recientemente Usado (LRU = Least Recently Used)

Este algoritmo selecciona para reemplazar, dentro de las líneas posibles, la que
tenga el bloque que haya sido accedido hace más tiempo. Una implementación sencila de
este algoritmo para una memoria cache asociativa por conjuntos de 2 vías es usar un bit
que indica cual fue la última línea que se accedió. En cada acceso a un conjunto se
actualizan los bits de ambas líneas del conjunto.

FIFO (First In First Out)

En este caso se selecciona la línea que contiene el bloque que haya sido traído
primero desde la memoria principal (el más antiguo), sin importar si fue accedido ni que
tantas veces lo fue. Una manera de implementar este algoritmo en hardware es mediante
un buffer circular (con un puntero de circular por conjunto que señala la línea a reemplazar
que se actualiza en cada reemplazo).

Menos Frecuentemente Utilizado (LFU = Least Frequently Used)

Este algoritmo utiliza la cantidad de veces que han sido accedidos los bloques de
las líneas candidatas a ser reemplazadas. Para su implementación se pueden utilizar
contadores en cada línea.

Random

El algoritmo random selecciona el bloque a reemplazar mediante una técnica


aleatoria (normalmente pseudo-aleatoria por razones de implementación).

19.6.7 Coherencia de la Cache

El problema de la coherencia de la cache es el que se genera por la necesidad de

Instituto de Computación - Facultad de Ingeniería - UDELAR 17


Arquitectura de Computadoras Notas de Teórico

que el contenido de la cache y el de la memoria principal debe estar sincronizado en todo


momento. Cuando existen situaciones que pueden provocar la pérdida del sincronismo es
que nos enfrentamos al problema de la coherencia.

El problema se da básicamente por tres situaciones:

DMA con Write-Through: para optimizar los intercambios de datos entre los
dispositivos de Entrada / Salida y la memoria principal se utilizan sistemas de acceso
directo a memoria (DMA = Direct Access Memory). Estos sistemas permiten realizar
transferencias en ambos sentidos, entre la E/S y la memoria, sin la intervención de la CPU.
El problema de la coherencia aparece porque si bien cuando usamos política de escritura
write-through la memoria principal está siempre actualizada respecto a los cambios
producidos por la CPU, si ocurre una escritura en la memoria principal realizada por el DMA
en un bloque que está almacenado también en la cache, quedarán fuera de sincronismo.
La forma de solucionar es invalidando la entrada del cache, de forma que el próximo
acceso al bloque por parte de la CPU produzca un miss y entonces se forzará la lectura del
bloque nuevamente hacia la memoria cache. La técnica que implementa el monitoreo del
sistema de memoria principal para determinar si hay un acceso por parte del DMA se
denomina bus snooping.

DMA con Write-Back: cuando se tiene la política “write-back”, si la CPU realiza


escrituras la cache queda expresamente des-sincronizada de la memoria principal, hasta
que al momento de reemplazar el bloque el mismo se actualiza en memoria, como vimos.
Por tanto en este caso el problema ocurre ya sea que el DMA quiera leer ó escribir en un
bloque “cacheado”. La forma de resolución depende de si es una lectura del DMA (se
necesita detener el DMA para proceder a actualizar la memoria con el contenido de la
cache si es que ésta había cambiado) ó una escritura del DMA (en este caso se invalida la
entrada del cache y el próximo acceso al bloque por parte de la CPU producirá un miss, en
forma análoga al caso de wite-through).

Sistemas multiprocesador: en los casos de sistemas con más de un procesador


que comparten la misma memoria principal se dan los mismos problemas que con el DMA
(solo que es un CPU el que lee o escribe en bloques de memoria almacenados en la cache
de otro), los que se resuelven de la misma manera. Pero además se da uno adicional: para
el caso de write-back se puede dar la situación que el mismo bloque de memoria esté
simultáneamente en más de una cache. Si un CPU actualiza el bloque en su cache, esto
implica que las copias del bloque que estén en los cache de otros CPUs quedarán
desactualizados. La solución en este caso es más compleja, ya que no alcanza con estar
observando la actividad del sistema de memoria principal, es necesario tener un sistema de
monitoreo cruzado entre todos los sub-sistemas de memoria cache de todos los
procesadores.

Instituto de Computación - Facultad de Ingeniería - UDELAR 18


Arquitectura de Computadoras Notas de Teórico

Departamento de Arquitectura Instituto de Computación

Universidad de la República

Montevideo - Uruguay

Notas de Teórico

Pipeline

Arquitectura de Computadoras
(Versión 4.3b - 2020)

Instituto de Computación - Facultad de Ingeniería - UDELAR 1


Arquitectura de Computadoras Notas de Teórico

18 PIPELINE

18.1 Introducción

En este capítulo veremos una de las técnicas de diseño de procesadores que


permite mejorar el rendimiento de los mismos medido en términos de cantidad de
instrucciones ejecutadas por ciclo de reloj.

Como hemos visto los procesadores son, en definitiva, circuitos secuenciales


sincrónicos, que trabajan con una cierta frecuencia de reloj. Tener mejor rendimiento,
entendido como disminuir el tiempo de ejecución de los programas, ha sido históricamente
la obsesión de los diseñadores de computadoras. En ese rendimiento hay muchos factores
que juegan, siendo la capacidad de ejecución de instrucciones de parte del procesador un
factor clave.

Una primera aproximación, obvia por tratarse de una máquina sincrónica, es


aumentar la frecuencia del reloj: a mayor cantidad de MHz (ó GHz) del reloj del procesador,
menor será su periodo y por tanto menor el tiempo de ejecución de las instrucciones que
conforman un programa. Sin embargo esta aproximación no es tan sencilla. En cada estadio
de la tecnología de fabricación de circuitos integrados está más o menos determinada la
frecuencia máxima del reloj admitida por el circuito. Recordemos que los circuitos del tipo
CMOS solo conducen corriente eléctrica, generando calor, en las transiciones; con lo que
cuanto más alta la frecuencia mayor es el calor generado que debe disiparse para que la
temperatura no suba hasta dañar el material (silicio) con el que están construidos los
transistores. Esto impone un límite tecnológico a la frecuencia de trabajo.

La técnica de pipeline apunta a mejorar el rendimiento sin necesidad de aumentar la


frecuencia de trabajo, utilizando los mismos principios que Henry Ford introdujo en las
formas de producción industrial a principios del siglo XX: la producción en cadena ó cadena
(línea) de montaje.

18.2 Producción en Cadena

El principio de la producción en cadena es la división del trabajo total para realizar


un objeto en un conjunto secuencial de tareas más simples, que pueden realizarse en
paralelo. Esto no logra mejorar el tiempo que se requiere para la realización de un objeto en
particular, pero mejora la capacidad de producción (la cantidad de objetos producidos por
unidad de tiempo).

Ilustremos con un ejemplo de lavado de ropa en una lavandería. Supongamos que el


proceso implica el lavado (en máquina), el secado (en otra máquina) y una tarea manual de
doblado de la ropa.
Supongamos que el lavado demora 30 minutos, el secado 40 minutos y el doblado
20. Si tenemos 4 cargas de ropa A, B, C y D para realizar el ciclo completo de
lavado/secado/doblado vamos a demorar 90 minutos (1 hora y media). Para completar las 4
cargas de ropa vamos a requerir, en principio, 360 minutos (6 horas) si las hacemos una
tras otra, como se ve en el siguiente diagrama:

Instituto de Computación - Facultad de Ingeniería - UDELAR 2


Arquitectura de Computadoras Notas de Teórico

6 7 8 9 10 11 12
Tiempo

O 30 40 20 30 40 20 30 40 20 30 40 20
r
d A
e
n
B
T
a
r C
e
a
s
D

Si aplicamos la técnica de la producción en cadena, lo que podemos hacer es:


lavamos la carga de ropa “A”, cuando se termina de lavar ponemos a secar la carga de ropa
“A” y al mismo tiempo ponemos a lavar la carga de ropa “B”. Cuando se termina de secar la
carga “A” podemos comenzar a doblar la carga “A” y simultáneamente poner a secar la
carga “B”.

Notar que como el tiempo de lavado es menor que el de secado, el lavado de la


carga “B” termina antes del secado de “A”. En ese momento podríamos esperar que termine
el secado de “A” y pasar la carga “B” de la lavadora a la secadora y allí comenzar a lavar la
carga “C” mientras se seca la carga “B” y se dobla la carga “A”. La alternativa es no
comenzar a lavar la “B” hasta 10 minutos después de comenzado el secado de “A”. De esta
manera el secado de “A” terminaría junto al lavado de “B”. Lo mismo haríamos con el lavado
de “C” respecto del secado de “B”.

Estas dos alternativas están representadas en los siguientes diagramas:

6 7 8 9 10 11 12
Tiempo
O
r 30 40 40 40 40 20
d
e A
n

T B
a
r
e C
a
s D

Instituto de Computación - Facultad de Ingeniería - UDELAR 3


Arquitectura de Computadoras Notas de Teórico

6 7 8 9 10 11 12
Tiempo
O
r 30 40 40 40 40 20
d
e A
n

T B
a
r
e C
a
s D
Notar que ambas alternativas dan como resultado el mismo tiempo total: 30 + 40 +
40 + 40 + 40 + 20 = 210 minutos (3,5 horas). Es decir con la “lavandería en pipeline”
logramos mejorar de 6 horas a 3,5 horas. Dicho de otra manera, pasamos de un promedio
de una carga de ropa cada 90 minutos a un promedio de una carga cada 52,5 minutos!!.

Algunas anotaciones importantes:


• cada carga demora lo mismo que antes (90 minutos) en completar el ciclo. Incluso
las “B”, “C” y “D” pueden demorar más (100 minutos) si usamos la alternativa de
comenzar el lavado apenas se pueda y esperar luego que se libere la secadora
(primera alternativa de “pipeline”).
• las cargas se entregan cada 40 minutos: es decir que en régimen la capacidad de
producción (lavado/secado/doblado) es de 1 carga / 40 minutos. Nos dio 52,5 porque
hay una penalización hasta llegar al régimen (debe “llenarse” de tareas la cadena de
montaje).
• si el tiempo de cada tarea fuera igual entre sí (en este caso 30 minutos), no habría
esperas entre tareas y el funcionamiento de la línea sería óptimo. En este caso en
régimen obtendríamos 1 carga / 30 minutos.
• cuando esto no se cumple, la tarea que demora más es la que determina la
capacidad de producción.
• cuando se cumple, la capacidad de producción en régimen es: n / duración total,
siendo “n” la cantidad de etapas del pippeline (o de “estaciones” en la terminología
de la línea de montaje).
• lo anterior significa que aumentando la cantidad de etapas mejoramos el
rendimiento. Sin embargo hay un límite al crecimiento de “n”: dado que las tareas
deben durar lo mismo y ser independientes entre sí, a medida que intento aumentar
la cantidad de tareas en que subdivido el trabajo, cada vez es más difícil lograr esa
condición.

Otro elemento que ha estado implícito en toda esta descripción es que las tareas
involucradas en la línea de montaje deben ser independientes entre sí y no pueden tener
otro vínculo que el de fin a comienzo. Supongamos por un momento que en la lavandería
hay un único enchufe para alimentar eléctricamente las máquinas (o, más realistamente,
que hay una llave eléctrica limitadora que, para proteger la instalación eléctrica, impide
poner a funcionar ambas máquinas en forma simultánea por el alto consumo de cada una).
En este caso no hay paralelismo posible entre el lavado y el secado, aunque sí entre

Instituto de Computación - Facultad de Ingeniería - UDELAR 4


Arquitectura de Computadoras Notas de Teórico

cualquiera de ellas y el doblado. Esto hace que las tareas de lavado y secado funcionen
como una sola y por tanto el rendimiento desciende a 1 carga / 70 minutos (70 minutos es la
duración combinada, serialmente, de ambas tareas).

18.3 Pipelines

18.3.1 Pipeline Simple

Un ejemplo de pipeline simple es el que fue implementado en los procesadores Intel


8086. Divide el ciclo de instrucción en dos etapas: Fetch y Execute.

Un diagrama de su funcionamiento es:

Instrucción Instrucción
Fetch Execute

Este diagrama sin embargo no explicita algunas características de esta división en


sub-tareas que impactan sobre el funcionamiento del pipeline:
• En los procesadores Intel las instrucciones son de largo variable, por lo que la etapa
de “Fetch” puede involucrar más de un acceso a memoria. Es decir no tiene una
duración fija.
• Por una razón similar (se trata de una arquitectura CISC) la etapa de “Execute”
tendrá una duración que dependerá significativamente del tipo de instrucción y de los
tipos de operando involucrados.

Ambas situaciones provocarán situaciones de espera en una ú otra etapa: o bien se


hizo el fetch de la próxima instrucción, pero aún no terminó de ejecutarse la anterior, o bien
la etapa de execute completó la ejecución de una instrucción, pero la etapa de “Fetch”
todavía está leyendo de memoria una instrucción muy larga.

También existe una situación de interrelación: las instrucciones de salto pueden


provocar que se deba hacer el “fetch” de un lugar distinto al siguiente en la memoria (que es
lo que asume la etapa de “Fetch”). En este caso se debe descartar la instrucción leída en la
operación de fetch completada ó en curso e iniciar un nuevo fetch a la nueva dirección (la
determinada por el salto).
Poniendo estos elementos en forma explícita el diagrama quedaría:
Espera Espera

Instrucción Instrucción
Fetch Execute

Descarte Nueva Dirección

Instituto de Computación - Facultad de Ingeniería - UDELAR 5


Arquitectura de Computadoras Notas de Teórico

18.3.2 Pipeline de 5 etapas

Como vimos en un capítulo anterior, una posible descomposición del ciclo de


instrucción incluye 5 etapas:
Fetch: la instrucción es leída de memoria y se incrementa el PC (Program Counter)
Decode: la instrucción es decodificada y las correspondientes señales de control
activadas.
Read: los operandos en registros o inmediatos son apropiadamente movidos a
registros de trabajo de la ALU. Los operandos en memoria son leídos y traídos a
los registros auxiliares de la ALU.
Execute: se ejecuta la operación. Si es un salto condicional relativo se evalúa la
condición y se calcula la dirección destino.
Write: se transfiere el resultado de la ejecución desde el registro auxiliar hacia el
registro destino ó la memoria.

Si asumimos que todas las etapas se ejecutan en el mismo tiempo (ej: un ciclo de
reloj), el diagrama de tiempos del pipeline sería:
tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W

Aun suponiendo que el Fetch se haga en un solo ciclo de reloj (lo que no es cierto si
se tratara de una arquitectura CISC que tiene largo variable de instrucción), hay algunos
elementos que pueden afectar el funcionamiento óptimo del pipeline. El más evidente es
que existe el mismo problema con las instrucciones de salto que vimos para el caso
anterior. Ya sea que identifiquemos el salto en la etapa de Decode (si es incondicional) ó en
la etapa de Execute (si es condicional), las instrucciones siguientes que ya se hayan leído
se deberán descartar.
Este no es el único problema como veremos más adelante.

18.3.3 Pipeline MIPS de 5 etapas

La arquitectura MIPS (microprocesador RISC desarrollado originalmente en la


Universidad de Stanford) tenía, en su diseño original, un pipeline de 5 etapas:
Fetch: la instrucción es leída de memoria y se incrementa el PC (Program Counter)
Decode / Register Fetch: la instrucción es decodificada y las correspondientes
señales de control activadas. Los operandos en registros o inmediatos son
apropiadamente movidos a registros de trabajo de la ALU. En caso de salto
condicional, la condición es verificada y la dirección a saltar calculada.
Execute: se ejecuta la operación. Si la instrucción es de memoria (load/store) se
calcula la dirección de memoria a acceder.
Memory Read/Write: si la operación es de memoria se lee o escribe la misma.
Write Back: se transfiere el resultado de la ejecución desde el registro auxiliar hacia
el registro destino.

Los diseñadores de MIPS eligieron que todas las instrucciones recorran todas las
etapas aún cuando no las requieran. Esto incluso para el caso de la etapa de acceso a

Instituto de Computación - Facultad de Ingeniería - UDELAR 6


Arquitectura de Computadoras Notas de Teórico

memoria, que solo está presente en las instrucciones LOAD y STORE del set de
instrucciones. Esto es porque optaron por un diseño del pipeline radical: no tiene
mecanismos de hardware para resolver ese tipo de situaciones, donde eventualmente una
etapa del proceso no se ejecute. De hecho la sigla MIPS corresponde a Microprocessor
without Interlocks Pipeline Stages (Microprocesador sin Dependencias en las Etapas de
Pipeline).

El siguiente es un diagrama de las etapas del pipeline de MIPS y su vinculación con


los recursos de hardware que utiliza en cada una de ellas:

Instruction Instr. Decode Execute Memory Write


Fetch Reg. Fetch Addr. Calc Access Back

Next PC
MUX
Add

4 Zero?
RS1

MEM/WB
EX/MEM
Reg File
Memory

MUX
RS2
ID/EX
IF/ID

ALU
PC

Memory
IR

Data
MUX

MUX

WB Data
Sign
Imm Extend

RD RD RD

18.3.4 Pipeline SPARC de 4 etapas

La arquitectura SPARC (microprocesador RISC basado en un desarrollo originado


de la Universidad de Berkeley) posee, en su diseño original, un pipeline de 4 etapas
Fetch: la instrucción es leída de memoria y se incrementa el PC (Program Counter)
Execute: la instrucción es decodificada y se ejecuta la operación correspondiente. Si
la instrucción es de memoria (load/store) se calcula la dirección de memoria a
acceder, si es un salto relativo se computa la dirección destino.
Memory: si la operación es de memoria se lee o escribe la misma.
Store: se transfiere el resultado de la ejecución desde el registro auxiliar hacia el
registro destino.

18.4 Aceleración del Pipeline

Podemos calcular el aumento de la velocidad de procesamiento de instrucciones


que se logra con la técnica de pipeline de la siguiente manera.
Supongamos un pipeline de k etapas, cada una de duración T. Para ejecutar n
instrucciones tendríamos los siguientes tiempos:

Instituto de Computación - Facultad de Ingeniería - UDELAR 7


Arquitectura de Computadoras Notas de Teórico

Sin pipeline: Ttot= nkT

Con pipeline: Ttot= [n + k -1]T

El primer tiempo es sencillo de justificar: si las instrucciones se ejecutan una tras


otra, cada una demora kT (ya que cada etapa demora T y hay k etapas) y por tanto n
instrucciones demoran lo expresado en la fórmula.
Para el caso del pipeline, si recordamos los diagramas de tiempo vistos, vemos
que el tiempo total es el correspondiente a n veces el de la etapa de fetch y luego debe
completarse la ultima instrucción, lo que requiere k-1 etapas, de allí la expresión de la
fórmula.
Por tanto podemos definir la “aceleración” del pipeline como la relación entre
ambos tiempos de ejecución:

Aceleración: S = nk / [n + k - 1]

El siguiente gráfico muestra como mejora el rendimiento a medida que aumentamos


el número de instrucciones ejecutadas, para distintos diseños de pipeline:

Notemos que si n >> k, entonces S = k, lo que coincide con un resultado ya


encontrado: la ganancia de rendimiento coincide con el número de etapas. Como ya se
adelantó la técnica de agregar cada vez mas etapas para lograr mayores rendimientos tiene
la limitante de que a medida que k crece se hace más difícil mantener la independencia de
las etapas y la similitud en la duración de las mismas, principios básicos del funcionamiento
del pipeline y de la expresión hallada para la aceleración.

18.5 Obstáculos / Peligros (Hazards)

Como dijimos para que un pipeline pueda funcionar de manera óptima, no deben
existir dependencias entre las etapas del mismo. En la práctica esto no es posible. El
ejemplo más simple es el del salto (condicional o no), ya que invalida el fecth de la próxima
instrucción ya realizado (y eventualmente otras etapas que también haya recorrido la
próxima instrucción y, eventualmente las siguientes, dependiendo del momento en que se
determina el salto).

Instituto de Computación - Facultad de Ingeniería - UDELAR 8


Arquitectura de Computadoras Notas de Teórico

Hay otros posibles problemas y situaciones que generan problemas para el


funcionamiento óptimo del pipeline. En general estas situaciones se denominan en inglés
hazards, término que puede ser traducido como obstáculo ó peligro.

Estos hazards se clasifican en tres grandes grupos:

Hazards Estructurales: hay un conflicto de hardware entre dos o más etapas del
pipeline para alguna combinación de instrucciones.
Hazards de Datos: existen dependencias de datos entre instrucciones. Por ejemplo
la ejecución de una instrucción depende del resultado de otra previa, que aún
está en el pipeline.
Hazards de Control: causados por instrucciones de salto u otras modificaciones del
registro IP (Instruction Pointer ó PC = Program Counter).

18.5.1 Hazards Estructurales

Un ejemplo de este tipo de hazard se da en el hardware de acceso a memoria entre


la etapa de fetch y alguna que lea ó escriba en memoria:

tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W

En este ejemplo (señalado con azul) si la instrucción 1 tiene efectivamente etapa de


Read (o sea posee un operando en memoria) se produce un conflicto entre dicha etapa y la
etapa de Fetch de la instrucción 3 por el uso del bus de comunicación con la memoria: la
instrucción 1 necesita leer un operando de la memoria y a la vez se necesita leer la
instrucción 3. Esta situación podría resolverse mediante una arquitectura Harvard, en la cual
tenemos memorias separadas para datos e instrucciones.

Otro ejemplo (señalado con rojo) podría darse si pensamos que la etapa de Fetch
necesita calcular la dirección de la próxima instrucción (sumando 4, por ejemplo en el caso
de RISC). Si para esta operación intentara utilizar la ALU generaría un conflicto con la etapa
de Execute de otra instrucción (ej: instrucciones 1 y 4 del diagrama de tiempo). Esto se
puede solucionar agregando un sumador independiente de la ALU para el cálculo de la
dirección de la próxima instrucción.

Una solución general al problema de la falta de un recurso de hardware es esperar.


La espera no es una solución óptima pero es la más sencilla, en el sentido que no agrega
hardware. Una forma de esperar es agregar, artificialmente, operaciones del tipo “NOP” (No
OPeration), que no requieren de recursos. Esta técnica también se denomina: burbuja de
pipeline.

Es habitual encontrar una combinación de soluciones: se agrega hardware para los


casos más comunes (ej: sumador en la etapa de Fetch) y se implementan esperas para los
casos menos comunes.

Instituto de Computación - Facultad de Ingeniería - UDELAR 9


Arquitectura de Computadoras Notas de Teórico

18.5.2 Hazards de Datos

En este caso el problema aparece porque hay datos en común entre instrucciones
que están en el pipeline, ya sea una instrucción siguiente que utiliza un resultado aún no
calculado como operando ó altera un operando antes que sea leído como operando.

Se distinguen 3 tipos de hazards de datos:

RAW (Read After Write): ocurre cuando una instrucción posterior intenta obtener un
operando que está siendo calculado por una instrucción anterior, que aún está en el
pipeline y aún no llegó a la etapa donde escribe el resultado en el registro destino (W
ó WB). Este tipo de obstáculo se denomina “dependencia”.
Veamos un ejemplo (usaremos instrucciones de 3 operandos, el primero es destino
y los otros dos son origen):

add r1, r2, r3


sub r4, r1, r3

en este caso la segunda instrucción (sub) necesita como operando origen el


contenido de r1, pero si suponemos un pipeline de 5 etapas (F-D-R-E-W) el r1 debe
volcarse al registro auxiliar en la etapa R de la segunda instrucción, pero su valor
recién se guardará en r1 al realizarse la etapa W de la primer instrucción, lo que
ocurre mas adelante como vemos en el siguiente diagrama de tiempos:

tiempo
1 2 3 4 5 6 7 8 9 10
Instrucción 1 F D R E W
Instrucción 2 F D R E W
Instrucción 3 F D R E W
Instrucción 4 F D R E W
Instrucción 5 F D R E W
Instrucción 6 F D R E W

WAR (Write After Read): ocurre cuando una instrucción posterior escribe un
registro que actúa como operando de una instrucción anterior antes que ésta pueda
leerlo. Este tipo de hazard de datos, que se denomina “anti-dependencia” no es
posible en los pipelines que hemos visto (porque en todos la etapa de Write está
luego de la de Read). Sin embargo es posible que sucedieran en diseños más
avanzados (del tipo “out of order execution”), los que obviamente dispondrán de
mecanismos para evitarlos.

WAR (Write After Write): ocurre cuando una instrucción anterior escribe un registro
que también actúa como resultado de una instrucción posterior después de ésta.
Este tipo de hazard de datos, que se denomina “dependencia de salida” tampoco es
posible en los pipelines que hemos visto (porque en todos la etapa de Write está
luego de la de Read). También como en el caso anterior es posible que sucedieran
en diseños más avanzados (del tipo “out of order execution”), los que obviamente
dispondrán de mecanismos para evitarlos.

Para el caso del RAW las formas de resolver el problema pueden ser:
• esperar (introducir una burbuja en el pipeline)
• recurrir a técnicas avanzadas como la ejecución fuera de orden (out of order
execution)

Instituto de Computación - Facultad de Ingeniería - UDELAR 10


Arquitectura de Computadoras Notas de Teórico

• hacer register forwarding. Esta técnica consiste en propagar hacia las etapas
tempranas del pipeline los resultados apenas estén disponibles, sin necesidad de
esperar a que culmine la etapa de Write. En este caso la etapa de Read podrá
leer el operando desde el registro indicado ó desde la salida de la ALU
directamente, en función de la lógica de control que implemente esta
funcionalidad.

18.5.3 Hazards de Control

Los obstáculos de este tipo lo constituyen los ya comentados problemas que se


generan al ejecutarse saltos, ya sea incondicionales o condicionales. La etapa de Fetch
asume, por defecto, que la próxima instrucción a ejecutarse es la que está a continuación
en memoria, lo que nunca es correcto si la instrucción es un salto incondicional ó no es
siempre correcto si se trata de un salto condicional.

Las técnicas para resolver la penalización provocada por este tipo de hazards
incluyen: prefetch del destino, multiples flujos (streams), salto demorado y predicción del
salto.

18.5.3.1 Prefetch del destino

Esta técnica consiste en realizar simultáneamente el fetch de la próxima instrucción


en memoria y de la instrucción apuntada por la dirección destino del salto. Cuando el salto
se efectiviza la instrucción que no corresponde a la secuencia lógica se descarta.

Esta técnica fue utilizada inicialmente en la IBM 360.

18.5.3.2 Múltiples flujos

Este caso va un poco más allá del anterior y duplica las etapas del pipeline que
están ubicadas hasta la que decide el salto. De esta manera se puede avanzar en la
ejecución de ambos flujos de instrucciones, por lo que al momento de tomar el salto no hay
ninguna penalización, ya que no es necesario “vaciar” el pipeline (en realidad se vacía uno
de los dos: el que estaba ejecutando el flujo que finalmente no resultó elegido por el salto).

Esta técnica fue utilizada inicialmente en la IBM 370. Tiene el inconveniente de


propender a generar hazards estructurales.

18.5.3.3 Salto demorado

El salto demorado es una técnica muy utilizada en los procesadores RISC. La idea
es simple: siempre se ejecuta la instrucción que está luego del salto (se dice que la
instrucción luego del salto está ubicada en el “delayed slot”). Es responsabilidad del
compilador (ó del programador de bajo nivel) acomodar allí una instrucción útil. Si no hay
forma de hacerlo se deberá colocar un NOP y se recomienda nunca colocar dos saltos
seguidos (en algunos casos si se hace se produce una “excepción”).
La idea se complementa con el hecho que los procesadores que utilizan este
recurso deben resolver las instrucciones de salto en la segunda etapa del pipeline. De esta
manera no incurren en penalización por salto, ya que no se requiere vaciar el pipeline. Esto
es cierto para las primeras generaciones de procesadores RISC (ej: los primeros diseños de

Instituto de Computación - Facultad de Ingeniería - UDELAR 11


Arquitectura de Computadoras Notas de Teórico

MIPS y SPARC).

18.5.3.4 Predicción del salto

Como no siempre es posible alocar una instrucción útil en el “delayed slot” se


termina teniendo una penalización de todos modos, lo que también ocurre cuando tenemos
pipelines más complejos que resuelven los saltos en etapas mas avanzadas del mismo. Por
esto es que se recurre a otro tipo de técnicas (que pueden combinarse con el salto
demorado), como ser la predicción del salto, que aplica a los saltos condicionales,
naturalmente.

La técnica consiste en determinar, en base a un cierto algoritmo o criterio, si el salto


se va a tomar o no. Esto permite seguir haciendo el fetch de las instrucciones que con cierta
probabilidad serán las que el flujo lógico del programa ejecute. Si la predicción es acertada
no habrá penalización ya que no será necesario vaciar ninguna etapa del pipeline. Por tanto
en este caso la eficiencia del pipeline está condicionada por la eficiencia del mecanismo de
predicción del salto condicional.

Hay distintos mecanismos utilizados en la predicción:

Asumir que nunca se ejecuta: este criterio es como si se considerara el salto como
una instrucción cualquiera. Siempre se carga la próxima instrucción en memoria.
Asumir que siempre se ejecuta: este criterio continúa la carga de instrucciones en
la dirección destino del salto. Estadísticamente los saltos condicionales se toman en más
del 50% de los casos.
Predicción basada en la condición del salto: parte de la constatación que
determinados tipos de condición del salto (que están codificados en el código de operación
de la instrucción de salto) tienen mayor tendencia a realizar el salto y otros a no realizarlo.
Con esta técnica se consigue más del 75% de aciertos.
Conmutar Taken / No Taken: utiliza la historia reciente de los saltos, mediante una
máquina de estados que “recuerda” si el último salto fue tomado o no. La predicción debe
fallar dos veces seguida para cambiarla. El problema de la técnica es que predice el
comportamiento de un salto en función de lo que hizo uno anterior que no tiene por qué ser
el mismo. Por eso es que es apropiado para bucles (loops), pero no en general.
Tabla de Historia de Saltos (BHT = Branch History Table): es un
perfeccionamiento del mecanismo anterior, donde se almacena en una tabla la información
de un cierto conjunto de saltos recientemente evaluados. Entonces permite realizar el
algoritmo anterior sobre el comportamiento del mismo salto, sin que sea interferido por otros
saltos. Esto mejora la eficiencia de la predicción.

18.6 Ejecución Fuera de Orden (Out of Order Execution)

Una de las propuestas más radicales para atender toda la problemática de los
distintos tipos de “hazards” que ocurren en los pipeline es la posibilidad de realizar la
ejecución de las instrucciones fuera del orden establecido por su ubicación en memoria
pero, obviamente, respetando su orden lógico para mantener la integridad de los resultados.
Para lograr esto los procesadores que utilizan esta técnica manejan un conjunto de
instrucciones que ya fueron leídas desde la memoria hacia una especie de
“estacionamiento, y las van catalogando como “prontas para ejecutar” o no en función que
sus dependencias de datos y control hayan sido satisfechas. Las instrucciones “prontas
para ejecutar” avanzan en el pipeline a la etapa de ejecución y a medida que se van
generando nuevos resultados, se van actualizando los estados de las instrucciones que aún

Instituto de Computación - Facultad de Ingeniería - UDELAR 12


Arquitectura de Computadoras Notas de Teórico

esperan. De esta manera nuevas instrucciones quedan prontas para ejecutar y así sigue el
proceso.
El orden lógico de ejecución es el que determina, en definitiva, la existencia de
restricciones de datos o control (los hazards) y por tanto es tenido en cuenta al momento de
determinar la condición de “pronta para ejecutar” de una instrucción.

Por ejemplo en el trozo de programa:

add r1, r2, r3


add r5, r2, r4
sub r4, r1, r3

las dos primeras instrucciones pueden ejecutarse en cualquier orden que el


resultado del programa no va a ser alterado, pero la instrucción 3 (tres) debe ejecutarse
luego de la 1 (uno) porque depende de ella. Suponiendo que las tres instrucciones están en
un momento en el “estacionamiento” y no hay instrucciones pendientes que guarden
resultados en r2 ó r3, las dos primeras instrucciones recibirán la categoría de “prontas para
ejecutar”, pero no la recibirá la tercera. Cuando la primer instrucción complete la ejecución,
la condición de la tercer instrucción pasará a “pronta para ejecutar”.

Un sistema de este tipo, si bien tiene una lógica de control muy compleja, permite
altas tasas de ocupación de las etapas del pipeline y, en particular, de la ALU. Es decir logra
una gran eficiencia del pipeline.

Instituto de Computación - Facultad de Ingeniería - UDELAR 13

También podría gustarte