Schieberegisterproblem in VHDL

Ich entwerfe ein 56-Bit-Schieberegister, um die eingehenden Bits zu speichern.

In meinem System kommen immer wieder 8-Bit-Daten von einem Generator an, und ich muss den erkannten Maximalwert mit 3 Bytes auf beiden Seiten davon ausgeben. Ich möchte, dass die in einem 56-Bit-Schieberegister gespeicherten Daten eine Ausgabe ergeben, die besteht des Maximums und die anderen 7 Bytes, wie in der Grafik gezeigt.

Das System vergleicht jedes eingehende Byte mit einem vorübergehenden Maximalwert und gibt jedes Mal eine 56-Bit-Ausgabe aus, wenn ein neuer Maximalwert erkannt wird.

Ich frage mich nur, wie ich die neu eingehenden Daten in der Mitte halten kann, damit ich das gesamte serielle 56-Bit-Signal ausgeben kann, sobald festgestellt wird, dass die neu eingehenden Daten größer als das vorübergehende Maximum sind.

Ich habe versucht, etwas zu schreiben, aber Modelsim hat mir das hier gegeben

Der Zieltyp ieee.std_logic_1164.STD_LOGIC_VECTOR in der Signalzuweisung unterscheidet sich vom Ausdruckstyp ieee.NUMERIC_STD.SIGNED. für temp_shift_register (31 bis 24) .....

shift : process (clk)
begin
  if rising_edge(clk) and begin_req ='1' then 
    for i in 55 downto 8 loop 
      temp_shift_register(i) <= temp_shift_register(i-8); 
    end loop;
    temp_shift_register(31 downto 24) <= temp_byte; 
  else null;
  end if;
end process;

Geben Sie hier die Bildbeschreibung ein

Die Signaldeklarationen sind:

signal temp_shift_register : std_logic_vector (55 downto 0):= "00000000000000000000000000000000000000000000000000000000";
signal perm_shift_register : std_logic_vector (55 downto 0):= "00000000000000000000000000000000000000000000000000000000";
signal temp_byte : signed (7 downto 0);
Wir müssen die Deklarationen für die verschiedenen Signale sehen. Offensichtlich haben Sie irgendwo auf dem Weg eine Typkonvertierung verpasst.
Was ist mit temp_byte?
@DaveTweed Das ist signiert (7 bis 0), aber wie kann ich den Signaltyp in einem einzelnen Prozess ändern. Das Signal temp_byte wird auch in anderen Prozessen verwendet, daher weiß ich nicht, wie ich damit umgehen soll.

Antworten (1)

Da die Array-Typen signedund std_logic_vectordenselben Elementtyp haben, können Sie zwischen beiden Typen folgendermaßen konvertieren:

signal x : std_logic_vector(7 downto 0); -- 8 bit for example
signal y : signed(7 downto 0);

y <= signed(x);

und zurück

signal y : signed(7 downto 0);
signal z : std_logic_vector(7 downto 0); -- 8 bit for example

z <= std_logic_vector(y);

Anstelle von Signalen können Sie natürlich auch Variablen verwenden (über die :=Zuweisung).

Für Ihr Schieberegister benötigen Sie also:

temp_shift_register(31 downto 24) <= std_logic_vector(temp_byte);

Weitere Bemerkungen

Diese Zeile wird nicht benötigt:

  else null;

Es fehlt Ihnen, neue Werte an der Position einzugeben temp_shift_register(7 downto 0).

Anstelle von for ... end loop;können Sie einfach alle Bits auf einmal zuweisen:

temp_shift_register(55 downto 8) <= temp_shift_register(47 downto 0);

Wie geht es weiter

Unter Berücksichtigung Ihrer anderen Frage besteht die Grundidee darin, ein zweites 56-Bit breites Ergebnisregister zu haben, das das aktuelle Maximum und die Werte (Bytes) daneben speichert:

signal result_register : std_logic_vector(55 downto 0) := (others => '0');

Dann müssen Sie:

  • Schieben Sie die neuen Werte aus dem Speicher in das Schieberegister bei den niedrigeren Bits.
  • Vergleichen Sie das mittlere Byte des Schieberegisters mit dem mittleren Byte des Ergebnisregisters. Wenn ersteres größer ist, dann kopiere das Schieberegister in das Ergebnisregister.

Der Code würde so aussehen:

process (clk) is
begin
  if rising_edge(clk) then
    -- shift register
    temp_shift_register(55 downto 8) <= temp_shift_register(47 downto 0);
    temp_shift_register(7 downto 0)  <= new_byte_from_memory;

    -- check for new maximum
    if signed(temp_shift_register(31 downto 24)) > signed(result_register(31 downto 24))  then
      result_register <= temp_shift_register;
    end if;
  end if;
end process;

Sie müssen den Code mindestens erweitern, um 1) beide Register zurückzusetzen und 2) das Register nur zu verschieben, wenn neue Daten aus dem Speicher verfügbar sind.

Wie soll ich das Byte in der Mitte halten? Ich möchte, dass jedes neu kommende Byte in die Mitte geht. Wenn es also mit dem Maximum verglichen wird, kann ich die im Schieberegister gespeicherten Bytes direkt ausgeben jeder Seite.
@EEEidolt Ich habe meine Antwort erweitert, um die Grundidee zu beschreiben. Wenn Sie eine Frage zu dem angegebenen Code haben, können Sie diese hier in den Kommentaren stellen. Wenn Sie jedoch eine Frage zum weiteren Vorgehen haben, stellen Sie bitte eine neue Frage. Ich werde meine Antwort nicht noch einmal erweitern , ich werde sie nur bei Bedarf korrigieren.
Danke, aber ich denke, wenn die neuen Bytes von der linken Seite (7 bis 0) eingehen, würden sie am Anfang aus dem Register verschoben, wenn sich keine Daten im Register befinden. Daher frage ich mich, ob ich den Satz ändern kann temp_shift_register(7 downto 0) <= new byte from memory;in temp_shift_register(55 downto 48)........?
Das ergibt für mich keinen Sinn. In meinem Code habe ich die gleiche Verschiebungsrichtung wie in Ihrem Code verwendet. Ein neues Byte wird an Position 7 bis 0 platziert. Bei der nächsten Taktflanke wird es auf 15 bis 8 verschoben. Dann auf 23 bis 16 und so weiter bis 55 bis 48. Dann wird es hinausgeschoben. Einfach eine Testbench aufbauen und ausprobieren :-)