Implementación de la arquitectura Zetta – PASO 2


Ahora que tenemos un horizonte claro del sistema que estamos construyendo demos un paso hacia ABAJO (ya que estamos usando la metodología Top-Down).

Al bajar lo que estamos haciendo es adentrándonos en los detalles del sistema para llevar a cabo su implementación, esto es lo mismo que aumentar el nivel de detalle.

Usando en Altium podemos “bajar” usando la herramienta Create Sheet From Sheet Symbol. como se muestra en la imagen. Esto nos creará un nuevo diagrama de bloques con los puertos definidos en el bloque de manera que podemos ahi diseñar el interior de la caja negra (para que deje de serlo).

zetta1a

A continuación una imagen que refleja mi diseño en este nivel.

zetta2

En esta imagen se puede ver como he compuesto un sistema a partir de nuevos bloques funcionales que todavía no he definido internamente (por ahora son cajas negras)

Para que quede mas claro lo que hemos hecho aquí muestro como se relacionan los bloques.

zetta2a

Este nivel muestra claramente elementos nuevos que son producto de la creatividad del diseñador / ingeniero en donde se divide el problema general (procesador ZETTA) en subproblemas mas pequeños (Register File, ALU, Memoria de programa, Unidad de Control, Program counter). OJO: Note que las señales en magenta son señales que salen de la unidad de control, y están conectadas entre si cuando llevan el mismo nombre. Estas líneas no se extienden por todo el diagrama SOLO PARA PODER CONSERVAR EL DIAGRAMA ORDENADO Y UN POCO MAS CLARO DE ENTENDER.

Explicación del diseño

Bloque I_IRam = Memoria de Instrucciones

Esta es una memoria que contiene el programa que ejecutará el procesador que estamos construyendo. Aquí residen las instrucciones una a una en cada posición que esta almacena. Esta memoria saca a su salida data la instrucción en la posición que indica la señal address (que viene del contador de programa).

Bloque I_UnpackInst = Instruction Decoder / Desempacador de Instrucción

Este bloque toma la instrucción que sale de la memoria de instrucciones (I_IRam)  y separa los elementos que la constituyen para poder trabajarlos en los otros bloques. Los elementos que constituyen una instrucción estaban definidos cuando definimos la arquitectura en otro articulo.

Bloque I_PC = Program Counter / Contador de Programa

Registro que indica la dirección de la instrucción que esta siendo ejecutada.

Bloque I_RegFile = Register File / Banco de Registros

Es un conjunto de registros que el programador puede utilizar para realizar operaciones con los datos que desee procesar. Dependiendo de la instrucción que se ejecute se operan ciertos registros, por eso las entradas incluyen dos selectores de registro rs1 y rs2; y las salidas rs1_data y rs2_data son respectivamente la información de estos registros seleccionados.

Como también es posible guardar resultados de algunas instrucciones en un registro, este bloque también incluye unas entrada rd_wrh y rd_wrl que cuando están en 1 indican que se debe guardar la parte alta o baja respectivamente; una entrada rd que selecciona el registro de destino; y una entrada rd_data con los datos que serán guardados.

Bloque I_Alu = Arithmetic & Logic Unit / Unidad Aritmética y Lógica

Es un bloque que realiza las operaciones aritméticas o lógicas necesarias para poder cumplir con la ejecución de algunas instrucciones. Recibe la información de los registros seleccionados en el banco de registros y los opera (los suma, o los resta, o los multiplica, según sea el caso) dejando ver a su salida el resultado de la operación.

Bloque I_Mux = Multiplexor / Multiplexor

Este multiplexor permite seleccionar de donde se van a sacar los datos que se guardarán en el registro de destino de I_RegFile.

En el registro de destino se puede guardar un dato que es….

  • Proveniente del Bus o puerto de comunicación externo.
  • Resultado de una operación entre registros mediante la ALU
  • Un valor inmediato codificado en instrucciones LL y LH (instrucciones I-Type)

Bloque I_Control = Control Unit / Unidad de Control

La unidad de control aplica la lógica necesaria para configurar cada uno de los otros bloques según corresponda el caso para cumplir con la instrucción que esta siendo ejecutada. Es por eso que su principal entrada es opcode.

Implementación de la arquitectura Zetta – PASO 1


Para la implementación de nuestra arquitectura tengo una restricción: La FPGA de la que dispongo es un chip Cyclone II 2C20 de Altera que viene en la tarjeta de desarrollo DE1 ensamblada por Terasic sin embargo el procedimiento puede ser aplicado a otras tarjetas de desarrollo y chips FPGAs incluso (como las de Xilinx o Actel).

Adicionalmente aclaro que usaré el siguiente software:

Metodología de diseño TOP-DOWN

Como lo que estamos diseñando es un sistema, debemos definir claramente 3 cosas: Entradas, Salidas y Comportamiento. Las entradas y salidas las ingresaremos en forma grafica en Altium Designer.

Empezamos creando un proyecto de FPGA en Altium Designer (Menu New + Project + FPGA Project ) y añadimos un nuevo diagrama de bloques para empezar a ingresar nuestro diseño de sistema.

En la imagen puede verse como queda mi diseño de nivel superior del sistema general en un diagrama de bloques en Altium Designer.

zetta1

El sistema es un bloque (hasta ahora una caja negra) cuyas entradas son las señales clk, reset, y data_rd  y sus salidas son las señales address, data_wr, wr, y rd.

Con esto lo que estoy haciendo es dotando a mi sistema de un bus de comunicación con el mundo exterior, de esta manera el procesador podrá interactuar con otros dispositivos (memorias, LEDs, Registros, UARTs, etc) cuando el programa que este ejecutando use las instrucciones SW y LW.

Explicación de las señales

clk Señal de reloj cuyo flanco de subida es la base de tiempo del sistema.
reset Señal que lleva al sistema a un estado inicial conocido.
address[31..0] Dirección en el bus que se quiere acceder ya sea para escritura o lectura. Observe que la dirección posible es de 32 bits.
data_wr[31..0] El procesador pone en estas líneas el dato que quiere comunicar al dispositivo en la dirección seleccionada. Observe que dato es de 32 bits.
data_rd[31..0] El procesador recibe por estas líneas el dato que el dispositivo seleccionado por la dirección le quiere comunicar. Observe que dato es de 32 bits.
wr Se pone en 1 cuando el procesador quiere comunicar  algo (escribir en el bus).
rd Se pone en 1 cuando el procesador quiere recibir algo. (leer del bus)

Ya que se han explicado las señales, vamos a ver como el procesador puede usar el bus.

Transacción de Lectura (El procesador lee del bus)

  1. El procesador asigna una dirección del dispositivo que quiere leer.
  2. El procesador asigna rd = 1 y wr = 0   (si leer, no escribir)
  3. La señal clk realiza un cambio de 0 a 1 (flanco de subida)

La transacción se considera completa.

Transacción de Escritura (El procesador escribe del bus)

  1. El procesador asigna una dirección del dispositivo que quiere escribir.
  2. El procesador asigna el dato que quiere escribir en data_wr
  3. El procesador asigna rd = 0 y wr = 1   (no leer, si escribir)
  4. La señal clk realiza un cambio de 0 a 1(flanco de subida)

La transacción se considera completa.

Bus inactivo (sin transacción)

  1. El procesador asigna rd = 0 y wr = 0  (no leer, no escribir)
  2. La señal clk realiza un cambio de 0 a 1(flanco de subida)

El bus no realiza ninguna transacción ni de lectura ni de escritura en este ciclo de reloj.

Primeros pasos en descripcion de hardware con VHDL


VHDL source code for a signed adder
Image via Wikipedia

Hace un tiempo cuando estudiaba en la U, hice este video para la monitoria de logica digital que dictaba los fines de semana. Aqui lo dejo, quiza sea de ayuda para alguien.

Aunque habia hecho una serie de varios videos, desgraciadamente este es el unico que tengo ahora.

Es una tutoria sobre descripcion de hardware con VHDL incluyendo una práctica con el software Altera Quartus II aunque lo que se examina vale tambien para otros entornos como el de Xilinx o Actel. Se trata de modelar un multiplexor con VHDL para mostrar algo de la descripcion combinatoria y luego se agrega un registro al circuito para mostrar el uso de la funcion rising_edge(). para cada caso se compara con la interpretacion RTL que el sintetizador hace de la descripcion.