Mejorar estabilidad del Netgear DGN3500


Los propietarios del DGN3500 estarán de acuerdo conmigo en que es una maquinita muy problemática.

Si en principio sus especificaciones en papel son espectaculares, a la hora del té, este router se queda muy corto en estabilidad y fiabilidad. En mi caso este router tiende a colgarse inesperadamente dejando de responder a toda solicitud. Usualmente la funcionalidad de switch nunca se detiene, pero el enrutamiento y punto de acceso si mueren por completo. En ocasiones el router empieza a funcionar con una conectividad muy lenta hacia Internet de poco menos de 1Mbps.

Resumen de especificaciones

  • Modem ADSL2+ integrado
  • Puerto USB integrado
  • WiFi b/g/n con ancho de banda teorico de  300Mbps
  • Switch Ethernet de 1Gbps

Diagnóstico

Bueno, para no seguir criticando hablemos de las razones:

He notado que este router se calienta demasiado cuando es utilizado por largos periodos de tiempo ininterrumpidos. Por supuesto, para que otra cosa es un router Gigabit con modem ADSL y punto de acceso WiFi, si no es para operar continuamente?

El sistema esta compuesto de tres integrados principales. El PSB508010, un SoC de Lantiq (antes Infineon) que le da la capacidad de modem ADSL2+ y provee el procesador MIPS 4Kc principal. El chip Realtek RTL8366RB responsable del switch Gigabit Ethernet; y El chip Atheros  AR9233 que provee WiFi IEEE-802.11bgn esta conectado al resto sistema via bus PCI cableado en la tarjeta.

El culpable según mi análisis es el chip SoC Lantiq PSB que disipa demasiado calor. Por otro lado, el RTL8366RB  no tiene problemas de disipación excesiva de calor. El AR9233 también se calienta considerablemente.

DGN3500
DGN3500 – Placa PCB

Netgear DGN3500 - original

Solución propuesta

Para verificar si el calentamiento era una verdadera razón del mal funcionamiento, decidí añadir un disipador de calor al SoC de Lantiq, la mayor fuente de calor en el sistema y abrir una entrada de aire adicional dentro de la caja. Es curioso que el ensamblado no ofrece ningún tipo de blindaje ni siquiera para la sección de RF. Para ello fue necesario un disipador viejo tomado de una placa base de computador inservible, seguro puedes conseguir alguno fácilmente escarbando en computadores viejos o equipos de sonido dañados, un poco de pasta o crema disipadora de calor. Un moto-tool con disco de carburo para abrir el hueco en el acrilico. Y muchas ganas de ver tu router funcionando bien.

NETGEAR DGN3500 con disipado de calor añadido y funcionando
NETGEAR DGN3500 con disipado de calor añadido y funcionando
NETGEAR DGN3500 con disipado de calor añadido
NETGEAR DGN3500 con disipado de calor añadido

Este Post fue subido a traves de el 🙂

Undercover! HP Envy 4 – 1050LA


Que hay dentro de un Envy4-1050la?

En otros paises fuera de suramerica este PC tambien se vende con el nombre de ENVY 6t-1000 series

Specs

La verdad bajo las cubiertas. The truth under the hood!

Curiosidades

  • El promocionado Beats Audio fisicamente consiste de un codec de audio HD integrado fabricado por IDT y un sistema de bocinas con gomas que atenuan los trastabilleos cuando las bocinas vibran cerca del chasis.
  • El procesador Intel Core i5-3317U esta directamente soldado sobre la PCB, no hay socket y ya no tendremos oportunidad de reemplazarlo. Con esto se ha logrado un diseño de menor espesor.
  • El Intel Core i5-3317U es un modelo de muy bajo voltaje para lograr larga vida en la bateria logrando un sistema con estas dimensiones. Incorpora los ahora ya afamados transistores 3D  Tri-Gate fabricado en el nodo de 22nm. Sus caracteristicas pueden verse aqui.
  • La memoria RAM DDR3 viene en sockets, y por lo tanto es ampliable.
  • La memoria RAM OEM no viene en configuracion simetrica. En su lugar usa dos modulos: 4GB+2GB, algo un poco raro sabiendo que tenemos un diseño de controlador doble canal.
  • Un gran porcentaje del volumen es ocupado por la bateria de 52Wh
  • Hay un gran espacio vacio en la PCB contiguo al procesador. La gran isla de cobre en el parece indicar que se uso para crear una capacitancia para desacople de fuente de muy alta frecuencia.
  • Hay un modulo de PCB desacoplable con la pila del RTC sobre el. A mis ojos parece ser el alojador del firmware BIOS/EFI.

Por qué no usar el LM741 en nuestros circuitos de hoy en dia?


Pinout of a generic 741 operational amplifier ...
Image via Wikipedia

El mundialmente conocido amplificador operacional LM741 (caballito de batalla de todos los tiempos)  es un diseño muy antiguo cuyas especificaciones han sido enormemente superadas por muchos otros amplificadores operacionales de los ultimos tiempos. El 741 se gano el aprecio de multitudes de diseñadores por sus espectaculares prestaciones en su época, sin embargo hoy en dia (Octubre 2011) existen muchos nuevos modelos de op-amps que superan al 741 en prácticamente todos los escenarios donde un 741 antes hubiese sido ideal, especialmente en el tema de la alimentación.

El 741 es muy popular en diseños aficionados y de estudiantes debido a que es el ejemplo típico en los salones de clase y libros teóricos acerca del funcionamiento interno de los amplificadores a par diferencial.

Que alternativas hay?

En mi pais, Colombia, no es muy fácil conseguir ICs especializados pero los siguientes son los modelos que según mi experiencia son fáciles de conseguir en las tiendas de componentes electrónicos y son apropiados para aplicaciones de bajo ancho de banda.

Puedes considerar estos integrados para reemplazar el 741 en tus diseños: LF351, LF353, LM358, LM324, TSV321, TSV358, TSV324.

Las ventajas de los nuevos modelos usualmente estriban en el ancho de banda, slew rate, y sobre todo en el requerimiento de tensión de alimentación, ya que hoy dia la tendencia es usar bajos voltajes (especialmente si involucras circuiteria digital en la que el estandar es 3.3V o si esperas operar el circuito desde baterias comerciales). Normalmente todos estas opciones están disponibles también en empaquetados SMD SOIC-8 por un precio igual o menor al de un 741.

LM358 y LM324

Un solo chip LM358 contiene dentro de si, dos amplificadores operacionales. (ver datasheet)

Un solo chip LM324 contiene dentro de si, cuatro amplificadores operacionales (ver datasheet).

Los amplificadores integrados en el LM358 y LM324 son identicos.

Ancho de banda a ganancia unitaria: 1MHz

Alimentacion dual desde ±1.5V hasta ±16V (3V hasta 32V a fuente sencilla). Lo cual le permite reducir los requerimientos de tensión en la fuente.

LF353 y LF351 o TL084

Un chip LF351 contiene un solo amplificador operacional (ver datasheet).

Un solo chip LF353 contiene dentro de si, dos amplificadores operacionales (ver datasheet).

Los amplificadores integrados en el LF353 y LF351 son identicos.

Ancho de banda a ganancia unitaria: 4MHz  (lo cual lo hace a penas apropiado para aplicaciones de audio como preamplificadores, ecualizadores, filtros activos, etc).

Entrada JFET, lo cual le da una impresionante impedancia de entrada de 12MOhms. (Ideal para acoplar sensores u otros dispositivos de señal muy débil).

Alimentación a fuente dual desde +/-6V (o a fuente sencilla de 12V) menos de este valor causará una gran degradacion en el ancho de banda y rango de voltaje de salida, operable hasta +/-18V (o hasta 36V a fuente sencilla).

Fue diseñado para reemplazar al LM358 en casi todas sus aplicaciones pero observa bien los requerimientos de alimentación y encontrarás casos en donde no es posible el reemplazo.

TSV321, TSV358, TSV324

Su voltaje de operación es mucho mas limitado (+2.5V hasta +6V ) sin embargo se trata de dispositivos Rail to rail. (ver datasheet)

Ancho de banda a ganancia unitaria: 1.4MHz

Son dispositivos Rail-to-Rail (riel a riel) es decir que pueden operar en todo el rango de voltaje en el que están alimentados. Lo cual permite diseñar usando fuentes de voltaje de menor tension.

Mi “top useful EDA software list” de 2011


Altium Designer  – http://products.live.altium.com/

Pros:

Altium Designer esta lleno de características que no voy a detallar aquí, pero si nombraré mis dos favoritas.

  • UI Acelerada en Hardware: Aprovecha tu tarjeta de video para renderizar el contenido (si señores no es mentira). Layouts de PCB complejos y también diagramas de bloques están totalmente acelerados en hardware, esto le da una usabilidad y sensación de interfaz veloz especialmente durante los paneos y los zooms continuos (non ticking).
  • Flujo de diseño de nivel de sistema integrado: Te permite diseñar sistemas completos usando FPGAs o microprocesadores mientras mantienes la coherencia entre los detalles del Layout PCB, del Diagrama de bloques, código fuente de nivel de software y las especificaciones del sistema (Backannotate). De esto se deriva que te deja OPTIMIZAR LA DISTRIBUCION DE ASIGNACION DE PINES DE LOS CHIPS BASADOS EN LA CERCANIA FISICA EN LA PCB dejándote mas fácil el proceso de layout. Muy útil para proyectos de nivel de sistema.

Contras:

  • Elevado costo: una licencia empieza alrededor de USD $5.000

LTspice IV – http://www.linear.com/designtools/software/

Pros:

  • Ultraliviano simulador análogo compatible con la sintaxis de SPICE también con interfaz grafica.
  • Puedes añadirle modelos SPICE (disponibles en las paginas de los fabricantes de dispositivos) muy fácil.
  • Maniobrable y rápido. Muy útil para simular rápidamente nuevos proyectos o hacer pruebas de concepto.
  • Gratis.
  • Puedes arrancar a trabajar en segundos sin configurar rutas, ni proyectos, ni directorios.

Contras:

  • Limitada interfaz de usuario.
  • No realiza simulación mixta.

ModelSim – http://www.model.com/

Pros:

  • Excelente simulador HDL. Rápido y estable. Te permite ver el estado de todas las señales internas en un sistema durante la simulación.
  • Consigues gratis versiones Starter mediante los fabricantes de FPGAs con buenas prestaciones o Student.

Contras:

  • Sin quejas hasta ahora Sonrisa
  • SOLO la edición COMPLETA SOPORTA CODE COVERAGE

Implementación de la arquitectura Zetta – PASO 4


Síntesis del diseño

Vamos a tomar nuestros (diagramas de bloques y archivos en VHDL)  y a partir de ellos vamos obtener una descripción de todo nuestro sistema totalmente en VHDL, Como? en Altium Designer:

Usamos la opción Compilar proyecto

compilePrj

Si por alguna extraña razón Llorón obtienes un error de la forma “Port PortName not matched to Sheet-Entry at Location”, configura el proyecto para ignorar estos errores (suena a trampa, y lo es!) en el menú Project + Project Options, en la pestaña Error Reporting desactiva busca el ítem Port not linked to parent sheet-symbol y a su modo de reporte donde dice Fatal Error ajústalo a No Report. En mi caso: luego de compilar, guardar, cerrar, y volver a ajustar esta propiedad a la normalidad (Fatal Error), el problema dejo de presentarse en las compilaciones Sonrisa.

Fixbug

Añade un nuevo Constraint File haciendo click derecho en el proyecto.

AddConstraintFile

Yo añadí la línea al final del archivo para indicar la FPGA que voy a usar.

Record=Constraint | TargetKind=Part | TargetId=EP2C20F484C7

La cual también es posible usando un cuadro de dialogo mas amigable mediante el menú Design + Add/Modify Constraint + Part…

fpgaSel

Luego de compilar exitosamente usa el comando Síntesis haciendo click derecho en el proyecto.

Luego de esto puedes ver los archivos generados por el comando de sintesis como se muestra en esta figura.

VhdlGenerated

En estos archivos generados podemos ver como Altium ha hecho escrito todo el cableado por nosotros. Ahora cono el sistema totalmente en VHDL podemos utilizar cualquier herramienta de la industria para continuar nuestro trabajo (simuladores, sintetizadores para FPGA, compiladores de diseño, etc).

La síntesis también genera un archivo de extension .EDN usualmente llamado netlist EDIF, este archivo contiene nuestro diseño convertido a primitivas lógicas pero esa es otra historia.

Simulación

En este paso vamos a realizar una simulación de nuestro procesador usando el software MentorGraphics ModelSim.

Este software es de pago, pero podemos usar una edición gratuita (que puedes descargar aquí) para nuestros propósitos preparada por el fabricante Altera formalmente llamada ModelSim-Altera Starter Edition yo uso la mas reciente al momento de escribir esto (v6.6d for Quartus II v11.0SP1).

  • Debemos crear un nuevo proyecto en ModelSim usando File+New Project…
  • Ajusta el directorio a una carpeta nueva para no polucionar un solo folder.
  • Añade al proyecto todos los archivos VHD que están en la carpeta del proyecto de Altium, preferiblemente como una referencia y no copiando los archivos, Y RECUERDA AÑADIR TAMBIEN LOS ARCHIVOS VHD GENERADOS. Generalmente estan en la carpeta ProjectOutputs/
  • Usa Compile+Compile All.  Todos los archivos deben compilar sin problemas.
  • Usando ModelSim abre cualquier archivo VHD en el proyecto.
  • Con el foco en el editor de código, aparece un menú llamado Source. Úsalo y activa en el la opción Show Language Templates
  • En el panel que aparece llamado Language Templates, usa la opción Create Testbench.
  • En el cuadro de dialogo selecciona la unidad de diseño Entidad sys que esta dentro del Library work. presiona Next y Finish.

Verás que ModelSim ha creado un nuevo archivo llamado sys_tb.vhd y lo ha añadido al proyecto. En el no hay mas que una entidad sin entradas ni salidas que instancia a la entidad sys y le cablea todas su señales pero que no les asigna ningún valor.

Este archivo se llama unTESTBENCH, es un archivo en el que se instancian las unidades de diseño que vamos a someter a prueba y les cableamos y les asignamos señales que cambian en el tiempo para poder ver como se comportan. OJO: la clave entre un archivo de diseño para sintesis y uno para testbench es que en el ultimo normalmente no hay entradas ni salidas y las señales cambian en el tiempo. Por eso es común encontrar partículas wait o after en el código de un testbench.

Añade esto al cuerpo de la arquitectura en el nuevo sys_tb.vhd:

clk <= not clk after 50 ns; -- Generacion de CLK

resetgen: process  -- Generacion de RESET begin reset <= '1'; wait for 300 ns; reset <= '0'; wait; end process;

También inicializa la señal clk en 0 añadiendo := ‘0’ a la declaración de la señal, la línea debería quedarte así:

  SIGNAL clk   :  std_logic := '0' ; 

Compila este archivo del proyecto haciendo click derecho sobre el y escogiendo Compile+Compile Selected.

Aquí les muestro como va mi pantalla.

screenModelSim

Para simular escoge la pestaña Library (en la imagen esta donde queda) y selecciona dentro de la library work la entidad sys_tb, esta entidad corresponde al testbench (banco de prueba) que acabamos de crear. Dale click derecho y enseguida Simulate. La pantalla cambiará drásticamente para mostrarnos el entorno de simulación.

Configura la simulación como puedes ver en la imagen en el orden en que se muestra.

LaunchSimulation

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.