Zugriff auf Register/Signal von mehreren Modulen (gemeinsamer Speicher)

Ich möchte ein Datenregister implementieren, um bis zu 256 8-Bit-Blöcke (VHDL) zu speichern. Ich muss auch in der Lage sein, auf diese Werte von mehreren vhdl-Modulen zuzugreifen und sie zu ändern. Ein Modul greift auf das Register zu, um die Werte vom Spi-Port zu ändern. Dann schiebt ein anderes Modul, das das EPP-Protokoll implementiert, um mit dem PC zu kommunizieren, die Daten heraus.

Im Moment habe ich nur das Signal, das das Register in einem meiner Module implementiert:

type type_dataRegisterWithAddress is array (0 to generic_numRegisters-1) of std_logic_vector(7 downto 0); 
signal dataRegister: type_dataRegisterWithAddress;

Ich bin mir der technischen Details eines Registers nicht sicher, aber ich speichere nur logische Vektoren und greife mit einer to_integer(address).

Ich weiß nicht, wie ich dies mit einem anderen Modul teilen würde, da ich die Port-Map nicht einfach einfügen kann, da es sich um ein Array handelt. Selbst wenn es im Top-Level-Modul wäre, weiß ich immer noch nicht, wie ich es teilen würde.

Was ist die beste Methode, um einige Register zu erstellen, auf die von vielen Modulen aus zugegriffen werden kann?

EDIT: Um einige von Daves Fragen zu beantworten ...

Ich wollte es irgendwie in Code implementieren, wie ich es tue, da dies ein kleiner Speicher ist und ich nicht wirklich 256 verwenden werde, es ist nur so, dass die EPP-Schnittstelle 256 Adressen haben kann. Aber Sie sprechen einen guten Punkt an.

Ich verwende das Basys2 250k-Board mit 72 Kbits Dual-Port-Block-RAM. Ich habe es bisher nur mit der IP Core-Funktion in diesem Tutorial/Modul verwendet . Ich denke, das ist vielleicht das Beste, was man verwenden kann.

Jetzt habe ich den richtigen Begriff. Was ist Ihre persönliche Herangehensweise an Shared Memory?

Shared Memory ist ein sehr weites Thema, und es gibt viele Ansätze, die Sie verfolgen können, die von der Anzahl der erforderlichen Ports, der Bandbreite an jedem Port und der zulässigen Zugriffslatenz abhängen. Einige Ansätze ermöglichen die Verwendung von Dual-Port-"Block-RAM"-Modulen, die auf vielen FPGAs verfügbar sind. Es gibt nicht die eine „beste Methode“. Es hört sich so an, als würden Sie an einem FPGA-basierten Projekt arbeiten. Wenn Sie also das von Ihnen verwendete Teil zusammen mit einigen Antworten auf die obigen Fragen angeben könnten, könnten wir möglicherweise eine geeignete Implementierung vorschlagen.
@DaveTweed Danke für die zusätzliche Klarheitsprüfung. Ich habe den Beitrag aktualisiert.

Antworten (1)

Zunächst einmal hindert Sie die Tatsache, dass es sich um ein Array handelt, nicht daran, es in der Portdeklaration zu verwenden.

Sie könnten beispielsweise ein Paket erstellen, das die in Ihrem Projekt verwendeten allgemeinen Typen enthält:

-- common_types.vhd
-- This package contains common types used in your project.

library ieee;
use ieee.std_logic_1164.all; 

package common_types is

    -- Example use of slv8_array: 
    -- signal a : slv8_array(0 to 3);
    type slv8_array  is array(integer range <>) of std_logic_vector( 7 downto 0); 

end package;

Fügen Sie das Paket in jedes Modul ein, das einen Ihrer Typen verwenden möchte, indem Sie Folgendes schreiben:

use work.common_types.all;

Dann können Sie es in Ihrer Entity-Deklaration jetzt in Ihrem Port oder Ihrer generischen Deklaration verwenden:

entity e is
port (      
    a   : out slv8_array(0 to 3)
);
end entity;

Zweitens in Bezug auf die gemeinsame Nutzung einer Ressource (wie Speicher):

  • Wenn Sie Block-RAM verwenden, unterstützt es normalerweise Dual-Port, sodass Sie mindestens zwei Ports zur gemeinsamen Nutzung haben und sie wirklich gleichzeitig sind.
  • Wenn Sie mehr Ports benötigen, müssen Sie sich eine Art Ressourcen-Arbitrierungsschema einfallen lassen. Dieser Arbiter ist das Frontend für alle Module, die Zugriff auf die Ressource benötigen. Dies bedeutet, dass der Arbiter Zugriff auf den tatsächlichen Port der Ressource hat , aber mehrere andere Ports für die Clients deklariert, die ihn verwenden möchten. Es gewährt dann jedem von ihnen nacheinander Zugriff, gemäß einer Art Ressourcenteilungsalgorithmus, der so einfach wie ein Round-Robin sein kann.

Ein Beispiel, wenn auch in Verilog, finden Sie im Angebot von Altera (Quellcode kann kostenlos heruntergeladen werden) http://www.altera.com/support/kdb/solutions/rd11252011_496.html

Der MPFE-Arbiter verwendet eine verbesserte Version des gewichteten Round-Robin-Schemas, das Zugriff auf aufeinanderfolgende Slave-Ports in mittelgroßen Blöcken (bis zu 64 Takten) gewährt, aber ein Leaky-Bucket-Bandbreitenzuweisungssystem hat, um die Zugriffe gleichmäßiger zu verteilen.

Das wird dir wahrscheinlich zu viel des Guten sein. Wenn Ihre Bandbreitenanforderungen nicht hoch sind, schreiben Sie Ihren eigenen Arbiter, der ein Schreib-/Leseanforderungssignal von jedem Client nacheinander abfragt und, wenn er ein bestätigtes Signal findet, diese dann mit der realen Ressource überbrückt. Wenn die Transaktion abgeschlossen ist, setzen Sie den Abfrageprozess fort.

Eine letzte Sache, die im Fall einer relativ kleinen Registerbank zu erwähnen ist, ist, dass Sie für Leser einen großen Mux für jeden von ihnen bereitstellen könnten, so dass mehrere Clients jedes Register gleichzeitig lesen könnten, ohne dass ein Arbiter erforderlich wäre. Der Umgang mit mehreren Writern ist jedoch etwas anders, Sie hätten einen großen Decoder für jeden Writer, aber Sie müssten Kollisionen auflösen. Eine Möglichkeit wäre, Priorität festzulegen, sodass Schreiber gleichzeitig in jedes Register schreiben könnten, aber wenn es eine Kollision gibt, wäre nur eines von ihnen erfolgreich, und es wäre Sache einer höheren Ebene, sicherzustellen, dass dies eines von beiden ist kein Problem, oder irgendwie gehandhabt. Das verbraucht viel kombinatorische Logik und wäre daher nur für kleine Registerbanken sinnvoll.

Sieht so aus, als müsste ich einen vhdl-Arbiter mit mehreren Ports finden. Ich dachte, es wäre so einfach wie eine Inout-Deklaration zu machen und den Speicher an jedes Modul zu übergeben, aber ich erhalte einen mehrfachen Treiberfehler. Danke, dass du mich in die richtige Richtung weist!