2017-12-05 1 views
0

Hallo allerseits,Nehmen Sie die Summe von 3 adc Daten für 3 Sampling

Ich bin ein Neuling in der Programmierung FPGA von Verilog-Sprache. Derzeit versuche ich, die Firmware zu entwerfen, um die Summe der adc-Daten bei 3 Sampling zu berechnen. Zuerst erkläre ich in meinem Code über ein adc bei einer Stichprobe. Wenn Sie den Code anschauen, können Sie das mit ansteigenden Flanke von clkr Uhr und adcIfEnb == 1 finden Sie in der adc_data den Wert von adcIfData bekommen und dies ist es, die Daten für eine Probenahme . In der nächsten steigenden Flanke von clkr Takt und adcIfEnb == 1 sind diese Daten in iradcTrg gespeichert. Schließlich werde ich die 3 Daten von adc_data für 3 Proben haben, die in iradcTrg gespeichert sind, und dann fasse ich 3 diese Daten zusammen.

wire adcIfData[79:0]; 
reg 
always @(posedge clkr) begin 
if(adcIfEnb) begin 
adc_data[9:0] <= adcIfData[9:0]; 
end 
end 
reg [29:0] iradcTrg; 
reg [9:0] adcTrg; 
always @(posedge clkr) begin 
if (adcIfEnb) begin 
iradcTrg[29:0] <= {adc_trg[19:10],adc_trg[9:0],adc_data[9:0]}; 
adcTrg[9:0] <= adc_trg[29:20] + adc_trg[19:10] + adc_trg[9:0]; 
end 
end 

Allerdings gibt es zwei Probleme, die ich weiß nicht, wie zu lösen.

Zum einen an der Anfangszeit, als die ersten Daten von adc_data bei iradcTrg gespeichert und adcTrg auch die Summe nehmen. Es bedeutet, dass adcTrg = 0 + 0 + first_adc_data aber diese Summe vermieden werden muss.

Zweitens nach meinem Entwurf, ich sehe, dass adc_data in iradcTrg serialisiert wird. Es bedeutet, dass die adc_data wird wie folgt gespeichert werden:

[1 2 3] 4 5 6 => 1 [2 3 4] 5 6 => 1 2 [3 4 5] 6

Aber in meinem Fall, würde Ich mag, dass die adc_data wird so gespeichert werden, die Summe

[1 2 3] 4 5 6 => 1 2 3 [4 5 6]

daher zu bekommen, wie Soll ich meinen Code reparieren, um das Ergebnis zu erhalten, das ich erwartet habe, oder gibt es irgendwelche Dokumente, die mir in diesem Fall helfen können?

Antwort

1

Um zu beginnen: Stellen Sie sicher, dass Ihr Code korrekt eingerückt ist, wenn Sie ihn auf Stackexchange setzen.
Zweitens: Ich nehme an, Sie haben den Code vor dem Posten hier bearbeitet, weil dieser Code z. Es gibt ein schwebendes "reg" an der Spitze und keine Moduldeklaration.
Drittens: Sie haben einen Draht adcIfData [79: 0] definiert. Ich gehe davon aus, dass Sie das mit [9: 0] meinten.
Forth: Sie verwenden Variablen, die nicht definiert sind: adc_data, adc_trg.
Fünftens: Ich schlage vor, Sie geben Ihren Variablen sinnvollere Namen wie: gater_samples, sum_off_samples.
Jetzt sehen wir uns den Kern des Codes an. Sie möchten Samples nehmen und sie in ein 30-Bit-Register verschieben. Es besteht keine Notwendigkeit, "adc_trg [19:10], adc_trg [9: 0]" zu schreiben. Adc_trg [19: 0] wird ausreichen. Es besteht auch keine Notwendigkeit, es vorher in ein anderes Register zu setzen. Ich würde nur verwenden:

always @(posedge clkr) 
    if (adcIfEnb) 
     iradcTrg[29:0] <= {iradcTrg[19:0],adcIfData[9:0]}; 

In Bezug auf Ihre grundlegenden Problem Proben zu sammeln und nicht die ersten beiden mit: alles, was Sie tun müssen, ist einen Zähler hinzuzufügen, die auf drei zählt. Dann fügen Sie das Ergebnis bei der dritten Zählung hinzu. Sie benötigen einen Reset, um dem Zähler beim Start einen bekannten Wert zu geben, aber ich sehe kein Reset-Signal. Ich versuche immer, minimale Logik zu verwenden, also würde ich iradcTrg 20 Bits breit machen, um nur das Zwischenergebnis zu speichern, und bei der Zählung von drei addiere es mit dem letzten Beispiel. Speichert weitere 10 Register. Hier ist ein Code. Ich schrieb dies ohne zu simulieren oder zu kompilieren. Es ist nur ein Leitfaden, wie alles aussehen sollte.

reg [ 1:0] count; 
reg [19:0] gather_samples; 
reg [ 9:0] sum_of_samples; 
reg  sum_valid; 

always @(posedge clkr) 
begin 
    if (some_reset) 
     count <= 2'd0; 
    else 
    if (adcIfEnb) 
    begin 
     if (count==2'd2) 
     begin // third sample arriving, add it to the previous 2 
     sum_of_samples <= gather_samples[19:10] + gather_samples[9:0] + adcIfData; 
     count <= 2'd0; 
     else 
     begin // intermediate: gather samples 
     gather_samples <= {gather_samples[9:0],adcIfData}; 
     count <= count + 2'd1; 
     end 
     sum_valid <= (count==2'd2);     
    end // if (adcIfEnb) 
end // clocked 
1

Ihre Arbeit wird viel einfacher, wenn Sie eine Zustandsmaschine verwenden. Hier ist ein kleines (und unvollständiges) Beispiel für eine Zustandsmaschine.

parameter FIRST_DATA=0, SECOND_DATA=1, THIRD_DATA=2, OUTPUT=3; 
reg [2:0] current_state = FIRST_DATA; 

reg [9:0] adc_data1; 
reg [9:0] adc_data2; 
reg [9:0] adc_data3; 
reg [11:0] adc_data_sum; 

always @ (posedge clk) 
begin 
// TODO: use proper reset 
case (current_state): 
FIRST_DATA: 
    if(adcIfEnb): 
     current_state <= SECOND_DATA; 
SECOND_DATA: 
    if(adcIfEnb): 
     current_state <= THIRD_DATA; 
THIRD_DATA: 
    if(adcIfEnb): 
     current_state <= OUTPUT; 
OUTPUT: 
    if(adcIfEnb): 
     current_state <= FIRST_DATA; 
endcase 
end 

always @ (negedge clk) 
begin 
    if (current_state == FIRST_DATA && adcIfEnb) 
     adc_data1 <= adcIfData; 
end 

always @ (negedge clk) 
begin 
    if (current_state == SECOND_DATA && adcIfEnb) 
     adc_data2 <= adcIfData; 
end 

always @ (negedge clk) 
begin 
    if (current_state == THIRD_DATA && adcIfEnb) 
     adc_data3 <= adcIfData; 
end 

always @ (negedge clk) 
begin 
    if (current_state == OUTPUT) 
     adc_data_sum <= adc_data1 + adc_data2 + adc_data3; 
end 
0

Ein paar Kommentare zuerst:

1) Ich weiß nicht, warum Sie so viele Variablen mit seltsamen Namen vorstellen kann. Sie benötigen nur eine adc_buffer und adc_sum. Ist iradcTrg das gleiche wie adc_trg? Warum gibt es eine leere Reg-Anweisung? Warum hat adcIfData 80 Bits und Sie verwenden nur 8 LSB Bits? Ich bin verwirrt.

2) Da adc_sum eine Summe von 3 (adcTrg in Ihrem Fall) sein wird, denken Sie über mögliche Überlauf. Was sollte die Breite von adc_sum sein, wenn Sie 3 10-Bit-Nummern hinzufügen möchten?

3) Sollten Sie Ihren Entwurf nicht zuerst in einen bekannten Zustand zurücksetzen, indem Sie zuerst den asynchronen oder synchronen Reset verwenden?

Sie können zum Wickeln auf 0 zurück ein 2-Bit-Zähler mit Asynchron-Reset und eine Logik verwenden:

reg [1:0] adc_buffer_counter_reg; 
    always @(posedge clkr or negedge rst_n) begin 
     if (!rst_n) 
     adc_buffer_counter_reg <= 2'd0; 
     else if (adcIfEnb) begin 
     if (adc_buffer_counter_reg == 2'd2) //trigger calc of the sum here 
      adc_buffer_counter_reg <= 2'd0; 
     else 
      adc_buffer_counter_reg <= adc_buffer_counter_reg + 2'd1; 
    end 

Sie diesen Zähler können alle 3. gültige Daten eine Berechnung der Summe auszulösen.

Verwandte Themen