Taktdomänenkreuzung zwischen OV7670-Schnittstelle und AXI4-Stream

Aktualisierung 1:

xpm_cdc_handshakeMein erster Ansatz besteht darin, das Makro folgendermaßen zu verwenden :

xpm_cdc_handshake_inst : xpm_cdc_handshake
   generic map (
      DEST_EXT_HSK => 0,            -- DECIMAL; 0=internal handshake, 1=external handshake
      DEST_SYNC_FF => 4,            -- DECIMAL; range: 2-10
      INIT_SYNC_FF => 0,            -- DECIMAL; 0=disable simulation init values, 1=enable simulation init values
      SIM_ASSERT_CHK => 0,          -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
      SRC_SYNC_FF => 4,             -- DECIMAL; range: 2-10
      WIDTH => 32                   -- DECIMAL; range: 1-1024
   )
   port map (
      dest_clk => M_AXIS_ACLK,      -- 1-bit input: Destination clock.
      dest_req => AXIS_DestReq,     -- 1-bit output: Assertion of this signal indicates that new dest_out data has been
                                    -- received and is ready to be used or captured by the destination logic. When
                                    -- DEST_EXT_HSK = 1, this signal will deassert once the source handshake
                                    -- acknowledges that the destination clock domain has received the transferred
                                    -- data. When DEST_EXT_HSK = 0, this signal asserts for one clock period when
                                    -- dest_out bus is valid. This output is registered.
      dest_ack => AXIS_DestAck,     -- 1-bit input: optional; required when DEST_EXT_HSK = 1
      dest_out => AXIS_SyncData,    -- WIDTH-bit output: Input bus (src_in) synchronized to destination clock domain. This output is registered.
      src_clk => Clock,             -- 1-bit input: Source clock.
      src_rcv => OV7670_SrcRcv,     -- 1-bit output: Acknowledgement from destination logic that src_in has been
                                    -- received. This signal will be deasserted once destination handshake has fully
                                    -- completed, thus completing a full data transfer. This output is registered.
      src_send => OV7670_SrcSend,   -- 1-bit input: Assertion of this signal allows the src_in bus to be synchronized
                                    -- to the destination clock domain. This signal should only be asserted when
                                    -- src_rcv is deasserted, indicating that the previous data transfer is complete.
                                    -- This signal should only be deasserted once src_rcv is asserted, acknowledging
                                    -- that the src_in has been received by the destination logic.
       src_in => OV7670_SyncData    -- WIDTH-bit input: Input bus that will be synchronized to the destination clock domain.
);

Die Idee ist, eine Logik zu entwerfen, die den OV7670-Empfangspuffer ( OV7670_SyncData) füllt und die Domänenüberquerung startet, indem das OV7670_SrcSendSignal aktiviert wird. Die AXI4-Stream-Übertragungslogik wartet auf das Signal AXIS_DestAck, und wenn dieses Signal aktiviert wird, werden die Daten synchronisiert und dann über die AXI4-Stream-Schnittstelle übertragen.


Ich versuche, eine OV7670-Kameraschnittstelle mit einer AXI4-Stream-Schnittstelle für die Datenübertragung zu implementieren. Meine aktuelle Idee ist, eine Art FIFO oder Ringpuffer zu implementieren, um die Daten von der Kamera (dh eine Zeile) zu speichern, und wenn der FIFO voll ist, wird eine Übertragung der Daten über die AXI4-Stream-Schnittstelle gestartet.

Aber ich bin mir nicht sicher, ob dies der ideale Ansatz ist, da ich zwei Taktdomänen (den Takt für das Kameramodul und den AXI-Takt) kreuzen werde, oder gibt es einen besseren Ansatz?

Antworten (1)

Asynchroner FIFO

Asynchrones FIFO ist ein idealer Ansatz, um eine Implementierung dazwischen in Betracht zu ziehen, um Daten sicher über die beiden Taktdomänen zu kreuzen.

Wenn Sie dies in Vivado tun, schlage ich vor, dass Sie die dedizierte Vivado-IP verwenden , anstatt eine zu entwerfen.

Wenn Sie daran interessiert sind, eines zu entwerfen, wäre es nützlich, dieses Papier durchzugehen:

Cummings Artikel über FIFOs

Auswahl der Tiefe des FIFO

Sie müssen die Tiefe des FIFO basierend auf folgenden Faktoren auswählen:

  1. Wie hoch sind die Häufigkeiten von Schreib- und Leseoperationen auf der Enqueue- bzw. Dequeue-Seite.
  2. Wie viele Datenbursts werden Sie in den FIFO einreihen.

Hier ist eine einfache Anleitung, die ich in der Vergangenheit für die Tiefenberechnung verwendet habe

BEARBEITEN:

Der vollständige Handshake-Bus-Synchronizer, den Sie verwenden möchten, hat einen geringeren Durchsatz, dient jedoch Ihrem Zweck und verbraucht weniger Ressourcen. vor allem, wenn Sie nicht viele Datenblöcke auf einmal senden müssen. Wenn ich mich gut erinnere, verlangt der FIFO-Generator ein Minimum. Tiefe und kann daher ein Overkill sein, wenn es um die Ressourcennutzung geht.

Danke Mitu Raj. Ich habe meine Frage mit meinem ersten Ansatz mit dem xpm_cdc_handshakeMakro aktualisiert. Kann ich das auch verwenden oder was ist der Unterschied zum FIFO-Generator in Vivado?
Ich habe die Antwort bearbeitet.