0% encontró este documento útil (0 votos)
57 vistas5 páginas

P4 Fco

Este documento describe la implementación de un microprocesador ARC de 4 estados. Incluye la descripción de la unidad de control, la integración de los componentes del microprocesador y las pruebas para validar su funcionamiento.

Cargado por

Josro Razei
Derechos de autor
© Attribution Non-Commercial (BY-NC)
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)
57 vistas5 páginas

P4 Fco

Este documento describe la implementación de un microprocesador ARC de 4 estados. Incluye la descripción de la unidad de control, la integración de los componentes del microprocesador y las pruebas para validar su funcionamiento.

Cargado por

Josro Razei
Derechos de autor
© Attribution Non-Commercial (BY-NC)
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

Fundamentos de los Computadores

Guión de la práctica 4. Fecha de entrega:


● Grupo A: 14/Enero
● Grupo B: 9/Enero
● Grupo C: 8/Enero

Objetivo de la práctica

En esta práctica se terminará la construcción del microprocesador ARC. La ruta de datos ya está
diseñada: sus componentes se desarrollaron en las prácticas anteriores (ALU, banco de registros
y PC). Ahora sólo hace falta crear la unidad de control y juntar todos los componentes para
tener ARC funcionando. Normalmente, la integración de todas las partes suele ser la parte de un
proyecto que más problemas genera.

Unidad de control

Se va a implementar una unidad de control cableada. Se utilizará un autómata con 4 estados.

• RESET: estado al que se pasa cuando se recibe un reset asíncrono (activo a nivel bajo). Al
liberarse el reset, pasa incondicionalmente al estado de captura
• CAPTURA: se obtiene la próxima instrucción desde la memoria, y se escribe en el registro de
instrucciones (IR). A continuación pasa siempre al estado de ejecución.
• EJECUCIÓN: se decodifica y se ejecuta la instrucción, esto es, se actualiza el registro de
resultado, los flags y el PC. A continuación pasa siempre al estado de escritura.
• ESCRITURA: se escriben los resultados de la instrucción, bien en el banco de memoria o en
la memoria. A continuación pasa siempre al estado de captura.

A partir del estado actual, de la instrucción en ejecución (los contenidos del registro IR) y de los
flags, se irán generando todas las señales de control. Estas señales son:

• IR_WE: habilitación de carga para el registro de instrucciones (IR). Se activa en el estado de


captura.
• MEM_REQ: indica un acceso a memoria en el ciclo actual. Se activa en el estado de captura,
y en el de escritura cuando la instrucción sea un load o un store
• MEM_WRITE: indica que el acceso a memoria señalado por MEM_REQ es de escritura. Se
activa en el estado de escritura, cuando haya un store.
• PC_JUMP: se debe activar cuando haya una instrucción jmpl
• PC_CALL: se debe activar cuando haya una instrucción call
• PC_BRANCH: se debe activar cuando haya una instrucción de branch que sea efectiva (el
valor de los flags se corresponda con es esperado por la instrucción en particular, p.ej. para
be esta señal se activará solo si FLAG_Z vale uno)
• PC_UPDATE: se activa siempre al pasar por el estado de ejecución
• RD_FROM_SETHI: indica que la entrada al banco de registros se hace desde los datos
inmediatos provenientes de la instrucción, que se pondrán en las posiciones más
significativas. Se debe activar cuando haya una instrucción sethi
• RD_FROM_MEM: indica que la entrada al banco de registros se hace desde la memoria. Se
debe activar cuando haya una instrucción load.
• REGS_WE: se debe activar al pasar por el estado de escritura, siempre que no se trate de
una instrucción de store o de branch
• RD_ADDR: se debe utilizar el valor apuntado en la propia instrucción, salvo para el call, que
siempre usa el registro 15.
• ALU_FUNC: se puede obtener como IR(24)&IR(21 downto 19), salvo en jmpl, load y store,
que se debe fijar siempre el código de la suma.
• ALU_IMM: indica que para la operación de la ALU se emplea el dato inmediato presente en la
instrucción. Se corresponde con IR(13).
• FLAGS_WE: se debe activar en el estado de ejecución sólo para las instrucciones tipo cc,
que actúan sobre los códigos de condición.
• RESULT_FROM_PC: indica que el registro de resultado se debe cargar no con los datos
provenientes de la ALU, sino con el PC. Se activa con las instrucciones call y jmpl.
• RESULT_WE: carga del registro de resultado, se activa siempre en el estado de ejecución
• ADDR_FROM_PC: salvo en las instrucciones de acceso a memoria, load y store, esta señal
estará activada para indicar que los datos para el bus de direcciones provienen del PC.

Implementar el microprocesador ARC

Una vez que se tienen todos los componentes, se deben juntar en el módulo ARC.VHD tal y
como indica en el esquema situado al final de este guión.

Para ello, se utilizará diseño jerárquico, donde los componentes que se instanciarán son:

• ALU.VHD (Prácticas anteriores)


• REGS.VHD (Prácticas anteriores)
• REG-PC.VHD (Prácticas anteriores)
• CTRL.VHD (apartado anterior)

Mientras que el resto de componentes (registro de resultado, registro de estado (flags) y diversos
multiplexores) se crearán empleando procesos y/o asignaciones concurrentes. Esto es
porque son componentes muy sencillos, y probablemente no valga la pena utilizar diseño
jerárquico en ellos.

El microprocesador, ARC.VHD, tendrá la siguiente interfaz:

entity ARC is
port(
CLK : in STD_LOGIC;
nRST : in STD_LOGIC;
DATA_IN : in STD_LOGIC_VECTOR(31 downto 0);
DATA_OUT : out STD_LOGIC_VECTOR(31 downto 0);
ADDR : out STD_LOGIC_VECTOR(31 downto 0);
WRITE : out STD_LOGIC;
MEM_WAIT : in STD_LOGIC
REQ : out STD_LOGIC
);
end ARC;

Donde:

• CLK es el reloj del sistema


• nRST es la señal del reset.
• DATA_IN y DATA_OUT son los buses de datos de entrada y salida respectivamente
• ADDR es el bus de direcciones
• WRITE es la señal que indica que el ciclo actual de acceso a la memoria es de escritura
• REQ indica que en el ciclo actual hay un acceso a la memoria
• MEM_WAIT: Indica que la memoria está ocupada

El protocolo de acceso a la memoria es síncrono. Tras el flanco de subida que da comienzo a un


ciclo de reloj, el microprocesador sube REQ para indicar que quiere acceder a la memoria. Si el
acceso va a ser de lectura, se deja la señal WRITE a 0. La memoria prepara el dato y lo deja en
DATA_IN, de tal manera que en el siguiente flanco de reloj el microprocesador lo capturará. Sin
embargo, si el ciclo es de escritura, se pone a 1 la señal WRITE y se deja el dato de salida en
DATA_OUT. La memoria lo guardará en el siguiente ciclo de reloj. Todo esto está resuelto con la
codificación que se ha hecho de la unidad de control, por lo que en un principio no hay que hacer
nada nuevo.
Como probarlo todo

Para probar el microprocesador se proporcionan dos archivos adicionales, ARC_TB.VHD y


MEM.VHD. El primero es un sistema completo, que incluye ARC, las memorias y procesos para
generar el reloj y el reset. Por otro lado, MEM.VHD es un sencillo modelo de memoria.

Las pruebas se harán ejecutando un programa en el microprocesador, y viendo con el visor de


formas de onda (Waveform Viewer) que los resultados son correctos. Por supuesto, también se
puede modificar el código del testbench para observar estos resultados de una manera
automatizada, pero esto no es necesario. Se deja al criterio del diseñador. Los pasos son los
siguientes:

• Crear el programa de pruebas, ensamblarlo y ejecutarlo en el ensamblador, y comprobar


que en efecto funciona como se espera.
• Renombrar el archivo .bin como prog.bin (es el nombre que espera MEM.VHD) y copiarlo
en el directorio del proyecto de ModelSim
• Ejecutar la simulación VHDL, y comprobar que los resultados son los esperados
Esto es así porque la memoria se inicia a sí misma con los contenidos del archivo prog.bin, de
tal manera que el microprocesador cuando empiece a leer de ella (a partir de la posición 0)
comenzará a ejecutar el programa.

Para comprobar que el microprocesador funciona correctamente, se recomienda hacer al menos


dos pruebas:

• Una que ejecute varias veces cada instrucción, para ver que cada una por separado
funciona bien
• Otra ya más completa, que sea ejecutar un algoritmo sencillo, para ver que programas
completos funcionan bien. Un ejemplo típico de esto es la serie de Fibonacci, o
multiplicar/dividir dos números, etc...

Microprocesador básico vs microprocesador avanzado

El ensamblador no sólo soporta las instrucciones básicas de ARC:

• sethi, be, bcs, bneg, bvs, ba, call, jmpl, addcc, andcc, subcc, orcc, orncc, xorcc, srl

Sino que soporta otras más:

• add, sub, and, or, orn, xor, bne, bcc, bpos, bvc, sll, sra

Los nuevos códigos de operación son:

Instrucción OP3 Instrucción COND


add 000000 bne 01001
sub 000100 bcc 01101
and 000001 bpos 01110
or 000010 bvc 01111
orn 000110
sll 100101
sra 100111
srl 100110

Las instrucciones de salto en este caso son efectivas cuando su correspondiente flag es 0 (p.ej,
bne salta cuando FLAG_Z es cero)
Ejercicios

• Ejercicio obligatorio: Implementar el microprocesador ARC, y probar su correcto


funcionamiento. Se deberán entregar los siguientes archivos
o ARC_TB.VHD
o MEM.VHD
o ARC.VHD
o ALU.VHD
o REGS.VHD
o CTRL.VHD
o REG-PC.VHD
o Cualquier otro código VHDL que se haya desarrollado, aunque lo más habitual es
que con los archivos anteriores sea suficiente para implementar ARC
completamente.
o Programa de prueba de todas las instrucciones, instr.asm
o Programa de prueba de funcionalidad total, func.asm

• Ejercicio optativo: Implementar ARC teniendo en cuenta para que pueda ejecutar el
conjunto de instrucciones avanzado. Este ejercicio incluye al anterior, por lo que si se
llega a hacer no es necesario entregar el microprocesador básico.

Todos estos archivos se deben comprimir en un ZIP llamado FCO_4_Y_ZZ.ZIP (donde Y es el


turno y Z es el grupo), que se debe dejar en el área de entrega de prácticas de la web de la
Escuela, como se hizo con el resto de prácticas.
PC_JUMP
nRST
PC_BRANCH
CLK
PC_CALL
DATA_IN PC_UPDATE

IR[21..0] & "0000000000" IR[31..0] RD_FROM_SETHI


RD_FROM_MEM

RD_FROM_SETHI
MEM_REQ
CTRL
MEM_WRITE REGS_WE
RD_FROM_MEM RD_ADDR

ALU_FUNC
FLAG_N ALU_IMM
RD_IN
FLAG_Z
RD_ADDR RD_ADDR FLAGS_WE
REGS_WE WE FLAG_V
RESULT_FROM_PC
CLK
REGS RS1_ADDR IR[18..14]
FLAG_C
RS2_ADDR IR[4..0] RESULT_WE
ADDR_FROM_PC
RS1 RD_OUT RS2 IR_WE

SXT(IR[12..0])
DATA_OUT
DATA_IN

ALU_IMM

CLK IR WE IR_WE
OP1 OP2

ALU FUNC ALU_FUNC IR[31..0]

RES N Z V C

IR[21..0] IR[29..0]

JUMP_ADDR SHORT_DISP LONG_DISP


WE FLAGS_WE
FLAGS CLK
PC_UPDATE UPDATE JUMP PC_JUMP
nRST nRST PC BRANCH PC_BRANCH
FLAG_N

FLAG_V
FLAG_C
FLAG_Z

CLK CALL PC_CALL


PC

RESULT_FROM_PC

RESULT WE
RESULT_WE
CLK

ADDR_FROM_PC

ADDR

También podría gustarte