miércoles, 22 de mayo de 2013

Práctica 4: Memoria


En dicha práctica tendremos que crear una memoria. Para ello tendremos que seguir varios pasos que nos indica la práctica.

Parte 1:

Debemos crear una memoria RAM con sus entradas de datos correspondientes y sus "pines" (SEL,IN,OUT,CLR), para ello cogeremos un módulo RAM de 64KB en la entrada de direcciones colocaremos un pin con 16 bits de datos que va hacia la entrada A de la memoria. En SEL,IN,OUT y CLR colocaremos independientemente un pin de 1 bit de dato y en  D colocaremos un pin de 8 bits como entrada de datos y  otro de salida.

Para comprobar el resultado introducimos en la dirección 0023h el dato 3A:


Realizamos otra comprobación introduciendo en la dirección 120C el dato 25




Parte 2:
En esta parte de la práctica añadiremos un nuevo módulo de memoria por lo tanto tendremos que aumentar la entra de 8 a 16 bits y la salida también. Conectaremos los buses de la primera memoria a la segunda, cada bus quedará conectado a la entrada del segundo módulo.
Realizaremos una comprobación:



Parte 3 :
Vamos añadir dos módulos más de memoria, por lo tanto conectaremos los buses de IN,OUT y CRL a las entradas de los nuevos módulos y el bus de selección le conectaremos una puerta NOT para cuando no estén seleccionados los módulos superiores lo estén los inferiores. El bus que conecta con la entrada A y el que conecta con la entrada D también se conectan a las entradas A y D de los nuevos módulos.

Realizaremos una comprobación:



Parte 4:
En esta parte de la práctica incluiremos cuatro módulos más de memoria, como en la parte anterior, conectaremos los buses IN,OUT y CLR a los nuevos módulos y debido a que son más módulos de los que puede seleccionar un pin tendremos que añadir un decodificador para seleccionar el módulo que deseemos. También conectaremos el bus de A y D de los primeros módulos a estos nuevos módulos.
Realizaremos una comprobación:



Parte 5:
A diferencias del resto de partes, aquí añadiremos dos módulos ROM, como ya sabemos, los módulos ROM son solo de lecturas por lo tanto solo tendremos tres entradas, entrada A, esta entrada seleccionará la dirección de memoria de la cual sacaremos el dato; SEL, para activar el módulo; D será el bus por donde saldrá el dato que contiene la ROM.
Comenzaremos por sustituir los dos primeros módulos RAM por los ROM. Los buses de las entradas A y D se conectarán a las salidas A y D de la ROM y la entrada SEL se conectará a la primera línea del decodificador.


FAQs
¿Para qué sirve el “clr” de la memoria?
Para limpiar todos los registros de la RAM, ya que actúa como clear.

¿Para qué sirve el “A” de la memoria?
Para dar la dirección de la memoria de donde introducir el dato.

¿Para qué sirve el “D” de la memoria?
Para introducir/sacar el dato por el buffer.

¿Para qué sirve el “triangulito” de la memoria?
Para grabar el dato en la memoria

¿Por qué teniendo seleccionada la ROM y activado el triestado nos da error el circuito?
Porque ambos están sacando un dato hacia el buffer.

¿Por qué no puedo introducir datos en la ROM?
Porque es una memoria solamente de lectura, que no permite que se escriba en ella.

¿Por qué utilizamos un decodificador en vez de un pin cuando tenemos cuatro módulos de memoria?
Debido a que no se pueden seleccionar varios módulos de memoria con un pin de un solo bit, por lo cual necesitamos más bits para poder seleccionar los distintos módulos.



lunes, 6 de mayo de 2013

Práctica 3: Unidad de Control


En esta práctica, utilizando una CPU de ejemplo implementada en Logisim, haremos las veces de Unidad de Control, es decir, controlaremos el procesamiento de las siguientes instrucciones:
a) ADD $t0, $t1, $t2                             f) LUI $s0,0x0011                                        
b) ADDI $s0,$s1, 0x0011                     g) SW $t4, 0x0111
c) ORI $t0, $t2, 0x00A1                       h) SLT $t1, $t2, $t0
d) SLL $t0, $t0, 0x0002                        i) J 0x000001A
e) SLR $t1, $t0, 0x0002                        j) JR $s0

Pasos a seguir:
1.      Codificación de las instrucciones
2.      Transferencia de registros y señales de control
3.      Simulación en Logisim.
1. Codificación de las instrucciones:
Una instrucción se puede codificar tomando los códigos de operación correspondientes y siguiendo la estructura del tipo de instrucción correspondiente (R, I, J). Para poder codificar las instrucciones anteriores, debemos saber a qué valores equivalen los registros.

2. Transferencia de registros y señales de control.
Escribir la secuencia de transferencias y acciones consiste en especificar lo que sucede dentro de la CPU por medio de las transferencias que se llevan a cabo entre los registros, indicando también las señales de carga, triestado y selección que permiten estas transferencias. Utilizaremos esta imagen para seguir los pasos:



Para ser lo más eficiente posible, siempre  que podamos, realizaremos varias acciones en un mismo ciclo, cuando éstas no necesiten utilizar el mismo bus.

3. Simulación en Logisim.
En este paso asumiremos el papel de la unidad de control para marcar en el presente circuito todas las señales de control establecidas en el paso anterior para llevar a cabo las instrucciones.


Al final de la práctica se explicará detalladamente todos los pasos necesarios para realizar la simulación de una de las instrucciones.

Solución de la Práctica

a) ADD $t0, $t1, $t  equivale a ADD R8, R9, R10

Instrucción tipo R
Nmemónico
0
RS=$t1=9
RT=$t2=10
RD=$t0=8
0
0x2a
Binario
000000
01001
01010
01000
00000
10000
Hexadecimal
0x012A4020


S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: R8 ß R9+R10                                            RA=01001, RB=01010, MA=0, MB=0, op="00001", T5,                                                                                  RC=01000
                                                                              SC
S7: Comprobar si hay interrupciones
b) ADDI $s0, $s1, 0x0011  equivale a      ADDI R16, R17, 0x0011

Instrucción tipo I
Nmemónico
8
RS=$s1=17
RT=$s0=16
Imm=0x0011
Binario
001000
10001
10000
0000000000010001
Hexadecimal
0x22300011


S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: RT2 ß RI (0x0011)                                   T8
                                                                              C10                       
S6: R16 ß R17 + RT2                                      RA=17, MA=0, MB=0, op="00001",
                                                                              T5, RC=16
                                                                              SC
S7: Comprobar si hay interrupciones





c) ORI $t0, $t2, 0x00A1  equivale a ORI R8,R10,0x00A1

Instrucción tipo I
Nmemónico
0xD
RS=$t2=10
RT=$t2=8
Imm=0x00A1
Binario
001101
01010
01000
0000000010100001
Hexadecimal
0x354800A1


S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: RT2 ß RI (0x00A1)                                  T8
                                                                              C10                       
S6: R8 ß R10 OR Rt2                                     RA=10, MA=0, MB=1, op="00003",
                                                                               T5, RC=8
                                                                              SC
S7: Comprobar si hay interrupciones

d) SLL $t0, $t0, 0x0002   equivale a SLL R8, R8, 0x0002

Instrucción tipo R
Nmemónico
0
RS=no hay
RT=$t0=8
RD=$t0=8
Desp=0x0002
0
Binario
000000
00000
01000
01000
00010
000000
Hexadecimal
0x00084080


S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: RT2 ßRI (0x0002)                                    T8
                                                                              C10                       
S6: R8 ßR8 << 0X0002                                  RA=01000, MA=0, MB=1, op="00008",
                                                                              T5, RC=01000
                                                                              SC
S7: Comprobar si hay interrupciones





e) SLR $t1, $t0, 0x0002 equivale a SLL R9, R8, 0x0002

Instrucción tipo R
Nmemónico
0
RS=$t0=8
RT=no hay
RD=$t1=9
Desp=0x0002
2
Binario
000000
01000
00000
01001
00010
000010
Hexadecimal
0x01004882


S1: MAR ß PC                                                T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: RT2 ß RI (0x0002)                                   T8
                                                                              C10                       
S6: R9 ß R8 >> 0X0002                                 RA=01000, MA=0, MB=1, op="00005",
                                                                              T5, RC=01001
                                                                              SC
S7: Comprobar si hay interrupciones

f) LUI $s0, 0x0011 equivale a lui R16,0x0011

Instrucción tipo I
Nmemónico
0xf
0
RT=$s0=16
Imm=0x0011
Binario
001111
00000
10000
0000 0000 0001 0001
Hexadecimal
0x3C100011

S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: RT2 ß RI                                                     T8
C10
S6: R16 ß R16                                                  RA=10000, MA=0, MB=1, op=”0006”
                                                                              T5, RC=10000
                                                                              SC
S7: Comprobar si hay interrupciones



g) SW $t4, 0x0111 equivale a sw R12, 0X0111

Instrucción tipo I
Nmemónico
0x2b
RS=0
RT=$t4=12
Imm=0x0111
Binario
101011
00000
01100
0000 0001 0001 0001
Hexadecimal
0xAC0C0111

S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: MAR ß RI(0x0111)                                  T8
C1
S6: MBR ß R10                                                               RA=01010
T1
C3
S7: MP ß MBR                                                Ta, Td, E
S8: Comprobar si hay interrupciones

h) SLT $t1, $t2, $t0 equivale a SLT R9,R10,R8     
               
Instrucción tipo R
Nmemónico
0
RS=$t2=10
RT=$t0=8
RD=$t1=9
0
0x2a
Binario
000000
01010
01000
01001
00000
101010
Hexadecimal
0x0148482A

S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5:RT3ßR10-R8                                          RA=01010,RB=01000,MA=0,MB=0, op=00001
                                                                        C11
      REßALU                                                  C8
S6:RT1ß RE(BIT SIGNO)                             T7
                                                                        C9
S7: R9ß NOT(RT2)                                     MA=1,Op=00110
                                                                        T5
                                                                        RC=01001,SC

S8: Comprobar si hay interrupciones



i) J 0x000001A                                  j target

Instrucción tipo J
Nmemónico
2
0x0000001A
Binario
000010
0000 0000 0000 0000 0000 0001 1010
Hexadecimal
0x0800001A

S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6

S4: Decodificación

S5: PC ß RI(0x0000001A)                            T8
C5
S6: Comprobar si hay interrupciones

j) JR $s0                                               jr rs
                               
Instrucción tipo R
Nmemónico
0
RS=$S0=16
0
8
Binario
000000
10000
000 0000 0000 0000
001000
Hexadecimal
0x02000008

S1: MAR ß PC                                                 T4, C1
S2: PC ß PC+4                                                 C4
       MBR ß MP                                                Td, L, C2
S3: RI ß MBR                                                   T3, C6
S4: Decodificación
S5: PC ß R16                                                    RA=10000, T1   
                                                                       C5
S6: Comprobar si hay interrupciones


Simulación con Logisim

En primer lugar vamos a introducir los códigos de operación obtenidos anteriormente en la memoria. Para ello:
1. Hacemos clic derecho en la memoria.
2. Clicamos en Editar contenidos...
3. Introducimos por teclado los códigos de operación en hexadecimal en las primeras  10 posiciones, debe quedar una cosa así:


4. Cerramos la ventana.
Es recomendable que guardemos el estado de la memoria (mediante uno de los botones de la parte inferior del editor de contenidos) para poder abrirlo en cualquier momento, ya que la memoria se limpia cada vez que cerramos Logisim.

Vamos a simular las instrucción ADD $t0, $t1, $t2.
En primer lugar debemos abrir el triestado T4 para sacar la dirección de memoria donde está contenida la instrucción. En este caso la primera está contenida en la primera dirección por lo que el contador estará todo a 0. A su vez activamos la señal de carga del registro MAR (C1) que es un registro que almacena la dirección de la instrucción a la que se va a acceder. En este ejemplo la instrucción que contendrá la memoria almacenada es la de la instrucción ADD $t0, $t1, $t2 pero como hemos dicho puede contener cualquier instrucción porque estos pasos son los mismos para
todas. Nótese que  la instrucción está almacenada en memoria en hexadecimal.


En el siguiente ciclo abriremos la memoria en modo lectura y accederemos a la posición que nos indica el registro MAR y acto seguido guardaremos el contenido de esa posición (instrucción en hexadecimal) en el registro MBR. Para ello abriremos el triestado TD y activaremos el modo lectura (L) y también el pin de selección, para seleccionar la posición de memoria que contiene la instrucción y activamos C2 para almacenar su contenido en el registro MBR. Simultáneamente debemos accionar la carga C4 del contador del programa para sumar 4 bytes al contenido de éste
para poder acceder más tarde a la siguiente instrucción mediante el mismo mecanismo que estamos haciendo ahora (hay que sumar 4 bytes ya que una instrucción ocupa 32bits en memoria).



Por último, antes de decodificar la instrucción en la unidad de control, debemos llevarla desde el registro MBR al registro RI, que es un registro que sirve para almacenar la instrucción justo antes de ser decodificada por la unidad de control. Para realizar este paso necesitamos activar el triestadoT3, y la carga C6.

A partir de aquí será la unidad de control la encargada de generar las señales para que se lleve a cabo la instrucción. En esta simulación seremos nosotros los encargados de generar dichas señales.
Como es necesario que  existan datos en los registro para realizar la suma, previamente  hemos introducido  1 en $t1 y 2 en $t2.
Primero debemos llevar los datos a la ALU. Para ello seleccionamos el registro $t1, mediante RA=01001 y RB=01010 (dejando los multiplexores que hay antes de la ALU a 0, que significa que los datos vienen del banco de registros) y una vez hecho esto se realiza la suma en la ALU mediante el código de operación 0. Y para almacenar el resultado de la suma debemos accionar T5, seleccionar el registro $t0 en la señal RC y activar SC para poder realizar el almacenamiento en el banco de registros. A la vez que se almacena la suma en el banco debemos almacenar los indicadores de la operación en el registro de indicadores mediante la señal de carga C8.


FAQs

¿Qué es una señal de triestado?
Son señales que sirven para liberar datos de los registros y se representan con una T.

¿Qué son las señales de carga?
Son señales que sirven para introducir datos en los registros y se representan con una
C.

¿Cómo se introduce un dato en la memoria con logisim?
Para introducir datos en la memoria con logisim debemos clickar con el botón derecho
del ratón sobre la memoria y pulsamos en Editar Contenidos... Una vez lo hayamos
hecho se nos abrirá una ventana. La primera columna de esa ventana nos dice cuál es
la dirección de la primera posición de cada fila, siendo las siguientes posiciones los
grupos de ceros que hay a la derecha y que a su vez, esos grupos de ceros son el
contenido de cada posición de la memoria. Para modificar esos contenidos, pinchamos
en la posición que queramos e introducimos los datos que queramos, sabiendo que el
contenido se expresa en hexadecimal. Aún así en el resumen del tema 4 ponemos una
breve explicación de como se hace.

¿Cómo sé el código de la operación que quiero realizar en la ALU?
Los códigos de las operaciones viene en una tabla del propio enunciado de la práctica.

¿Por qué $t0 es R8 o $s0 es R16?
Hemos utilizado una tabla vista en teoría, concretamente hemos utilizado los registro
del MIPS. También puedes verla en el propio enunciado de la práctica.

¿Cómo podemos saber el orden de los registros a la hora de codificar la instrucción y
si son de tipo R,I o J?
En la teoría del tema 3 vienen una serie de tablas con la sintaxis y el orden de los
registros, así como el número de bits que tienes que utilizar para ello, también te dice
de que tipo es cada instrucción.