2017-02-27 4 views
0

Ich muss einen Infrarot-Sender mit einem FPGA und Verilog entwerfen.Infrarot-Ausgang in Verilog

Eine der Bedingungen ist, ein Paket alle 10 Hz zu senden, ich habe einen Zähler, der einen sekundären Takt bei 10Hz von der Hauptuhr (100 MHz) erstellt. Das Paket enthält Start-Lücke-Auswahl-Lücke-Rechts-Lücke-Links-Lücke-Vorwärts-Lücke-Rückwärts-Lücke. Ich habe eine FSM, die diesen Übergang an der positiven Flanke des 10-Hz-Sekundärtakts durchführt. Jeder dieser Blöcke innerhalb des Pakets hat seine Größe, wobei Gap nur ein leerer Raum ist, der sie trennt. Die Richtungsblöcke haben eine größere Größe, wenn sie ausgewählt werden, und eine kleinere Größe. Mit der Bedingung, dass der Empfänger eine Impulsfrequenz von 36kHz hat, habe ich einen anderen Zähler, der den Haupttakt auf 36kHz reduziert, den ich benutze, um die Impulsgrößen für Start, Select usw. zu erzeugen und die Ausgangs-LED 1 zu machen, während der Zähler hochzählt auf diese Größe (für Fälle starten, wählen Sie ..) und 0 für Gap-Status.

Allerdings, wenn ich auf die LED durch meine Smartphone-Kamera schaue, zeigt es an, dass es die ganze Zeit ist, was ich erwarte zu sehen, wie es Pakete 10 mal pro Sekunde senden sollte.

Das Problem ist, dass das Auto überhaupt nicht bewegt, meine Frage ist, ist dies die richtige Logik, die Dinge zu tun, oder mir fehlt etwas? Dank

Gewünscht Code:

Der Zähler für die 36kHz Impuls

[email protected](posedge CLK) begin 
    if(RESET) begin 
     Counter <= 0; 
     SEC_CLK <= 0; 
    end 
    else if(Counter == 2778) begin 
     Counter <= 0; 
     SEC_CLK <= 1'b1; 
    end 
    else begin 
     Counter <= Counter + 1; 
     SEC_CLK <= 1'b0; 
    end 
end 

Der 10Hz Zähler, weiß nicht, ob gut ist die 36kHz oder verwenden Sie die Master Clock zu reduzieren, aber es ist eine schöne runde Zahl so habe ich die Hauptuhr

[email protected](posedge CLK) begin 
    if(sec_counter == 100000) begin 
     sec_counter <= 0; 
     send <= 1; 
    end 
    else begin 
     sec_counter <= sec_counter +1; 
     send <= 0; 
    end 
end` 

Die FSM LOGIC:

[email protected](Curr_State) begin 
      case(Curr_State) 
       1'd0: begin //START 
        Next_State <= 1'd1; 
        Previous_State <= Next_State; 
        max_count <= StartBurstSize; 
        flag <= 0; 
       end 
       1'd1: begin //GAP 
        if(Previous_State <= 1'd7) 
         Next_State<=1'd0; 
        else 
         Next_State <= Previous_State +1; 
        max_count <= GapSize; 
        flag <= 1; 
             IR_LED = 1'b1; 

        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd2: begin //SELECT 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        max_count <= CarSelectBurstSize; 
        IR_LED = 1'b0; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
       end 
       1'd3: begin //RIGHT 
        if(BTNR) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd4: begin //LEFT 
        if(BTNL) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd5: begin //FORWARD 
        if(BTNU) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 
       1'd6: begin //Backwards 
        if(BTND) 
         max_count <= AsserBurstSize; 
        else 
         max_count <= DeAssertBurstSize; 
        Next_State <= 1'd1; 
        Previous_State <= Curr_State; 
        flag <= 0; 
        if(change) 
         Curr_State <= Next_State; 
        else 
         Next_State <= Curr_State; 
         IR_LED = 1'b1; 
       end 

      endcase 
end 

DIE IMPULSE FÜR DEN IR SENDING LED

[email protected](posedge SEC_CLK) begin 
    if(send) begin 
     if(Pcounter == max_count) begin //COUNTING BLOCK SIZE 
      Pcounter <= 0; 
      IR_LED=1'b0; 
     end 
     else begin 
      if(flag) 
       IR_LED=1'b0; //GAP 
      else 
       IR_LED=1'b1; 
      Pcounter <= Pcounter+1; 
     end 
    end 
end 
+1

Schwer zu sagen, ohne Ihren Code zu sehen. Bitte geben Sie Ihren Code in die Frage ein. Ein Screenshot der Ausgangswellenformen (z. B. in ISim) wäre ebenfalls äußerst hilfreich. – duskwuff

Antwort

0

Es gibt keine Reset auf sec_counter, so dass das Verhalten unberechenbar sein könnte (es sei denn Sie einen Anfangswert festgelegt, wenn Sie die reg erklärt). Da Sie den Deklarationsteil des Codes nicht eingeschlossen haben, ist es schwer zu sagen.

Ihr State Machine Design ist ein wenig ungewöhnlich und ich denke, dass Sie nicht das Verhalten erhalten, das Sie erwarten. Im Allgemeinen werden Zustandsautomaten auf eine von zwei Arten codiert. Eine Methode platziert die next_state-Berechnung in einen kombinatorischen Block mit allen Eingaben der Zustandsmaschine und dem aktuellen Zustand in der Empfindlichkeitsliste des Blocks. Ein zweiter synchroner immer-Block (d. H. Die Empfindlichkeitsliste posedge clk) des Codes weist den nächsten Zustand dem aktuellen Zustand an der Stelle des Zustandsmaschinentakts zu. Eine zweite Methode verwendet einen einzigen synchronen always-Block sowohl für die Zustandsmaschinen als auch für die Ausgänge. In diesem Fall gibt es keine Variable next_state. Sie weisen den neuen Wert einfach direkt der Statusvariablen zu und stellen sicher, dass Sie den Statuswert für jeden Zweig einer case- oder if/else-Anweisung zuweisen. Die zweite Version kann schneller laufen, da alle Ausgänge registriert sind, die erste Version verwendet weniger Logik und ich persönlich finde es einfacher zu dekodieren. Da Ihr Design sehr langsam ist, würde ich vorschlagen, diese erste Version zu verwenden.

Ihr Zustandsautomat hält den Status nicht, da keine Uhr verwendet wird - es handelt sich also nicht um eine Zustandsmaschine. Versuchen Sie, es von Ihrem CLK-Signal abzuziehen. Stellen Sie außerdem sicher, dass Sie die Taktdomänenkreuzung richtig handhaben, um Metastabilitätsprobleme zu vermeiden.

0

Ich weiß nicht, ob Sie über diese Frage noch egal, aber in Ihrem Fall Aussagen haben Sie so etwas wie

1'd2: begin //SELECT 

oder sogar

Previous_State <= 1'd7 

bedeutet jedoch, 1'd eine Dezimalzahl Nummer 1 Bit breit, so dass es nicht anders als 0 oder 1 sein kann, werden die höchstwertigen Bits einfach verworfen.

Haben Sie versucht, dies zu simulieren?