Verbessere meine „From NAND to Tetris“ ALU in VHDL

Ich verfolge den Kurs From NAND to Tetris , aber anstatt die Software des Autors zu verwenden, versuche ich, direkt ein Spartan 6 FPGA zu programmieren . Ich löse jetzt die ALU-Übung und habe am Ende den folgenden Code geschrieben ( Haftungsausschluss: Ich habe gestern angefangen, VHDL zu lernen):

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;

Ich frage mich jetzt, ob es einen einfacheren Weg gibt, dasselbe zu erreichen, wenn man bedenkt:

  1. (VHDL) Gute Praktiken;
  2. (VHDL) Codegröße;
  3. Verwenden Sie so wenig sequentielle Logik wie möglich;
  4. Synthesegröße.

Antworten (1)

(VHDL) Gute Praktiken;

Es ist viel einfacher, das Timing von Besprechungen zu planen, wenn Sie jede Entität synchron machen - geben Sie ihr eine Uhr (und setzen Sie sie gegebenenfalls zurück) und schreiben Sie einen getakteten Prozess. Sie müssen sich dann auch nicht darum kümmern, Sensitivitätslisten aktuell zu halten.

Beachten Sie Folgendes:

use IEEE.STD_LOGIC_UNSIGNED.ALL;

Verwenden Sie das nicht - obwohl es sich besser benimmt als std_logic_arith . Verwenden Sie ieee.numeric_std.all;stattdessen und verwenden Sie dann die entsprechenden Typen für Ihre Vektoren.

Verwendung von Variablen - das ist ein gutes Zeichen in meinem Buch. Hält lokale Dinge sehr lokal.

Sie könnten Ihre Variablen automatisch skalieren:

variable px : std_logic_vector(x'range);

und Ihre Konstante (die Sie in die Architektur verschieben könnten, was konventioneller wäre):

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

(VHDL) Codegröße

Ich bin mir nicht sicher, ob Sie so viel Code speichern könnten, ohne die Lesbarkeit zu verlieren

Verwenden Sie so wenig sequentielle Logik wie möglich;

Warum? Flipflops sind in FPGAs fast kostenlos. Mir gehen fast immer zuerst die LUTs aus.

Synthesegröße

Es kommt nicht oft vor, dass der Code den größten Einfluss auf die Synthesegröße hat. Es sind Dinge auf höherer Ebene wie parallel (viel Logik) vs. sequentiell (ein wenig Logik wiederum - aber vergessen Sie nicht, dass die Zustandsmaschine, die sie steuert, ein Overhead sein kann).