2016-08-02 12 views
0

Ich schreibe Verilog-Code aus einigen Tagen und eine Frage, die ich habe, ist 'Können wir schreiben Block innerhalb generieren Block' schreiben? Ich schreibe eine RTL etwas wie folgt aus:generate generieren verilog + error near generate (veri - 1137)

Where 'n' is a parameter. 
reg [DATA_WIDTH:0] flops [n-1:0]; 

generate 
    if (n > 0) begin 
    always @(posedge clk) begin 
     if (en) begin 
     flops[0] <= mem[addr]; 
     end 
    end 
    generate 
     genvar i; 
     for (i = 1; i <= n ; i = i + 1) begin 
     always @(posedge clk) begin 
      flops[i] <= flops[i-1]; 
     end 
     end 
    endgenerate 
    always @(flops[n - 1]) 
     douta = flops[n - 1]; 
    else 
    always @(posedge clk) begin 
     if (en) begin 
     primary_output = mem[addr]; 
     end 
    end 
    end 
endgenerate 

Während die oben genannten Code kompilieren, erhalte ich:

ERROR: syntax error near generate (VERI-1137) 

nicht sicher, warum. Zweck dieser RTL ist es, eine Pipeline von 'n' Flops auf der Ausgangsseite des Designs zu erstellen.

Können sagen, n 2 ist, dann sollte Schaltung werden:

flop1-> flop2-> primary output of design 

flop1 und flop2 sind neu Flops erstellt.

Antwort

5

Sie sind ein langer Weg von wo Sie sein sollten.

Verilog ist keine Programmiersprache; es ist eine Hardwarebeschreibungssprache. Sie modellieren Hardware als ein Netzwerk von gleichzeitig Prozessen. Jeder Prozess modelliert ein kleines bisschen Hardware wie einen Zähler, eine Zustandsmaschine, ein Schieberegister, irgendeine kombinatorische Logik ... In Verilog wird jeder Prozess als always Block codiert. Also, eine always Aussage kann nie in einer anderen erscheinen; das macht keinen Sinn.

Zweitens ist generate eine ziemlich spezialisierte Aussage. Sie verwenden es, wenn Sie eine große Anzahl oder eine variable Anzahl gleichzeitiger Prozesse wünschen. Das ist nicht üblich, so dass generate nicht üblich ist, aber nützlich ist, wenn erforderlich. Sie benötigen keine generate-Anweisung, um ein parametrierbares Schieberegister zu implementieren. Und weil ein always Block eine gleichzeitige Anweisung ist, sitzt er in einer generate Anweisung, nicht umgekehrt.

Ich weiß nicht, was Ihre Absicht genau ist, ich vermute, dass dieser Code nicht genau das tut, was Sie wollen. Es ist jedoch nicht implementiert eine parametrierbare Schieberegister der Länge n und Breite DATA_WIDTH+1 (meinst du das wirklich?), Aktiviert durch die en Eingang:

module N_FLOPS #(n = 2, DATA_WIDTH = 8) (input [DATA_WIDTH:0] dina, input clk, en, output [DATA_WIDTH:0] douta); 

    reg [DATA_WIDTH:0] flops [n-1:0]; 

    always @(posedge clk) 
    if (en) 
     begin : SR 
     integer i; 
     flops[0] <= dina; 
     for (i = 1; i <= n ; i = i + 1) 
      flops[i] <= flops[i-1]; 
     end 

    assign douta = flops[n-1]; 

endmodule 

http://www.edaplayground.com/x/3kuY

Sie sehen können - keine generate Aussagen erforderlich. Dieser Code entspricht diese Vorlage, die für jede sequentielle Logik ohne ein asynchrones Rücksetz genügt:

always @(posedge CLOCK) // or negedge 
    begin 
    // do things that occur on the rising (or falling) edge of CLOCK 
    // stuff here gets synthesised to combinational logic on the D input 
    // of the resulting flip-flops 
    end 
+0

@Matther, ich sehe. Danke für die wundervolle Erklärung. –

+1

FYI: SystemVerilog erlaubt mehrdimensionale Array-Zuweisung in einer einzelnen Anweisung. Daher könntest du die for-Schleife überspringen mit 'always @ (posedge clk) begin flop [0] <= dina; wenn (n> 1) Flop [n-1: 1] <= Flop [n-2: 0]; Ende – Greg