Hallo Teilnehmer,
wollen wir langsam zum Ende von Lektion 1 kommen und uns anschauen wie die Lösungen der Aufgaben aussehen könnten.
In Aufgabe 1 hatten wir ja den Democode zur Einrichtung des EP2C5-Boards dahingehend abzuändern, das eine Art Lauflicht entsteht.
Eine ganz einfache Lösung könnte so aussehen (ich hoffe die Code-Formatierungen bleiben hier im Post erhalten):
PHP-Code:
module countpro(sys_clk,led);
input sys_clk;
output [2:0] led;
reg [25:0] count;
reg [1:0] lednum;
reg [2:0] led;
always @(posedge sys_clk)
begin
count <= count + 1; // 50 MHz Systemtaktzaehlung
if( count == 6250000 ) // alle 6250000 Clks, schalte
begin
// negiere Schaltzustand bei led
led[lednum] <= ~led[lednum];
// naechste led
lednum <= lednum + 1;
// Zaehler zuruecksetzen fuer nachsten Schaltzustand
count <= 0;
// ueberpruefen ob Ueberlauf in lednummerierung
if (lednum == 2)
begin
lednum <= 0;
end
end
else
led[lednum] <= led[lednum];
end
endmodule
Wir erhalten ein IC welches ein Lauflicht realisiert, was als Fahrtrichtungsanzeiger in einer Fahrstuhlanlage oder einem PKW mit LED-Blinker dienen kann. Ebenfalls im Code sichtbar, begin-end-Schlüsselworte sind bei Blöcken mit Einzelanweisungen nicht unbedingt notwendig, wenn klar ist, dass ohne diese Blockmarkierung nur eine(!) Befehlszeile nach einer if/if-else oder Schleifen-anweisung ausgeführt wird!
In Aufgabe 2 sollte ein IC eine 7-Segmentanzeige treiben und einen Zähler bereitstellen. Über zwei Taster sollte ein Hoch- bzw. Runter-zählen eingeleitet werden.
Schauen wir uns zuerst diesen Teilcode an, der wiederum auf dem Democode zum EP2C5-Board basiert:
PHP-Code:
module countpro(sys_clk,up_down,segment);
input sys_clk;
input up_down;
output [6:0] segment;
reg [6:0] segment;
reg [25:0] count;
reg [3:0] num;
always @(posedge sys_clk)
begin
count <= count + 1; // 50 MHz Systemtaktzaehlung
if( count == 25000000 )
begin
if (up_down)
begin
if (num < 9)
num <= num + 1;
else
num <= 0;
end
else
begin
if (num > 0)
num <= num - 1;
else
num <= 9;
end
count <= 0; // Zaehler zuruecksetzen fuer nachsten Schaltzustand
end
if (num == 0 )
begin
segment <= 7'b0111111;
end
if (num == 1 )
begin
segment <= 7'b0001100;
end
if (num == 2 )
begin
segment <= 7'b1011011;
end
if (num == 3 )
begin
segment <= 7'b1011110;
end
if (num == 4 )
begin
segment <= 7'b1101100;
end
if (num == 5 )
begin
segment <= 7'b1110110;
end
if (num == 6 )
begin
segment <= 7'b1110111;
end
if (num == 7 )
begin
segment <= 7'b0011100;
end
if (num == 8 )
begin
segment <= 7'b1111111;
end
if (num == 9 )
begin
segment <= 7'b1111110;
end
end
endmodule
Auch hier wird wieder der Systemtakt runter auf einen internen Modultakt geteilt, danach erfolgt die Überprüfung wie der Eingang up_down aussieht, gefolgt von der Zählaktion. Der C-Software-Programmierer würde jetzt sagen, der Zähler zählt aber doch bei jedem internem Modultakt und nicht auf Tastendruck! Ist up_down auf high wird inkrementiert, auf low dekrementiert. Das ist richtig, dennoch verhält es sich bei FPGAs etwas anders, es gibt nicht nur high und low, sondern auch noch hochohmig/offen! Ist das bei unserem Beispiel der Fall, also wird der Pin weder auf high noch auf low-Pegel gesetzt, bleibt der Zähler einfach auf dem aktuellen Zahlenwert! Somit können wir an einem Pin mit zwei Schaltern also drei Schaltzustände abbilden!
Für jeden Wert des Zählers (0...9) erfolgt die Zuweisung der Segmente in if-Blöcken! Auch hier könnte man auf begin/end verzichten, da nur eine(!) Anweisung benötigt wird. Ebenso wäre Anstelle der vielen if-Zweige auch die Verwendung des switch/case-Konstrukts wie wir es aus der Programmiersprache C kennen zu überlegen, in Verilog sieht diese ganz ähnlich aus:
PHP-Code:
// Here 'expression' should match one of the items (item 1,2,3 or 4)
case (<expression>)
case_item1 : <single statement>
case_item2,
case_item3 : <single statement>
case_item4 : begin
<multiple statements>
end
default : <statement>
endcase
Kommen wir nun zu einer Variante, wo wir zwei Eingänge für die Zählrichtung verwenden und wo wir den Zählerüberlauf für einen internen Takt auf Meldeausgänge kopieren:
PHP-Code:
module countpro(sys_clk,up,down,segment,overflow);
input sys_clk;
input up;
input down;
output [6:0] segment;
reg [6:0] segment;
output [1:0] overflow;
reg [1:0] overflow;
reg [25:0] count;
reg [3:0] num;
always @(posedge sys_clk)
begin
count <= count + 1; // 50 MHz Systemtaktzaehlung
if( count == 25000000 )
begin
if (up == 1)
begin
if (num < 9)
begin
num <= num + 1;
overflow[0] <= 0;
end
else
begin
num <= 0;
overflow[0] <= 1;
end
end
if (down == 1)
begin
if (num > 0)
begin
num <= num - 1;
overflow[1] <= 0;
end
else
begin
num <= 9;
overflow[1] <= 1;
end
end
count <= 0; // Zaehler zuruecksetzen fuer nachsten Schaltzustand
end
if (num == 0 )
begin
segment <= 7'b0111111;
end
if (num == 1 )
begin
segment <= 7'b0001100;
end
if (num == 2 )
begin
segment <= 7'b1011011;
end
if (num == 3 )
begin
segment <= 7'b1011110;
end
if (num == 4 )
begin
segment <= 7'b1101100;
end
if (num == 5 )
begin
segment <= 7'b1110110;
end
if (num == 6 )
begin
segment <= 7'b1110111;
end
if (num == 7 )
begin
segment <= 7'b0011100;
end
if (num == 8 )
begin
segment <= 7'b1111111;
end
if (num == 9 )
begin
segment <= 7'b1111110;
end
end
endmodule
Für mehrstellige 7-Segmentanzeigen kann dieses Modul nun entsprechend oft im FPGA "vervielfältigt" werden, wobei die Meldeausgänge des Überlaufs auf die Zähleingänge des nachgeschalteten Moduls gelegt werden.
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung.
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")