Projekte.PCI-Tutorial-TGEntwBurst (Struktur)


Burst Transfer PCI Target mit 4 KByte RAM

Übersicht

Die für dieses Projekt modifizerten Dateien des LogiCore PCI Interface und die darüber hinaus benötigten Dateien sind [xc2s200fg456_32_33.ucf] [pcim_top.vhd] [bram_1k_32b.vhd] [cfg.vhd] [displayrom.vhd] [userapp.vhd] .

Die bisher beschriebenen PCI-Targets unterstützen nur Single Transfers zur Übertragung von genau einem Datenwort pro Transferzyklus. Der Transfer besteht aus einer Adressphase gefolgt von genau einer Datenphase. Für jedes weitere Datenwort beginnt ein neuer Zyklus bestehend aus Adress- und Datenphase. Diese einfachen Transfers können effizienter gestaltet werden, wenn Datenwörter mit aufeinanderfolgenden Adressen übertragen werden sollen. Dann genügt es offensichtlich, zu Beginn des Transfers einmal die Startadresse in einer Adressphase zu senden und dann nur noch die aufeinanderfolgenden Datenwörter bis der gesamte Transfer abgeschlossen ist oder eine andere Unterbrechungsbedingung den Transfer stoppt. Dies sind die sogenannten Burst Transfers.

In diesem Kapitel wird der Entwurf "Single Transfer PCI Target mit 4 KByte RAM" auf Bursttransfers erweitert. Über die bloße Erweiterung des PCI-Interfaces hinaus werden die Burstlängen gemessen und auf den 7-Segment-Anzeigen ausgegeben. Die Module userapp und pcim_top müssen dazu um diese zusätzlichen I/O-Ports ergänzt und passende LOC-Constraints in der User Constraint Datei eingetragen werden. Für die 7-Segment-Anzeigen wird die Komponente displayrom aus dem "Board-Test"-Projekt recycelt.

Verwendete Signale des LogiCore PCI Interfaces

Die exakten vollständigen Definitionen sind dem [Logic Core PCI Design Guide] zu entnehmen.

Allgemeine Signale

ADIO (31 downto 0)
(PCI ↔ Userapp.)
Über diesen bidirektionalen Bus werden Daten- und Adresstransfer durchgeführt (Zeitmultiplex).
ADDR_VLD
(PCI → Userapp.)
ADDR_VLD zeigt an, dass eine Adressphase, die ein beliebiges Target betreffen kann, auf dem PCI-Bus beobachtet wurde und diese Adresse nun auf dem internen ADIO-Bus verfügbar ist. (Einen Takt später steht sie dann auch gelatcht auf dem internen ADDR-Bus zur Verfügung.)

Signale des Target- ("Slave"-) Automaten des LogiCore PCI Interfaces

BASE_HIT (7 downto 0)
(PCI → Userapp.)
Dieses Signal ist der erste Indikator dafür, dass die aktuelle PCI-Transaktion in einen der Adressräme des Targets zielt. Da das LogiCore PCI Interface nur max. drei Adressräume implementiert, sind auch nur die unteren drei Bits BASE_HIT(2) bis BASE_HIT(0) relevant (One-Hot-Codierung).

Gültigkeit: genau ein Takt.

S_WRDN
(PCI → Userapp.)
S_WRDN gibt die Richtung der aktuellen Target-Transaktion an.
  • '1' : schreiben (PCI → Userapp.)
  • '0' : lesen (Userapp. → PCI)
Gültigkeit: S_WRDN wird in dem Taktzyklus gültig, in dem auch BASE_HIT(x) gesetzt wird, und für die Dauer der Transaktion gehalten.
S_DATA
(PCI → Userapp.)
S_DATA signalisiert, dass sich der Target-Automat des LogiCore PCI Interfaces im Datentranfer-Zustand befindet: Die Adresse wurde zuvor dekodiert und erfolgreich mit einem der Basisadressregister abgeglichen. Das Target hat die Anfrage akzeptiert und wird nun reagieren.
S_DATA_VLD
(PCI → Userapp.)
S_DATA_VLD hat zwei Bedeutungen, die von der Richtung des Datentransfers abhängen:
  • Bei einem Schreibzyklus (PCI → Userapp.) sind die Daten auf dem ADIO-Bus gültig, wenn S_DATA_VLD gesetzt ist.
  • Innerhalb eines Lesezyklus (Userapp. → PCI) signalisiert S_DATA_VLD, dass eine Datenphase auf dem PCI-Bus abgeschlossen wurde.
S_SRC_EN
(PCI → Userapp.)
S_SRC_EN ist ein wichtiges Signal für den Burst-Lesezugriff. Es wird benutzt, um den internen Adresszähler zu erhoehen. Das PCI-Interface signalisiert so, dass es ein neues Datenwort braucht, wenn es in die nächste Datenphase (Steuersignal S_DATA) eintritt. Genaueres siehe unten.

Signale zur Flusssteuerung und Transferabbruch

S_READY
(Userapp. → PCI)
Mit S_READY wird dem LogiCore PCI Interface die Bereitschaft zum Datentransfer angezeigt. Dieses Signal kann dazu benutzt werden, Wartezyklen in den Transfer einzuügen.
S_TERM
(Userapp. → PCI)
Der Datentransfer soll beendet werden.

Die Kombination von S_READY und S_TERM realisiert die verschiedenen Möglichkeiten eines Targets, den Transfer "geordnet" zu beenden oder zu steuern.

Bedingung S_TERM S_READY Erläuterung
Wait 0 0 Einfügen von Wartezyklen
Normal 0 1 Die Datenphase(n) werden normal, d.h. ohne zusätzliche Wartezyklen und Transfer-Abbruch durch das Target ausgeführt.
Disconnect Without Data (Retry) 1 0 Beendigung der aktuellen PCI-Bus Transaktion ohne einen Datentransfer in der letzten Datenphase. Der Initiator des Transfers ("Master") muß den Datentransfer später wiederholen.
Disconnect With Data 1 1 Der Datentransfer in der letzten Datenphase wird zuendegeführt, bevor die Transaktion terminiert.

S_ABORT
(Userapp. → PCI)
S_ABORT dient der Signalisierung schwerer Fehler (Target Abort auf dem PCI-Bus). Ein schwerer Fehler leigt z.B. dann vor, wenn ein Burst-Transfer die obere Grenze des Adressbereichs des Targets überschreitet.

Um dieses Beispiel möglichst klein zu halten, wird S_ABORT nicht verwendet. Überschreitet ein Bursttransfer die obere Grenze, kommt es stattdessen zu einem internen Adresszählerüberlauf. Der Transfer setzt sich an der Adresse 0 fort.

Der Hardware-Entwurf des PCI-Targets

Der Entwurf ist eine Erweitung des "Single Transfer PCI Target mit 4 KByte RAM" und baut auf dem schon vorhandenen VHDL-Code in der Datei userrapp.vhd auf.


Abb.: Das schon bekannte RAM-Modul bram_1k_32b mit vorgeschaltetem Target Address Pointer

Die Abbildung zeigt die strukturelle Erweiterung. Da bei einem Bursttransfer im allgemeinen (der Single Transfer ist ein spezieller Burst Transfer der Länge 1) nicht mehr zu jedem Datenwort eine expilizite Adresse geliefert, sondern nur noch die Startadresse der Datenwortsequenz, muss das Target die aktuelle Adresse mit einem internen Adresszähler (Target Address Pointer) selbst berechnen. Der Target Address Pointer ist ein Register mit zwei taktsynchronen Operationen:

  • Ist LOAD gesetzt, übernimmt das Register die Adresse vom ADIO-Bus. Dies geschieht zu Beginn des Bursttransfers. Der Target Address Pointer wird so initialisiert.
  • Das INC-Signal erhöht den Adresswert um 1 für das nächste Datenwort.
  -- Steuersignale Target Address Pointer
  signal tap_inc, tap_ld : std_logic;

  -- Register fuer Target Address Pointer (10 Bit Adresszaehler 1 K (10 Bit) x 32 Bit = 4 KByte)
  signal tap : std_logic_vector(9 downto 0);

  [...]

    begin

      [...]

      tap_register: process (CLK, RST)
      begin

        if RST = '1' then      

          -- Reset-Kosmetik
          tap <= (others => '0');

        elsif CLK'event and CLK = '1' then

          if tap_ld = '1' then

            -- Target Address Pointer initialisieren
            tap <= ADIO(11 downto 2);

          elsif tap_inc = '1' then
        
            -- Target Address Pointer weiterzaehlen
            tap <= tap + '1';

          end if;
        end if;
      end process;

Target Address Pointer initialisieren

Ist ADDR_VLD gesetzt, wurde eine Adressphase, die ein beliebiges Target betreffen kann, auf dem PCI-Bus beobachtet. Diese Adresse ist mit der nächsten steigenden Taktflanke auf dem internen ADIO-Bus verfügbar. Damit ergibt sich für das LOAD-Signal:
    tap_ld <= ADDR_VLD;

Target Address Pointer inkrementieren

  1. Bei Schreibzugriffen (PCI → RAM) liefert das LogiCore PCI Interface die Datenwörter gepipelined über den ADIO-Bus. Werden keine Wartezyklen im Bursttransfer eingebaut, kommen mit jedem Takt neue Daten. S_DATA_VLD signalisiert dabei, dass gültige Daten auf dem Bus liegen und wird dazu verwendet, die Datenübernahme vom Bus in das Zielregister oder das RAM zu steuern. Zugleich kann es aber auch für die Erhöhung des Adresszählers verwendet werden: Ist S_DATA_VLD gesetzt, werden mit der nächsten steigenden Flanke die Daten in das RAM an die Stelle tap geschrieben. Außerdem wird der Adresszähler inkrementiert. Bleibt S_DATA_VLD gesetzt, kann so mit der nächsten steigenen Taktflanke das nächste Datenwort in das RAM an die Stelle tap + 1 geschrieben und der Adresszähler weiter erhöht werden usw.
     
  2. Bei Lesezugriffen (RAM → PCI) dient das S_SRC_EN Signal zum Weiterzählen des Target Address Pointers. Ist es gesetzt, muss dem LogiCore PCI Interface das nächste Datenwort über den ADIO-Bus geliefert werden. Mit der folgenden Taktflanke übernimmt PCI-Interface den Inhalt des ADIO-Busses in seine internen Register, die den PCI-Datenbus treiben, während auf dem ADIO-Bus das nächste Datenwort geliefert werden muss, wenn S_SRC_EN noch gesetzt war.
    Bemerkung: Das PCI Interface eilt dem tatsächlichen Busgeschehen um mehrere Takte voraus (Pipelining)! Details und Auswirkungen siehe unten.
Aus diesen Überlegungen ergibt sich für das INC-Signal:
    tap_inc <= (bar_0_wr and S_DATA_VLD) or (bar_0_rd and S_SRC_EN);

Die übrigen Steuersignale / Unbenutzte Eingänge des LogiCore PCI Interfaces

Die Erkennung, ob das Target überhaupt Ziel der aktuellen Transaktion auf dem PCI-Bus ist, bleibt unverändert. Das RAM übernimmt seine Daten weiterhin direkt vom ADIO-Bus bzw. gibt sie bei Lesezugriffen über den ADIO-Bus direkt an das PCI-Interface weiter, siehe Abbildung. Auch hier ändert sich also nichts.
    -- Deklaration der RAM-Komponente bram_1k_32b
    component bram_1k_32b is
      port ( 
        ADDR : in std_logic_vector(9 downto 0);
        CLK  : in std_logic;
        DIO  : inout std_logic_vector(31 downto 0);
        OE   : in std_logic;
        RST  : in std_logic;
        WE   : in std_logic
      );
    end component;

    -- Steuersignale
    signal bar_0_rd, bar_0_wr : std_logic;
    signal ram_wr, ram_oe     : std_logic;

    [...]

    begin
  
      [...]
  
      -- Instanziierung des RAMs
      ram_inst : bram_1k_32b
        port map ( 
          ADDR => tap,     -- Adressierung durch Target Address Pointer
          CLK  => CLK,
          DIO  => ADIO,   
          OE   => ram_oe,
          RST  => RST,
          WE   => ram_wr
        );

      -- Ist das Target Ziel eines Transfers? Lesen oder Schreiben?
      decode_hit : process (CLK, RST)
      begin
        if RST = '1' then
          bar_0_rd <= '0';
          bar_0_wr <= '0';
        elsif CLK'event and CLK = '1' then
          if BASE_HIT(0) = '1' then            
            bar_0_rd <= not S_WRDN;
            bar_0_wr <= S_WRDN;
          elsif S_DATA = '0' then
            bar_0_rd <= '0';
            bar_0_wr <= '0';
          end if;
        end if;
      end process;

      -- Schreibsignal fuer das RAM:
      -- "Schreibzugriff auf das Target" und "Daten auf ADIO gueltig"
      ram_wr <= bar_0_wr and S_DATA_VLD;

      -- Lesesignal fuer das RAM
      -- "Lesezugriff auf das Target" und "PCI-Interface in der Datenphase"
      ram_oe <= bar_0_rd and S_DATA;
Die Bedienung der unbenutzten Eingänge des LogiCore PCI Interfaces wird unverändert übernommen, siehe VHDL-Code userapp.vhd.

Datenflusssteuerung und Transfer-Terminierung: Always Ready, Burst Transfers

Dieser Entwurf ist immer zum Datentransfer bereit. Daher brauchen die Datenphasen eines Zugriffs nicht durch Wartezyklen verzögert werden (S_READY <= '1'). Der Initiator des Transfers kann solange Daten anfordern oder schicken, bis er selbst den Transfer beendet (S_TERM <= '0').
Ein Target, das vorübergehend keine Daten schicken oder annehmen kann, kann von sich aus den Transfer mit dem S_TERM-Signal beenden, wenn es keinen Sinn macht, den Transfer durch Wartezyklen aufrecht zu erhalten. Der Initiator wird dann im allgemeinen nach einiger Zeit einen erneuten Versuch starten.

Erinnerung: Aus Timing-Gründen (Optimierungsauswirkungen) ist es nicht erlaubt, die Signale S_READY und S_TERM statisch auf feste Pegel zu legen. Deshalb werden die Signale über D-Flipflops gesetzt, die nicht wegoptimiert werden können.

    term_control: process (RST, CLK)
    begin
      if RST = '1' then

        -- hier die invertierten Werte
        S_READY <= '0'; 
        S_TERM  <= '1';

      elsif CLK'event and CLK = '1' then

        -- hier die richtigen Werte
        S_READY <= '1';
        s_TERM  <= '0';

      end if;
    end process;

Bemerkung zum Pipeling im PCI Interface und die Konsequenzen

Pipelining

Um die strengen PCI Timing Anforderungen erfüllen und eine robuste unkritische Schnittstelle zu der Userapplikation (dem eigenen Design) bieten zu können, speichert das LogiCore PCI Interface alle Steuersignale und Daten in internen Registern.

Abb.: Signalverzögerungen durch Pipelining (Quelle: LogiCore PCI Design Guide)

Die Abbildung zeigt die daraus resultierenden Verzögerungen bzw. Vorgriffe.

  1. PCI-Bus → PCI-Interface → Userapplikation
    Wenn das PCI-Interface ein Signal vom Bus empfängt, wird es in einem Eingangsflipflip erfasst. Einen Takt später ist es dann an der Schnittstelle zum eigenen Entwurf verfügbar (siehe oberer Teil der Abbildung).
  2. Userapplikation → PCI-Interface → PCI-Bus
    Handelt es sich um ein kombinatorisches Signal, muss es die Userapplikation einen Takt bevor es auf dem PCI Bus erscheinen soll dem PCI Interface übergeben werden, da die meisten der PCI-Bus Ausgangssignale durch Ausgangsflipflops getrieben werden. Verwendet der eigene Entwurf selbst noch ein Ausgangsregister an der Schnittstelle zum PCI-Interface, kommt entsprechend noch ein weiterer Takt Vorlauf hinzu (siehe unterer Teil der Abbildung).
Bezüglich der Daten und Steuersignale, die auf dem PCI-Bus abgegeben werden, muss der Gesamtentwurf intern dem Geschehen auf dem PCI-Bus im allgemeinen mehrere Takte voraus sein, wohingegen Daten oder Steuersignale, die vom PCI-Bus gelesen werden, erst mit einem Takt Verspätung ihr Ziel im Gesamtentwurf erreichen.
Ablaufbeispiel:
Innerhalb eines Burst-Lesezugriffs auf das PCI Target wird ein weiteres (nicht das erste) Datenwort angefordert.
im Takt x : Das PCI Interface setzt SRC_EN. Die kombinatorische Logik erzeugt daraus das Signal tap_inc.
Takt x + 1 : Der Prozess tap_register erkennt tap_inc = '1' und erhöht den Adresszähler tap um 1.
Takt x + 2 : Das RAM übernimmt die neue Adresse (tap + 1) und stellt das entsprechende Datenwort auf den ADIO-Bus.
Takt x + 3 : Das PCI-Interface übernimmt die Daten vom ADIO-Bus in sein Ausgangsregister. Damit liegen sie auf den PCI-Bus an.
Takt x + 3 : Das Datenwort wird vom Initator des Transfers in seinen Eingangsflipflops erfasst.
Ist dieser Mechanismus erst einmal etabliert, d.h. die Pipeline gefüllt, liefert das Target mit jedem PCI-Takt ein weiteres Datenwort. Das Füllen der internen Verarbeitungspipeline benötigt jedoch Zeit, die sich das LogiCore PCI Interface durch Wartezyklen zwischen der Adressphase und dem Beginn der Datenphase auf dem PCI-Bus erkauft. (Das Beispiel sieht gravierender aus als es ist, da das erste Datenwort des Lesetransfers nicht über S_SRC_EN angefordert wird, sondern für das PCI Interface schon bereit gestellt wird, sobald die Startadresse des Bursttransfers bekannt ist. Inzwischen kann per S_SRC_EN-Mechanismus schon das nächste Datenwort aus dem RAM gelesen werden.)

Konsequenzen für nicht-prefetchbare Datenquellen bei Lesezugriffen auf das Target

Bei Burst-Lesezugriffen liefert der eigene Entwurf durch das Vorauseilen der internen Target-Logik Daten an das LogiCore PCI Interface, die unter Umständen gar nicht tatsächlich über den PCI-Bus übertragen werden, da der Initiator inwischen alle Daten hat, die er wollte, und daher den Transfer abgeschlossen hat oder unterbrechen musste (Latency Timer abgelaufen).
Im Fall dieses hier vorgestellten Entwurfs (prefetchbares RAM) stellt dies kein Problem dar. Will der Master seinen Transfer fortsetzen, startet er einen neuen Burst-Lesezugriff beginnend mit der Startadresse des ersten nicht mehr gelesenen Datenworts.
Eine nicht-prefetchbare Datenquelle im eigenen Design erfordert wesentlich mehr Aufwand. Ein typisches Beispiel dafür wäre eine Messwerterfassung: Ein Sensor liefert Daten an eine FIFO ab, die über das PCI-Interface regelmäßig ausgelesen wird. Wird aus einer einfachen FIFO ein Datenwort gelesen, kann es nicht nochmals aus der FIFO gelesen werden, da der interne Lesezeiger um ein Feld vorgerückt ist. Bricht in der Zwischenzeit der Bursttransfer ab, wäre das Datenwort unwiederbringlich verloren. Die Lösung: Auf der einen Seite lassen sich mit dem Signal S_SRC_EN die an das PCI-Interface abgelieferten Daten mitzählen. Auf der anderen Seite erhält man durch das Signal S_DATA_VLD bei Lesezugriffen die Bestätigung, dass ein (vorhergehendes) Datenwort erfolgreich auf dem PCI-Bus abgesetzt wurde. Der Lesezeiger der FIFO wird dann nach Beendigung des Bursttransfers um die Differenz zwischen der Anzahl der abgelieferten und der tatsächlich übertragenen Daten korrigiert, so dass alle nicht erfolgreich gesendeten Daten wieder für einen weiteren Zugriff zur Verfügung stehen.

Auf die Problematik wird noch ausführlich beim Entwurf eines PCI-Masters eingegangen und kann im LogiCore PCI Design Guide nachgelesen werden.

Die Zusatzlogik für die Messung der Burstlängen

Damit ist der Entwurf des eigentlichen PCI-Targets abgeschlossen. Um die Burstlängen, die der Chipsatz des PCs produziert, messen zu können, ist noch ein wenig Zusatzlogik in der Komponente userapp erforderlich. Die maximale bisher gemessene Burstlänge wird auf den 7-Segment-Anzeigen ausgegeben. Der erreichte Maximalwert kann mit dem Taster "USER" auf dem Entwicklungsboard zurückgesetzt werden.

Vorarbeit

Wie beim Projekt "Board-Test" müssen die I/O-Ports bzw. die sie repräsentierenden Signale von dem Top-Level-Modul pcim_top zur Komponente userapp "durchgereicht" werden. Daraus resultieren folgende Ergänzungen in der Datei pcim_top.vhd:
    [...]

    entity pcim_top is
      port (

        [...]

        USER_BUTTON     : in std_logic;
        ONE_DIGIT       : out std_logic_vector(6 downto 0);
        TEN_DIGIT       : out std_logic_vector(6 downto 0)
      );
    end pcim_top;

    architecture rtl of pcim_top is

    [...]

     component userapp
      port (
    
        [...]

        USER_BUTTON     : in std_logic;
        ONE_DIGIT       : out std_logic_vector(6 downto 0);
        TEN_DIGIT       : out std_logic_vector(6 downto 0)
      );
      end component;

    [...]

      USER_APP : userapp port map (

        [...]

        USER_BUTTON     => USER_BUTTON,
        ONE_DIGIT       => ONE_DIGIT,
        TEN_DIGIT       => TEN_DIGIT
      );

    end rtl;
In der Datei userapp.vhd muß die Portbeschreibung entsprechend erweitert werden:
    [...]

    entity userapp is
      port (

        [...]

        USER_BUTTON     : in std_logic;
        ONE_DIGIT       : out std_logic_vector(6 downto 0);
        TEN_DIGIT       : out std_logic_vector(6 downto 0);
      );
    end userapp;

    [...]
    
Nun fehlen noch die zugehörigen Pin-Vereinbarungen am Ende der User Constraint Datei xc2s200fg456_32_33.ucf:
    [...]

    NET "USER_BUTTON"    LOC = "B1";
    NET "TEN_DIGIT<0>"   LOC = "D6" ;   //DISPLAY.2A
    NET "TEN_DIGIT<1>"   LOC = "C5" ;   //DISPLAY.2B
    NET "TEN_DIGIT<2>"   LOC = "D5" ;   //DISPLAY.2C
    NET "TEN_DIGIT<3>"   LOC = "C7" ;   //DISPLAY.2D
    NET "TEN_DIGIT<4>"   LOC = "D7" ;   //DISPLAY.2E
    NET "TEN_DIGIT<5>"   LOC = "C6" ;   //DISPLAY.2F
    NET "TEN_DIGIT<6>"   LOC = "A8" ;   //DISPLAY.2G

    NET "ONE_DIGIT<0>"   LOC = "E10" ;  //DISPLAY.1A
    NET "ONE_DIGIT<1>"   LOC = "E9" ;   //DISPLAY.1B
    NET "ONE_DIGIT<2>"   LOC = "E8" ;   //DISPLAY.1C
    NET "ONE_DIGIT<3>"   LOC = "E6" ;   //DISPLAY.1D
    NET "ONE_DIGIT<4>"   LOC = "E7" ;   //DISPLAY.1E
    NET "ONE_DIGIT<5>"   LOC = "F11" ;  //DISPLAY.1F
    NET "ONE_DIGIT<6>"   LOC = "E11" ;  //DISPLAY.1G

Der Burstlängen-Zähler

    -- Deklaration der 7-Segment-Decoder-Komponente displayrom
    component displayrom 
      port (
        ADDR : in std_logic_vector(3 downto 0);
        DATA : out std_logic_vector(6 downto 0)
      );
    end component;

    -- Register zum Speichern der Byteanzahl der laengsten Burstsequenz
    signal burst_len_max : std_logic_vector(7 downto 0);  

    [...]
   
    begin
    
      [...]

      burst_len_register: process (CLK, RST, USER_BUTTON)
      variable burst_len : std_logic_vector(7 downto 0); -- Burstlaengen-Zaehler
      begin

        if RST = '1' or USER_BUTTON = '0' then

          -- Reset, wenn Reset-Signal oder User-Button gedrueckt
          burst_len_max <= x"00";
          burst_len     := x"00";

        elsif CLK'event and CLK = '1' then

          if tap_ld = '1' then

            -- internen Zaehler ruecksetzen, wenn Target Address Pointer geladen wird
            burst_len := x"00";

          elsif tap_inc = '1' then

            -- internen Zaehler erhoehen, ggf. das neue Maximum speichern
            burst_len := burst_len + 1;
            if burst_len > burst_len_max then
              burst_len_max <= burst_len;

            end if;
          end if;
        end if;
      end process;

      -- Instanziierung der 7-Segment-Dekoder zur Ausgabe der max. Burstlaenge
  
      displayrom_inst2 : displayrom
      port map (
        ADDR  => burst_len_max(3 downto 0),
        DATA  => ONE_DIGIT
      );

      displayrom_inst1 : displayrom
      port map (
        ADDR  => burst_len_max(7 downto 4),
        DATA  => TEN_DIGIT
      );





Autor: gkemnitz, Letzte Änderung: 14.04.2011 15:09:59


 TU Clausthal 2020  Impressum