Ich bin gerade dabei Verilog zu lernen. Leider scheine ich dafuer wohl zu doof zu sein. Jedenfalls popel ich hier bereits seit einer Woche damit rum einen SPI-Bus zu implementieren, etwas das ich in C vermutlich in 1-2min runterschreiben koennte. Eniviroment: Xilinx Webpack8.2, Demoboard mit XC3S100E, mehrere Taste(entprellt), LEDs, diverse IO-Ports... SPI_CLK gewinne ich ueber einen Teiler aus einem 33Mhz Quarz und betraegt momentan 1Hz. Waer nett wenn da mal einer drueber schauen koennte und mir sagt wo der Fehler liegt. reg [3:0] state, next_state; parameter S_0 = 4'b0000, S_1 = 4'b0001, S_2 = 4'b0010, S_3 = 4'b0011, S_4 = 4'b0100, S_5 = 4'b0101, S_6 = 4'b0110, S_7 = 4'b0111; reg [7:0] tmp; integer bitcounter; //Ausgabe eines Datenbit und generierung des notwendigen Clocks //Ausserdem bei Reset das Datenregister initialisieren always@(state) begin case (state) S_0 : begin tmp <= {tmp[6:0],MAX_DOUT}; next_state <= S_1; end S_1 : begin clockout <= 1'b1; //Clock auf HighPegel next_state <= S_7; end S_2 : begin clockout <= 1'b0; //Clock auf Low bitcounter = bitcounter +1; if (bitcounter == 7) next_state <= S_7; else next_state <= S_0; end S_6 : begin tmp <= 8'b10101010; //Bei Reset Kommandowort laden bitcounter = 0; next_state <= S_0; //Statemachine starten end S_7 : begin //Wir sind fertig next_state <= S_7; end endcase end assign Led1 = tmp[7]; assign Led2 = !clockout; //Haelt unser Statemachine in Schwung always @(posedge SPI_CLK) begin if (Taste1 == 1'b1) //Das ist erstmal unsere Resettaste begin state <= S_6; // tmp <= 8'b10101010; end else begin state <= next_state; //Statemachine triggern end end Meine Vorstellung ist das das Programm beim druecken von 'Taste1' die Statemachine bei S6 startet, den Vorgabewert ins Register laedt, die einzelnen Bits ausgibt und dazu jeweils einen Clock generiert. Danach sollte die UEbertragung anhalten. Passieren tut folgendes: Nach dem reinladen des Programms in den FPGA werden unendlich viele Clockimpulse ausgeben, aber kein Registerinhalt. Druecke ich Taste1 stoppt die Ausgabe der Clockimpulse, laesst man los werden sie wieder erzeugt. Aber sie hoeren halt nicht auf. Dabei sollte die Statemachine doch irgendwann mal anhalten. Ausserdem wird entweder mein Vorgabewerte nicht uebernommen, oder es wird nicht geshiftet. Es sieht so aus als wenn nur S1 und S2 in einer Endlosschleife abgearbeitet werden. Warum ist das so? Irgendwie muss ich da was entscheidendes in der Logic von Verilog nicht verstanden haben. Olaf
Mach doch erst mal eine Testbench und schau ob da alles funktioniert wie du willst. Du hast mit parameter 8 states spezifiziert aber nutzt nur 5 in der case Anweisung. Gibt dir die Synthese diesbezüglich eine Warnung? Dein state S_2 wird nie angesprungen. Ist das beabsichtigt?
> Mach doch erst mal eine Testbench und schau ob da alles funktioniert wie > du willst. Ich hab mir gerade Ikarus installiert. (Hat den Vorteil das ich nicht immer fuer Windows booten muss, und laeuft 10^499mal schneller als der Compiler von Xilinx. http://iverilog.wikia.com/wiki/User_Guide Dann hab ich mir dafuer ein Testbench geschrieben und laufen gelassen. Die Ausgabe sieht genauso aus wie ich das erwarte. Ich versteh jetzt leider ueberhaubt nicht wieso das im FPGA nicht laeuft, seufz. > Du hast mit parameter 8 states spezifiziert aber nutzt nur 5 in der case > Anweisung. Gibt dir die Synthese diesbezüglich eine Warnung? Ja. Ich hab einige Parameter und IOs spezifiziert die ich momentan noch nicht nutze und bekomme da Warnungen. Ich denke aber mal das kann ich einfach ignorieren? > Dein state S_2 wird nie angesprungen. Ist das beabsichtigt? Das war ein kleiner Fehler in meinem geposteten Programm. Ich hatte das vorher mal zu testzwecken geaendert und vergessen es rueckgaengig zu machen. Ich probier mal die aktuelle Version anzuhaengen wie ich sie gerade mit Ikarus erfolgreich getestet habe. Ausser den "display" Zeilen unterscheidet die sich nur im Clock des letzten always. Im Testbench generiere ich direkt einen passenden Clock damit ich nicht ewig warten muss. Im Xilinx benutze ich einen anderen Clock den ich vorher durch runterteilen eines angeschlossenen Oszillator gewinne. Das funktioniert aber. Wenn ich mir eine LED an meine Teile route kann ich die im Sekundenrythmus blinken sehen. Olaf
Hier noch die Testbench falls es einer mal selber probieren will. Aber wie gesagt, die Simulation sieht gut aus. Probleme habe ich erst im FPGA. Olaf
Nicht, dass ich auch nur den Hauch einer Ahnung von Verilog hätte, aber in VHDL müssten in der sensitivity-list des Prozesses alle verwendeten Variablen stehen. Siehe O-Text von http://www.doulos.com/knowhow/verilog_designers_guide/rtl_verilog/ : : The statements inside the always block describe the functionality of the design (or a part of it). Let's reconsider the AND-OR-INVERTER gate: always @(sensitivity-list) begin F = ~((a & b) | (c & d)); end Instead of a continuous assignment, we now have a procedural assignment to describe the functionality of the AOI gate. Perhaps a better question is what do we need to do in order to have F change value. Answer: F can only change when at least one of a, b, c or d changes. After all, these are the four inputs to the AOI gate. That's our sensitivity list: always @(a or b or c or d) begin F = ~((a & b) | (c & d)); end : : Bezogen auf deinen Code müsste da also eher stehen : : always@(state or tmp or bitcounter) begin case (state) S_0 : begin tmp <= {tmp[6:0],MAX_DOUT}; next_state <= S_1; end S_1 : begin : : Insgesamt kann ich mir keine Hardware vorstellen, die das ausführen kann. Wenn da steht always @(posedge SPI_CLK) dann ist das getaktet --> FlipFlops --> ok Wenn da aber steht always@(state or tmp or bitcounter) dann gibt das Kombinatorik, und kombinatorische Schieberegister sind genau wie kombinatorische Counter nur Rauschgeneratoren. Fazit: Geschoben und Gezählt wird nur getaktet. BTW: Warum lernst du Verilog? Willst du auswandern? Über den Daumen gepeilt gilt: Europa = VHDL
> Bezogen auf deinen Code müsste da also eher stehen Nein, ich will ja nur das dieser Block ausgefuehrt wird wenn sich an state etwas aendert. Die anderen Variablen werden zwar geaendert, sollen aber nicht selbst eine Aenderung ausloesen. Ich weiss jetzt aber wo mein Problem lag. Man muss zu jederzeit , also bei case in jeder der Moeglichkeiten, festlegen welchen Zustand jede Variable haben soll. Man kann nicht davon ausgehen das sie einfach ihren Vorzustand beibehaelt wenn man sie nicht aendert. Macht man das nicht wandelt der Compiler die Variable in ein Latch um. (und gibt auch eine Warnung dazu aus) Die habe ich zwar gesehen, aber ignoriert weil eine Warnung erstmal noch kein Fehler ist, und zum zweiten nicht so unmittelbar einzusehen ist was an einem Latch fehlerhaft ist. Aber anscheinend kann der FPGA an dieser Stelle kein Latch benutzen und deshalb laeuft es dann in der Hardware nicht, obwohl die Simulation kein Problem sieht. > Warum lernst du Verilog? Willst du auswandern? Die Beispiele bei meinem Kit waren bereits alle in Verilog und ausserdem sieht die Sprache IMHO schoener aus als VHDL. > Über den Daumen gepeilt gilt: Europa = VHDL Ich bin kosmopolitisch orientiert. Ausserdem waere es doch langweilig immer das zu machen was alle anderen auch machen. .-) Olaf
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.