Implementación de la arquitectura Zetta – PASO 3


Ahora que ya conocemos los detalles de que hace cada bloque en el diagrama de la arquitectura, procedemos a bajar un poco mas en el nivel de abstracción y entonces implementaremos cada uno de los bloques necesarios usando VHDL.

Bloque I_IRam – IRam.vhd

--------------------------------------------------------------------------------
-- SubModule IRam
-- Created   12/09/2011 11:03:47 a.m.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;

entity IRam is port
   (
     address        : in    std_logic_vector(31 downto 0);
     data           : out   std_logic_vector(31 downto 0)
   );
end IRam;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
architecture rtl of IRam is
    -- Tipos para la memoria ROM
    subtype word_t is std_logic_vector(31 downto 0);
    type memory_t is array(0 to 255) of word_t;

    -- funcion para inicializar la memoria
    function init_rom
        return memory_t is
        variable tmp : memory_t := (others => (others => '0'));
        variable s : std_logic_vector(7 downto 0);
    begin
    		-- Inicializa la memoria
        -- Por ahora solo vamos a inicializar contenido "basura", cuando
        -- estemos usando el procesador sera necesario cambiar esta
        -- inicializacion por un programa verdadero (secuencia de instrucciones
        -- de nuestro procesador Zetta)
        for addr_pos in 0 to 255 loop
            s := std_logic_vector(to_unsigned(addr_pos, s'length));
            tmp(addr_pos) := s & s & s & s; -- uso esto solo para probar
        end loop;
        return tmp;
    end init_rom;

    -- Declara la señal con el tipo de memoria y asigna una funcion
    -- de inicializacion, Quartus II creara un archivo (.mif)
    -- para esta memoria basado en esta inicializacion
    signal rom : memory_t := init_rom;

begin
	-- retorna la posicion de memoria
  data <= rom(conv_integer(address));
end rtl;
--------------------------------------------------------------------------------

Bloque I_UnpackInst – UnpackInst.vhd

--------------------------------------------------------------------------------
-- SubModule UnpackInst
-- Created   12/09/2011 11:04:05 a.m.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;

entity UnpackInst is port
   (
     INST         : in    std_logic_vector(31 downto 0);
     OPCODE       : out   std_logic_vector(5 downto 0);
     RD           : out   std_logic_vector(4 downto 0);
     RS1          : out   std_logic_vector(4 downto 0);
     RS2          : out   std_logic_vector(4 downto 0);
     IMM          : out   std_logic_vector(15 downto 0);
     VAL          : out   std_logic_vector(25 downto 0)
   );
end UnpackInst;
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
architecture Structure of UnpackInst is
begin
     opcode <= inst(31 downto 26);
     rd <= inst(25 downto 21);
     rs1 <= inst(20 downto 16);
     rs2 <= inst(15 downto 11);
     imm <= inst(15 downto 0);
     val <= inst(25 downto 0);
end Structure;
--------------------------------------------------------------------------------

Bloque I_RegFile – RegFile.vhd

--------------------------------------------------------------------------------
-- SubModule RegFile
-- Created   12/09/2011 11:04:13 a.m.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity RegFile is port
   (
     rd_data         : in    std_logic_vector(31 downto 0);
     rd_wrl           : in    std_logic;
     rd_wrh           : in    std_logic;
     rd              : in    std_logic_vector(4 downto 0);
     rs1             : in    std_logic_vector(4 downto 0);
     rs2             : in    std_logic_vector(4 downto 0);
     rs1_data        : out   std_logic_vector(31 downto 0);
     rs2_data        : out   std_logic_vector(31 downto 0);
     clk             : in    std_logic
   );
end RegFile;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
architecture Structure of RegFile is
  type regs_t is array(0 to 31) of std_logic_vector(15 downto 0);
  signal regsh : regs_t;
  signal regsl : regs_t;
begin

     process(clk)
     begin
     if rising_edge(clk) then
        -- Engancha la parte baja
        if rd_wrl='1' then
          regsl(conv_integer(rd)) <= rd_data(15 downto 0);
        end if;
        -- Engancha la parte alta
        if rd_wrh='1' then
          regsh(conv_integer(rd)) <= rd_data(31 downto 16);
        end if;
     end if;
     end process;

    -- Muxes
    rs1_data <= regsh(conv_integer(rs1)) & regsl(conv_integer(rs1));
    rs2_data <= regsh(conv_integer(rs2)) & regsl(conv_integer(rs2));

end Structure;
--------------------------------------------------------------------------------

Bloque I_Alu – Alu.vhd

--------------------------------------------------------------------------------
-- SubModule Alu
-- Created   12/09/2011 11:04:20 a.m.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity Alu is port
(
  A           : in    std_logic_vector(31 downto 0);
  B           : in    std_logic_vector(31 downto 0);
  R           : out   std_logic_vector(31 downto 0);
  FLAGS       : out   std_logic_vector(2 downto 0);
  OP          : in    std_logic_vector(3 downto 0)
);
end Alu;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
architecture Structure of Alu is

  signal rres : std_logic_vector(31 downto 0);
begin

  process(a, b, op)
  begin
  case conv_integer(op) is
    when 0 => rres <= a + b;
    when 1 => rres <= a - b;
    when 2 => rres <= CONV_STD_LOGIC_VECTOR(conv_integer(a * b), 32);
    when 3 => rres <= a and b;
    when 4 => rres <= a or b;
    when 5 => rres <= not a;
    when 6 => rres <= shr(a, b);
    when 7 => rres <= shl(a, b);
    when others => rres <= a;
  end case;
  end process;

  r <= rres;
  flags(0) <= '1' when rres = 0 else '0';
  flags(1) <= '1' when rres > 0 else '0';
  flags(2) <= '1' when rres < 0 else '0';
end Structure;
--------------------------------------------------------------------------------

Bloque I_Mux – Mux.vhd

--------------------------------------------------------------------------------
-- SubModule Mux
-- Created   12/09/2011 11:04:29 a.m.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;
use ieee.std_logic_unsigned.all;

entity Mux is port
   (
     a         : in    std_logic_vector(15 downto 0);
     b         : in    std_logic_vector(31 downto 0);
     o         : out   std_logic_vector(31 downto 0);
     sel       : in    std_logic_vector(1 downto 0);
     c         : in    std_logic_vector(31 downto 0)
   );
end Mux;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
architecture Structure of Mux is
begin
  process(a,b,c, sel)
  begin
  case conv_integer(sel) is
  	when 0 => o <= a & a; -- "&" significa concatenar, NO es la operacion AND
    when 1 => o <= b; -- seleccion de b
    when others => o <= c; -- seleccion de c
  end case;
  end process;
end Structure;
--------------------------------------------------------------------------------

Bloque I_PC – PC.vhd

--------------------------------------------------------------------------------
-- SubModule PC
-- Created   12/09/2011 11:10:36 a.m.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.Std_Logic_1164.all;
use ieee.std_logic_unsigned.all;

entity PC is port
   (
     pc         : out   std_logic_vector(31 downto 0);
     inc        : in    std_logic_vector(25 downto 0);
     jump       : in    std_logic_vector(1 downto 0);
     clk        : in    std_logic;
     reg        : in    std_logic_vector(31 downto 0);
     reset      : in    std_logic
   );
end PC;
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
architecture Structure of PC is
   signal rpc : std_logic_vector(31 downto 0);
begin
     process(clk, reset)
     begin
     if reset = '1' then
     -- Usamos reset asincrono para volver a cero
        rpc <= (others => '0');
     elsif rising_edge(clk) then
     -- En el flanco de subida realizamos el salto si es requerido o
     -- incrementamos en 1 si no es necesario el salto
        case(conv_integer(jump)) is
        when 0 => rpc <= rpc + 1; -- incremento
        when 1 => rpc <= rpc + inc; -- salto relativo
        when others => rpc <= reg; -- salto absoluto
        end case;
     end if;
     end process;

     pc <= rpc;

end Structure;
--------------------------------------------------------------------------------

Bloque I_Control – Control.vhd

--------------------------------------------------------------------------------
-- SubModule Control
-- Created   12/09/2011 11:03:37 a.m.
--------------------------------------------------------------------------------
Library IEEE;
Use IEEE.Std_Logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity Control is
  port(
    opcode      : in  std_logic_vector(5 downto 0);
    flags       : in  std_logic_vector(2 downto 0);
    jump        : out std_logic_vector(1 downto 0);
    sel_rd_data : out std_logic_vector(1 downto 0);
    alu_op      : out std_logic_vector(3 downto 0);
    mem_rd      : out std_logic;
    mem_wr      : out std_logic;
    rd_wrl      : out std_logic;
    rd_wrh      : out std_logic
  );
end Control;
--------------------------------------------------------------------------------
architecture Structure of Control is
  type topcode is (
    OP_ADD, OP_SUB, OP_MUL, OP_AND, OP_OR, OP_NOT, OP_SL, OP_SR, -- Regs to Reg
    OP_MOV, -- Reg to Reg
    OP_JR, OP_J, OP_JE, OP_JNE, OP_JL, OP_JG, -- Jumps
    OP_LH, OP_LL, -- Load immediate
    OP_LW, OP_SW -- Load/Store Memory (Read/Write External Bus)
    );
  -- Tipo de salto
  type tjump is (J_NONE, J_JUMP_INC, J_JUMP_REG);
  -- Tipo de operacion posible en la ALU
  type taluop is (AO_ADD, AO_SUB, AO_MUL, AO_AND, AO_OR, AO_NOT, AO_SR, AO_SL, AO_BYPASS);
  -- Selectores de informacion que va al registro de destino
  type tselrd is (SR_IMM, SR_ALU, SR_MEM);
  -- Tipo de operacion de memoria / bus
  type tmemop is (MO_NONE, MO_READ, MO_WRITE);
  -- Tipos de escritura al register file
  type trfw is (RF_NONE, RF_BOTH, RF_LOW, RF_HIGH);

  signal iopcode   : topcode;
  signal ijump     : tjump;
  signal ialuop    : taluop;
  signal iselrd    : tselrd;
  signal imemop    : tmemop;
  signal irfw      : trfw;
  signal zeroflag  : std_logic;
  signal greatflag : std_logic;
  signal lessflag  : std_logic;
begin

  -- convierte el valor de entrada en valor simbolico
  iopcode   <= topcode'val(conv_integer(opcode));
  zeroflag  <= flags(0);
  greatflag <= flags(1);
  lessflag  <= flags(2);

  -- convierte los valores simbolicos en valores de salida
  jump        <= conv_std_logic_vector(tjump'pos(ijump), jump'length);
  alu_op      <= conv_std_logic_vector(taluop'pos(ialuop), alu_op'length);
  sel_rd_data <= conv_std_logic_vector(tselrd'pos(iselrd), sel_rd_data'length);
  mem_rd      <= '1' when imemop = MO_READ else '0';
  mem_wr <= '1' when imemop = MO_WRITE else '0';
  rd_wrl <= '1' when irfw = RF_BOTH or irfw = RF_LOW else '0';
  rd_wrh <= '1' when irfw = RF_BOTH or irfw = RF_HIGH else '0';

  process(iopcode, zeroflag, greatflag, lessflag)
  begin
    case iopcode is
      when OP_ADD =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_ADD;
      when OP_SUB =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_SUB;
      when OP_MUL =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_MUL;
      when OP_AND =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_AND;
      when OP_OR =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_OR;
      when OP_NOT =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_NOT;
      when OP_SL =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_SL;
      when OP_SR =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_SR;
      when OP_MOV =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_BOTH;
        ialuop <= AO_BYPASS;

-- DC: significa Dont-Care (no importa)
      when OP_JR =>
        ijump  <= J_JUMP_REG;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC

      when OP_J =>
        ijump  <= J_JUMP_INC;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC

      when OP_JE =>
        if zeroflag = '1' then
          ijump <= J_JUMP_INC;
        else
          ijump <= J_NONE;
        end if;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC
      when OP_JNE =>
        if zeroflag = '0' then
          ijump <= J_JUMP_INC;
        else
          ijump <= J_NONE;
        end if;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC
      when OP_JL =>
        if lessflag = '1' then
          ijump <= J_JUMP_INC;
        else
          ijump <= J_NONE;
        end if;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC
      when OP_JG =>
        if greatflag = '1' then
          ijump <= J_JUMP_INC;
        else
          ijump <= J_NONE;
        end if;
        iselrd <= SR_ALU;       -- DC
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC

      when OP_LH =>
        ijump  <= J_NONE;
        iselrd <= SR_IMM;
        imemop <= MO_NONE;
        irfw   <= RF_HIGH;
        ialuop <= AO_BYPASS;    -- DC
      when OP_LL =>
        ijump  <= J_NONE;
        iselrd <= SR_IMM;
        imemop <= MO_NONE;
        irfw   <= RF_LOW;
        ialuop <= AO_BYPASS;    -- DC

      when OP_LW =>
        ijump  <= J_NONE;
        iselrd <= SR_MEM;
        imemop <= MO_READ;
        irfw   <= RF_BOTH;
        ialuop <= AO_BYPASS;    -- DC
      when OP_SW =>
        ijump  <= J_NONE;
        iselrd <= SR_MEM;       -- DC
        imemop <= MO_WRITE;
        irfw   <= RF_NONE;
        ialuop <= AO_BYPASS;    -- DC

      when others =>
        ijump  <= J_NONE;
        iselrd <= SR_ALU;
        imemop <= MO_NONE;
        irfw   <= RF_NONE;
        ialuop <= AO_NOT;
    end case;
  end process;
end Structure;
--------------------------------------------------------------------------------

Descripción terminada…

La descripción del sistema en su forma funcional esta terminada. Con esto me refiero a que en este momento tenemos todo un diseño que incluye elementos básicos descritos con VHDL y cableados mediante diagramas de bloques (de manera que es mas sencilla su interpretación) para así formar un sistema completo. Recordemos los elementos que eran necesarios para describir un sistema en forma completa:

El paso siguiente  será obtener a partir de todo esto, una descripción totalmente en HDL (sin diagramas de bloques) de manera que nuestro sistema pueda ser simulado. Para lograr esto, le pediremos a Altium que convierta nuestros diagramas de bloques en archivos VHDL que representan el mismo cableado.

Noten que pudimos haber escrito todo el sistema usando VHDL, pero visualizar la estructura a partir del código VHDL no es para nada intuitivo, por el contrario la claridad de nuestro objetivo se pierde en el código, Es mucho mas intuitivo ingresar el diagrama al software y mantener estos diagramas por ello usamos una herramienta que nos facilitara el trabajo.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s