Dokumentation

VHDL-Projekt III/37 - Gruppe 4
Benutzung des Multiplikationsbausteins
Quellcode der Schaltung
Testumgebung
     Testbench
     Top Entity
Testablauf
Schaltbild
Erkenntnisse
 
Navigation: Projekthauptseite

Benutzung des Multiplikationsbausteins

An den Multiplikationsbausteins müssen an den beiden 8-Bit-Eingängen in_data_1 und in_data_2 die beiden Faktoren der Multiplikation angelegt werden. Das Einlesen der Werte und der Start der Berechnung wird über den load Eingang gesteuert, indem man ihn auf '1' setzt.
Die Multiplikation ist abgeschlossen, wenn ready='1' ist. Dann kann das Ergebnis der Multiplikation über den 16-Bit Ausgang out_data gelesen werden.
Während der Berechnung ist ready='0' und an out_data liegt der Wert 0 an.
Neue Werte werden erst eingelesen, wenn ready='1' ist.

Die Schaltung kann vereinfacht als Kasten folgender Gestalt angesehen werden:


Anfang

Quellcode der Schaltung

LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY synth;
USE synth.vhdlsynth.all;

ENTITY multiplier IS
PORT  (
      clk       : IN STD_LOGIC;                      -- Taktsignal
      load      : IN STD_LOGIC;                      -- "Werte laden" Signal
      in_data_1 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);   -- 1. Faktor
      in_data_2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);   -- 2. Faktor
      ready     : OUT STD_LOGIC;                     -- 1=Berechnung abgeschlossen
      out_data  : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)  -- Ergebnis
      );
END multiplier;

ARCHITECTURE multiplier_arch OF multiplier IS

SIGNAL add      : STD_LOGIC_VECTOR(7 DOWNTO 0)  := "00000000";          -- Summand
SIGNAL counter  : STD_LOGIC_VECTOR(7 DOWNTO 0)  := "00000000";          -- verbleibende Additionen
SIGNAL speicher : STD_LOGIC_VECTOR(15 DOWNTO 0) := "0000000000000000";  -- Zwischenergebnis

BEGIN

  multiplication:
  PROCESS (clk)
  BEGIN
    IF clk'EVENT AND clk='1' THEN
      IF counter > 0 THEN

        speicher <= speicher + ("00000000" & add);  -- Berechnungsschritt
        counter  <= counter-1;

      ELSE

        IF load='1' THEN                    -- geladen wird nur, wenn
          speicher <= "0000000000000000";  -- keine Berechnung angestoßen wurde

          IF in_data_1<in_data_2 THEN      -- um benötigte Taktzyklen zu
            counter <= in_data_1;          -- minimieren wird der kleinere
            add   <= in_data_2;            -- Wert als Zähler verwendet
          ELSE
            counter <= in_data_2;
            add   <= in_data_1;
          END IF;

        END IF;
      END IF;
    END IF;

  END PROCESS;

  out_data <= speicher WHEN counter=0 ELSE "0000000000000000";  -- Ergebnis nur ausgeben,wenn
                                                                   -- Berechnung abgeschlossen ist
  ready <= '1' WHEN counter=0 ELSE '0';

END multiplier_arch;
Verhalten.vhd

Die genaue Beschreibung der Ein-/Ausgänge und des Verhaltens des Bausteins finden Sie in der Spezifikation.

Anfang

Testumgebung

Testbench

Um die Korrektheit unserer Schaltung zu überprüfen, wurde die Schaltung mit Hilfe einer Testbench getestet.
Der Testbench-Baustein erzeugt zum einen ein 10 MHz Taktsignal, mit dem die Schaltung dann betrieben wird.
Außderdem erzeugt er alle 256*256=65536 möglichen Kombinationen für in_data_1 und in_data_2. Das wird dadurch erreicht, daß die Testbench ständig über das ready Signal des Multiplizierers überprüft, ob eine Berechnung abgeschlossen ist in diesem Fall load auf 1 setzt, um eine neue Berechnung anzustoßen. Gleichzeitig werden die Werte von in_data_1 und (wenn in_data_1 von "11111111" auf "00000000" springt) in_data_2 um 1 erhöht.
Um das Zeitverhalten der Schaltung nachvollziehen zu können, wird in dem 16-Bit Signal tempcyc die Anzahl der verstrichenen Taktzyklen festgehalten.

Hier der Quellcode von Testbench.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY synth;
USE synth.vhdlsynth.all;

ENTITY testbench IS
PORT (
     in_data_1,
     in_data_2 : OUT STD_LOGIC_VECTOR(7 downto 0);  -- die beiden Faktoren
     load      : OUT STD_LOGIC;                     -- "Werte Laden" Signal
     ready     : IN STD_LOGIC;                      -- =1, wenn multiplier fertig ist
     clk       : OUT STD_LOGIC                      -- generiertes Taktsignal
     );
END testbench;


ARCHITECTURE testbench_arch OF testbench IS

SIGNAL   tempcyc    : NATURAL := 0;                 -- zählt verstrichene Taktzyklen
SIGNAL   tempclk    : STD_LOGIC := '0';             -- zur Generierung des Takts
CONSTANT clk_period : TIME := 100 ns;               -- 10 MHz Taktfrequenz
SIGNAL   buffer1,                                   -- Zwischenspeicher für die Faktoren
         buffer2    : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";

BEGIN
  clk       <= tempclk;
  in_data_1 <= buffer1;
  in_data_2 <= buffer2;

  clock: PROCESS
    -- generiert das Taktsignal
  BEGIN
    tempclk <= '1';
    WAIT FOR clk_period / 2;   -- fallende Taktflanke
    tempclk <= '0';
    WAIT FOR clk_period / 2;   -- steigende Taktflanke
    tempcyc <= tempcyc + 1;    -- ein Taktzyklus verstrichen
  END PROCESS clock;

  stimulus: PROCESS(tempclk)
    -- durchläuft alle möglichen Kombinationen der
    -- beiden Faktoren (65536 verschiedene)
  BEGIN
    IF (tempclk'EVENT AND tempclk = '1') THEN
      IF (ready='1') THEN                    -- ist multiplier bereit ?

        load <= '1';                      -- neue Werte laden
        buffer1 <= buffer1 + "00000001";

        IF (buffer1 = "11111111") THEN
          buffer2 <= buffer2 + "00000001";
        END IF;

      ELSE                                   -- noch nicht bereit, also warten
        load <= '0';
      END IF;
    END IF;

  END PROCESS stimulus;

END testbench_arch;

Anfang

Top Entity

Die Top Entity stellt die Verbindung zwischen der Testbench und dem Multiplizierer her.

Hier der Quellcode von Top.vhd:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY synth;
USE synth.vhdlsynth.all;

ENTITY TOP IS
END TOP;

ARCHITECTURE TOP_ARCH OF TOP IS

SIGNAL clk,
       load,
       ready      : STD_LOGIC := '0';
SIGNAL in_data_1,
       in_data_2  : STD_LOGIC_VECTOR (7 DOWNTO 0) := "00000000";
SIGNAL out_data   : STD_LOGIC_VECTOR (15 DOWNTO 0) := "0000000000000000";

COMPONENT multiplier
PORT (
     clk       : IN STD_LOGIC;                       -- Takt
     load      : IN STD_LOGIC;                       -- "Werte laden" Signal
     in_data_1 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);    -- 1. Faktor
     in_data_2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0);    -- 2. Faktor
     ready     : OUT STD_LOGIC;                      -- =1, wenn multiplier fertig ist
     out_data  : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)   -- Ergebnis
     );
END COMPONENT;

FOR TEIL_1: multiplier USE ENTITY WORK.multiplier(multiplier_arch);

COMPONENT testbench
PORT (
     in_data_1,
     in_data_2  : OUT STD_LOGIC_VECTOR(7 downto 0);  -- die beiden Faktoren
     load       : OUT STD_LOGIC;                     -- "Werte Laden" Signal
     ready      : IN STD_LOGIC;                      -- =1, wenn multiplier fertig ist
     clk        : OUT STD_LOGIC                      -- generiertes Taktsignal
     );
END COMPONENT;

FOR TEIL_2: testbench USE ENTITY WORK.testbench(testbench_arch);

BEGIN
    TEIL_1:  multiplier PORT MAP (clk, load, in_data_1, in_data_2, ready, out_data);
    TEIL_2:  testbench PORT MAP (in_data_1, in_data_2, load, ready, clk);
END TOP_ARCH;

Anfang

Testablauf

Mit Hilfe des Programms Speedwave wurde die Gesamtschaltung der Topentity simuliert und gleichzeitig mit dem Programm VWave der Verlauf der wichtigsten Signale aufgezeichnet.

Nachfolgend ist ein Ausschnitt dieser Aufzeichnung zu sehen:

In dem markierten Bereich kann man die Multiplikation von 0Fh mit 03h verfolgen.
Takt 1   Man erkennt, wie der kleinere Faktor 03h in counter und der größere Faktor 0Fh in add eingelesen wird. Außerdem wird speicher mit 0 initialisiert.
Takt 2 Der erste Additionsschritt wird ausgeführt, also 0Fh zu speicher addiert. Gleichzeitig wird counter um 1 dekrementiert.
Takt 3 zweiter Addititionsschritt
Takt 4 Letzter Additionsschritt. counter wurde auf 0 heruntergezählt, deswegen wird nun ready auf 1 gesetzt und out_data mit dem Ergebnis 2Dh der Multiplikation geladen.

Anfang

Schaltbild

Die in VHDL beschriebene Schaltung multiplier wurde nun noch mit dem Programm Aurora synthetisiert. Das mit dem Programm Viewdraw darstellbare Ergebnis ist ein Schaltbild, in dem multiplier auf Gatterebene dargestellt wird.

Wir beschränken uns hier auf die Übersichtsdarstellung der Schaltung, Details (z.B. Gatter) werden erst bei starker Vergrößerung (mit Viewdraw) gut erkennbar.

Eingänge

Ausgänge

Anfang

Erkenntnisse

Die Multiplikation durch fortgesetzte Addition ist sicher nicht die schnellste Methode. Wie in der Spezifikation bereits angegeben, benötigt die Schaltung
  T = min(in_data1, in_data2) + 1
Takte, bis sie ein Ergebnis liefert. Im Zeitalter der Hochgeschwindigkeitsrechner sind z.B. 101 Takte für die Multiplikation von 100 mit 200 eine viel zu lange Zeit. So benötigt z.B. der Pentium Prozessor für eine 8-Bit Multiplikation unabhängig vom Wert der Faktoren nur 11 Takte.
Eine Alternative zu unserer Lösung wäre z.B. ein Multipliziernetz.

Anfang
zu den TGI-SeitenZu den TGI-Seiten der TUM

01.07.98