Forum: FPGA, VHDL & Co. Verilog Task


von hans (Gast)


Lesenswert?

Hallo,

ich habe ein Problem und ich finde einfach keine Lösung.

1
always @(posedge clkin_150) begin
2
3
case(state_square)
4
 
5
 IDLE: begin
6
          if(control_go_square_psd==1'b1)begin
7
               control_done_square_psd_reg<=0;
8
             state_square <= COPY;
9
             
10
            end
11
          else begin state_square <= IDLE; end
12
      end
13
 COPY: begin  
14
            for(int j=0;j<process_steps;j=j+1) begin      --// copy new psd values to task
15
              new_psd_reg_task[j]<=psd[steps_offset_square+j];
16
              new_psd_reg_task_temp[j]<=psd[steps_offset_square+j];
17
          end
18
          
19
          state_square <= COPY_END;
20
      end
21
COPY_END: begin
22
             state_square <= SQUARE;
23
      end
24
     
25
 SQUARE: begin
26
               
27
           square(psd,new_psd_reg_task,new_psd_reg_task_temp,tolerance_delta,maxima); // calling task
28
  
29
          state_square <= DELAY;
30
       end   
31
    
32
 DELAY: begin
33
34
          
35
              state_square <= SQUARE_END;
36
      end
37
 SQUARE_END: begin
38
              
39
          for(int i=0;i<process_steps;i=i+1)begin  --// save values
40
          new_psd_reg[steps_offset_square+i]<=new_psd_reg_task[i];
41
          end
42
          if(steps_offset_square==steps-process_steps) begin -- // last interval was processed
43
             state_square <= DONE;
44
            steps_offset_square<=0;
45
          end
46
          else begin
47
            steps_offset_square<=steps_offset_square+process_steps; --// increase offset 
48
            state_square<=COPY;
49
          end
50
51
          
52
       end
53
 DONE: begin
54
              control_done_square_psd_reg<=1;
55
            if(control_go_square_psd==0) begin
56
              state_square<=IDLE;
57
            end
58
          else begin
59
          state_square <=DONE;  
60
            end
61
     end
62
63
64
65
66
endcase
67
end

Ich habe eine Zustandsmaschine die abhängig von der Anzahl der 
Werte(steps_offset) den Task square aufrufen soll. Nun passiert es aber 
das nachdem ausführen auf dem FPGA nur der letzte Aufruf des Tasks das 
richtige Ergebnis bringt. Die anderen Aufrufe werden nicht bearbeitet.

Nun frage ich mich warum immer nur der letzte Aufruf bearbeitet wird in 
der Simulation funktioniert alles einwandfrei.

Ich habe auch schon versucht den task auf automatic zu setzen was aber 
keine Besserung gebracht hat.

Liegt es vielleicht an den Zuweisungen in den for - Schleifen und das 
mir Quartus die vorherigen Aufrufe wegsynthetisiert?

von auch Hans (Gast)


Lesenswert?

Der Code des Tasks wäre evtl. auch ganz hilfreich!

von hans (Gast)


Lesenswert?

1
task square;
2
   input signed [7:0]psd[0:steps-1];
3
   inout signed [7:0]new_psd_reg_task[0:process_steps-1];
4
  input signed [7:0]new_psd_reg_task_temp[0:process_steps-1];
5
  input [7:0]tolerance_delta;
6
  input signed [7:0] maxima [0:max_channels-1];
7
8
  
9
  for(int j=0;j<process_steps;j=j+1) begin
10
   
11
      for(int i=0;i<max_channels;i=i+1)begin // for every maxima value +/- tolerance delta, psd is compared and adapt to maxima value if in this interval
12
                           
13
            if (new_psd_reg_task_temp[j]<=maxima[i]+tolerance_delta && new_psd_reg_task_temp[j]>=maxima[i]-tolerance_delta) begin
14
            
15
              new_psd_reg_task[j]=maxima[i];
16
              
17
              
18
             end // end if
19
             
20
             
21
          end  // end i
22
    end // end j
23
  
24
endtask

von auch Hans (Gast)


Lesenswert?

Also ich würde ja eher eine Function statt einem Task empfehlen. Die hat 
jedenfalls einen Rückgabewert. Und wieso ist new_psd_reg_task ein als 
inout deklariert?

von hans (Gast)


Lesenswert?

na new_psd_reg_task brauch ich doch um im Zustand Square_END die Werte 
zu übertragen. Mein gedanke dahinter ist Ressourcen zu sparen indem ich 
imemr wieder den selben Task verwende und die berechneten Werte danach 
übertrage.

von auch Hans (Gast)


Lesenswert?

Aber du überschreibst doch alle Werte von 'new_psd_reg_task' in dem 
Task, ohne sie dort vorher zur Berechnung zu verwenden. Da brauchst du 
doch kein inout. Ein output hätte doch gereicht.

Und wieso sollen Tasks beim Resourcen sparen helfen? Es kommt doch das 
gleiche bei raus, wenn du den Code aus dem Task direkt in deine State 
Machine kopierst. Was anderes macht das Synthesetool später dann ja auch 
nicht.
Tasks dienen dazu, häufig verwendete Codeteile nur an einer Stelle zu 
beschreiben.

Außerdem wird dein Input 'psd' im Task garnicht verwendet. Der kann also 
auch weg.

von hans (Gast)


Lesenswert?

mit psd hast du recht aber new_psd_reg_task überschreib ich nicht alle 
Werte sondern nur die welche die if Bedingugn erfüllen deswegen das 
inout.


Ich habe ein problem mit dem Konstruct
1
for(int i=0;i<process_steps;i=i+1)begin  --// save values
2
          new_psd_reg[steps_offset_square+i]<=new_psd_reg_task[i];
3
          end

Nehmen wir an ich bekomme vom Task immer 10 Werte und möchte diese in 
das große Feld new_psd_reg abspeichern was z.B. 600 Werte hat. MEine 
Lösung verschlingt im RTL Viewer viel Platz fällt jemanden eine bessere 
Lösung ein?

von auch Hans (Gast)


Lesenswert?

Schreib einen Task oder eine Funktion, die nur 10 Werte als Eingang 
annimmt und auch 10 wieder rausgibt und sortiere sie dann entsprechend 
in das Array mit 600 Einträgen ein (aber nicht mit einer for-Schleife).

von hans (Gast)


Lesenswert?

auch Hans schrieb:
> in das Array mit 600 Einträgen ein (aber nicht mit einer for-Schleife).

Ja wie ich das mache ist gerade meine Frage Danke für die Antwort

von auch Hans (Gast)


Lesenswert?

Nimm einen Zähler, der in 10er Schritten Zählt. Mit dem selektierst du 
die Eingangswerte für den/die Task/Function und auch die Position im 
Ergebnis-Array. Bei jedem Aufruf von square() wird der Zähler 
hochgezählt (aber bitte nicht in dem Task, sondern dort wo der Task 
aufgerufen wird!!!)

von hans (Gast)


Lesenswert?

auch Hans schrieb:
> Nimm einen Zähler, der in 10er Schritten Zählt. Mit dem selektierst du
> die Eingangswerte für den/die Task/Function und auch die Position im
> Ergebnis-Array. Bei jedem Aufruf von square() wird der Zähler
> hochgezählt (aber bitte nicht in dem Task, sondern dort wo der Task
> aufgerufen wird!!!)

Das tu ich ja im Prinzip mit steps_offset_square das zähl ich immer 10 
hoch und wähle so die stelle im Ergebnisarray aus aber wie soll ich die 
for Schleife umgehen

new_psd_reg[steps_offset_square:steps_offset_square+10]<=new_psd_reg_tas 
k;


sowas erzeugt bei mir einen Fehler bei der Codegenerierung

von auch Hans (Gast)


Lesenswert?

Bei dem Fehler schlägt jedes handelsübliche Verilogbuch sowas vor:
1
new_psd_reg[steps_offset_square+:10]<=new_psd_reg_task;

Ansonsten schmeiß das bekloppte inout aus dem Task raus. Was soll das 
da? Schreib das mal um.

Also new_psd_reg_task_temp und new_psd_reg_task sind ja beim Aufruf des 
Tasks identisch, oder? Dann kannst du den ..._temp weglassen und 
fütterst den Task mit new_psd_reg_task. Im Task legst du einen output 
an, z.B. new_psd_reg_task_out. In der for-Schleife weist du jedem 
Arrayelemt des Outputs entweder den Wert des Inputs new_psd_reg_task 
oder den entsprechenden maxima-Wert zu.
Das was du da treibst sieht wie Software in-place Denkweise aus und ist 
hier völlig falsch. Hab dir ja in ein paar anderen Threads schon geraten 
mal etwas Geld in ein Buch zum digitalen Hardwaredesign zu investieren.

von hans (Gast)


Lesenswert?

new_psd_reg[steps_offset_square+:10]<=new_psd_reg_task;

zu solchen kontrukten kommt bei mir immer der Fehler steps_offset_square 
is not a constant deswegen habe ich aj den Weg über die forschleifen 
gewählt

von auch Hans (Gast)


Lesenswert?

Dann wäre es wohl günstiger dein Array in ein RAM aufzuteilen. Die 
Datenbreite des RAMs wählt du so, daß z.B. 10 Elemente gleichzeitig 
gelesen/geschrieben werden können. Also in diesem Fall 80 Bit. Dann 
würdest du in der State Machine einen Satz auslesen, ihn modifizieren 
und dann wieder ins RAM schreiben. Allerdings könntest du dann niemals 
auf alle Array-Elemente gleichzeitig zugreifen.
Du könntest auch dein Array dreidimensional gestalten. Also 8 Bit * 10 
Elemente * 60. Dann würdest du ein zweidimensionales Array daraus 
selektieren und könntest mit dem Arbeiten. Ob die Synthese das frisst 
weiß ich aber gerade nicht.

von hans (Gast)


Lesenswert?

ich ahbe es jetzt mit so einem Konstrukt versucht
1
reg signed [7:0]new_psd_reg[process_steps-1:0][0:steps/process_steps-1];
2
3
4
new_psd_reg[process_steps-1:0][0]<=new_psd_reg_output; -- zuweisung

allerdings erhalte ich folgenden Fehler


range must be the final index in the indexed name


Was mach ich falsch.

von hans (Gast)


Lesenswert?

ok hab den fehler selbst behoben

reg signed [7:0]new_psd_reg[0:steps/process_steps-1][0:process_steps-1]; 
dann geht es


Vielen dank auch hans für deine hilfe und geduld :D

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
Noch kein Account? Hier anmelden.