2012-07-26 1 views
5

Wie ich gewusst habe, tastet D-Flipflop seinen Eingangswert bei jeder positiven Flanke der Uhr ab.Warum wartet mein D Flip Flop nicht auf die positive Flanke der Uhr?

So wird es eine 1-Zyklus-Verzögerung erzeugen. Recht?

Aber warum erzeugt mein D-Flipflop keine 1-Zyklus-Verzögerung?

  module flipflop(
      input clk, 
      input rstn, 
      input [7:0] i_data, 
      output reg [7:0] o_data 
     ); 

      always @(posedge clk) begin 
        if (~rstn) begin 
          o_data <= 0; 
        end 
        else begin 
          o_data <= i_data; 
        end 
      end 
     endmodule 

     module test; 
      reg clk; 
      reg [7:0] i_data; 
      reg rstn; 
      wire [7:0] o_data; 

      initial begin 
        clk = 0; 
        rstn = 1; 
        i_data = 0; 
        #20; 
        rstn = 0; 

        #30; 
        rstn = 1; 
        #20; 
        i_data = 8'hFA; 
        #20; 
        i_data = 8'hF0; 
        #20 
        i_data = 8'hF1; 
        #20 
        #10 $finish; 
      end 

      always #10 clk = !clk; 

      flipflop flipflop(
        .clk (clk), 
        .rstn(rstn), 
        .i_data(i_data), 
        .o_data(o_data) 
      ); 

      initial begin 
        $dumpfile("flipflop.vcd"); 
        $dumpvars(); 
      end 
     endmodule 

dff no delay

hier Meine D-Flip-Flop-Funktionen wie eine kombinatorische Schaltung.

Antwort

5

Der Simulator wahrscheinlich so etwas wie dies zu tun ist:

 initial begin 
       clk = 0; 
       rstn = 1; 
       i_data = 0; 
       #10; 
       clk = !clk; 
       #10; 
       rstn = 0; 
       clk = !clk; 

       #10; 
       clk = !clk; 
       #10; 
       clk = !clk; 
       #10; 
       rstn = 1; 
       clk = !clk; 
       #10; 
       clk = !clk; 
       #10 
       i_data = 8'hFA; //Input updated 
       clk = !clk;  //Clock event 
           //o_data assigned here 
       #10; 
       clk = !clk; 
       #10; 
       i_data = 8'hF0; 
       clk = !clk; 
       #20 
       i_data = 8'hF1; 
       #20 
       #10 $finish; 
     end 

Da die Taktereignis auftritt von in jedem Zeitschritt zuletzt Ihre Testbench, es sieht so aus, als ob der Flop sofort zugewiesen wird. Sie möchten wahrscheinlich, dass Ihre Testbench völlig außer Kontrolle geraten ist, so dass Martys Vorschlag, @ (posedge ...) zu verwenden, dies erreichen wird. Sie könnten Ihre Aufgaben auch einfach ganz am Anfang verzögern:

 initial begin 
       clk = 0; 
       #1; 
       rstn = 1; 
       i_data = 0; 
       #20; 
       rstn = 0; 

       #30; 
       rstn = 1; 
       #20; 
       i_data = 8'hFA; 
       #20; 
       i_data = 8'hF0; 
       #20 
       i_data = 8'hF1; 
       #20 
       #10 $finish; 
     end 
+0

Das ist eine gute Möglichkeit, das Problem zu beschreiben. – Marty

5

Sie haben mit den Feinabstimmungen im Verilog-Simulator-Event-Scheduling mithalten können! Das Ändern der Datenzuweisungen, um nicht blockierende Zuweisungen zu verwenden, ist wahrscheinlich die einfachste Lösung.

#20; 
i_data <= 8'hFA; 
#20; 
i_data <= 8'hF0; 
#20 
i_data <= 8'hF1; 
#20 

Was in Ihrer ursprünglichen Version passiert ist, dass die Uhr und die Eingabedaten zur gleichen Zeit geplant wurden. Da der Simulator nur eine Sache gleichzeitig ausführen kann, muss er entscheiden, ob er zuerst die Uhr oder die Daten ändern wird. Es änderte zuerst die Daten, so dass, wenn die Taktflanke kommt, die Eingabedaten bereits auf den nächsten Wert gewechselt haben, so dass es aussieht, als würden die Daten durch das FF gleiten.

Nichtblockierende Zuweisungen (<=) werden nach der Ausführung aller blockierenden Zuweisungen (=) geplant. Wenn die Datenzuweisungen nicht blockiert werden, wird sichergestellt, dass sie nach den blockierungszugeordneten Taktflanken auftreten.

Eine andere Möglichkeit, die Dinge neu zu schreiben, wäre zu arbeiten:

initial begin 
    @(posedge clk) i_data = 8'hFA; 
    @(posedge clk) i_data = 8'hF0; 
    @(posedge clk) i_data = 8'hF1; 
end 
+0

Marty, können Sie Ihren letzten Vorschlag überprüfen? Es sollte "@ (posedge clk) i_data <= 8'hFA;" (nicht blockierend) sein. Auf diese Weise haben wir nach der Aktualisierung der Uhr 2 @ (posedge clk). Beide verwenden nicht blockierende Zuweisungen, so dass das Ergebnis unabhängig von der Reihenfolge der Ausführung gleich ist: Das Flipflop registriert einen alten Wert, und "i_data" wird mit dem neuen Wert aktualisiert. Wenn wir jedoch eine blockierende Zuweisung zu "i_data" und keine Blockierung zu "o_data" haben, hängt die Ausgabe von der Simulationsplanung ab. Beim Testen auf Cadence 'Irun' bekomme ich das fehlerhafte Ergebnis, identisch mit dem OP-Anfangsproblem. – RaZ