Bidirektionaler I/O-Pin in Verilog

Ich möchte irgendwann etwas Speicher an mein FPGA anschließen. Dies erfordert Pins auf dem FPGA, die sowohl Daten lesen als auch Ausgaben in den RAM schreiben können.

Ich bin noch weit davon entfernt, irgendetwas davon zu tun, aber als Lernübung wollte ich ein einfaches Modul in Verilog erstellen, das, wenn ein Richtungssignal "1" ist, ein Signal an einen Pin ausgibt und wenn es "0" ist, einen Wert liest von diesem Stift.

Aber ich bekomme nichts zum kompilieren. Ich bin nicht völlig unerfahren mit Verilog, aber ich habe das Gefühl, dass mir hier etwas Grundlegendes fehlt, anstatt nur einen einfachen Tippfehler in meinem Beispiel zu haben.

Dieser Code lässt sich nicht kompilieren, ich suche entweder, wie er funktioniert, oder nur einen Hinweis darauf, was mir grundlegend fehlt, damit bidirektionale Signale funktionieren. Wenn es darauf ankommt, verwende ich Xilinx-Tools und plane, dies zu einem xc3s50 oder ähnlichem zu synthetisieren.

// This doesn't compile...
module test(
    input  clock,           // The standard clock
     input  direction,  // Direction of io, 1 = set output, 0 = read input
     input  data_in,        // Data to send out when direction is 1
     output data_out,       // Result of input pin when direction is 0
     inout  io_port     // The i/o port to send data through
     );

always @(posedge clock)
begin

    // If direction is 1 then set 
    if (direction == 1)
    begin
        io_port <= data_out;
    end

    if (direction == 0)
    begin
         data_in <= io_port;
    end
end

endmodule

bearbeiten Die Fehler, die ich bekomme, sind -

ERROR:HDLCompilers:247 - "test.v" line 16 Reference to scalar wire 'io_port' is not a legal reg or variable lvalue
ERROR:HDLCompilers:106 - "test.v" line 16 Illegal left hand side of nonblocking assignment
ERROR:HDLCompilers:247 - "test.v" line 21 Reference to scalar wire 'data_in' is not a legal reg or variable lvalue
ERROR:HDLCompilers:106 - "test.v" line 21 Illegal left hand side of nonblocking assignment

Antworten (1)

Inouts sind eigentlich "wire", also können Sie keine prozeduralen/sequentiellen Zuweisungen verwenden (wobei die linke Seite ein Reg sein muss). Allgemein gesagt:

  • input : intern muss immer vom Typ net sein, extern können die Eingänge mit einer Variablen vom Typ reg oder net verbunden werden.
  • output : intern kann vom Typ net oder reg sein, extern müssen die Ausgänge mit einer Variablen vom Typ net verbunden werden.
  • inout : intern oder extern muss immer vom Typ net sein, kann nur mit einem variablen net type verbunden werden.

Ein üblicher Ansatz besteht darin, ein "Aktivierungs" -Signal für den Ausgang Ihres Eingangs zu haben und auf hohe Impedanz zu fahren, wenn der Ausgang nicht aktiviert ist. In Ihrem Fall spielt die Richtung diese Rolle.

Probieren Sie stattdessen Folgendes aus:

module test(
    input  clk,      // The standard clock
    input  direction,  // Direction of io, 1 = set output, 0 = read input
    input  data_in,    // Data to send out when direction is 1
    output data_out,   // Result of input pin when direction is 0
    inout  io_port     // The i/o port to send data through
    );

    reg a, b;    

    assign io_port  = direction ? a : 1'bz;
    assign data_out = b;

    always @ (posedge clk)
    begin
       b <= io_port;
       a <= data_in;
    end

endmodule

Die Hardware, die dem obigen Code entspricht, würde ungefähr so ​​​​aussehen:

Geben Sie hier die Bildbeschreibung ein

Ah ich sehe. Danke. Ich habe die z-Zustände völlig vergessen. Obwohl dies data_in immer als die Daten festlegen wird, die ich sende, nicht wahr, und nicht der Wert des Pins?
@JohnBurton Ich habe das Verilog so geändert, dass es ein bisschen mehr so ​​ist, wie ich denke, was Sie wollten.
Der aktualisierte Code (und das Bild) wird io_port an data_out übergeben, wenn die Richtung niedrig ist, und wird data_in an io_port (und data_out einen Zyklus später) übergeben, wenn die Richtung hoch ist.
Welche Software verwendest du, um diese Syntheseausgabe zu erzeugen?
@sybreon heh, ich habe gerade die schematische Erfassung von Eagle verwendet, um eine Zeichnung zusammenzuhacken.