Mejorar mi ALU “De NAND a Tetris” en VHDL

Estoy siguiendo el curso From NAND to Tetris , pero en lugar de usar el software del autor, estoy tratando de programar directamente un Spartan 6 FPGA . Ahora estoy resolviendo el ejercicio ALU y terminé escribiendo el siguiente código ( descargo de responsabilidad: comencé a aprender VHDL ayer):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity alu is
    Port (x  : in  STD_LOGIC_VECTOR(15 downto 0);
          y  : in  STD_LOGIC_VECTOR(15 downto 0);

          zx : in  STD_LOGIC;
          nx : in  STD_LOGIC;
          zy : in  STD_LOGIC;
          ny : in  STD_LOGIC;
           f : in  STD_LOGIC;
          no : in  STD_LOGIC;

          output : out STD_LOGIC_VECTOR(15 downto 0);
          zr     : out STD_LOGIC;
          ng     : out STD_LOGIC);

             constant zeros: STD_LOGIC_VECTOR(15 downto 0) := "0000000000000000";
end alu;

architecture Behavioral of alu is
begin
    op: process(x, y, zx, nx, zy, ny, f, no)
      variable px: STD_LOGIC_VECTOR(15 downto 0);
      variable py: STD_LOGIC_VECTOR(15 downto 0);
      variable po: STD_LOGIC_VECTOR(15 downto 0);
    begin
      px := x;
      py := y;

      px := zeros   when (zx = '1');
      px := not(px) when (nx = '1');
      py := zeros   when (zy = '1');
      py := not(py) when (ny = '1');

      if (f = '1') then 
        po := (px + py);
      else
        po := (px AND py);
     end if;

      po := not(po) when (no = '1');
      output <= po;

     if (po = zeros) then
        zr <= '1';
      else
        zr <= '0';
      end if;

      ng <= po(0);
    end process;
end Behavioral;

Ahora me pregunto si hay una forma más sencilla de lograr lo mismo, considerando:

  1. (VHDL) Buenas prácticas;
  2. (VHDL) Tamaño del código;
  3. Usar la menor lógica secuencial posible;
  4. Tamaño de síntesis.

Respuestas (1)

(VHDL) Buenas prácticas;

Es mucho más fácil programar la reunión si haces que cada entidad sea sincrónica: dale un reloj (y reinícialo si es necesario) y escribe un proceso cronometrado. Entonces tampoco tiene que preocuparse por mantener actualizadas las listas de confidencialidad.

Tenga en cuenta esto:

use IEEE.STD_LOGIC_UNSIGNED.ALL;

No use eso, aunque se comporta mejor que std_logic_arith . Use ieee.numeric_std.all;en su lugar y luego use los tipos apropiados para sus vectores.

Uso de variables: esa es una buena señal en mi libro. Mantiene las cosas locales muy locales.

Puede dimensionar sus variables automáticamente:

variable px : std_logic_vector(x'range);

y tu constante (que podrías trasladar a la arquitectura, que sería más convencional):

constant zeros: STD_LOGIC_VECTOR(x'range) := (others => '0');

(VHDL) Tamaño del código

No estoy seguro de que puedas guardar tanto código sin perder legibilidad.

Usar la menor lógica secuencial posible;

¿Por qué? Los flipflops son casi gratuitos en los FPGA. Casi siempre me quedo sin LUT primero.

Tamaño de síntesis

No es frecuente que el código tenga la mayor influencia en el tamaño de la síntesis. Son cosas de nivel superior como paralelo (mucha lógica) frente a secuencial (un poco de lógica a su vez, pero no olvide que la máquina de estado que lo controla puede ser una sobrecarga).