Hallo zusammen, ich versuche gerade einen FIR-Filter mit einer Abtastrate von 16 kHz auf dem Genesys 2 Board (https://reference.digilentinc.com/reference/programmable-logic/genesys-2/reference-manual) zu implementieren (Vivado 2019.2, VHDL). Für diesen Zweck muss ich den boardinternen Audio-Codec (ADA1761) konfigurieren. Ich habe bereits ein FIR-Filter in der transponierten Direktform implementiert und getestet, welches ich zu einem späteren Zeitpunkt anbinden möchte. Ich habe einen Artikel von Stefan Scholl „Audio Interface for the Zedboard“ gefunden (TU Kaiserslautern Germany, see https://kluedo.ub.uni-kl.de/frontdoor/deliver/index/docId/4034/file/zedboard_audio_doc.pdf). Dieses Framwork basiert auf einem Framework von Mike Field (alias hamster). Die VHDL-files sind auch dabei (https://github.com/ems-kl/zedboard_audio). Ich habe das alte Framework in ein angepasstes Framework für das Genesys 2 umgewandelt, da es sich um denselben Audio-Codec handelt. Leider funktioniert etwas nicht, und ich weiß NOCH nicht wie ich den Fehler behebe (Critical Timing Problem). Als erstes möchte ich den LINE IN Input direkt an den HP OUT Ausgang weitergeben. Als nächsten Schritt möchte ich dann meinen FIR-Filter (Festkommarealisierung) anbinden. Für die Funktionsanalyse benutze ich dann das Analog Discovery 2 von Digilent (Frequenzgang messen mit Sinussweeps). Critical Warnings: [Timing 38-282] The design failed to meet the timing requirements. Please see the timing summary report for details on the timing violations. [Board 49-67] The board_part definition was not found for digilentinc.com:genesys2:part0:1.1. This can happen sometimes when you use custom board part. You can resolve this issue by setting 'board.repoPaths' parameter, pointing to the location of custom board files. Valid board_part values can be retrieved with the 'get_board_parts' Tcl command. Ich dachte erst mein Framework funktioniert, aber wenn man hphone_out_l und hphone_out_r auf 0 setzt höre ich immer noch die Musik von meinem IPod über die Kopfhörern (aufgrund des defaultmäßigen Startup-Programms). Wenn das Design funktioniert, möchte ich das Codec-Interface hochladen. Vielleicht kann auch jemand anderes dieses Interface benötigen. Wenn mir jemand helfen könnte, oder ein anderes Audio-Codec Interface hat, würde ich mich sehr freuen. Ich habe eine Modulübersicht, das Block Design und die vhdl-Dateien angehängt. Auch die Codec Konfiguration (docx) sowie die Fehlermeldungen befinden sich im Anhang. Wenn erwünscht, kann ich weitere Files hochladen. Vielen Dank im Voraus. Bleibt gesund und beste Grüße Mario
Weitere Dateien Ich werde jetzt mal versuchen den Systemtakt auf 50 MHz zu reduzieren. Vielleicht verschwinden die Timing-Probleme ja dann...
In der STA steht ein Requirement von 0.8 ns. Das kommt mir zu klein vor. Asynchroner Taktübergang? Wahrscheinlich springst du ohne Vorkehrungen zwischen 48 MHz und 100 MHz. Die würde ich wie asynchrone Takte behandeln. Oder du stellst diese auf 48 und 96 MHz (oder 48 und 144 MHz), falls 48 MHz fix bleiben muss. Dann können die Übergänge wieder synchron bleiben. Wie sieht das Constraint-File aus? ... und schau dir die Taktübergänge genauer an.
Danke für deine Anmerkungen! Was meinst du mit STA? Das Constraints File sieht so aus (https://github.com/Digilent/digilent-xdc/blob/master/Genesys-2-Master.xdc): #### This file is a general .xdc for the Genesys 2 Rev. H #### To use it in a project: #### - uncomment the lines corresponding to used pins #### - rename the used ports (in each line, after get_ports) according to the top level signal names in the project ## Clock Signal set_property -dict { PACKAGE_PIN AD11 IOSTANDARD LVDS } [get_ports { sysclk_n }]; #IO_L12N_T1_MRCC_33 Sch=sysclk_n set_property -dict { PACKAGE_PIN AD12 IOSTANDARD LVDS } [get_ports { sysclk_p }]; #IO_L12P_T1_MRCC_33 Sch=sysclk_p ## Audio Codec set_property -dict { PACKAGE_PIN AH19 IOSTANDARD LVCMOS18 } [get_ports { aud_adc_sdata }]; #IO_L8N_T1_32 Sch=aud_adc_sdata set_property -dict { PACKAGE_PIN AD19 IOSTANDARD LVCMOS18 } [get_ports { aud_adr0 }];#{ aud_adr[0] }]; #IO_L10P_T1_32 Sch=aud_adr[0] set_property -dict { PACKAGE_PIN AG19 IOSTANDARD LVCMOS18 } [get_ports { aud_adr1 }];#{ aud_adr[1] }]; #IO_L8P_T1_32 Sch=aud_adr[1] set_property -dict { PACKAGE_PIN AG18 IOSTANDARD LVCMOS18 } [get_ports { aud_bclk }]; #IO_L11N_T1_SRCC_32 Sch=aud_bclk set_property -dict { PACKAGE_PIN AJ19 IOSTANDARD LVCMOS18 } [get_ports { aud_dac_sdata }]; #IO_L7P_T1_32 Sch=aud_dac_sdata set_property -dict { PACKAGE_PIN AJ18 IOSTANDARD LVCMOS18 } [get_ports { aud_lrclk }]; #IO_L9P_T1_DQS_32 Sch=aud_lrclk set_property -dict { PACKAGE_PIN AK19 IOSTANDARD LVCMOS18 } [get_ports { aud_mclk }]; #IO_L7N_T1_32 Sch=aud_mclk set_property -dict { PACKAGE_PIN AE19 IOSTANDARD LVCMOS18 } [get_ports { aud_scl }]; #IO_L10N_T1_32 Sch=aud_scl set_property -dict { PACKAGE_PIN AF18 IOSTANDARD LVCMOS18 } [get_ports { aud_sda }]; #IO_L11P_T1_SRCC_32 Sch=aud_sda ## IIC Bus #set_property -dict { PACKAGE_PIN AE30 IOSTANDARD LVCMOS33 } [get_ports { SYS_SCL }]; #IO_L16P_T2_13 Sch=sys_scl #set_property -dict { PACKAGE_PIN AF30 IOSTANDARD LVCMOS33 } [get_ports { SYS_SDA }]; #IO_L16N_T2_13 Sch=sys_sda Ich habe die nicht verwendeten Ports gleich mal weggelassen.
:
Bearbeitet durch User
Okay --> STA = Static Timing Analysis. Requirement 0.833.
Mario A. schrieb: > Das Constraints File sieht so aus da sind nur PIN-Assignments drin? Wenn Du die asynchronen Clock-Domänen nicht aktiv für die Timing-Analyse auftrennst, wird die Synthese (trotz evt. vorhandenen Synchronizern) versuchen, die sich aus der CDC ergebenden Timing-Requirements zu optimieren. Das kann nicht gutgehen.
Danke für den Tipp! Das wusste ich bisher nicht. Solange arbeite ich leider auch noch nicht mit FPGAs. Hab mir gerade nochmal das vorher verwendete XDC für das Zedboard angesehen. Unter Anderem sieht es folgendermaßen aus: # timing constraints create_clock -period 10.000 -name clk_100 [get_ports clk_100] set_false_path -from [get_clocks zed_audio_clk_48M] -to [get_clocks clk_100] set_false_path -from [get_clocks clk_100] -to [get_clocks zed_audio_clk_48M] # 100 mhz clock set_property PACKAGE_PIN Y9 [get_ports clk_100] set_property IOSTANDARD LVCMOS33 [get_ports clk_100] Die von dir beschriebene Auftrennung, die ich vornehmen muss ist dann wohl set_false_path ... ? Ich werde das morgen probieren und die 2 Zeilen set_false_path anpassen und einbinden.
Ich habe mal versucht das Constraintsfile anzupassen, aber bislang ohne Erfolg. Unter Anderem habe ich es mit set_false_path -from [get_clocks zed_audio_clk_48M] -to [get_clocks clk_100] set_false_path -from [get_clocks clk_100] -to [get_clocks zed_audio_clk_48M] --> [Vivado 12-4739] set_false_path:No valid object(s) found for '-to [get_clocks clk_100]'. [Genesys2Master.xdc:13] und set_false_path -from [get_clocks zed_audio_clk_48M] -to [get_clocks sysclk_p] set_false_path -from [get_clocks sysclk_p] -to [get_clocks zed_audio_clk_48M] --> The design failed to meet the timing requirements. Please see ... und set_false_path -from [get_clocks zed_audio_clk_48M] -to [get_clocks sysclk_p] set_false_path -from [get_clocks sysclk_p] -to [get_clocks zed_audio_clk_48M] set_false_path -from [get_clocks zed_audio_clk_48M] -to [get_clocks sysclk_n] set_false_path -from [get_clocks sysclk_n] -to [get_clocks zed_audio_clk_48M] --> [Vivado 12-4739] set_false_path:No valid object(s) found for '-to [get_clocks sysclk_n]'. [Genesys2Master.xdc:19] versucht, nachdem ich clocking.vhd (Originaldatei) wieder eingebunden und die (Clock-)Signale wieder in den Ausgangszustand des Autors zurückgesetzt habe. Da ich nur sysclk_p und sysclk_n über das XDC ansprechen kann, muss ich mir über den Clocking-Wizard meinen Clock (differential input) erzeugen oder? Ich kann ja nicht einfach, wie der Autor: create_clock -period 10.000 -name clk_100 [get_ports clk_100] set_property PACKAGE_PIN Y9 [get_ports clk_100] set_property IOSTANDARD LVCMOS33 [get_ports clk_100] schreiben. Leider muss ich jetzt bis zum Wochenende erstmal ein paar andere Dinge erledigen, bevor ich wieder viel Zeit investieren kann.
Ich sehe in deinem Toplevel nur diese Clocks:
1 | clk_48_MHz : in STD_LOGIC; |
2 | clk_100_MHz : in STD_LOGIC; |
Die sehe ich aber wiederum in deinen Constraints nicht?
Hallo Markus, das eigentliche Toplevel ist audio_testbench (die Namensbezeichnung ist etwas unglücklich, aber entspricht dem Originalprojekt --> werde ich besser bald mal ändern!). Dort verwende ich sysclk_p und sysclk_n in der Entity. Aus denen erzeuge ich mir über den Clocking Wizard die weiteren Clocks. Eine Ebene darunter kommt dann audio_top. Dort verwende ich die vom Clocking Wizard erzeugten Signale.
wenn die Clocks noch durch einen Clock-Manager laufen hilft es die generierten Clocks mit einzubeziehen:
1 | get_clocks -include_generated_clocks clk1 |
Natürlich kann man die Taktübergänge generell von der Prüfung abschalten. Ich rate dir dies nicht kopflos zu tun. Schau dir betroffenen Signale ganz gut an und stell dir die Frage, ob du in jeder Phasenlage mit dem Signal umgehen kannst. Will man vorsichtig sein, reicht es aus nur die betroffenen Signale per set_false_path (oder set_max_delay) zu constrainieren.
Danke für deine Hilfe! Also unter Report Timing Summary zeigt es mir den Fehler bei clk_out1_clk_wiz_0 to clk_out2_clk_wiz_0 und clk_out2_clk_wiz_0 to clk_out1_clk_wiz_0 an. Erst einmal nur diese beiden mit set_false_path setzen? Variante 1 in xdc: get_clocks -include_generated_clocks clk_out1_clk_wiz_0 get_clocks -include_generated_clocks clk_out2_clk_wiz_0 set_false_path -from [get_clocks clk_out1_clk_wiz_0] -to [get_clocks clk_out2_clk_wiz_0] set_false_path -from [get_clocks clk_out2_clk_wiz_0] -to [get_clocks clk_out1_clk_wiz_0] --> In den Messages steht nur noch [Board 49-67] The board_part definition was not found for digilentinc.com:genesys2:part0:1.1. This can happen sometimes when you use cumstom board part. You can resolve this issue by setting 'board.repoPaths' parameter, pointing to the location of custom board files. Valid board_part values can be retrieved with the 'get_board_parts' Tcl command. Unter Implementation --> Report Timing Summary zeigt es mir allerdings immer noch denselben Fehler an. Variante 2 in xdc: get_clocks -include_generated_clocks clk_out1 get_clocks -include_generated_clocks clk_out2 set_false_path -from [get_clocks clk_out1] -to [get_clocks clk_out2] set_false_path -from [get_clocks clk_out2] -to [get_clocks clk_out1] --> set_false_path: No valid object(s) found for '-from [get_clocks clk_out1]'. Leider schaffe ich es voraussichtlich nicht vorm Wochenende mich intensiv mit false_paths zu beschäftigen. Ich kann es aber kaum erwarten und hoffe, dass es der entscheidende Fehler ist und der Codec dann endlich funktioniert. Eine Stunde am Tag versuche ich dennoch bis dahin einzuräumen.
Klakx -. schrieb: > Will man vorsichtig sein, reicht es aus nur die betroffenen Signale per > set_false_path (oder set_max_delay) zu constrainieren. Kenne Vivado nicht, aber set_clock_groups -asynchronous -group <clock1> -group <clock2> ... ist meist die bessere Wahl (anstatt x set_false_path Statements)?
Hallo, ich hab heute mal wieder versucht die asynchronen Clocks zu setzen. Unter anderem im XDC mit: get_clocks -include_generated_clocks clk_out1_clk_wiz_0 get_clocks -include_generated_clocks clk_out2_clk_wiz_0 set_clock_groups -asynchronous -group {clk_out1_clk_wiz_0} -group {clk_out2_clk_wiz_0} nachdem ich mir in der Tcl Console mit report_clocks die Clocks angesehen habe. Die Ergebnisse von report_cdc hänge ich euch auch noch an. Außerdem habe ich mir mit Report Clock Interaction die Abhängigkeiten angesehen. Ein Critical Warning bzgl. Timing habe ich jetzt nicht mehr. Allerdings: [Vivado 12-4739] set_clock_groups:No valid object(s) found for '-group clk_out1_clk_wiz_0'. ["C:/Users/aim34424/Desktop/Forum/Genesys2AudioCodecPlayground/FIRFilter withCodec.srcs/constrs_1/new/Genesys2Master.xdc":56] und [Board 49-67] The board_part definition was not found for digilentinc.com:genesys2:part0:1.1. This can happen sometimes when you use custom board part. You can resolve this issue by setting 'board.repoPaths' parameter, pointing to the location of custom board files. Valid board_part values can be retrieved with the 'get_board_parts' Tcl command. Ich habe dann noch einmal versucht statt hphone_l <= line_in_l; hphone_r <= line_in_r; nur 0en an den Ausgang zu geben: hphone_l <= (others => '0'); hphone_r <= (others => '0'); --> man hört immer noch die Musik vom IPod über die angeschlossenen Kopfhörer. Sche
set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] habe ich noch ins XDC eingefügt. Jetzt sind wieder 2 Warnings weg.
Okay, ich habe nun set_clock_groups wie folgt angewandt: https://www.xilinx.com/video/hardware/clock-group-constraints.html Jetzt kennt Vivado auch auf einmal mein Constraints-File. Daraufhin wurde set_clock_groups -asynchronous -group [get_clocks *clk_out1*] -group [get_clocks *clk_out2*] automatisch eingefügt in ein neues (leeres) XDC-File. Anschließend habe ich noch meine Pin-Assignments eingefügt. Nun habe ich noch: [Board 49-67] The board_part definition was not found for digilentinc.com:genesys2:part0:1.1. This can happen sometimes when you use custom board part. You can resolve this issue by setting 'board.repoPaths' parameter, pointing to the location of custom board files. Valid board_part values can be retrieved with the 'get_board_parts' Tcl command.
:
Bearbeitet durch User
Jetzt habe ich noch zusätzliche Board-Files hinzugefügt. https://reference.digilentinc.com/reference/software/vivado/board-files. Die Warning: [Board 49-67] The board_part definition was not found for ... hat sich nun auch erledigt. Es bleiben die angehängten Warnings. Wenn ich den Bitstream auf das Board spiele hört man wieder die Musik vom IPod über die Kopfhörer. Wenn ich dann wieder hphone_l und hphone_r auf 0 setze höre ich leider immer noch die Musik vom IPod. Die Warning "No constraints selected or write" kann man denke ich ignorieren. https://www.xilinx.com/support/answers/73510.html Ich denke ich werde nun mal versuchen den ILA einzubauen.
:
Bearbeitet durch User
Hallo zusammen, leider ist schon wieder ein Problem aufgetreten. Wenn ich den ILA einbinde, bekomme ich eine Warning (siehe Anhang). Wenn ich aber ein anderes (bereits getestetes) Programm auf dem Genesys2 zum laufen bringe erhalte ich zwar die selbe Fehlermeldung, aber der ILA zeigt das richtige Ergebnis an und triggert auch. Ist diese Warning evtl. der Grund, warum es nicht funktioniert, oder beeinflusst diese die Funktionsweise nicht? Der Clock ist direkt mit dem Ausgang des clocking wizards verbunden. Der Link https://www.xilinx.com/support/answers/64764.html hat mir bisher noch nicht weitergeholfen. Als Trigger habe ich new_sample=1 und die steigende Flanke von sample_clk_48k versucht. Leider triggert der ILA nicht automatisch. Als Eingangssignal (Line In) habe ich sowohl meinen IPod, als auch das Analog Discovery verwendet (Sinussweeps). Seltsamerweise hat sich die Variable count manchmal nach dem ersten erzwungenen Trigger erhöht, danach aber nicht mehr (das Signal ist defaultmäßig auf 0 gesetzt). Code zum Einbinden es ILAs: COMPONENT ila_0 PORT ( clk : IN STD_LOGIC; probe0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe1 : IN STD_LOGIC_VECTOR(23 DOWNTO 0); probe2 : IN STD_LOGIC_VECTOR(23 DOWNTO 0); probe3 : IN STD_LOGIC_VECTOR(23 DOWNTO 0); probe4 : IN STD_LOGIC_VECTOR(23 DOWNTO 0); probe5 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe6 : IN STD_LOGIC_VECTOR(0 DOWNTO 0); probe7 : IN STD_LOGIC_VECTOR(5 downto 0) ); END COMPONENT ; signal sample_clk_48k_vec : STD_LOGIC_VECTOR (0 downto 0):= "0"; signal new_sample_vec : STD_LOGIC_VECTOR (0 downto 0):= "0"; signal hphone_valid_vec : STD_LOGIC_VECTOR (0 downto 0):= "0"; -- keep signals for tracking them with the Logic Analyzer attribute keep : string; attribute keep of sample_clk_48k : signal is "true"; attribute keep of hphone_l : signal is "true"; attribute keep of hphone_r : signal is "true"; attribute keep of line_in_l : signal is "true"; attribute keep of line_in_r : signal is "true"; -- neu eingefügt attribute keep of new_sample : signal is "true"; attribute keep of hphone_valid : signal is "true"; attribute keep of counter : signal is "true"; -- neu eingefügt ende ... sample_clk_48k_vec(0) <= sample_clk_48k; new_sample_vec(0) <= new_sample; hphone_valid_vec(0) <= hphone_valid; ila : ila_0 PORT MAP ( clk => s_clk_100_MHz, probe0 => sample_clk_48k_vec, probe1 => line_in_l, probe2 => line_in_r, probe3 => hphone_l, probe4 => hphone_r, probe5 => new_sample_vec, probe6 => hphone_valid_vec, probe7 => std_logic_vector(counter) ); Hat jemand eine Idee, was ich machen kann? Leider komme ich gerade nicht mehr weiter... Ich bin für jede Hilfe dankbar! Ich erstelle gerade noch eine Zeichnung zur Übersicht mit allen Signalen, die ich anschließend hochladen werde. Beste Grüße Mario
:
Bearbeitet durch User
ist das Signal s_clk_100_MHz angeschlossen? Im top sah ich sonst immer nur das signal clk_100_MHz.
Ja das Signal ist angeschlossen. clk_wiz : clk_wiz_0 port map ( -- Clock out ports clk_out1 => s_clk_48_MHz, clk_out2 => s_clk_100_MHz, -- Clock in ports clk_in1_p => sysclk_p, clk_in1_n => sysclk_n );
:
Bearbeitet durch User
Ich habe mal die aktuelle Beschaltung zur Übersichtlichkeit angehängt. Grad noch gesehen: line_in_l und _r sind natürlich nicht in der Entity.
:
Bearbeitet durch User
Nach 2 Wochen Urlaub beschäftige ich mich nun wieder intensiv mit der Codec-Anbindung. Zu den angehängten Warnings habe ich nicht großartig was gefunden. Ich denke man kann diese ignorieren(?). Hat jemand eine Idee wie ich die Signale (ohne ILA) sonst noch analysieren/debuggen kann? Ich werde mal versuchen Testbenches für die einzelnen Module zu schreiben... Vielen Dank im Voraus!
Was mich etwas wundert ist die Tatsache, dass deine Testbench selbst noch Ein- und Ausgänge nach Außen hat. Normalerweise, also so wie ich das kenne, nutzt man die Testbench NUR zur Simulation und nicht auf der Hardware. Die Testbench tut also so, als sei sie die Hardware rund um das FPGA. Dazu müsstest du in der Testbench zumindest die zwingend notwendigen Bestandteile vom FPGA Board nachbilden wie den Taktgeber, den Audio Codec, ...
Hallo Gustl, audio_testbench, ist keine Testbench. Das File wird als Top-Modul verwendet. Sorry für die Unklarheit, ich hab das so vom Originalframework übernommen und war auch erst verwundert/irritiert. Ich denke auch nicht, dass der Autor des alten Frameworks die Datei audio_testbench als Testbench verwendet hat.
:
Bearbeitet durch User
Hallo zusammen, kann es sein, dass im Zusammenhang mit IOBUF etwas nicht stimmt? I wird im Schematic auf Ground gerouted. Das Signal i2c_sda_o wird allerdings nirgends auf '1' gesetzt, also könnte es schon passen... Auszug aus adau1761_izedboard.vhd i_i2s_sda_obuf : IOBUF port map ( IO => AC_SDA, -- Buffer inout port (connect directly to top-level port) O => i2c_sda_i, -- Buffer output (to fabric) I => i2c_sda_o, -- Buffer input (from fabric) T => i2c_sda_t -- 3-state enable input, high=input, low=output );
itse_me_mario schrieb: > Dieses Framwork basiert auf einem Framework von Mike Field (alias > hamster). Dessen Webseite verschwunden ist, weil sich jemand über geklauten Code, den er verbreitet haben soll, beschwert hat.
Ah okay. Das wusste ich nicht.
Hat jemand ein paar Tipps, wo man sonst noch Hilfe bekommen kann? Leider komme ich seit geraumer Zeit nicht mehr weiter... Vielen Dank im Voraus!
Sorry, ich habe mich da jetzt nicht tiefer eingearbeitet, so wie ich das verstanden habe möchtest du Audio vom ADA1761 bekommen, durch einen FIR Filter schicken und dann irgendwie weiterverarbeiten. Was du aktuell versuchst ist das Audio von einem ADA1761 Eingang wieder über den ADA1761 ausgeben zu wollen? Dazu musst du den ADA1761 irgendwie konfigurieren und das klappt nicht? Wenn du später das Audio sowieso nicht über den ADA1761 ausgeben willst, dann lass das doch jetzt auch weg. Nehme das Audio von dem ADA1761 und gebe das erstmal digital aus. Z. B. über UART zum PC mit nur wenigen Bits je Sample oder so. Dann im nächsten Schritt setzt du zwischen UART und ADA1761 den FIR. Und dann guckst du was du mit dem gefilterten Audio am Ende machen möchtest. Bei Digitelnt gibt es auch Hardwaredemobeschreibungen, auch mit Audio. Nur Audio vom ADA1761 bekommen und filtern braucht nicht viel HDL, das sollte recht leicht gehen und ohne komplizierte Konfiguration des ADA1761.
Hallo zusammen, ich bin gerade auf eine Idee gebracht worden und habe dazu was passendes gefunden: https://store.digilentinc.com/pmod-i2s2-stereo-audio-input-and-output/ Somit spare ich mir die Konfiguration des Codecs über I2C und müsste mich wohl nur um das I2S-Interface kümmern. Ich werde mir das Bauteil gleich mal bestellen. Ich hoffe das funktioniert so, wie ich mir das vorstelle. Gruß Mario
Ja das kannst du ntürlich auch machen. Aber die Frage ist eigentlich was dein Ziel ist. Was soll mit den gefilterten Daten passieren? Willst du das wieder am Ende als Audio ausgeben oder soll das zu einem PC oder ... Wenn du das nur zum Debugging ausgeben möchtest als Audio, dann kanst du das auch zum PC schicken und dort ausgeben oder anzeigen lassen. Der UART auf deinem Board kann maximal 3 MBaud. Das reicht für 16 Bit Audio mit so 15 kSamples/s. Oder für 8 Bit Audio bei so 30 kSamples/s. Klar, nicht optimal, aber zum Testen ob da was rauskommt reicht das vielleicht. Du könntest auch einen IO nehmen und da mit PWM Audio ausgeben und danach analog tiefpassfiltern. Oder du nimmst noch BRAM dazu, dann kannst du Werte aufnehmen und dann über UART ausgeben. Du hast ausserdem einen FT2232H auf dem Board, damit kannst du die Daten mit voller USB 2.0 Datenrate ausgeben. Ein kleines I2S Audio Modul ist auch eine Lösung. Wenn du später für dein langfristiges Zeil den Audio Codec nicht konfigurieren musst, dann würde ich das auch zwischendrin vermeiden wenn es geht.
Hallo Gustl, vielen Dank für deine ausführlichen Tipps! Hauptziel: Audio-Daten über Audioanschluss einlesen, filtern und anschließend per Audioanschluss wieder ausgeben (in Echtzeit). Die Funktion der Filter kann ich einfach mit dem Analog Discovery 2 überprüfen (Frequenzgangsmessung mit Sinussweeps). Danach will ich ein adaptives Filter zur Störgeräuschunterdrückung darauf implementieren. Gut wäre es, wenn ich hierfür später noch die Daten für die Analyse mit z.B. Matlab (gerade für das adaptive Filter --> ERLE-Messungen) auf dem PC hätte. Wäre es dann aus deiner Sicht sinnvoller die gefilterten Daten mittels UART (FT232R) oder PC-FPGA Data Transfer DPTI/DSPI (FT2232) an den PC zu schicken (siehe Bilder)? Den Codec muss ich nicht speziell konfigurieren. Es reicht, wenn ich ein paar Abtastraten (16 kHz, 32 kHz, 48 kHz) einstellen kann. Vielen Dank im Voraus!
:
Bearbeitet durch User
Mario A. schrieb: > Audio-Daten über Audioanschluss einlesen, filtern und anschließend per > Audioanschluss wieder ausgeben (in Echtzeit). OK, du willst das Audio also wieder als Audio ausgeben mit diesem FPGA Board. Gut, dann solltest du in der Tat herausfinden wie man über diesen Codec Audio aufnimmt/einliest und wie man es über diesen Codec auch wieder ausgibt. Das Einlesen kannst du ja schon. Klappt es denn auch Audio auszugeben? Z. B. einen Sinus den du im FPGA erzeugst? Mario A. schrieb: > Die Funktion der Filter > kann ich einfach mit dem Analog Discovery 2 überprüfen > (Frequenzgangsmessung mit Sinussweeps). Naja, das ist zwar praktisch, aber ich würde das Filter mit einem Filterdesigner wie Pyfda entwerfen und dann im Simulator (z. B. dem in Vivado) testen ob es auch funktioniert. Auf die Hardware würde ich nur im letzten Schritt gehen. Mario A. schrieb: > Wäre es dann aus deiner Sicht sinnvoller die gefilterten Daten mittels > UART (FT232R) oder PC-FPGA Data Transfer DPTI/DSPI (FT2232) an den PC zu > schicken (siehe Bilder)? Hm, kommt drauf an was du mit dem Audio machen willst. Eigentlich musst du dir das ja nicht angucken. Den Frequenzgang und so Filtereigenschaften zeigt dir der Filterdesigner und ob das auch so funktioniert siehst du in der Simulation. Mario A. schrieb: > Den Codec muss ich nicht speziell konfigurieren. Es reicht, wenn ich ein > paar Abtastraten (16 kHz, 32 kHz, 48 kHz) einstellen kann. Du willst aber ja auch gefiltertes Audio ausgeben. Kannst du das schon? Das hier itse_me_mario schrieb: > Als erstes möchte ich den LINE IN Input direkt an den HP OUT Ausgang > weitergeben. würde ich nicht machen. Weil du das ja später nicht brauchst. Ich würde als Ziele definieren: 1. Audio ausgeben über den Codec. Und zwar nicht das Audio vom Line Eingang (weil du dafür den Codec irgendwie konfigurieren müsstest), sondern z. B. einen Sinus den du im FPGA erzeugst. 2. Audio mit dem Codec einlesen. 3. Filter entwerfen mit dem Filterdesigner. 4. Filter mit Vivado oder so simulieren. Du kannst für das Filter den Xilinx IP verwenden, den FIR Compiler. Da wirfst du nur die Koeffizienten rein und das filtert dann sehr fein, kann man auch simulieren. In der Simulation, also der Testbench, erzeugst du dir den Sinussweep. 5. Alles zusammenleben und auf die Hardware bringen.
Hallo Gustl, nochmal danke für deine Antwort. Manches ist mir allerdings noch unklar. Warum kann ich nicht mit dem o.g. Modul mein Audio einlesen, es bearbeiten (z.B. FIR-Filtern) und wieder über den Line Out ausgeben? Das sollte doch funktionieren? Oder versteh ich dich gerade falsch? The Digilent Pmod I2S2 (Revision A) features a Cirrus CS5343 Multi-Bit Audio A/D Converter and a Cirrus CS4344 Stereo D/A Converter, each connected to one of two audio jacks. These circuits allow a system board to transmit and receive stereo audio signals via the I2S protocol. The Pmod I2S2 supports 24 bit resolution per channel at input sample rates up to 108 kHz and output sample rates up to 200 kHz. Quick Start To set up a simple 44.1 kHz audio passthrough, three control signals need to be generated by the host system board. 1. A master clock (MCLK) at a frequency of approximately 22.579 MHz. 2. A serial clock (SCLK), which fully toggles once per 8 MCLK periods. 3. A Left/Right Word Select signal, which fully toggles once per 64 SCLK periods. >>Das Einlesen kannst du ja schon. Ich habe bisher noch nichts eingelesen. Für den Filterentwurf verwende ich Matlab. Welchen Vivado Simulator meinst du? Einen graphischen? Oder in der Testbench? >>Eigentlich musst du dir das ja nicht angucken. Bei normalen IIR- und FIR-Filtern nicht. Für das adaptive Filter muss ich den Ausgang schon betrachten. Das ist für die anschließende Auswertung (ERLE-Kurven) wichtig. Dafür brauch ich die Werte. >>Du willst aber ja auch gefiltertes Audio ausgeben. Kannst du das schon? Nein, dafür will ich ja das Bauteil (mit AD und DA Wandlern) verwenden: https://store.digilentinc.com/pmod-i2s2-stereo-audio-input-and-output/ Halt du hast das Bauteil, welches ich verwenden will dabei nicht einbezogen, oder? Ich habe nämlich deine Nachricht um 11.49 Uhr übersehen. Entschuldigung... Also nochmal zusammenfassend: - ich möchte Audiosignale über einen Audioanschluss einlesen - ich möchte das Signal filtern - ich möchte das gefilterte Signal anschließend über einen Audioanschluss ausgeben - später (für das adaptive Filter) würde ich gerne die gefilterten Werte zus. an den PC senden.
:
Bearbeitet durch User
Mario A. schrieb: > Warum kann ich nicht mit dem o.g. Modul mein Audio einlesen, es > bearbeiten (z.B. FIR-Filtern) und wieder über den Line Out ausgeben? Das > sollte doch funktionieren? Oder versteh ich dich gerade falsch? Du meinst dieses PMOD Teil? Klar. Aber wieso? Der audio Codec auf deinem FPGA Board sollte das auch können. Also würde ich mit diesem Codec schrittweise dem Ziel näher kommen. Zuerst damit Audio einlesen. Dann damit Audio ausgeben. Dann das mit dem Filter dazwischen versuchen. Mario A. schrieb: > Ich habe bisher noch nichts eingelesen. Du hast also noch nicht mit dem Codec auf dem FPGA Board Audio eingelesen? Dann würde ich das als erstes Zwischenziel setzen. Mario A. schrieb: > Für den Filterentwurf verwende ich Matlab. Welchen Vivado Simulator > meinst du? Einen graphischen? Oder in der Testbench? Welcher Simulator ist eingentlich egal. Er sollte aber deine Hardwarebeschreibung simulieren können. Die Testbench füttert das Filter mit einem Sweep und gibt dann das Ergebnis aus. Mario A. schrieb: > Für das adaptive Filter muss > ich den Ausgang schon betrachten. Das ist für die anschließende > Auswertung (ERLE-Kurven) wichtig. Dafür brauch ich die Werte. Um so besser, das kann man in der Simulation wunderbar sehen. Mario A. schrieb: > Nein, dafür will ich ja das Bauteil (mit AD und DA Wandlern) verwenden: > https://store.digilentinc.com/pmod-i2s2-stereo-audio-input-and-output/ Ja, das kannst du dafür nutzen. Aber warum das und nicht den Codec der auf dem FPGA Board sitzt? Der sollte das doch ebenfalls können? Also eigentlich ist das natürlich egal, nimm das was leichter aussieht. Ich bin selber eher gegen Zusatzhardware wenn das sowieso schon auf dem Board drauf ist. Mario A. schrieb: > Also nochmal zusammenfassend: > - ich möchte Audiosignale über einen Audioanschluss einlesen > - ich möchte das Signal filtern > - ich möchte das gefilterte Signal anschließend über einen > Audioanschluss ausgeben > - später (für das adaptive Filter) würde ich gerne die gefilterten Werte > zus. an den PC senden. Wunderbar. Dann würde ich zuerst das Einlesen alleine ans Laufen bekommen. Dann das Ausgeben alleine. Und dann das Filter. Die Verbindung mit dem PC würde ich aber ganz an den Anfang stellen. Du nimmst im FPGA etwas Speicher. Z. B. 64 kByte BRAM. Dann nimmst du Audio auf und schreibst das in diesen Speicher. Dann liest du den Speicher aus und guckst am PC ob das Signal OK ist. Für die Ausgabe kannst du dir im FPGA einen Sinus erzeigen und den über den Line out ausgeben lassen und angucken.
Danke für die schnelle Antwort! >> Aber wieso? Weil das ursprüngliche Framework ja leider nicht funktioniert und ich den Fehler nicht finde. Die I2C-Initialisierung entfällt dadurch zusätzlich und ich kann mein eigenes Framework schreiben. >>Du hast also noch nicht mit dem Codec auf dem FPGA Board Audio eingelesen? Dann würde ich das als erstes Zwischenziel setzen. Naja das sagst du so leicht. :P Aber wenn der Codec nicht funktioniert und ich den Fehler einfach nicht finde, wird das schwierig. :D :D >>Die Testbench füttert das Filter mit einem Sweep und gibt dann das Ergebnis aus. Eine graphische Ausgabe wäre hierfür natürlich schön, aber mans kann´s natürlich auch so leicht überprüfen, wenn man sich ein kleines C-Programm (mit demselben Filter) schreibt und sich die Ergebnisse ausgeben lässt. >>Um so besser, das kann man in der Simulation wunderbar sehen. Genau. Und für weitere Matlab-Berechnungen/-Auswertungen brauche ich die Daten am PC. >>Ich bin selber eher gegen Zusatzhardware wenn das sowieso schon auf dem Board drauf ist. Da stimme ich dir zu 100% zu. Aber leider bin ich nun seit über 2 Monaten dran ein Framework aus dem Internet zu Debuggen/zum Laufen zu bringen und es funktioniert immer noch nicht. Wenn ich dann selber "nur" noch ein I2S-Interface schreiben muss (so scheint es zu sein, wenn ich die externe Hardware verwende), erleichtert das die Fehlersuche doch enorm. >>Dann würde ich zuerst das Einlesen alleine ans Laufen bekommen. Dann das Ausgeben alleine. Und dann das Filter. Das wäre der Plan.
Mario A. schrieb: > Weil das ursprüngliche Framework ja leider nicht funktioniert und ich > den Fehler nicht finde. Die I2C-Initialisierung entfällt dadurch > zusätzlich und ich kann mein eigenes Framework schreiben. Ich würde das "Framework" nicht nutzen, das sieht nicht wirklich gut aus. Der Codec ist doch ordentlich dokumentiert, die IOs am FPGA sind klar, da kann man schon selber was schreiben das aus dem Codec die Audiowerte rausholt. Mario A. schrieb: > Aber wenn der Codec nicht funktioniert > und ich den Fehler einfach nicht finde, wird das schwierig. :D :D Klar funktioniert der Codec. Du stocherst da ziemlich im Nebel. Ich würde als Anfangspunkt mal die Demo vom Hersteller Digilent nehmen. Da wird Audio mit dem Codec erfasst und ins RAM geschrieben. Den Teil mit dem RAM und so würde ich weglassen oder eben in einen kleinen BRAM Speicher schreiben und dann über UART zum PC ausgeben. Mario A. schrieb: > Eine graphische Ausgabe wäre hierfür natürlich schön, aber mans kann´s > natürlich auch so leicht überprüfen, wenn man sich ein kleines > C-Programm (mit demselben Filter) schreibt und sich die Ergebnisse > ausgeben lässt. Natürlich mit graphischer Ausgabe. Das macht der Vivado Simulator wunderbar. Mario A. schrieb: > Genau. Und für weitere Matlab-Berechnungen/-Auswertungen brauche ich die > Daten am PC. Klar, da hast du die auch. Sowohl bei der Simulation mit Vvado, auch da kannst du die gefilterten Werte wegschreiben für Matlab. Als auch mit dem UART. Da kannst du dir die Abtastwerte vom FPGA schicken lassen und dann am PC weiterverarbeiten/untersuchen. Mario A. schrieb: > Aber leider bin ich nun seit über 2 > Monaten dran ein Framework aus dem Internet zu Debuggen/zum Laufen zu > bringen und es funktioniert immer noch nicht. Das verstehe ich. Aber ich finde es ist deutlich schwerer etwas zu debuggen was man nicht selbst geschrieben hat als etwas von Null an neu zu schreiben. Wobei jetzt erstmal die Frage ist ob du den Codec auf dem Board nutzen solltest oder einen anderen IC. Der Codec auf dem Board kann ziemlich viel. Im Datenblatt https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1761.pdf ist eine Registerübersicht am Ende. Da müsstest du abschätzen wie aufwändig das wird. Oft muss man nur wenige Register beschreiben weil die Register oft sinnvolle/passende Defaultwerte haben. Das müsstest du nachgucken. Dann ist auch zu rüfen ob du die Registerwerte selber herausfinden musst, oder ob dir da eine Software helfen kann. Da gibt es das Sigmastudio https://www.analog.com/en/design-center/evaluation-hardware-and-software/software/ss_sigst_02.html#software-overview das kenne ich nicht. Aber vielleicht kannst du da den Codec auswählen, die Einstellungen machen die du haben willst, also Ausgeben/Einlesen und dann wirft dir das den Inhalt der Register aus den du in die Register schreiben musst. Ich weiß nicht ob das so ist, würde ich aber mal angucken. Es kann auch sein, dass alle Register schon sinnvolle Defaultwerte haben, dann würde es reichen ADC_SDATA/GPIO1 DAC_SDATA/GPIO0 LRCLK/GPIO3 und BCLK/GPIO2 zu bespaßen. Also über ADC_SDATA/GPIO1 kommt das Audio vom Codec und über DAC_SDATA/GPIO0 schickst du Audiowerte zum Codec. LRCLK/GPIO3 sagt dir ob das links oder rechts ist und BCLK/GPIO2 ist der Takt. MCLK muss natürlich auch anliegen. Zitat Digilent: ------------------------------------------------------ At the very least an audio-aware FPGA design should do the following: Provide MCLK for the audio codec. Use an I2C master controller to configure the core clocking, sample rates, serial interface format and audio path. Send or receive audio samples over the serial audio data channel for playback or record. More advanced users might want to try additional features of the ADAU1761. For example, the on-chip SigmaDSP core can be programmed to do user-defined digital signal processing. ------------------------------------------------------ Aber ja, andere Codecs sind da vielleicht leichter zu verwenden wenn du die vielen Features nicht brauchst. Ich würde also mal versuchen selbst eine passende Hardwarebeschreibung zu bauen um dem Codec Abtastwerte zu entlocken. Für einen ersten Test kannst du die Abtastwerte ja als PWM auf einem IO Pin ausgeben und glätten. Dann siehst du zumindest ob Audio ankommt auch wenn es nicht ideal klingt.
Zu dem Filter und der Simulation: Im Anhang ist ein Bildchen wie das im Filterdesigner aussieht, bei dir wäre das dann Matlab. Dann ein Bildchen der Simulation. Die dauert hier lange (lange Zeit die simuliert werden muss) weil ich die Samplerate auf 44.1 kHz gesetzt habe. Der Xilinx IP braucht dann nur einen Multiplizierer bei den 256 Filterkoeffizienten. Ausserdem sieht das nicht sehr toll aus, weil hier nur 64 Werte für die Sinustabelle verwendet werden. Das reduziert aber die Simulationszeit. Für eine schnellere Simulation müsste man mit einer höheren Frequenz Abtastwerte an das Filter übergeben, dau aber auch dem Filter die höhere Abtastfrequenz mitteilen. Dann würde das Filter mit mehr Multiplizierern gebaut werden. In dem ZIP ist das Vivado Projekt drinnen. Da kommen die Abtastwerte von der Testbench und gehen gefiltert in die Testbench. Du müsstest das ersetzen durch eine Beschreibung um die Werte vom Codec einzulesen und über den Codec oder/und einen UART auszugeben. Aber auch das kann man erst mal simulieren.
Ich hab diesen Thread seit einiger Zeit mitgelesen, mir das Datenblatt vom ADA1761 angeschaut - und gedacht: oha - was für ein Overhead, um ein paar Audio-Daten auszugeben. Der CS4344 (der Codec auf dem PmodI2S) dagegen ist ein "schlanker" IC, ohne I2C-Konfiguration und mit frei wählbarer MCLK bzw. Datenrate bis 200 kSp/s. Von daher halte ich die Idee erstmal mit einem externen Pmod weiterzumachen durchaus für sinnvoll. Mein I2S-Interface für den CS4344 habe ich vor ein paar Jahren entwickelt und fand das ziemlich straight-forward. Extrem hilfreich war dabei, dass ich meinen Logic-Analysator direkt an die Pmod-Pins hängen konnte - bei dem intern verbauten AD1761 müsstest Du dazu den "Debug-Output" herausführen. Just my 2 cent.
:
Bearbeitet durch User
Naja, der Codec auf dem Board kann auch anscheinend laut Digilent ohne Konfiguration betrieben werden. Dann kann man über den seriellen Port sowohl Daten vom ADC abholen als auch über den DAC ausgeben. Aber ja, das Datenblatt https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1761.pdf ist eher schlecht. Auf Seite 42/43 ist der serielle Port beschrieben: Register R15 and Register R16 (serial port control registers, Address 0x4015 and Address 0x4016) allow control of clock polarity and data input modes. The valid data formats are I2S, left-justified, right-justified (24-/20-/18-/16-bit), and TDM. Tja aber wo stelle ich das in den Registern ein? Da finde ich diese Einstellung zu den Input Modes nicht. Dann ist in Register 58 und 59 jeweils der ADC zum DSP und der DSP zum DAC geroutet. Macht ja auch Sinn wenn man den DSP verwenden möchte, aber der DSP ist per Default aus R61/R62. Bekommt also der DAC die Daten vom seriellen Port oder muss ich dazu entweder den DSP einschalten oder das Routing umkonfigurieren? Und bekommt der serielle Post das Audio vom ADC ohne aktiven DSP und mit Defaultrouting? Also ja, viel Overhead, aber vielleicht trotzdem einfach zu benutzen. Digilent hat dieses Demoprojekt: https://reference.digilentinc.com/learn/programmable-logic/tutorials/genesys-2-dma-audio-demo/start Da kann man auf Knopfdruck Audio aufnehmen und über UART zum PC schicken. Anders herum kann man vom PC über UART Audio ausgeben. Für mich sieht das reichlich komplex aus. Ja, das mag man so machen mit AXI hier und uBlaze dort, aber das ginge auch einfacher. Die Beschreibung für den seriellen Port ist hier: https://github.com/Digilent/Genesys-2-DMA/blob/master/repo/local/ip/d_axi_i2s_audio_v2_0/src/i2s_ctl.vhd Ob der Codec zusätzlich noch konfiguriert wird weiß ich nicht, könnte aber gut sein. Burkhard K. schrieb: > Extrem hilfreich war > dabei, dass ich meinen Logic-Analysator direkt an die Pmod-Pins hängen > konnte - bei dem intern verbauten AD1761 müsstest Du dazu den > "Debug-Output" herausführen. Das ist vielleicht gar nicht so verkehrt die Idee. Er könnte mal diese Demo von Digilent auf das Board laden und gucken ob das Konfiguratonsinterface für den Codec überhaupt verwendet wird. Also Oszi direkt beim Start mit Normaltrigger ranhalten an SCL/CCLK Pin 32. Und wenn sich da nix tut, dann kann er sich noch den seriellen Port, die Pins 26, ... , 29 angucken. Da sieht er wie Audio übertragen wird.
:
Bearbeitet durch User
Vielen Dank euch! @Gustl Vielen Dank für die Simulationsbilder. Jetzt weiß ich was du gemeint hast. :) Ich steh ab und zu auch ein bisschen aufm Schlauch. >>Ich würde das "Framework" nicht nutzen, das sieht nicht wirklich gut aus. War wohl etwas naiv zu glauben, dass es nach ein paar Anpassungen einwandfrei funktioniert. Eigentlich schreibe ich auch immer gerne meinen eigenen Code. Allerdings stammt das überarbeitete Framework auch von einer Uni und ich dachte das wird schon funktionieren. Höchstwahrscheinlich funktioniert es auch, nur hab ich scheinbar irgendwo etwas falsch gemacht, auch wenn der Fehler nicht ganz offensichtlich ist (zumindest für mich). >>Aber ja, andere Codecs sind da vielleicht leichter zu verwenden wenn du die vielen Features nicht brauchst. Genau. Wenn ich doch noch den ADAU verwenden will, brauche ich erst mal wieder einen I2C Mastercontroller. Auf Digikey gibt es an sich ein Modul, welches einen guten Eindruck macht. Das wollte ich damals schon fast verwenden, aber dann bin ich auf das Zedboard-Framework gestoßen. Das Datenblatt des ADAUs ist teilweise echt sehr unpräzise formuliert. Ich habe es schon mehrmals durchgelesen und trotzdem sind mir noch einige Dinge unklar... Die Initialisierung über Sigma Studio kann funktionieren, oder eben wieder Probleme machen. Ich hätte gerne erst mal so wenige ? wie möglich. Was ich aktuell möchte, ist eine schnelle Lösung, die meine Anforderungen erfüllt. Das PMOD-Modul scheint hierbei die einfachste Möglichkeit zu sein. Was mir auch sehr gefällt ist die Option, dieses Modul auch auf anderen Boards zu verwenden.
Mario A. schrieb: > Das PMOD-Modul scheint hierbei die einfachste > Möglichkeit zu sein. Was mir auch sehr gefällt ist die Option, dieses > Modul auch auf anderen Boards zu verwenden. Ah! Ich dachte du wärst auf dieses eine Board festgelegt. Klar wenn du das nicht bist, dann nimm das PMOD Teil. Dazu gibt es bestimmt auch Code bei Digilent. Mario A. schrieb: > Wenn ich doch noch den ADAU verwenden will, brauche ich erst mal > wieder einen I2C Mastercontroller. Vielleicht nein. Vielleicht reicht es aus diesen seriellen Port zu bedienen mit den 4 Signalen + MCLK.
>> Vielleicht nein. Vielleicht reicht es aus diesen seriellen Port zu
bedienen mit den 4 Signalen + MCLK.
Naja spätestens wenn ich eine andere Abtastrate einstellen will, komm
ich nicht drum herum, denke ich.
Ich kann das Board hernehmen, muss es aber nicht. Das PMOD-Modul werde
ich erstmal an das Genesys 2 anbinden, da es einfach mehr DSP-Slices hat
für die spätere Performancemessung.
Alles klar. ;) Kein Problem. Ich hoffe, dass die Module diese Woche noch
kommen.
Mario A. schrieb: > Das PMOD-Modul werde > ich erstmal an das Genesys 2 anbinden Hallo Mario, ich hab mal meinen alten Code für den CS4344/PmodI2S angehängt. Ist schon eine Weile her und der Controller ist insofern speziell, als das ich zwischen 4 verschiedenen, nicht Standard-Samplerates umschalten kann (200/100/50/25 kSp/s per Signal "sr_sel"). Zu beachten ist natürlich, dass der Controller in einer eigenen Takt-Domäne läuft, d.h. die eingehenden Daten und umgekehrt die ausgehenden Statussignale (l_txd, r_txd) müssen in die jeweilige Domäne einsynchronisiert werden. In meiner damaligen Anwendung habe ich das (in einem Wrapper) für die Daten mit einem asynchronen FiFo gemacht. Testdaten lassen sich mit einer einfachen Sinus-LUT oder einem NCO generieren. Ist wie gesagt alter Code (den ich heute wohl anders schreiben würde) - und noch mit ISE entwickelt - d.h. keine AXI-Anbindung.
:
Bearbeitet durch User
Hallo, danke für deine Dateien! Ich werde sie mir die Tage mal ansehen.
Soo ein I2S-Interface habe ich heute eingebunden und getestet: Es scheint auf den ersten Blick zu funktionieren. Ich habe das Interface aus dem ursprünglichen Framework (i2s_data_interface) verwendet. Wenn ich die Hardware habe und es funktioniert (oder nicht :D) dann lade ich euch den Code hoch. Ich habe einen MCLK von 8,192 MHz, einen LRCK von 32 kHz und einen SCLK von 2,048 MHz verwendet. Dafür habe ich den MCLK mit dem Clocking Wizard erzeugt. Die anderen beiden Clocks habe ich davon abgeleitet (clock divider): entity clock_divider_4 is port( CLK_IN : IN STD_LOGIC; RESET : IN STD_LOGIC; CLK_OUT : OUT STD_LOGIC ); end clock_divider_4; architecture Behavioral of clock_divider_4 is begin process(CLK_IN,RESET) VARIABLE COUNT : integer :=0; VARIABLE TEMP : std_logic := '0'; begin if RESET ='1' then count := 0; temp := '0'; elsif rising_edge(clk_in) then count := count+1; if count = 2 then -- count = 2 --> :4, 4 --> :8, 8 --> : 16, ... 32 --> : 64 temp := not temp; count := 0; end if; end if; clk_out <= temp; end process; end Behavioral;
:
Bearbeitet durch User
Gustl B. schrieb: > so wie ich das > verstanden habe möchtest du Audio vom ADA1761 bekommen, durch einen FIR > Filter schicken und dann irgendwie weiterverarbeiten. und so wie ich es verstanden habe, möchte er mit 16kHz arbeiten. Kann der ADC das überhaupt?`Oder muss man da nicht auch mit einer "offiziellen" Audiorate ran? Also z.B. 48000?
Ob 16 kHz möglich sind, ist mir auch noch nicht völlig klar. 32 kHz gehen auf jeden Fall (laut Datenblatt). Hierfür sind die Einstellungen für MCLK und SCLK gegeben. Wenn es jetzt 32 kHz werden ist es auch erst einmal kein Problem. Aber es wäre schon cool, wenn auch kleinere Abtastraten gehen würden.
:
Bearbeitet durch User
Hallo zusammen, heute ist der I2S-PMOD-Adapter gekommen! Mein Interface scheint zu funktionieren (laut Logic Analyzer und Kopfhörern). Wichtig war auch hier die Clocks "asynchron" zu setzen. Über die Kopfhörer höre ich nun endlich die Musik vom IPod (allerdings verrauscht --> evtl. Sättigung wegen den 11 dB Offset im Frequenzgang). Die Frequenzgangmessung mit dem Analog Discovery liefert ein typisches tiefpassähnliches Verhalten. Trotz Warning funktioniert der ILA. Im Anhang befindet sich ein Screenshot ohne s_audio_l_in <= (others => '0'); und s_audio_r_in <= (others => '0'); und ein Screenshot mit. Erst habe ich im Process die Signale s_audio_l_in und s_audio_r_in immer auf 0 gesetzt und mich gewundert, warum ich nichts höre... :P process (s_clk_100_MHz) begin if (s_clk_100_MHz'event and s_clk_100_MHz = '1') then s_hphone_valid <= '0'; -- s_audio_l_in <= (others => '0'); -- s_audio_r_in <= (others => '0'); if s_new_sample = '1' then s_counter <= s_counter + 1; s_hphone_valid <= '1'; s_audio_l_in <= s_audio_l_out; s_audio_r_in <= s_audio_r_out; end if; end if; end process; Ich muss noch rausfinden, wo dieser Offset im Frequenzgang herkommt. Wird ja vermutlich irgendwo im Datenblatt stehen. Außerdem möchte ich testen, ob auch 16 kHz (Abtastrate) möglich sind. Vielen Dank nochmal an alle für die tolle Hilfe! Als nächsten Schritt binde ich mein FIR-Filter ein. Danach möchte ich den I2C Mastercontroller von Digikey verwenden, um den Codec des Zybo Z7020 zu initialisieren. Dieser ist nicht so umfangreich und man muss kaum etwas initialisieren. Wenn das funktioniert, will ich den Codec auf dem Genesys 2 zum laufen bringen.
:
Bearbeitet durch User
Hier noch das XDC-File.
Mario A. schrieb: > Über die Kopfhörer höre ich nun endlich die Musik vom IPod (allerdings > verrauscht --> evtl. Sättigung wegen den 11 dB Offset im Frequenzgang). 11 dB Offset? Eher 11 dB Verstärkung. Du kannst ja das Eingangssignal mal durch vier teilen und gucken ob es dann passt. > Trotz Warning funktioniert der ILA. Manchmal macht einem der ILA das Timing kaputt, vielleicht kommen die Störungen daher. > if (s_clk_100_MHz'event and s_clk_100_MHz = '1') then Wo lernt man denn so altmodisches VHDL? Die Funktion rising_edge() gibt es meines Wissens seit VHDL'93... > Ich muss noch rausfinden, wo dieser Offset im Frequenzgang herkommt. Sind die Wortbreiten identisch? Was zeigt das Analog Discovery an, wenn Du direkt den Eingang mit dem Ausgang verbindest? Duke
>>11 dB Offset? Eher 11 dB Verstärkung. Du kannst ja das Eingangssignal mal durch vier teilen und gucken ob es dann passt. Ja es ist aber ein 11 dB Offset zur 0 dB Linie. :) Natürlich passt es dann, wenn ich es manuell rausrechne, aber mich interessiert noch woher genau die Verstärkung kommt. Das wird sicher im Datenblatt zu finden sein. Ist auch erst mal egal. >>Manchmal macht einem der ILA das Timing kaputt, vielleicht kommen die Störungen daher. Gerade habe ich es so implementiert, dass keine 11 dB Verstärkung auftritt und ohne ILA. Leider ist das Signal immer noch verrauscht. Trotzdem danke für den Tipp. mit s_audio_l_in <= std_logic_vector(shift_right(unsigned(s_audio_l_out, 2)); s_audio_r_in <= std_logic_vector(shift_right(unsigned(s_audio_r_out, 2)); bleiben dann noch ca. -0.8 dB im Frequenzgang. >>Wo lernt man denn so altmodisches VHDL? Old but gold. :P Ist doch eh völlig egal, welche Funktion ich dafür verwende. Sollte jedem bekannt sein. >>Sind die Wortbreiten identisch? Die Wortbreiten sollten identisch sein. >>Was zeigt das Analog Discovery an, wenn Du direkt den Eingang mit dem Ausgang verbindest? 0 dB. Danke dir, Gruß Mario
Ich bin mir noch nicht ganz sicher, ob der Frequenzgang wirklich passt. Laut Datenblatt sollte der Frequenzgang nicht schon so früh abfallen (siehe Screenshot_TT). Als ich mal mein FIR-Filter eingebunden habe, kam seltsamerweise derselbe Frequenzgang raus. Ich werde nochmal die ganzen Taktraten und Anschlüsse prüfen. Vielleicht verwende ich das I2S-PMOD Interface auch mal im Master-Mode. Heute habe ich einen Zwischenstecker für das PMOD-I2S bekommen und kann so die Signale mit dem Analog Discovery messen. Allerdings schaffe ich es erst wieder am Mittwoch weiterzuarbeiten. Gruß Mario
:
Bearbeitet durch User
Mario A. schrieb: >>>Manchmal macht einem der ILA das Timing kaputt, vielleicht kommen die > Störungen daher. > Gerade habe ich es so implementiert, dass keine 11 dB Verstärkung > auftritt und ohne ILA. Wenn das Timing getroffen wird, macht der ILA keinen Ärger. Wenn der ILA aber drin ist und etwas nicht geht, dann fehlen da constraints.
ach ja, an dem ADU Interface muss noch gearbeitet werden, meine ich :-) Bissl wenig drinne ...
Hi,
danke für deine Antwort! Ich arbeite gerade an einer Testbench für das
Audio-Interface. Ich habe mein FIR-Filter dafür schon eingebunden.
Irgendetwas stimmt auf jeden Fall noch nicht. Ich habe ein paar
verschiedene Filter getestet und manchmal stimmt der Frequenzgang so in
etwa... :P Mal sehen, ob ich den Fehler finde.
>>ach ja, an dem ADU Interface muss noch gearbeitet werden, meine ich
Meinst du da etwas spezielles?
Ich lade nun mal die Ergebnisse des Talkthroughs hoch. Ich habe i2s_data_interface.vhd noch angepasst (Grund: siehe Timing_neu): Hierfür wurde if i2s_lr = '1' and i2s_lr_last = '0' then in if i2s_lr = '0' and i2s_lr_last = '1' then geändert. Die Eingangsdaten s_AD_SDOUT für beide Channels habe ich simuliert (1, 2, 3, 4). Ich denke am Ausgang s_DA_SDIN müsste der Wert um einen SCLK früher auf 1 gesetzt werden. Vllt liegt das aber auch an meiner Simulation. Wenn man i2s_d_out <= sr_out(sr_out'high) in i2s_d_out <= sr_out(62) ändert, wird der Wert 1 SCLK früher ausgegeben. Mein Filter (welches in diesem Fall auskommentiert ist) arbeitet mit 16 Bit Daten (den 16 MSBs des Audio-Signals). Deshalb sind 16 Bit Signale enthalten. Nach dem Filtern sehe ich mir das Vorzeichen an und führe dann eine Vorzeichenerweiterung aus. D.h. die 16 LSBs des Audiosignals enthalten das Filterergebnis und die Bits 23-17 enthalten lediglich das VZ.
:
Bearbeitet durch User
Hallo zusammen, ich stehe gerade auf der Leitung. Vllt kann mir ja jemand helfen. Irgendwie erhalten die Werte in meinem Array a_sop (Sum of Products) zwischenzeitlich falsche Werte (siehe FehlerhafteWerte.png und Zoom.png). Eigentlich sollte es so aussehen wie in Richtig.png. Irgendetwas stimmt da mit dem Timing nicht und ich komm gerade nicht drauf was falsch ist... Der Screenshot Richtig.png stammt aus der Testbench des FIR-Filters allein (vorheriges Projekt, welches funktioniert). Vom Prinzip her wird das Filter in gleicher Weise genutzt. Wenn s_hphone_valid <= '1' ist werden die 16 MSB´s des Audiosignals in das parallele Datenregister (reg_par) geladen. Diese Daten werden von den einzelnen Multiply Adder Blöcken (für jeden Koeffizienten wird 1 Block benötigt) verwendet. Die Berechnung der Multiply Adder Blöcke wird mit s_ready_1 gestartet. Anschließend werden die 16 Bits des 48 Bit Ergebnisses in a_sop(0) (-> zus. Guard-Bits) extrahiert und wieder über ein paralleles Datenregister ausgegeben (wenn s_ready_2 = '1') ist. Ich würde mich sehr freuen, wenn mir jemand helfen könnte. Vielen Dank im Voraus!
:
Bearbeitet durch User
Mario A. schrieb: > Irgendwie erhalten die Werte in meinem Array a_sop (Sum of Products) > zwischenzeitlich falsche Werte (siehe FehlerhafteWerte.png und > Zoom.png). Nein, XXXXX bedeutet nicht falsche Werte, sondern ein Konflikt. Verwendest du irgendwo in deinem Design einen FIFO von Xilinx? Oder sonst Xilinx IP? Wenn ja: Die (also mache der IPs) brauchen einen Reset am Anfang. Ja, für die Simulation. Auf der Hardware laufen die auch ohne Reset wunderbar.
RTLFIRFilter.png veranschaulicht nochmal das eben beschriebene. Den 10
MHz Process für die Erzeugung von s_fs_tic_16_kHz gibt es nicht mehr.
Anstelle von s_fs_tic_16_kHz wird nun hphone_valid verwendet.
>>Nein, XXXXX bedeutet nicht falsche Werte, sondern ein Konflikt.
Danke Gustl!
Ja ich verwende die Multiply Adder Blöcke, den Clocking Wizard, den ILA
und Block Memory Generator.
Hm das ist aber seltsam, weil ich dieselben IPs auch in meinem
FIR-Projekt verwendet habe und da scheint alles zu funktionieren... Nur
der ILA ist neu.
:
Bearbeitet durch User
Du kannst in der Simulation auf das Signal klicken, Rechtsklick und dann Report Drivers. Da siehst du die verschiedenen Treiber die im Konflikt sind. Guck dir das mal an. Mario A. schrieb: > Multiply Adder Blöcke, den Clocking Wizard, den ILA > und Block Memory Generator. Also der Clocking IP braucht einen Reset für die Simulation, aber nur wenn du den Takt an dessen Eingang änderst. Den ILA habe ich noch nie verwendet weil wenn es in der Simulation läuft und das Timing passt, dann läuft es auch auf der Hardware. Der BRAM braucht keinen Reset.
Hallo Gustl, danke für den Tipp. In meinem anderen Projekt hatte der Clocking Wizard tatsächlich einen Reset. Den habe ich nun auch hinzugefügt. Leider sieht die Simulation noch immer gleich aus... Report Drivers hat ergeben: : Driver Encrypted process: no data available 0 : Net /tb_AudioInterface/uut/FIR_Left_Channel/a_sop[0][46] : Driver Encrypted process: no data available 0 : Net /tb_AudioInterface/uut/FIR_Left_Channel/a_sop[0][45] : Driver Encrypted process: no data available 0 : Net /tb_AudioInterface/uut/FIR_Left_Channel/a_sop[0][44] ... (siehe Anhang) Eigentlich müssten die Daten anlegen (siehe FehlerhafteWerte_neu2)... Theoretisch hätte der Block Memory Generator noch einen Reset, aber beim anderen Projekt hat es auch so funktioniert.
Jetzt hab ich nochmal was versucht... Aber das Ergebnis ist wieder dasselbe. Außerdem habe ich nochmal die funktionierende FIRFilter.vhd-Datei eingebunden und lediglich die Signale der Parallelregister und der FSM entsprechend angepasst. Hat nichts gebracht. Zur Übersichtlichkeit habe ich mal das RTL von AudioInterface angehängt.
:
Bearbeitet durch User
Nun, ich verstehe das nicht ganz. Du hast einen Strom aus Abtastwerten. Die fütterst du in den FIR und bekommst dahinter wieder einen Strom aus gefilterten Abtastwerten. Ich verstehe nicht wieso das Format von a_sop 2D ist und nicht 1D. Ich hätte da einfach nur einen SLV erwartet aber kein Array aus SLVs. Was ist das genau und warum hast du das Array? Sinnvoll wären auch Screenshots deiner Einstellungen im FIR IP Compiler. Oder hast du den FIR selbst geschrieben? Ach so, ich finde a_sop nicht in deinem Überblick-Bildchen, ist das also ein internes Signal im FIR?
:
Bearbeitet durch User
>>Was ist das genau und warum hast du das Array? Da sind alle Werte des Filters enthalten (für jeden Koeffizienten 1 Wert). Dies ist für die transponierte Direktform notwendig. >>Sinnvoll wären auch Screenshots deiner Einstellungen im FIR IP Compiler. >>Oder hast du den FIR selbst geschrieben? Das FIR habe ich selbst geschrieben. >>Ach so, ich finde a_sop nicht in deinem Überblick-Bildchen, ist das Signal also ein internes Signal im FIR? Das Signal ist im FIRFilter-Modul. Ein einfaches Array.
:
Bearbeitet durch User
Ah, OK. Dann teste den FIR doch erstmal ohne den Rest. Also Testbench schreiben, den FIR mit einem Sweep füttern und gucken was rauskommt. Was macht der FIR bei dir noch alles? Sieht reichlich kompliziert aus ... Hier hatte ich FIR geschrieben: Beitrag "FIR parallel und seriell braucht zu viele LUTs." Mittlerweile nutze ich aber den FIR IP von Xilinx weil der sehr gut optimiert und weniger DSPs braucht.
Hi danke für deine Hilfe,
der Screenshot Richtig.png bezieht sich auf das FIR-Filter alleine (also
vorheriges Projekt). Ich füttere das Filter mit genau denselben Werten.
An sich sollte es also funktionieren.
>>Mittlerweile nutze ich aber den FIR IP von Xilinx weil der sehr gut
optimiert und weniger DSPs braucht.
Das wäre später definitiv auch eine Option. Mit AXI4-Anbindung quasi,
oder?
Mario A. schrieb: > Ich füttere das Filter mit genau denselben Werten. > An sich sollte es also funktionieren. Das mag sein, aber er funktioniert ja nicht wie er soll. Ist im FIR ein Xilinx IP der einen Reset brauchen könnte? Mario A. schrieb: > Mit AXI4-Anbindung quasi, > oder? Das ist kein richtiges AXI.
1 | component AD7960_FIR is Port( |
2 | aclk: in std_logic; |
3 | s_axis_data_tvalid: in std_logic; |
4 | s_axis_data_tready: out std_logic; |
5 | s_axis_data_tdata: in std_logic_vector(23 downto 0); |
6 | m_axis_data_tvalid: out std_logic; |
7 | m_axis_data_tdata: out std_logic_vector(15 downto 0)); |
8 | end component; |
Das legt man einen Abtastwert an und setzt ein Bit wenn der valide ist und auf der anderen Seite bekommt man einen gefilterten Wert und ein Bit das sagt wann der vailde ist.
>>Was macht der FIR bei dir noch alles? Sieht reichlich kompliziert aus
...
Als Eingang werden 16 Bit Daten verwendet (Q1.15: 1 VZ Bit und 15 für
den Nachkommaanteil). Die Koeffizienten sind ebenfalls 16 Bits groß
(Q1.15). Das Produkt zweier Q1.15 Zahlen ergibt eine Q2.30 Zahl (2 VZ
Bits und 30 Bits für den Nachkommaanteil).
Das Array a_sop enthält zus. Guard-Bits falls zwischenzeitlich ein
Überlauf auftreten sollte beim MAC-Befehl.
Anschließend wird das Ergebnis noch überprüft (ob es im gültigen
Wertebereich liegt). Wenn das Ergebnis zu groß oder zu klein ist wird es
gesättigt. Abschließend wird das Filterergebnis als Q1.15 Zahl wieder
ausgegeben.
>>Das mag sein, aber er funktioniert ja nicht wie er soll. Ist im FIR ein
Xilinx IP der einen Reset brauchen könnte?
Das vorherige Projekt schon. Nur nach den kleinen Änderungen und dem
Einfügen in das AudioInterface Projekt nicht mehr. Aber ich verstehe
einfach nicht warum. Woher kommen diese XXXX...XX es liegt immer ein
gültiger Wert an.
Also Clocking Wizard, Block Memory Generator und Multiply Adder sind
enthalten. Der Clocking Wizard hat mittlerweile einen Reset bekommen.
Soll ich dem Block Memory Generator auch einen Reset verpassen? Im
FIR-Projekt hat es auch ohne funktioniert.
:
Bearbeitet durch User
Hm, ich verstehe das Schaltbild nicht. Aber ganz grob: Du machst da was mit Audio, also sehr niedrige Frequenz. Da reicht dann eigentlich ein Multiplizierer. Oder bei dir brd_clk/Sample_clk ergibt die Anzahl dder maximal möglichen Koeffizienten die mit einem DSP möglich sind. Das läuft dann nicht parallel sondern seriell. So eine Beschreibung wird recht einfach ... Aber gut zu den XXXXXX, das ist ein Konflikt, also irgendwo wird dein Array von mehreren Treibern zeitgleich beschrieben.
Ich habe gerade für s_filter_input_data_l und s_filter_input_data_r konstante Werte angegeben (0x00FF). Das Phänomen bei a_sop tritt dann nicht mehr auf. Dann wirds ja doch was mit den beiden Signalen (welche als Eingang für das FIR dienen) zu tun haben. Nur was? :D
Mario A. schrieb: > Also Clocking Wizard, Block Memory Generator und Multiply Adder sind > enthalten. Der Clocking Wizard hat mittlerweile einen Reset bekommen. > > Soll ich dem Block Memory Generator auch einen Reset verpassen? Im > FIR-Projekt hat es auch ohne funktioniert. Huiuiui, das ist ziemlich viel Zeug für einen einfachen FIR. Der Clock und BRAM brauchen eigentlich für die Simulation keinen Reset - ausser du änderst den Eingangstakt vom Clock IP. Bei Multiply Adder habe ich keine Ahnung. Du kannst Multiplikationen auch einfach als * schreiben und BRAM als Array in VHDL, das sind beides IPs die ich nicht oft verwende.
:
Bearbeitet durch User
>>Du machst da was mit Audio, also sehr niedrige Frequenz. Da reicht dann
eigentlich ein Multiplizierer.
Ja später soll das auch für höhere Frequenzen dienen. Maximale
Ausnutzung der Parallelität ist eigtl. das Ziel, damit die Berechnung
schnellstmöglich erfolgen kann.
Ich würds dir auch gerne mal per Screensharing zeigen, wenn Interesse
besteht. :D
:
Bearbeitet durch User
Gut, also schnellst möglich ist so eine Sache, oft genügt es wenn es einfach rechtzeitig fertig wird. Noch schneller bringt dann nix. In dem Xilinx IP kann man das alles einstellen. Aber auch selber zu Fuß mit relativ wenig VHDL geht das wunderbar. Man kann auch schöne Mischformen aus parallel und seriell schreiben. Mario A. schrieb: > Ich würds dir auch gerne mal per Screensharing zeigen, wenn Interesse > besteht. :D Sowas habe ich hier nicht. Aber du kannst das doch schön simulieren. Hier https://www.mikrocontroller.net/attachment/highlight/427492 ist eine Testbench die einen Sweep anlegt.
Wenn ich das alte FIR-Projekt und das aktuelle Projekt mit konstanten
Werten (0x00FF) versorge, erhalte ich dasselbe Ergebnis. Wenn jetzt noch
die XXX..XX verschwinden würden, müsste das Filter eigentlich endlich
funktionieren.
Danke für den Tipp mit der Testbench für den Filter Block aus dem IP
Catalog.
>>Sowas habe ich hier nicht.
Für Screensharing über Zoom bräuchtest du auch nichts. :)
:
Bearbeitet durch User
Mario A. schrieb: > Für Screensharing über Zoom bräuchtest du auch nichts. :) Stimmt, aber ich finde das bringt nix. Ich bin da auch nicht Profi genug um anderer Leute Code zu verstehen. Mario A. schrieb: > Danke für den Tipp mit der Testbench für den Filter Block aus dem IP > Catalog. Da kannst du auch deinen FIR mit testen, musst du halt etwas anpassen. So wie ich dein FIR Blockschaltbild verstanden habe hat der sowieso also Eingänge den Takt und Daten und als Ausgang die Daten. Für mein Verständnis fehlen da die Valid oder Ready Signale. Oder kommt da wirklich mit jedem Takt von brd_clk ein neuer Abtastwert? Also ja, das kann man schon so machen aber so ein paralleles Design macht man eigentlich nur aus Not, denn wenn der FIR in einem Takt fertig sein muss, dann werden da viele DSPs verwendet. Wenn du aber Audio oder sonst was langsames feilterst, dann hast du für jeden Abtastwert viele Takte Zeit. Da würde sich dann eine serielle Form oder wenn die Anzahl der Takte kleiner als die Zahl der Koeffizienten ist eine Mischform anbieten. Im oben verlinkten Thread filtert mein FIR ein Signal mit 5 MHz Abtastrate. Dazu wird ein Systemtakt von 100 MHz verwendet. Bedeutet ich habe 20 Takte je Abtastwert. Rein Seriell könnten da maximal 20 Koeffizienten verwendet werden (ohne Beachtung der Symmetrie). Ich verwende 200 Koeffizienten und rechne in jedem Takt 10 Multiplikationen. Das ist also ein Kompromiss. Rein parallel bräuchte das 200 DSPs, rein seriell 1 DSP aber es wären nur 20 Koeffizienten möglich. Mischform braucht 10 DSPs und kann 200 Koeffizienten. Wenn dein Audio mit z. B. 44.1 kHz ankommt und deine brd_clk 100 MHz hat, dann bleiben dir 100M/44.1k grob 2267 Takte je Abtastwert. Du könntest also mit nur einem DSP im FPGA einen FIR mit 2267 Koeffizienten rechnen lassen. Ganz ohne Mischform oder sonstige Parallelität, rein seriell.
Ja wenn ich DSP-Slices einsparen wollte würde ich es auch anders machen. Aber aktuell möchte ich eine komplett parallele Berechnung (unabhängig von der Abtastrate). Eine Testbench habe ich ja. Das einzige Problem ist noch, dass beim neuen Projekt dieses XXX...XX bei a_sop vorkommt.
>>So wie ich dein FIR Blockschaltbild verstanden habe hat der sowieso also
Eingänge den Takt und Daten und als Ausgang die Daten.
Genau.
Eingänge:
- 16 Bit (ungefilterte) Daten
- 100 MHz Clock
- Signal für "Daten sind verfügbar" (hphone_valid)
Ausgang:
- gefilterter Wert
Mario A. schrieb: > Eine Testbench habe ich ja. Das einzige Problem ist noch, dass beim > neuen Projekt dieses XXX...XX bei a_sop vorkommt. Gut, aber da hilft es in der Testbench herumzustochern. So wie das aussieht wird das Signal mit den XXXX nur von den Multiply Addern geschrieben. Tja ... da wäre mal spannend die wie konfiguriert sind. Sonst kannst du die IP MACs mal durch einfache Multiplikation * ersetzen. Wenn das möglich ist. Oder nutzt du z. B. Pipelining bei den MACs?
Einstellungen habe ich dir angehängt. Denke aber dass das passt. Hm fraglich ob´s an der Testbench liegt. Die richtigen Werte liegen an (an s_AD_SDOUT) und die entsprechenden std_logic_vectors für die Berechnung werden erzeugt. Ich hab noch ein anderes Filter (in welchem ich die Berechnung in einem Process mit einfachen Multiplikationen durchführe). Ich denk ich versuch das mal einzubinden. Vivado generiert daraus auch eine parallele Filterstruktur. Sollte es wirklich an den Multiply Addern liegen wird mans hoffentlich sehen.
@Gustl Ich hab gerade die Testbench angepasst. Du hattest recht, da war was "falsch". Ich habe nicht sofort meine AD_SDOUTs gesetzt. Erst einen LRCK später. Dadurch hol ich mir wohl einen ungültigen Wert ins Array a_sop... Also die Simulation läuft jetzt. Bin gespannt ob´s auch auf dem Board funktioniert. Danke dir schon mal! :)
Also da die Testbench funktioniert habe ich nun den Bitstream generiert. Ich habe die Signale direkt mit einem Analog Discovery gemessen. Die Clocks (Master Clock, Serial Clock, Left/Right Clock) kann ich messen. Die seriellen Daten (DA_SDIN und AD_SDOUT) zeigt es mir allerdings nicht an. In meiner Testbench (für die Simulation ob das Filter funktioniert) habe ich für AD_SDOUT feste Werte vorgegeben, da ich ja keinen Eingang von außen habe (in der Simulation). DA_SDIN wird dann auch generiert. Vllt stimmt dann etwas mit i2s_data_interface.vhd nicht. Ich denke da muss evtl. noch was rein (z. B. was aus audio_top.vhd aus dem Originalframework von Stefan Scholl).
:
Bearbeitet durch User
Auch das kannst und solltest du simulieren. Erstmal alle Blöcke einzeln und dann zusammen wenn es Fehler gibt. Wenn Signale von ausserhalb des FPGAs benötigt werden, dann erzeugt man sich diese in der Testbench. Also schreib dir z. B. eine Quelle die einen Sinus sweept und den dann über I2S ausgibt. Das fütterst du dann in deinen I2S Block als Eingang.
So sieht das Ergebnis der Testbench aus. Sollte soweit eigentlich passen. Einbindung des PMOD-Moduls (https://reference.digilentinc.com/reference/pmod/pmodi2s2/reference-manual) wie folgt: DA_LRCK : OUT STD_LOGIC; DA_MCLK : OUT STD_LOGIC; DA_SDIN : OUT STD_LOGIC; DA_SCLK : OUT STD_LOGIC; AD_LRCK : OUT STD_LOGIC; AD_MCLK : OUT STD_LOGIC; AD_SDOUT : IN STD_LOGIC; AD_SCLK : OUT STD_LOGIC --*************************alle PMODS zuweisen******* DA_LRCK <= s_clk_32_kHz_LRCK; DA_MCLK <= s_clk_8_192_MHz_MCLK; DA_SCLK <= s_clk_2_048_MHz_SCLK; ------------------------------------ AD_LRCK <= s_clk_32_kHz_LRCK; AD_MCLK <= s_clk_8_192_MHz_MCLK; AD_SCLK <= s_clk_2_048_MHz_SCLK; --*************************************************** i2s_interface : i2s_data_interface port map ( clk => s_clk_8_192_MHz_MCLK, audio_l_in => s_audio_l_in, audio_r_in => s_audio_r_in, audio_l_out => s_audio_l_out, audio_r_out => s_audio_r_out, new_sample => s_new_sample, i2s_bclk => s_clk_2_048_MHz_SCLK, i2s_d_out => DA_SDIN, i2s_d_in => AD_SDOUT, i2s_lr => s_clk_32_kHz_LRCK ); Auszug meines XDCs: ## PMOD Header JA set_property -dict {PACKAGE_PIN U28 IOSTANDARD LVCMOS33} [get_ports { DA_LRCK }]; #IO_L13N_T2_MRCC_14 Sch=ja_n[1] set_property -dict {PACKAGE_PIN U27 IOSTANDARD LVCMOS33} [get_ports { DA_MCLK }]; #IO_L13P_T2_MRCC_14 Sch=ja_p[1] set_property -dict {PACKAGE_PIN T27 IOSTANDARD LVCMOS33} [get_ports { DA_SDIN }]; #IO_L12N_T1_MRCC_14 Sch=ja_n[2] set_property -dict {PACKAGE_PIN T26 IOSTANDARD LVCMOS33} [get_ports { DA_SCLK }]; #IO_L12P_T1_MRCC_14 Sch=ja_p[2] set_property -dict {PACKAGE_PIN T23 IOSTANDARD LVCMOS33} [get_ports { AD_LRCK }]; #IO_L5N_T0_D07_14 Sch=ja_n[3] set_property -dict {PACKAGE_PIN T22 IOSTANDARD LVCMOS33} [get_ports { AD_MCLK }]; #IO_L5P_T0_D06_14 Sch=ja_p[3] set_property -dict {PACKAGE_PIN T21 IOSTANDARD LVCMOS33} [get_ports { AD_SDOUT }]; #IO_L4N_T0_D05_14 Sch=ja_n[4] set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports { AD_SCLK }]; #IO_L4P_T0_D04_14 Sch=ja_p[4] Auszug Original XDC: ## PMOD Header JA #set_property -dict { PACKAGE_PIN U28 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L13N_T2_MRCC_14 Sch=ja_n[1] #set_property -dict { PACKAGE_PIN U27 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L13P_T2_MRCC_14 Sch=ja_p[1] #set_property -dict { PACKAGE_PIN T27 IOSTANDARD LVCMOS33 } [get_ports { ja[2] }]; #IO_L12N_T1_MRCC_14 Sch=ja_n[2] #set_property -dict { PACKAGE_PIN T26 IOSTANDARD LVCMOS33 } [get_ports { ja[3] }]; #IO_L12P_T1_MRCC_14 Sch=ja_p[2] #set_property -dict { PACKAGE_PIN T23 IOSTANDARD LVCMOS33 } [get_ports { ja[4] }]; #IO_L5N_T0_D07_14 Sch=ja_n[3] #set_property -dict { PACKAGE_PIN T22 IOSTANDARD LVCMOS33 } [get_ports { ja[5] }]; #IO_L5P_T0_D06_14 Sch=ja_p[3] #set_property -dict { PACKAGE_PIN T21 IOSTANDARD LVCMOS33 } [get_ports { ja[6] }]; #IO_L4N_T0_D05_14 Sch=ja_n[4] #set_property -dict { PACKAGE_PIN T20 IOSTANDARD LVCMOS33 } [get_ports { ja[7] }]; #IO_L4P_T0_D04_14 Sch=ja_p[4] Beschreibung i2s: i2s_data_interface wandelt die seriellen Daten (AD_SDOUT) in die entsprechenden std_logic_vectors (audio_l_out und audio_r_out) um. Die 16 MSBs der beiden Vektoren dienen dann als Eingang für das Filter. Das gefilterte Ergebnis dient wiederum als Eingang für i2s_data_interface (audio_l_in, audio_r_in) und wird dort für die Ausgabe in einen seriellen Datenstrom umgewandelt.
:
Bearbeitet durch User
Ich habs auch mal mit set_clock_groups -asynchronous -group [get_clocks *clk_out1*] -group [get_clocks *clk_out2*] set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 5 [current_design] statt set_clock_groups -asynchronous -group [get_clocks *clk_out1*] -group [get_clocks *clk_out2*] set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] probiert. Aber bisher auch ohne Erfolg.
Ich hab ein Warning übersehen... Wenn ich set_property CONFIG_VOLTAGE 5.0 [current_design] anstatt set_property CONFIG_VOLTAGE 3.3 [current_design] schreibe, erhalte ich leider eine Warning. Weiß jemand wie ich die Spannung an den Pins direkt auf 5V setze? Scheinbar reichen 3.3V nicht aus, siehe https://forum.digilentinc.com/topic/20297-pmodi2s2/#comment-56983. "You will likely need a higher voltage for the Pmod I2S2; the Analog to Digital converter chip (CS5343) has a minimum recommended operating voltage of 3.1V, so it will likely not operate correctly when you are trying to debug/listen to incoming analog signals." Eigentlich werden die PMODs ja mit 3.3V versorgt (LVCMOS33)... Oder verstehe ich die Lösung im Link falsch? [Netlist 29-154] Cannot set property 'CONFIG_VOLTAGE' because incorrect value '5.0' specified. Expecting type 'enum' with possible values of ',1.5,1.8,2.5,3.3'. ["C:/Users/aim34424/Desktop/Gen2_PMOD_FIR2_5V/Genesys2ExternalAudioInter face.srcs/constrs_1/new/Genesys2Master.xdc":3]
Ich bin gerade verwirrt... Mein Talkthrough (ohne Filter) funktioniert nur, wenn ich die Spannung fälschlicherweise auf 5V setze... Trotz Critical Warning... Mit CONFIG_VOLTAGE 3.3, bzw. komplett ohne set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] funktioniert nichts. Wenn ich das Filter einbinde (in dem funktionierenden Design) funktioniert wieder nichts.
:
Bearbeitet durch User
Üblicherweise wird die Spannung nicht im Constraint/Config-File einstellt, sondern an die Pins mit der Bankspannung angelegt. Im Zweifelsfall schaut man in den Schaltplan, was der Entwickler da vorgesehen hat. Im Constraint-File teilt man dem Tool nur mit, welche Spannung man genau angelegt hat. Das Tool kann dann prüfen, ob alle Pins und Buffer an dieser Bank auf die richtige Spannung eingestellt sind. Duke
Ja, die PMODs haben 3.3V oder 5V als Versorgungsspannung. Die konnte man bei älteren Digilent Boards mit Jumper umstellen. Bei deinem PMOD geht es aber nicht um die Versorgung, sondern die Signale. Die kommen aus dem FPGA und haben bei logisch high 3.3V. Oder sollten haben. Das kannst du ja selber nach messen. Mit den Constraints die du da schreibst änderst du nix an der Spannung, du teils dem Vivado nur mit welche Spannung am FPGA angeschlossen ist. Da solltest du den korrekten Wert schreiben, was der ist steht im Schaltplan.
Danke für eure Antworten! Laut Schematic liegen 3.3V an den PMODs an. Im XDC wird das bei den Pins auch standardmäßig so angegeben. >>sondern an die Pins mit der Bankspannung angelegt. Aber ich kann jetzt quasi nicht einfach die Spannung auf 5V erhöhen (außer ich versorge die Module extern mit einer Spannungsquelle)? >>Die konnte man bei älteren Digilent Boards mit Jumper umstellen. Das kann gut sein! Ich finde jedenfalls nichts, womit ich die Spannung auf 5V umstellen kann. >>Oder sollten haben. Das kannst du ja selber nach messen. Leider habe ich aufgrund der aktuellen Lage nur mein Analog Discovery zur Verfügung... Aber das kann das glaube ich auch. Werde ich mal prüfen, danke. Aber ihr geht nicht davon aus, dass es an der 3,3V Versorgung liegt? Vielen Dank!
Mario A. schrieb: > Aber ich kann jetzt quasi nicht einfach die Spannung auf 5V erhöhen > (außer ich versorge die Module extern mit einer Spannungsquelle)? Richtig. Und auch das würde nichts bringen. Denn die Signale die vom FPGA zum PMOD gehen haben dann weiterhin die 3,3 V des FPGAs. Da aber dann die Signale vom PMOD zum Signal 5 V sind könntest du dir sogar die FPGA IOs schlachten. Mario A. schrieb: > Aber ihr geht nicht davon aus, dass es an der 3,3V Versorgung liegt? Genau. Beide Bausteine auf der PMOD Platine sind für 3,3 V ausgelegt und sollten daher wunderbar funktionieren. Aber du kannst natürlich die Spannung nachmessen mit einem Multimeter.
:
Bearbeitet durch User
Danke! Ich war aufgrund es Links (https://forum.digilentinc.com/topic/20297-pmodi2s2/#comment-56983.) nur sehr skeptisch. :) Ich versuchs dann mal weiter!
Ich komme aktuell leider nicht weiter. In der Testbench passt alles, aber auf der Hardware nicht. Wenn man sich die Signale mit dem ILA ansieht, fällt auf, dass filtered_output_r_16_bit und filtered_output_l_16_bit konstant bei 0 bleiben. Deshalb wird auch kein serieller Datenstrom über DA_SDIN ausgegeben. Ich habe auch mal versucht das Filter direkt einzubinden (ohne Auslagern in FIRFilter.vhd). Leider auch ohne Erfolg...
Da kann ich auch nicht weiterhelfen. Ohne das Filter funktioniert alles? Dann lade doch mal den Code für das Filter hoch. Oder noch besser: Ersetze das Filter durch eines das ganz sicher funktioniert, z. B. das von Xilinx.
Hallo Gustl, danke für deine Antwort und Hilfe. Ich versuche morgen mal das Filter von Xilinx einzubinden. Ich habe mittlerweile ziemlich viele verschiedene Versionen. Ich lade mal eine davon hoch. Kurz zu den Dateien: AudioInterface.vhd -> Erzeugung der Clocks (LRCK, SCLK, MCLK, ...) -> Versorgt Filter mit 16 Bit Daten und erhält 16 Bit Daten vom Filter FIRFilter.vhd -> erhält 16 Bit Daten -> gibt ein 16 Bit Ergebnis zurück i2s_data_interface.vhd -> wandelt serielle Daten vom ADC in Signale um (audio_l_out, audio_r_out) -> wandelt audio_l_in und audio_r_in in ein serielles Signal für die Ausgabe tb_AudioInterface.vhd -> Werte für AD_SDIN werden vorgegeben Wenn in AudioInterface.vhd im Process s_audio_l_in <= s_audio_l_out; s_audio_r_in <= s_audio_r_out; steht funktioniert zumindest Talkthrough. Ich denke es ist irgendeine Kleinigkeit aber ich bin irgendwie blind dafür. An sich müssten audio_l_in und audio_r_in gesetzt werden... Wie auch in der Testbench...
Einen Fehler habe ich gefunden... Das dürfte so auch nicht auf der Hardware funktionieren. In der Statemachine „fsm_fir_get_data.vhd“ taucht im Case-Statement eine „Rising-Edge“-Bedingung auf, die noch dazu nicht auf den Systemtakt taktet. Hab das jetzt mal geändert und überprüfe das. Neu: entity fsm_fir_get_data is port ( ck : in STD_LOGIC; start_fs_tic_f : in STD_LOGIC; reg_ready_f : OUT STD_LOGIC := '0' ); end fsm_fir_get_data; architecture arch_fsm_fir_get_data of fsm_fir_get_data is signal d_out_reg_ready_f : STD_LOGIC ; type states is ( s_idle, s_read ); signal state,nxt_state : states; begin calc_next_state: process ( state,start_fs_tic_f ) begin case state is when s_idle => if (start_fs_tic_f='1') then nxt_state <= s_read; end if; --****************************** --vorher: if (start_fs_tic_f='1' AND rising_edge(start_fs_tic_f) ) then --nxt_state <= s_read; end if; --***************************** when s_read => nxt_state <= s_idle; end case; end process calc_next_state; -- Auscodierung Ausgaenge; with nxt_state select d_out_reg_ready_f <= '1' when s_read, '0' when s_idle; clkd:Process(ck) Begin if rising_edge(ck) THEN state <= nxt_state ; reg_ready_f <= d_out_reg_ready_f; end if; END PROCESS clkd; end arch_fsm_fir_get_data;
:
Bearbeitet durch User
Nun ... ich bekomme das natürlich nicht ans Laufen weil die ganzen Xilinx IPs fehlen. Aber ich habe mir den Code mal angeguckt. Und da finde ich viele Kritikpunkte: 1. Viele Signale haben keinen Startwert. Was die Simulation da also macht ist vermutlich ein U. 2. start_fs_tic_f='1' AND rising_edge(start_fs_tic_f) mag ich nicht um eine steigende Flanke zu erkennen. rising_edge(start_fs_tic_f) sollte genügen. 3. use IEEE.STD_LOGIC_UNSIGNED.ALL; use ieee.numeric_std.all; Da genügt es die Letztere zu verwenden. Eigentlich reicht fast meistens: library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; Und generell: Du machst da ziemlich viele Baustellen gleichzeitig auf mit deinem Projekt. Koeffizienten aus ROM lesen, Filter verwenden, ... Hast du diese einzelnen Komponenten denn schon mal unabhängig getestet? Wie wäre es mal mit einer Testbench nur für das FIR Filter? Und zwar nicht nur mit einem statischen Wert, sondern mit einem Sinus oder noch besser einen Sweep? Mario A. schrieb: > Wenn in AudioInterface.vhd im Process > s_audio_l_in <= s_audio_l_out; > s_audio_r_in <= s_audio_r_out; > steht funktioniert zumindest Talkthrough. Dann funktioniert schon mal das I2S Interface, das ist doch fein. Ich baue da mal ein kleines Minimalprojekt ...
So und da ist es. Was musst du noch machen? Vielleicht die XDC anpassen, vielleicht -size 64 in der Bitstream_post.tcl anpassen (das muss zu der Größe des Bitstreams passen). Auf jeden Fall musst du aber das korrekte FPGA einstellen, das geht bei meiner gratis Version von Vivado nicht. Was habe ich gemacht? - Viel gelöscht. - ADC und DAC für die Testbench geschrieben. Der ADC liefert einen Sinus Sweep als I2S, der DAC empfängt I2S und gibt die Werte aus. - Xilinx FIR Filter eingebaut. Linker Kanal ist Tiefpass, rechter Kanal Hochpass.
Hallo Gustl, wenn es dich interessiert kann ich dir gerne die Einstellungen und mein .coe File schicken. >>1. Viele Signale haben keinen Startwert. Was die Simulation da also macht ist vermutlich ein U. Die Simulation passt allerdings. Aber trotzdem sollte ich das noch ändern, da geb ich dir Recht. >>Koeffizienten aus ROM lesen, Filter verwenden, ... Habe ich alles schon getestet im Zusammenspiel mit dem Filter (in der Simulation). >>nicht nur mit einem statischen Wert, sondern mit einem Sinus oder noch besser einen Sweep? Ich habe ja sozusagen einen Sweep mit meinen Daten an ADC_SDOUT. Ich lese die Zahlen 1,2,3,4,5,...,15,16,16,16,...16 ein und filtere diese. >>Ich baue da mal ein kleines Minimalprojekt ... Danke!
Mario A. schrieb: > Die Simulation passt allerdings. Kann ich nicht nachvollziehen. Mag sein, aber ein Screenshot bringt da reichlich wenig. Kann ja sein, dass zu einem späteren Zeitpunkt dein Filter keine neuen Werte mehr liefert oder so. Weiß ich aber nicht. Wenn du dein Filter selber bauen willst, dann lade mal alles hoch was zu diesem Filter gehört. Also alles was da eingebunden wird in deiner FIRFilter.vhd . Ich werde da aber nicht tief rumstochern weil ich das deutlich zu komplex finde für ein FIR Filter. Aber ich würde eine Testbench schreiben und nur dieses Filter mal testen. Mario A. schrieb: > Ich > lese die Zahlen 1,2,3,4,5,...,15,16,16,16,...16 ein und filtere diese. Ja, aber was wenn dein Filter nach mehreren us oder ms irgendwann aufgibt und die Füße hochlegt? Oder wenn irgendwelche Werte überlaufen und dann dauerhaft eine Konstante ausgegeben wird? Das siehst du so alles nicht. Oben in dem Minimalprojekt sind ja zwei FIRs drinnen. Die kannst du 1:1 durch deinen FIR ersetzen. Da bekommst du am Eingang einen Sinussweep und kannst den Ausgang beobachten. Im Anhang noch zwei FIRs von mir geschrieben. Einmal seriell, also je Multiplikation ein Takt und einmal parallel, also mit jedem Takt ein neuer Abtastwert. Ja, Code ist nicht hybsch, ist schon etwas her. Aber funktioniert.
:
Bearbeitet durch User
Hallo Gustl, vielen Dank schon mal für alles! Das mit dem ADC und DAC ist eine sehr gute Idee. Ich hänge dir mal die Einstellungen meiner IPs an. Ich schaue mir morgen Vormittag deinen Code an und binde ihn ein. Danke!
Lade die IPs doch einfach hoch. Aus dem jeweiligen Ordner wird glaube ich nur die .xml und die .xci benötigt. Mein ganzes Minimalprojekt oben sind nur wenige kByte.
Noch ein kurzes Update: Der ILA funktioniert nun auch mit den Filterversionen (ich erhalte Werte für DA_SDIN, etc.). Den Frequenzgang muss ich allerdings noch überprüfen.
Hier die IP Dateien. Hab deinen Beitrag leider übersehen.
Hallo Gustl, ich habe jetzt mal dein Projekt zum Laufen gebracht. Vielen Dank hierfür! Gefällt mir sehr gut und kann ich auch so noch gebrauchen! Danke. Hast du die Simulation von IN_RIGHT, IN_LEFT, OUT_RIGHT, OUT_LEFT auch mit Vivado gemacht? Also Run Simulation? Das rechnet ewig bei mir, bis ich da mal ein paar Werte habe. Ich habe mal den Bitstream für dein Projekt generiert und die Frequenzgänge mit dem Analog Discovery 2 gemessen (siehe Anhang). Tiefpass- und Hochpassverhalten sind zu erkennen. Außerdem hab ich mir den Frequenzgang mit deinen Koeffizienten mit Matlab plotten lassen. Ich möchte jetzt noch mein FIR-Filter einbinden und schauen ob´s funktioniert. Dein serielles und dein Pipeline Filter schau ich mir auch demnächst noch an. Recht herzlichen Dank schon mal!
:
Bearbeitet durch User
Mario A. schrieb: > Hast du die Simulation von IN_RIGHT, IN_LEFT, OUT_RIGHT, OUT_LEFT auch > mit Vivado gemacht? Also Run Simulation? Das rechnet ewig bei mir, bis > ich da mal ein paar Werte hab Ja, Ja und Ja (-: Ist eben so, 32 kHz Samplerate braucht viel Echtzeit. Ausserdem brauchen die Xilinx Blöcke viel Rechenleistung. Mario A. schrieb: > Ich habe mal den Bitstream für dein Projekt generiert und die > Frequenzgänge mit dem Analog Discovery 2 gemessen (siehe Anhang). > Tiefpass- und Hochpassverhalten sind zu erkennen. Außerdem hab ich mir > den Frequenzgang mit deinen Koeffizienten mit Matlab plotten lassen. Fein. Filterdesign geht gut mit Pyfda ( https://github.com/chipmuenk/pyfda ). Mario A. schrieb: > Recht herzlichen Dank schon mal! Bitte! Viel Erfolg!
>>Ja, Ja und Ja (-: Alles klar klar klar. :) >>Filterdesign geht gut mit Pyfda Danke für den Tipp. Habe bisher Matlab verwendet, aber das ist halt leider kostenpflichtig. Ich hab mal mein Filter eingebunden und das im Anhang kam dabei raus. Ich habe für den linken Kanal ein Filter mit Fpass 2000 und Fstop 2200 und für den rechten Kanal ein Filter mit Fpass 500 und Fstop 1000 verwendet (jeweils 15ter Ordnung). Könnte schon passen. Die Messung mit dem AD2 ist allerdings nicht so aufschlussreich (siehe Anhang). Ich werde das mal am Montag mit Filtern höherer Ordnung prüfen.
Mario A. schrieb: > Die Messung mit dem AD2 ist allerdings nicht so aufschlussreich (siehe > Anhang). Doch das passt schon. Beachte zwei Dinge: 1. In der Simulation geht die Frequenz mit der Zeit linear. (Also wenn du den Sinus Sweep von mir verwendest.) Im Bildchen vom AD ist das aber log aufgetragen. 2. Die Amplitude ist in der Simulation ebenfalls linear, beim AD aber in dB. Halbe Amplitude bedeutet -3 dB. In der Simulation kann man schön sehen, dass sich zwar die Amplitude ändert, aber auch nicht so sehr. Zumindest keine -80 dB oder so. Mario A. schrieb: > jeweils 15ter Ordnung Das ist einfach sehr wenig, sollte aber schon reichen um -40 dB und etwas mehr zu erreichen. Mein Filter (das Bildchen aus meinem Post weiter oben) hatte so knapp 200 Koeffizienten.
:
Bearbeitet durch User
>>Doch das passt schon. Beachte zwei Dinge: Dessen bin ich mir bewusst. >>Das ist einfach sehr wenig, sollte aber schon reichen um -40 dB und etwas mehr zu erreichen. Man sollte dennoch einen deutlichen Unterschied erkennen bei Fpass 500/Fstop 1000 und Fpass 2000/Fstop 2200 denke ich. Ich habe mir jetzt mal mit dem filterDesigner die Koeffizienten für dieselben Filter für einen Signalprozessor generieren lassen und den Frequenzgang anschließend überprüft. Das sieht definitiv anders aus. Die Berechnung ist auch in Fixed-Point (INT16-Koeffizienten) realisiert. Die Koeffizienten des coe-Files und der C-Headerdateien kann man auch einwandfrei ineinander umrechnen, das sollte also passen. Außerdem habe ich auch mal versucht die Koeffizienten direkt einzufügen (als Vector) und nicht per COE-File: Keine Veränderung. Passt evtl. an meinen Einstellungen für den PMOD oder den FIR-Compiler irgendetwas nicht..? Slave: MCLK: 8,192 MHz SCLK: 2,048 MHz LRCK: 32 kHz Das sollte doch einer Abtastrate von 32 kHz entsprechen. Und je Kanal sollten 24 Bit für die Daten verwendet werden. Bei deinen Koeffizienten für den TP und den HP (in Kombination mit dem FIR-Compiler) messe ich wenigstens mal einen "anderen Frequenzgang" mit dem Analog Discovery. Ich werd mal den PMOD im Mastermodus verwenden und schauen, ob sich was ändert.
:
Bearbeitet durch User
Ich glaub ich muss das Verhältnis von MCLK/LRCK anpassen, damit die Daten im 24 Bit Format übertragen werden. Vllt sieht deshalb auch die Simulation gut aus, aber auf dem FPGA sieht´s anders aus.
:
Bearbeitet durch User
Davon habe ich leider keine Ahnung. In der Testbench den ADC und DAC habe ich für 24 Bits geschrieben und das sollte eigentlich auch 1:1 so auf der Hardware funktionieren. Ich empfehle dir aber weiterhin mal die Abtastwerte zum PC auszugeben. Das geht relativ einfach. Du nimmst dir im FPGA etwas BRAM, in den nimmst du Audio auf bis der voll ist und dann schickst du das über UART zum PC. Dann könntest du dir das Signal schön plotten und gucken ob alles passt. Mit einer hohen Baudrate kannst du dir sogar den BRAM sparen und das Audio direkt herausstreamen. 24 Bit ⋅ 2 Kanäle ⋅ 32 kHz Abtastrate ⋅ 1,4 (wegen Start und Stoppbit und Pause) = 2150400 Baud. Das bekommt der FTDI auf den Board locker hin. Ich würde gleich 4 Bytes je Abtastwert nehmen damit du da ein Framing einbauen und dazuschreiben kannst welcher Kanal das ist. Ein Paket auf 24 Datenbits und einem Kanalbit könnte dann so aussehen: K000DDD1 DDDDDDD0 DDDDDDD0 DDDDDDD0 Das braucht dann 2867200 Baud.
:
Bearbeitet durch User
Ich denke meine Clocks für den PMOD passen doch. >>Ich empfehle dir aber weiterhin mal die Abtastwerte zum PC auszugeben. Das geht relativ einfach. Du nimmst dir im FPGA etwas BRAM, in den nimmst du Audio auf bis der voll ist und dann schickst du das über UART zum PC. Über den UART-Anschluss meinst du? (USB-UART-Bridge, Anschluss 1: https://reference.digilentinc.com/reference/programmable-logic/genesys-2/reference-manual) set_property -dict { PACKAGE_PIN Y23 IOSTANDARD LVCMOS33 } [get_ports { uart_rx_out }]; #IO_L1P_T0_12 Sch=uart_rx_out set_property -dict { PACKAGE_PIN Y20 IOSTANDARD LVCMOS33 } [get_ports { uart_tx_in }]; #IO_0_12 Sch=uart_tx_in Und den BRAM mithilfe des Block Memory Generators erzeugen? Wie würdest du die Daten am PC auslesen (welches Programm?). Vielen Dank im Voraus! Das klingt vielversprechend!
:
Bearbeitet durch User
Mario A. schrieb: > Wie würdest du die Daten am PC auslesen (welches Programm?). Im Zweifelsfall erstmal mit HTerm. Das lann die Daten in Binär, Hex und ASCII ausgeben. So kann man erstmal schauen, ob da überhaupt was verwertbares kommt. Duke
Mario A. schrieb: > Über den UART-Anschluss meinst du? Genau den. Mario A. schrieb: > Und den BRAM mithilfe des Block Memory Generators erzeugen? Du kannst das einfach als Array schreiben. http://www.lothar-miller.de/s9y/archives/20-RAM.html Aber: Wenn du beim UART die Baudrate hoch genug wählst, dann kannst du das einfach streamen und brauchst keinen BRAM. Dein FTDI kann IIRC bis 12 MBaud. Nimm einfach mal 8 MBaud und es wird funktionieren. Mario A. schrieb: > Wie würdest du die Daten am PC auslesen (welches Programm?). Ich verwende Python: import serial ser = serial.Serial('COM8',8000000,timeout=0) data = ser.read(1000000) #einfach alles lesen was ankommt Natürlich liest du in einer Schleife periodisch. Und die Daten die du bekommst kannst du erstmal stumpf an die alten anhängen. Dann speicherst du die oder zerlegst die gleich in Samplewerte und plottest dir das Signal. Duke Scarring schrieb: > Im Zweifelsfall erstmal mit HTerm. Das lann die Daten in Binär, Hex und > ASCII ausgeben. So kann man erstmal schauen, ob da überhaupt was > verwertbares kommt. Exakt! Einfach Datenpakete ausgeben mit dem FPGA über UART und dann mal ein paar Sekunden Datenstrom aufnehmen. Das kannst du dann gerne hier posten als Anhang und wir plotten das, oder du plottest das selber. Ich empfehle da cutecom unter Linux oder realterm unter Windows.
Danke für die Tipps! Ich weiß leider noch nicht genau wie ich beginnen
soll. Soll ich einen IP Core für den UART verwenden (AXI UART16550, AXI
Uartlite)?
Also wenn ich es richtig verstanden habe: Meine empfangenen und
gefilterten 24 Bit Audiodaten jeweils in einen BRAM schreiben. Diesen
dann über die UART-Bridge senden, ODER direkt OHNE BRAM die Daten
streamen (auch mit IP Block?).
Und dann erst mal mit HTerm schauen, ob was entsprechendes rauskommt.
Die Daten von HTerm könnte ich dann auch mit MATLAB analysieren, oder?
Hab leider noch keine Erfahrung mit Python gemacht und möchte auch
gerade kein weiteres Fass aufmachen, wenn es nicht zwingend notwendig
ist. :P
>>Mit einer hohen Baudrate kannst du dir sogar den BRAM sparen und das
Audio direkt herausstreamen.
Wo stellt man denn die Baudrate ein? Du meinst in den IP Blöcken?
Maximale Baudrate AXI Uartlite bei 100 MHz Clock (8 Datenbits, ohne
Paritätsbits): 230400
Soll ich die 1en und 0en des seriellen Eingangs-/Ausgangssignals direkt
über uart_tx_in senden?
Vielen Dank!
:
Bearbeitet durch User
Mario A. schrieb: > Soll ich einen IP Core für den UART verwenden (AXI UART16550, AXI > Uartlite)? Kannst du machen, geht aber einfacher. Hier ist eine UART Komponente: http://www.lothar-miller.de/s9y/categories/42-RS232 Die funktioniert, verwende ich auch selbst aber ich habe die noch etwas modifiziert. Mario A. schrieb: > Also wenn ich es richtig verstanden habe: Meine empfangenen und > gefilterten 24 Bit Audiodaten jeweils in einen BRAM schreiben. Diesen > dann über die UART-Bridge senden, ODER direkt OHNE BRAM die Daten > streamen (auch mit IP Block?). Richtig. Ich würde der Einfachheit halber den BRAM weglassen. Mario A. schrieb: > Und dann erst mal mit HTerm schauen, ob was entsprechendes rauskommt. > Die Daten von HTerm könnte ich dann auch mit MATLAB analysieren, oder? Ja. Ich kenne HTerm nicht. Lass dir die Daten wenn möglich nicht als irgendwelches ASCII oder so speichern sondern schön die rohen Bytes. Du kannst das aber auch hier in den Anhang hochladen was du aufgenommen hast, ich gucke mir das dann gerne mal an. Mario A. schrieb: > Wo stellt man denn die Baudrate ein? Du meinst in den IP Blöcken? In dem oben verlinkten UART von Lothar kann man das per Generic einstellen. Sonst kannst du das in dem IP Block einstellen. Mario A. schrieb: > Maximale Baudrate AXI Uartlite bei 100 MHz Clock (8 Datenbits, ohne > Paritätsbits): 230400 Das ist zu wenig. Mario A. schrieb: > Soll ich die 1en und 0en des seriellen Eingangs-/Ausgangssignals direkt > über uart_tx_in senden? Nein. Du baust aus den Abtastwerten Pakete die man im Datenstrom als Paket erkennen kann. Z. B. so wie ich es oben vorgeschlagen hatte. Das waren 4 Bytes/Abtastwert. Und diese 4 Bytes schickst du dann nacheinander über den UART. Wenn du etwas Zeit hast schreibe ich das Minimalprojekt um und erweitere es um einen UART.
Zu lange gebraucht, also noch ein Post: Leider ist der UART "nur" ein FT232R, das limitiert auf 3 MBaud. Ich verwende daher nicht 4 Bytes je Samplewert, sondern 7 Bytes für zwei Abtastwerte. Paketformat: 0LLLLLL1 LLLLLLL0 LLLLLLL0 LLLLRRR0 RRRRRRR0 RRRRRRR0 RRRRRRR0 L: Linker Kanal, R: Rechter Kanal. Ein Paket kann durch die LSBs erkannt werden. Eingestellt sind 3 MBaud.
>>Hier ist eine UART Komponente: Perfekt, danke! >>Richtig. Ich würde der Einfachheit halber den BRAM weglassen. Alles klar. >>Du kannst das aber auch hier in den Anhang hochladen was du aufgenommen hast, ich gucke mir das dann gerne mal an. Danke! :) >>Du baust aus den Abtastwerten Pakete die man im Datenstrom als Paket erkennen kann. Alles klar. >>Wenn du etwas Zeit hast schreibe ich das Minimalprojekt um und erweitere es um einen UART. Wenn es dir keine allzu großen Umstände macht, wäre das natürlich sehr toll! Ich versuch mich auf jeden Fall auch mal. Vielleicht schaff´ ich es. ;) Vielen Dank dir wieder mal! :) Okay das ging schnell. :) :P
:
Bearbeitet durch User
Ich habe mir jetzt doch Python heruntergeladen. Mit Matlab hat es jetzt leider nicht wie erhofft auf Anhieb funktioniert.
OK, kommen Daten über UART am PC an? Steht die Baudrate auf 3 MBaud? Kannst du die empfangenen Daten abspeichern? Wenn du magst dann lade sie hier hoch als Anhang. Da reichen ja wenige 100 kBytes bis so wenige MBytes.
Mal eine Frage. Du hast in AudioInterface eine Baudrate von 3 000 000 eingestellt. Im Gerätemanager für den entsprechenden COM-Anschluss kann ich nur max. 921 600 Bits pro Sekunde einstellen. Dann muss ich noch was anpassen oder? MATLAB: s = serial('COM11', 'BaudRate', 3000000); fopen(s) [A,count,msg] = fread(s, 1000, ...) %muss ich noch ergänzen fclose(s); b = de2bi(A); Mit de2bi kann ich die Daten dann nach binär umwandeln.
:
Bearbeitet durch User
1 | data = ser.read(100000) |
2 | if len(data) > 0: |
3 | sr.extend(data) |
4 | while len(sr) >= 7: |
5 | if (sr[0] & 1 == 1) and (sr[1] & 1 == 0) and (sr[2] & 1 == 0) and (sr[3] & 1 == 0) and (sr[4] & 1 == 0) and (sr[5] & 1 == 0) and (sr[6] & 1 == 0): |
6 | L = (sr[0] >> 1)*2**18 + (sr[1] >> 1)*2**11 + (sr[2] >> 1)*2**4 + (sr[3] >> 4) |
7 | |
8 | R = (sr[3] & 14)*2**21 + (sr[4] >> 1)*2**14 + (sr[5] >> 1)*2**7 + (sr[6] >> 1) |
Den Code kannst du in einer Schleife ausführen. Und dann brauchst du noch ein Array für L und R das du dann befüllst und plottest. Aber lade das gerne wirklich hier noch.
Also ich hab jetzt in MATLAB: s = serial('COM11', 'BaudRate', 3000000); fopen(s) [A,count,msg] = fread(s, 100, 'uchar') fclose(s); b = dec2bin(A); Soll ich jetzt noch die Einstellungen im Geräte Manager anpassen, oder es so lassen? Vllt verwende ich mal deinen Pythonansatz von gerade und konvertier den in MATLAB Code.
Mario A. schrieb: > Im Gerätemanager für den entsprechenden COM-Anschluss kann > ich nur max. 921 600 Bits pro Sekunde einstellen. Dann muss ich noch was > anpassen oder? Ja. Der Gerätemanager zeigt dir das nicht an. Wenn du Python zum lesen vom UART verwendest, kannst du selber eine Baudrate einstellen, auch 3 MBaud. Mario A. schrieb: > [A,count,msg] = fread(s, 1000, ...) %muss ich noch ergänzen Gut, kenne mich da nicht so aus. Aber lese nicht nur 1000 Werte. Lese mal für ein paar Sekunden. Also in einer Schleife periodisch lesen. Denn da kommen immer einige Bytes an, und es passen nicht irre viele Bytes in den Empfangspuffer. Also so alle 10 ms oder so solltest du schon vom UART lesen. Und da liest du immer so viel wie möglich. Also nicht 1000 sondern den Maximalwert der erlaubt ist. Die gelesenen Daten hängst du dann einfach an die alten Daten an. Hier der Code, müsste so laufen, der liest mehrmals in einer Schleife vom UART alles was angekommen ist und speichert das dann binär in einer Datei:
1 | import serial |
2 | import time |
3 | |
4 | ser = serial.Serial('COM11',3000000,timeout=0) |
5 | sr = bytearray() |
6 | for i in range(0,1000): |
7 | data = ser.read(1000000) |
8 | if len(data) > 0: |
9 | sr.extend(data) |
10 | time.sleep(0.01) |
11 | ser.close() |
12 | aufnahme = open("Aufnahme.bin",'wb') |
13 | aufnahme.write(sr) |
14 | aufnahme.close() |
Mario A. schrieb: > Soll ich jetzt noch die Einstellungen im Geräte Manager anpassen, oder > es so lassen? Einfach lassen.
:
Bearbeitet durch User
Danke! Muss ich da noch was installieren? >>> import serial Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'serial' Ich sollte wohl noch einen Texteditor für Python installieren? Habs einfach hier heruntergeladen: https://www.python.org/downloads/
:
Bearbeitet durch User
Ne, du musst noch das Modul https://pypi.org/project/pyserial/ installieren. Am einfachsten mit dem Befehl: pip install pyserial
Das mit dem Befehl funktioniert so leider nicht...
Ne, nicht aus Python heraus. Also erst aus dem Python Terminal raus mit quit() und dann den Befehl.
Ich habe nur dieses Terminal oder sehe ich das falsch? Shell und das Terminal. Bei beiden kann ich den Befehl nicht eingeben. Ich schau mir jetzt mal ein Tutorial an..
Den Befehl gibst du in das normale Windowsterminal ein. Windowstaste, dann "CMD", Enter, Befehl eingeben, Enter.
Ich lade mir mal schnell Anaconda herunter. Ich hoffe es funktioniert dann. Danke Gustl!
:
Bearbeitet durch User
Ja gut, aber brauchst du wohl nicht. Ich verwende hier Winpython.
:
Bearbeitet durch User
Also ich konnte jetzt die Bibliothek installieren. Aufnahme.bin befindet sich im Anhang. SerialException: Attempting to use a port that is not open
Mario A. schrieb: > SerialException: Attempting to use a port that is not open Ist auch klar, du hast da im Code noch den Block Data = ser.read ... drinnen, der gehört da nicht rein. Der wäre zum dekodieren, aber das müsste man anders schreiben. Aber irgendwas passt da noch nicht. Wenn ich mir die LSBs angucke, dann passt das nicht zu meinem Paketformat. Hast du was am Takt geändert oder so? Jedenfalls ist die Aufnahme unbrauchbar.
:
Bearbeitet durch User
Hm okay. Das FPGA läuft und der Port ist angesteckt. Ich hab lediglich statt deinem 200 MHz Takt einen 100 MHz Takt verwendet bei AudioInterface.vhd.
Mario A. schrieb: > Ich hab lediglich > statt deinem 200 MHz Takt einen 100 MHz Takt verwendet bei > AudioInterface.vhd. OK, den hast du auch in der PLL geändert? MMCM: CLK_I2S port map( clk200 => s_clk_200_MHz, clk8_192 => s_clk_8_192_MHz_MCLK, clk_in1_p => sysclk_p, clk_in1_n => sysclk_n); Da ist jetzt ein 100 MHz Ausgang? Und das hast du auch dem UART mitgeteilt? UART_FT232R: UART Generic map( clk_freq => 100000000, ? Sonst könnte es noch sein, dass der Empfangspuffer vom UART überläuft während der 10 ms Schlafphase. Setze daher die Zeile time.sleep(0.01) mal auf time.sleep(0.001) .
>>Da ist jetzt ein 100 MHz Ausgang? Ich verwende den Clocking Wizard (sysclk_p, sysclk_n) und da kommt dann mein 100 MHz Takt raus. >>Und das hast du auch dem UART mitgeteilt? Ja. >>Setze daher die Zeile time.sleep(0.01) mal auf time.sleep(0.001) Hab dir das vorher nachher .bin in den Anhang gepackt. Danke!
:
Bearbeitet durch User
Hm. Ja also die Aufnahme ist weiterhin kaputt. Woran das liegen kann weiß ich nicht, du hast ja den Clockmanager hoffentlich korrekt konfiguriert. Vielleicht mag der FT232R keine 3 MBaud? Aber wenn man mit der Datenrate runter geht dann geht kein Streaming mehr mit vollen 24 Bits je Kanal und zwei Kanälen. Man könnte auf Streaming verzichten und BRAM verwenden, also z. B. 2^16 Werte in den BRAM aufnehmen und dann ausgeben. Oder man streamt weiterhin aber nur mit einem Kanal oder mit niedrigerer Auflösung. Die Datei im Anhang streamt nur den linken Kanal bei 2 Mbaud. Bonusfrage an die Profis: Ich verwende hier den FT232R problemlos mit 921600 Baud. Weil das der höchste Wert ist der in vielen Terminalprogrammen eingestellt werden kann. Allerdings kann der FT232R keine 921600 Baud laut Datenblatt. Was macht da die Software wenn ich da trotzdem einfach 921600 verwende und wieso bekomme ich da keinen Fehler?
:
Bearbeitet durch User
So, und hier noch eine Version die mit 921600 Baud streamt. Linker Kanal und nur 14 Bits/Sample, aber weiterhin volle Abtastrate.
>>du hast ja den Clockmanager hoffentlich korrekt konfiguriert. Ich versuch es morgen auch nochmal mit deiner Originaldatei, um das sicher ausschließen zu können, aber ich denke das sollte passen. >>Die Datei im Anhang streamt nur den linken Kanal bei 2 Mbaud. Werde ich auch ausprobieren danke! Ansonsten werde ich wohl den BRAM einbinden müssen. Also auf dem Genesys kann ich es leider erst wieder am Montag probieren, da ich nur an einem PC die Lizenz habe.. Hätte aber ein Zybo 7020 dabei. Vielen Dank!
Mario A. schrieb: > Ich versuch es morgen auch nochmal mit deiner Originaldatei, um das > sicher ausschließen zu können, aber ich denke das sollte passen. Simulation wäre zielführend. Mario A. schrieb: > Hätte aber ein Zybo 7020 dabei. Da ist der UART ein FT2232H. Der kann 12 MBaud, habe ich schon gemacht, funktioniert. Damit sollte das wunderbar funktionieren.
>>Simulation wäre zielführend. Wird morgen gemacht! Heute bin ich leider nicht dazugekommen. >>Da ist der UART ein FT2232H. Der kann 12 MBaud, habe ich schon gemacht, funktioniert. Damit sollte das wunderbar funktionieren. Klingt vielversprechend! :)
Ja, aber deine XDC musst du anpassen und deine Takte ebenfalls. Du könntest den 125 MHz Takt an Pin K17 verwenden.
Hallo Gustl, bin gerade dabei mein Projekt für das Zybo 7020 anzupassen. Ich weiß nur gerade nicht, welchen Pin ich für den UART-Transfer nehmen soll. Es gibt 2 Anschlüsse auf dem Board: PROG UART J12 und J10 Im XDC finde ich nichts passendes. https://github.com/Digilent/digilent-xdc/blob/master/Zybo-Z7-Master.xdc Über Callout 3 lade ich die Hardwarebeschreibung auf das FPGA, oder? https://reference.digilentinc.com/reference/programmable-logic/zybo-z7/reference-manual Auf der anderen Seite von Callout 6 wäre noch der selbe Anschluss wie bei PROG UART (Anschluss J10) aber ich finde den nicht im XDC. Morgen möchte ich dann noch einmal das Genesys verwenden und mit den anderen Modikfikationen von dir testen (nur 1 Channel, etc).
Mario A. schrieb: > Ich weiß nur gerade nicht, welchen Pin ich für den UART-Transfer nehmen > soll. > Es gibt 2 Anschlüsse auf dem Board: > PROG UART J12 und J10 Ja da kann ich leider nicht helfen. Da ist auf jeden Fall ein FT2232H drauf und der müsste auch mit dem UART am FPGA angeschlossen sein. Aber ob das "nur" am PS Teil ist oder am PL Teil weiß ich nicht. Im Schaltplan ist die Seite mit dem FTDI leider leer. Hast du noch einen USB-UART? Dann verwende einfach zwei Pins (oder für nur TX nur einen) von einem PMOD.
>>Im Schaltplan ist die Seite mit dem FTDI leider leer. Ja sehr ärgerlich... >>Hast du noch einen USB-UART? Dann verwende einfach zwei Pins (oder für nur TX nur einen) von einem PMOD. Nur das was man auf den Bildern sieht. Im XDC finde ich leider nichts passendes. Morgen versuch ich es auf dem Genesys 2.
Hallo Gustl, ich habe jetzt die beiden anderen Versionen von dir auf das Genesys 2 geladen. Das was rauskommt und wie es zustande kommt habe ich dir in den Anhang gepackt. UART: 3 MBAUD, beide Kanöle UART2: 2 MBAUD, linker Kanal UART3: 921600 Baud, linker Kanal Leider komme ich erst Ende der Woche wieder vermehrt zu meinem Projekt, da unerwartet was sehr Wichtiges reingekommen ist. Ich bin außerdem dabei mein Filter so umzuschreiben, dass ich 16/21/24 Bit Koeffizienten habe und 24 Bit Daten als Filterinput und 24 Bit Daten als Filteroutput habe. Ein erster Test war schon einmal vielversprechend. Vielen Dank! :)
Seltsam. Mir scheint du machst alles korrekt, aber die Aufnahmen sind wieder alle kaputt. Mir fällt nur der Takt ein, also dass du da zwar 100 MHz verwenden willst, aber noch 200 MHZ eingestellt hast oder so. Aber sonst bin ich da recht ratlos, sorry. Du kannst gerne nochmal dein komplettes Projekt hochladen, dann gucke ich ob das in der Simulation gut aussieht. Also zur Erklärung: In der Version mit den 921600 Baud packet <= s_audio_l_out(23 downto 17) & '1' & s_audio_l_out(16 downto 10) & '0'; sollte das LSB von jedem zweiten Byte 1 und von jedem zweiten Byte 0 sein. Und das ist nicht der Fall. Wenn du ein Oszi/Logicanalyzer hast, dann kannst du dir mal den UART Pin angucken und die minimale Pulsweite bestimmen. Die sollte 1,085 us sein.
:
Bearbeitet durch User
Hallo Gustl, ich lade mal nochmal das Projekt samt Binary hoch. Leider schaffe ich erst am Freitag wieder mich mit dem Projekt länger als ein paar Minuten auseinander zu setzen... In der Simulation sind es 100 MHz. Kannst du mal bitte kurz prüfen, ob Aufnahme_neu_UART3_921600Baud_Right ein richtiges Ergebnis liefert? Wenn ja, sind die Channels in meinem Programm vertauscht. Das ist meine Befürchtung. Ich habe jetzt beide Channels separat mit dem AD2 gemessen und aufgenommen. Mit dem AD2 kann ich leider nur immer den linken oder den rechten Kanal messen. Kann also gut sein, dass ich den falschen Kanal eingelesen habe. Ich denke Aufnahme_neu_UART3_921600Baud_Right könnte richtig sein! Sollte das funktionieren, teste ich auch nochmal die Versionen mit 2 und 3 MBaud. Vielen Dank im Voraus!!
Hier noch die Dateien für das 2 und 3 MBaud Projekt (UART2: 2 MBaud, UART: 3 MBaud).
:
Bearbeitet durch User
So, zwei Sachen: 1. Wenn du ein Projekt anhängst, dann bitte den ganzen Ordner als zip. Sonst müsste ich das alles händisch zusammenbauen. Auch zu den IPs, einfach die .xci und die .xml. 2. Fehler - oder zumindest einen Fehler - gefunden. Mario A. schrieb: > In der Simulation sind es 100 MHz. Nicht nur dort, leider. In dem Bildchen Clock1.png hast du als Taktfrequenz von deinem externen Taktgeber 100 MHz eingestellt. Das ist falsch. Der Taktgeber auf deiner Platine hat 200 MHz und lässt sich auch nicht ändern. Schreibe dort 200 MHz rein. Dort wie in Bildchen Clock2.png, da kannst du eintragen was du gerne hättest, also welche Tektfrequenz erzeugt werden soll. Also meinetwegen die 100 MHz, aber im Bildchen Clock1.png muss die Frequenz drinnen stehen die der Taktgeber tatsächlich hat. Das teilst du damit dem Vivado mit. Wenn du da 100 MHz (wie jetzt) reinschreibst, und 100 MHz haben willst, dann macht Vivado da 1:1 draus. In der Realität hat der externe Takt aber 200 MHz, 1:1 bedeutet, dass dein "100 MHz Takt" im FPGA in Wirklichkeit ebenfalls 200 MHz hat. Wenn du Vivado aber sagst der externe Takt hat 200 MHz und du willst 100 MHz, dann wird da 2:1 draus gemacht. Jedenfalls: Auf der ersten Seite vom Clock Wizard schreibt man was man hat, also was auf dem Board ist, das ist bei dir der 200 MHz Takt. Und auf der zweiten Seite schreibt man rein was man gerne hätte. Also die 8.192 MHz und 100 MHz. Ich hoffe das war verständlich. Mario A. schrieb: > Kannst du mal bitte kurz prüfen, ob Aufnahme_neu_UART3_921600Baud_Right > ein richtiges Ergebnis liefert? Ne, ist leider wieder kaputt, ist aber auch klar weil der Takt nicht passt. Ob die Aufnahme OK war siehst du im Hexeditor wenn du dir die LSBs mehrerer Bytes in Folge anguckst. In der 921600er Version sollten die immer abwechselns 1 und 0 sein.
:
Bearbeitet durch User
>>Wenn du ein Projekt anhängst, dann bitte den ganzen Ordner als zip. Alles klar. Hab dir den ganzen Ordner für das Projekt mit einer Baudrate von 921600 angehängt. >>In dem Bildchen Clock1.png hast du als Taktfrequenz Oh Mist... Danke! Das wär mir so schnell nicht aufgefallen... Hab das leider unterbewusst komplett ignoriert. Bei meinem Vorgängerboard waren es nämlich 100 MHz... Deshalb konnte der Frequenzgang auch nicht stimmen. Die Koeffizienten wurden für eine Abtastrate von 32 kHz entworfen. >>Ob die Aufnahme OK war siehst du im Hexeditor wenn du dir die LSBs mehrerer Bytes in Folge anguckst. Habs mir jetzt mal mit dem https://hexed.it/ angesehen. Das LSB ist abwechselnd 1 und 0 bei der 921600er Version! Und das würdest du jetzt mit Python umwandeln, oder? Vielen Dank dir!! Den Fehler hab ich total übersehen... Danke danke danke :)
:
Bearbeitet durch User
So, das sieht jetzt mal gut aus! Die 921600er habe ich angeguckt und geplottet, das ist ja jeweils nur ein Kanal und 14 Bits. Und die beiden Aufnahme_neu_UART_LeftChannel.bin und Aufnahme_neu_UART_RightChannel.bin habe ich mal geplottet. Das verstehe ich aber nicht wieso du die Left und Right nennst, die enthalten doch jeweils zwei Kanäle?! Oder ist ein Kanal vor dem Filter und einer hinter dem Filter? Um die Filtercharakteristik sehen zu können musst du das Audio durchsweepen und währenddessen aufnehmen. Das dauert vermutlich ein paar Sekunden oder so. Das müsstest du im Aufnahmeskript also anpassen, dass das länger aufnimmt. Also die Schleife öfter laufen lassen. Das Aufnahmeskript von mir macht nur 1000 Schleifendurchläufe, das ist ganz grob 1 s Aufnahmezeit. Ausserdem sind bei den 3 MBaud doch einige Fehler drinnen. Nicht irre viele, aber doch einige. 4275 Fehler und 52673 korrekte Pakete. Die Fehlerzahl muss man aber durch ca. 7 teilen weil wenn ein Fehler dabei ist wird erst ca. 6 mal geschoben im "Schieberegister" bis wieder ein korrektes Paket erkannt wird. Im Anhang mal Plots und das Pythonskript für die Aufnahmen mit den 3 MBaud. Edit: In den Bildchen ist nur ein Ausschnitt zu sehen den ich passend skaliert habe. Aber kann ja jetzt Jeder selber komplett plotten, die .bin Dateien und das Pythonskript sind ja da.
:
Bearbeitet durch User
Hallo Gustl, die Datei audio_decode.py bezieht sich jetzt nur auf die Version mit 3 MBaud und dem folgenden Format, oder? #Format: #0LLLLLL1 #LLLLLLL0 #LLLLLLL0 #LLLLRRR0 #RRRRRRR0 #RRRRRRR0 #RRRRRRR0 Ich versuche gerade mal die verschiedenen Versionen in Matlab zu decodieren. Am liebsten wärs mir nämlich, dass ich die decodierten Daten dann wieder mit Matlab bearbeite/analysiere, weil ich damit einfach schon mehr Erfahrung hab. Zu deinem Code: Mit if (sr[0] & 1 == 1) and (sr[1] & 1 == 0) and (sr[2] & 1 == 0) and (sr[3] & 1 == 0) and (sr[4] & 1 == 0) and (sr[5] & 1 == 0) and (sr[6] & 1 == 0): prüfst du auf das Format der letzten Spalte, oder? Würdest du das dann bei der Version mit 14 Byte auch in der Form machen? Dort haben wir ja #L L L L L L L 1 #L L L L L L L 0 Mit L_sign = int((sr[0] & 64)/64) R_sign = int((sr[3] & 8)/8) ermittelst du das Vorzeichen der einzelnen Channels, oder? >>Allerdings kann der FT232R keine 921600 Baud laut Datenblatt. https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf 3 MBaud kann er laut Datenblatt. Also könnte ich ja an sich beide Channels streamen? 32 Bit (mit Codierung) x 2 Kanäle x 32 kHz x 1,4 = 2,8672 MBaud
Achso ich habe immer Right and Left hochgeladen, weil ich nur jeweils an einen Channel den Sinussweep anschließen kann (zumindest glaube ich das). Der andere Channel ist vermutlich Floating.
Mario A. schrieb: > die Datei audio_decode.py bezieht sich jetzt nur auf die Version mit 3 > MBaud und dem folgenden Format, oder? Ja. Mario A. schrieb: > Zu deinem Code: > Mit > > if (sr[0] & 1 == 1) and (sr[1] & 1 == 0) and (sr[2] & 1 == 0) and (sr[3] > & 1 == 0) and (sr[4] & 1 == 0) and (sr[5] & 1 == 0) and (sr[6] & 1 == > 0): > > prüfst du auf das Format der letzten Spalte, oder? Ja. Mario A. schrieb: > Würdest du das dann bei der Version mit 14 Byte auch in der Form machen? > Dort haben wir ja > > #L L L L L L L 1 > #L L L L L L L 0 Ja, das sollte man immer machen. Dort mit: if (sr[0] & 1 == 1) and (sr[1] & 1 == 0): Mario A. schrieb: > Mit > L_sign = int((sr[0] & 64)/64) > R_sign = int((sr[3] & 8)/8) > ermittelst du das Vorzeichen der einzelnen Channels, oder? Ja. Mario A. schrieb: > 3 MBaud kann er laut Datenblatt. > Also könnte ich ja an sich beide Channels streamen? > 32 Bit (mit Codierung) x 2 Kanäle x 32 kHz x 1,4 = 2,8672 MBaud Ja, wird aber knapp. Ich würde statt 2 x 32 Bit = 8 Bytes lieber wie oben Mario A. schrieb: > #Format: > #0LLLLLL1 > #LLLLLLL0 > #LLLLLLL0 > #LLLLRRR0 > #RRRRRRR0 > #RRRRRRR0 > #RRRRRRR0 nehmen. Das sind nur 7 Bytes. Da wird die Pause zwischen den Bytes etwas länger, ob das einen Unterschied macht weiß ich nicht, ich glaube nicht. Du könntest also auch Folgendes machen: Nehme ein 4-Byte-Paket, z. B.: Format: 000KDDD1 DDDDDDD0 DDDDDDD0 DDDDDDD0 Dabei stehen die D für die Daten und das K für den Kanal. Dann sendest du eben zwei der Pakete. Eines für L und eines für R. Sollte gehen bei 3 MBaud. Wenn du nur einen Kanal übertragen willst, dann schickst du nur Pakete des entsprechenden Kanals. Aber: Weil du ja bei den 3 MBaud ab und zu Fehler drinnen hast, würde ich da runter gehen. Auf 2 MBaud z. B.. Was der FT232R kann steht hier: https://www.ftdichip.com/Support/Knowledgebase/index.html?whatbaudratesareachieveabl.htm Bei 2 MBaud kannst du aber nicht mehr beide Kanäle bei vollen 24 Bit/Kanal streamen. Ich würde da auch 20 Bits runtergehen wenn das akzeptabel ist. Da kannst du ein Paket für einen Kanal so bauen: Format: KDDDDDD1 DDDDDDD0 DDDDDDD0 Da kannst du bei 2 MBaud immer noch beide Kanäle knapp streamen bei 2 x 3 Bytes. Besser wäre dann aber vermutlich ein Paket für beide Kanäle. Das hier wären 17 Bits/Kanal und zusammen 5 Bytes: 0LLLLLL1 LLLLLLL0 LLLLRRR0 RRRRRRR0 RRRRRRR0 Da musst du etwas ausprobieren was bei dir fehlerfrei funktioniert oder welche Kompromisse du eingehen willst. Mario A. schrieb: > weil ich nur jeweils an > einen Channel den Sinussweep anschließen kann Ist OK. Aber den Sweep kann man nicht sehen in den Samples. Vermutlich dauert dein Sweep mehrere Sekunden und die Samples enthalten nur einen kurzen Aussschnitt dieser Zeit. Da müsstest du für eine längere Zeit aufnehmen.
:
Bearbeitet durch User
Habs jetzt geschafft das .bin-File mit Matlab zu decodieren. Erst mal für das Format (3 MBaud) -- 0LLLLLL1 -- LLLLLLL0 -- LLLLLLL0 -- LLLLRRR0 -- RRRRRRR0 -- RRRRRRR0 -- RRRRRRR0 Weitere Dateien folgen.:)
Habe kein Matlab, sieht etwas umständlich aus, aber wenn es funktioniert, dann wunderbar (-: Gratulation!
Ja geht bestimmt einfacher. Wenn ich for i in range(0,10000): statt for i in range(0,1000): schreibe, rechnet Matlab irgendwie ewig und kommt nicht zu einem Ende. Bei 1000 gehts nóch recht zügig. Irgendwie seltsam. Das funktioniert mit deinem Pythonskript deutlich besser. Hab bei meinem Code auch erst einmal nicht auf Effizienz geachtet... Ich werd morgen mal versuchen die Werte für die beiden Kanäle von deinem Python-Skript in ein File zu schreiben und diese dann mit Matlab grafisch auszuwerten.
Mario A. schrieb: > Das funktioniert mit > deinem Pythonskript deutlich besser. Komisch, Python ist eigentlich eher langsam. Aber ja, deine Methode jedes Bit einzeln herauszufischen ist nicht gerade der Performancekönig.
Ich hab jetzt die Daten von Python mit der Datei im Anhang in ein Textfile geschrieben und kann das nun einfach mit Matlab analysieren. Die Daten wurden mit den Einstellungen im Anhang aufgenommen (3 MBaud, 24 Bit, 7 Byte Paket, beide Kanäle, wobei bei den Messungen nur ein Kanal aussagekräftig ist). Oben ist jeweils der linke Kanal zu sehen und unten der rechte Kanal. Der rechte Kanal sollte in diesem Fall keine richtigen Werte aufweisen, da die Sinussweeps nur am linken Kanal gemacht werden. Das unten sieht nach Rauschen aus.
:
Bearbeitet durch User
Was mir gerade auffällt: packet <= '0' & s_audio_l_out(23 downto 18) & '1' & s_audio_l_out(17 downto 11) & '0' & s_audio_l_out(10 downto 4) & '0' & s_audio_l_out(3 downto 0) & s_audio_r_out(23 downto 21) & '0' & s_audio_r_out(20 downto 14) & '0' & s_audio_r_out(13 downto 7) & '0' & s_audio_r_out(6 downto 0) & '0'; audio_l_out und audio_r_out enthalten jeweils die Werte der gewandelten Eingangsdaten VOR dem Filter. audio_l_in und audio_r_in enthalten hingegen die gefilterten Daten. Ich habe mal den linken Kanal vor und nach dem Filter mittels UART übertragen und analysiert (siehe INvsOUT_LeftChannel). Die Filtercharakteristik ist sehr schön zu erkennen. Ein Sweep von 100 Hz bis 16 kHz entspricht in etwa 2,5*10^5 Werten laut Grafik. Abtastrate 32 kHz.
:
Bearbeitet durch User
Lob und Anerkennung! Das sieht tatsächlich schön aus, Gratulation!
Danke! :) Das ist das Ergebnis mit dem von dir vorgeschlagenen Datenformat mit den 7 Bytes (davon sind 48 Datenbits) bei 3 MBaud. Sieht ja gut aus. Denkst du ich sollte dann überhaupt nochmal mit der Baudrate runtergehen, oder es so belassen? Die 24 Bits für die Daten sind an sich nicht schlecht, wenn ich nachher noch Berechnungen durchführen will. Was jetzt natürlich für spätere Zwecke evtl. interessant wäre: Beide Kanäle vor und nach dem Filter zu streamen. Also 4x24 Bits reine Daten. Gerade wenn ich Stereosignale von außen analysieren möchte. Mit den 3 MBaud komme ich da ja leider nicht hin. Selbes Format wie zuvor: 14 Byte -> 112 Bits 112 x 32000 x 1,4 = 5,0176 MBaud. Z.B. so: -- Daten vor Filter -- KLLLLLL1 -- LLLLLLL0 -- LLLLLLL0 -- LLLLRRR0 -- RRRRRRR0 -- RRRRRRR0 -- RRRRRRR0 -- Daten nach Filter -- KLLLLLL1 -- LLLLLLL1 -- LLLLLLL1 -- LLLLRRR1 -- RRRRRRR1 -- RRRRRRR1 -- RRRRRRR0 Da müsste ich dann BRAM verwenden, oder? Es wäre doch evtl. sinnvoll sowieso BRAM zu verwenden, damit ich dann IMMER meine 4x24 Bit auswerten kann und weniger Fehler habe? >>Richtig. Ich würde der Einfachheit halber den BRAM weglassen. Wird das recht kompliziert? Den Link hast du schon mal gepostet: http://www.lothar-miller.de/s9y/archives/20-RAM.html Wäre vielleicht sinnvoll, das jetzt in einem Wisch zu machen. :) Was meinst du Gustl? Vielen Dank im Voraus! :)
Mario A. schrieb: > Denkst du ich sollte dann überhaupt nochmal mit der > Baudrate runtergehen, oder es so belassen? Kommt drauf an wie viele Fehler du bekommst und ob das für dich OK ist. Wenn du zufrieden bist, dann lass es. Mario A. schrieb: > Also 4x24 Bits reine > Daten. Gerade wenn ich Stereosignale von außen analysieren möchte. Tja, das geht leider nicht. Aber du kannst dir einen anderen UART kaufen. Der FT2232H und FT232H können bis 12 MBaud. Da gibt es fertige Module von FTDI https://www.ftdichip.com/Products/Modules/DevelopmentModules.htm und anderen Herstellern. Da müsstest du dann nur TX und Masse verbinden. Du kannst auch das Zybo verwenden das du ja hast, da ist ebenfalls ein FT2232H drauf. Wenn du beim FT232R bleiben willst, dann ist das Limit bei 3 MBaud. Ein Paket darf dann maximal 7 Bytes groß sein. Das sind ohne die LSBs 49 Nutzbits. Da passen als 12 Bits/Kanal rein. Das wären dann 48 Bits. Format: Kanäle A,B,C,D 0AAAAAA1 AAAAAAB0 BBBBBBB0 BBBBCCC0 CCCCCCC0 CCDDDDD0 DDDDDDD0 Tja wie ist das mit dem BRAM, das würdest du zum Aufnehmen verwenden. Also Aufnahme starten, warten bis der Speicher voll ist, dann Speicher über UART auslesen. Wie viel von diesem BRAM hat dein XC7K325T auf dem Board und wie lange könnte man da aufnehmen? Rechnen wir das mal aus: Das FPGA hat 16020 kBit BRAM. Das sind dann ca. 2 MByte. Bei vollen 24 Bits und 32 kSample/s benötigt ein Kanal 96 kByte/s. Du kannst also bei 1 Kanal ca. 20 Sekunden 2 Kanäle ca. 10 Sekunden ... aufnehmen. Wenn dir 5 Sekunden bei 4 Kanälen reichen dann wäre das ein möglicher Weg. Welche Möglichkeiten gibt es noch? Du hast da noch viel externes RAM drauf, du kannst die Daten nicht nur über UART sondern auch über andere Schnittstellen an den PC schicken.
>>Aber du kannst dir einen anderen UART kaufen. Das wäre eine Option. >>Du kannst auch das Zybo verwenden das du ja hast Da gabs ja leider das Problem mit den Pins im XDC. >>Wenn dir 5 Sekunden bei 4 Kanälen reichen Das ist schon etwas knapp ehrlich gesagt, aber könnte reichen für spätere Messungen mit dem adaptiven Filter. >>auch über andere Schnittstellen an den PC schicken. Okay das wäre auch eine Option, wenn es wieder Dateien zum Einbinden (wie diese von Lothar Miller) gibt. Das soll jetzt nämlich nicht meinen Schwerpunkt darstellen, aber es wäre halt sehr cool! :) Das Modul würde ja wahrscheinlich von den Daten her funktionieren oder? https://ftdi-uk.shop/collections/usb-uart-module/products/ft2232h-56q-mini-module https://www.ftdichip.com/Support/Documents/DataSheets/Modules/DS_FT2232H-56Q_Mini_Module.pdf Aber kann ich das dann nicht einfach anschließen, also nur draufstecken, oder? RXD und TXD müsste ich dann vermutlich löten? Ich seh einen USB-Anschluss. Vielen Dank dir!
Mario A. schrieb: > Okay das wäre auch eine Option, wenn es wieder Dateien zum Einbinden > (wie diese von Lothar Miller) gibt. Das soll jetzt nämlich nicht meinen > Schwerpunkt darstellen, aber es wäre halt sehr cool! :) So einfach wird das nicht. Du hast da noch Ethernet drauf und du hast da einen FT2232H drauf der ein FIFO Interface und ein SPI Interface hat. Von FPGA Seite ist das nicht so irre kompliziert, nur minimal schwieriger als UART. Aber auf der PC Seite musst du vermutlich irgendeine API nutzen. Mario A. schrieb: > Das Modul würde ja wahrscheinlich von den Daten her funktionieren oder? > https://ftdi-uk.shop/collections/usb-uart-module/products/ft2232h-56q-mini-module Ja, würde es. Das hat eine USB Buchse (Micro-USB) und RX/TX sind eben auf so Pfosten. Löten musst du da nix, du nimmst dir einen Draht und verbindest einen Pin im PMOD mit dem RX Pin auf dem FTDI Board. Und Masse solltest du noch verbinden. ------------------------- Als weitere Möglichkeit könnte man den FT2232H auf dem FPGA Board umflashen, also das EEPROM, damit der statt dem FIFO Interface und dem SPI ein UART darstellt. Aber das ist legal nicht möglich weil man da die JTAG Lizenz von Digilent mitclonen müsste. Ist aber möglich, ich hatte das hier getan, werde aber sonst keine Tipps dazu geben: Beitrag "FT2232H JTAG clonen?" Lass da die Finger weg wenn du nicht weißt was du tust.
>>Das hat eine USB Buchse (Micro-USB) und RX/TX sind eben auf so Pfosten. Das klingt sehr vielversprechend! >>du nimmst dir einen Draht und verbindest einen Pin im PMOD mit dem RX Pin auf dem FTDI Board. Und Masse solltest du noch verbinden. Stimmt ich könnte das ja einfach auf den PMOD routen. Ich hätte noch so Standard Arduino-Leitungen. Gibt nur 1 Modul in diesem Shop: https://ftdi-uk.shop/collections/usb-uart-module/products/ft2232h-56q-mini-module Danke für den Tipp!
:
Bearbeitet durch User
Ich habe mir jetzt dieses Modul bestellt: https://ftdi-uk.shop/collections/usb-uart-module/products/ft2232h-56q-mini-module Bin gespannt, danke schon mal für den Tipp! Ich bin gerade dabei mein eigens erstelltes FIR-Filter zu testen. Als Vergleich nutze ich dieselben Filterkoeffizienten mit dem Xilinx FIR-Compiler Projekt und schaue mir den Frequenzgang an. 24 Bit Daten, 16 Bit Koeffizienten Linker Kanal: Fpass 1000 Fstop 2000 Rechter Kanal: Fpass 4000 Fstop 5000 Filterordnung: 81 -> 82 Koeffizienten Der Vergleich mit den selben Filterkoeffizienten weist eine Verschiebung auf (siehe VglXilinx32kHzundMeinFIR32kHz.PNG). Ich habe nun mal die Koeffizienten für eine Abtastrate von 16 kHz designed und bei meinem FIR-Filter eingebunden. Nun sehen sich die Frequenzgänge des Xilinx FIR Compilers mit den für eine Abtastrate von 32 kHz designten Koeffizienten und meines FIR Filters mit den für 16 kHz designenten Koeffizienten sehr ähnlich. Ich denke also, dass ich versehentlich statt mit einer Abtastrate von 32 kHz nur mit 16 kHz arbeite. Ich werde jetzt mal versuchen eine FSM in meine Filtermodule für den Datenaustausch einzubauen. Wahrscheinlich braucht meine Version aktuell 2x32 kHz Durchläufe, also schlussendlich 16 kHz.
Mario A. schrieb: > Ich denke also, dass ich > versehentlich statt mit einer Abtastrate von 32 kHz nur mit 16 kHz > arbeite. Möglich, wenn du wieder was am Takt verändert hast. Gen2_FIR_D24_C16.zip (93,5 MB, 0 Downloads) Lass das besser mit so irre fetten Anhängen.
>>Möglich, wenn du wieder was am Takt verändert hast. Eigentlich habe ich da nichts verändert. Es hat davor auch noch nicht richtig funktioniert. Ich hoffe das lässt sich mit einer FSM in den Filter-Dateien lösen. >>Lass das besser mit so irre fetten Anhängen. Ja habs zu spät gesehen, dass der Bitstream auch noch dabei ist... Einfach nur die einzelnen Dateien und die xci und xml-Files reichen, oder?
Mario A. schrieb: > Einfach nur die einzelnen Dateien und die xci und xml-Files reichen, > oder? Ja. Und das brauchst du auch nur anhängen wenn du eine Frage dazu hast. Bei deinen Bildchen finde ich die Darstellung irgendwie komisch. Vor allem die y-Achse oder schafft das Filter wirklich nur eine so geringe Dämpfung?
Habe jetzt mal noch eine FSM und zwei parallele Datenregister eingebunden. Führt leider zum selben Ergebnis wie ohne FSM, also lad ich es gar nicht erst hoch... Irgendwo hab ich noch einen Fehler drin. Scheint ich kreiere mir ein 16 kHz Filter. :D Die Abtastrate sollte ja meinem LRCK (32 kHz) entsprechen, denke ich. Werd mir das morgen nochmal ansehen.
Mario A. schrieb: > Die Abtastrate sollte ja > meinem LRCK (32 kHz) entsprechen, denke ich. Das könntest du in der Simulation sehen.
So war das nicht gemeint. :) Ich meine die Abtastrate sollte ja an sich 32 kHz sein, wenn LRCK 32 kHz hat (und LRCK hat 32 kHz). Ich vergleiche gerade die Xilinx-FIR-Compiler Version mit meiner Version.
Die Koeffizienten werden falsch in meinem Koeffizientenarray abgespeichert. Das änder ich morgen ab. Hoffentlich funktionierts dann!
:
Bearbeitet durch User
Irgendwie spinnt Vivado bei mir... Meine Änderungen werden in der Testbench oftmals nicht aktualisiert, auch wenn ich die Simulation neu starte (Relaunch Simulation). Manchmal muss ich das Projekt dann umbenennen und an einem anderen Ort speichern...
:
Bearbeitet durch User
Das Problem kenne ich auch. Was hilft ist: Vivado oder zumindest Projekt schließen und im Projektordner den Ordner mit der Endung .sim löschen. Abar ja, ist extrem nervig und ich kenne keine bessere Lösung.
Leider funktioniert mein Filter noch nicht so wie es soll. Ich habe die Rundung mit Bias und die Overflow-/Underflowerkennung weggelassen - leider ohne Veränderung. Außerdem habe ich die Koeffizienten nun mal direkt als Konstantenarray eingebunden. Muss ich vllt den ungefilterten Wert erst verzögert mit dem gefilterten Wert ausgeben? Ich schaue mir nachher nochmal an, wie das hier gemacht wurde: https://github.com/ems-kl/zedboard_audio/blob/master/hdl/audio_testbench.vhd @Gustl Das UART-Modul ist heute gekommen! Darf ich dich nochmal fragen, ob das so passt? Möchte nichts falsch machen. :) Folgende Schritte: 1. Ich weise jetzt quasi an 2 PMOD-Pins (z.B. PMOD Port B, Pin 1 und 2) 2 Signale für das Senden und Empfangen im Code zu (also 1x Out und 1x In). Die Signale weise ich im Code dem UART-Modul wie im vorherigen UART-Projekt zu (siehe AudioInterface.vhd). 2. Mit 2 Leitungen schließe ich diese Signale vom PMOD an das UART-Modul an. 3. Den PMOD Massepin (Pin 5 oder 11) verbinde ich zus. noch mit dem Massepin des UART-Moduls. Frage: Brauche ich diese Masseverbindung überhaupt? 4. Das UART Modul verbinde ich über den Micro USB Anschluss mit dem PC. Ich bin mir nachdem ich das Datenblatt gelesen habe leider noch nicht 100% sicher, wie das Modul richtig anzuschließen ist. Ich hätte jetzt mal beide Jumper (JP1 und JP2) draufgelassen, damit sollte das Modul "USB Bus-powered" sein (siehe Seite 8: http://www.farnell.com/datasheets/2035221.pdf) >>du nimmst dir einen Draht und verbindest einen Pin im PMOD mit dem RX Pin auf dem FTDI Board. https://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232H.pdf Ich suche gerade, welche Pins ich verbinden muss. Ich denke es ist Pin 16 (TxD) und 17 (RxD) des FT2232H und somit VIO = Pin 16 und AD4 = Pin 17 auf dem UART-Modul, siehe DS_FT2232H, S. 11. Also müsste ich jetzt den PMOD Pin 2 (Tx) mit dem Pin 17 (AD4) verbinden und den PMOD Pin 1 (Rx) mit dem Pin 16 (VIO)? Für VIO gibt es sogar mehrere Pins auf dem UART-Modul. Ich habe als Treiber den VCP (x64 (64-bit) für Windows heruntergeladen (siehe Treiber.png). Muss ich da jetzt noch was machen..? In dem heruntergeladenen Ordner ist nämlich keine exe. Meinen angepassten Code für das Senden von 14 Bytes, also beide Kanäle vor und nach dem Filter, habe ich schon mal angehängt (AudioInterface.vhd). Da muss aber noch die Baudrate geändert werden. 14 Byte x 8 x 32 kHz x 1,4 = 5,0176 MBaud. Könnte ja mal 6 MBaud einstellen. Treiberseite: https://www.ftdichip.com/FTDrivers.htm Ich lese mir morgen mal den Installation Guide durch. https://www.ftdichip.com/Support/Documents/InstallGuides/AN_396%20FTDI%20Drivers%20Installation%20Guide%20for%20Windows%2010.pdf
:
Bearbeitet durch User
Mario A. schrieb: > Frage: Brauche ich diese Masseverbindung > überhaupt? Ja. Ohne Bezugspotential geht das nicht. Mario A. schrieb: > Ich hätte jetzt mal beide Jumper (JP1 und JP2) draufgelassen, damit > sollte das Modul "USB Bus-powered" sein Ja, klingt OK. Mario A. schrieb: > siehe DS_FT2232H, S. 11. Für dich ist aber Seite 18 relevant. Daher ist das am FT2232H-56Q die Pins 12 und 13 oder 32 und 33. Also ADBUS0 und ADBUS1 oder BDBUS0 und BDBUS1 und somit an deinem Modul die Pins CN2-7 AD0 und CN2-10 AD1 oder CN3-26 BD0 und CN3-25 BD1. Mario A. schrieb: > In dem > heruntergeladenen Ordner ist nämlich keine exe. Ganz normal. Verbinde das Modul mit dem PC und gucke erstmal ob das nicht automatisch erkannt wird. Wenn nein, dann lass Windows einen Treiber im Internet suchen. Wenn das nicht geht, dann sage Windows, dass es einen Treiber aus deinem Ordner da installieren soll. Wenn das Modul installiert wurde sollte es mit FT_Prog https://www.ftdichip.com/Support/Utilities.htm#FT_PROG gefunden werden und der Gerätemanager im Windows sollte die zwei serielle Schnittchenstellen anzeigen. Mario A. schrieb: > Könnte ja mal 6 MBaud einstellen. Zitat: Please notethe FT2232H doesnot support the baud rates of 7 Mbaud 9 Mbaud, 10Mbaud and 11 Mbaud. Also beachte, dass manche Baudraten nicht unterstützt werden. Ich habe erfolgreich 12 MBaud, 8 MBaud und 921600 Baud verwendet. Andere habe ich nicht probiert. Das PySerial aus Python kann diese Baudraten auch, welche noch weiß ich nicht. Und dann noch das mit der Filterei: Du kannst schön die Daten an den Filterkoeffizienten vorbeischieben. Dabei musst du ebenfalls jeweils die Summe mit den Daten verschieben. Du kannst aber auch anders herum die Koeffizienten an den Daten vorbeischieben und ebenfalls je eine Summe vorbeischieben. Ich weiß gerade nicht ob du alle Multiplikationen in einem Takt machen willst oder ob du das seriell nacheinander machst. Jedenfalls ist es so: Du hast n Koeffizienten und n Abtastwerte, wobei der Abtastwert 1 der Neueste ist und der Abtastwert N der Älteste. Wenn ein neuer Abtastwert reinkommt, dann muss folgendes passieren: - Die Abtastwerte werden um 1 verschoben indem du den Abtastwert n wegwirfst und am anderen Ende den neuen Abtastwert hinzufügst. Abtastwerte <= neuer_Abtastwert & Abtastwerte(2 ... n) - Du beginnst mit einer neuen Summe, also beim Summenwert Null. - Du multiplizierst und addierst jetzt für alle m in 1 ... n: Summe <= Summe + Abtastwert(m)*Koeffizienten(m) - Du skalierst die Summe, das wird ja eine große Zahl indem du sie durch eine Zweierpotenz teilst. Wenn du konkreten Pseudocode haben möchtest, dann wüsste ich gerne ob du das als Pipeline, in einem Takt oder seriell rechnen lassen möchtest.
>>Ja. Ohne Bezugspotential geht das nicht. Ah ja stimmt... Micro USB geht ja auf den PC nicht aufs FPGA.. Denkfehler. :D >>Für dich ist aber Seite 18 relevant. Perfekt, danke! >>Ganz normal. Verbinde das Modul mit dem PC und gucke erstmal ob das nicht automatisch erkannt wird. Hast Recht, es zeigt mir 2 USB-Ports an (COM17 und COM18), siehe USBAnschluesse.PNG. Danke. >>Ich habe erfolgreich 12 MBaud, 8 MBaud und 921600 Baud verwendet. Alles klar, danke! Ich verwende jetzt mal 8 MBaud. Ich habe jetzt mal alles angeschlossen: PMOD Pin 1 (FT2232H_RX_PMOD) geht auf AD1 (RxD) PMOD Pin 2 (FT2232H_TX_PMOD) geht auf AD0 (TxD) PMOD Pin 5 auf GND Jetzt muss ich noch das Pythonskript anpassen (neues Datenformat und neue Baudrate). Mal schauen, ob ich es vor Mittag noch schaffe. :) Muss leider später weg... >>Du kannst schön die Daten an den Filterkoeffizienten vorbeischieben. Ich möchte alle Multiplikationen parallel in einem Takt haben. Meine Mutliply Adder Blöcke haben an sich alle dasselbe Startsignal und schreiben ihr Ergebnis alle in das Array a_sop. Eigentlich müssten die Werte so automatisch immer weitergeschoben werden. Aber vllt sollte ich mal ein zus. Schieberegister einbauen. Derselbe Eingangswert liegt auch an allen Blöcken gleichzeitig an. Nur das Array a_sop (Summe der Produkte) sollte sich nach jeder Berechnung ändern. Und die Berechnung von allen Blöcken wird eigtl. gleichzeitig gestartet. Hab dir nochmal ein Bild angehängt (die Datenformate sind allerdings veraltet). Vllt sollte ich wirklich noch ein zusätzliches Schieberegister einbauen, welches die Werte a_sop weiterschiebt, wobei es ja so eigtl. automatisch klappen müsste. Scheint irgendwie so zu sein, dass ich mir aus den 32 kHz Abtastrate intern versehentlich eine 16 kHz Abtastrate mache. Vielen Dank Gustl! Hast mir mal wieder sehr gut geholfen.
:
Bearbeitet durch User
Ich habe gerade mal versucht die Daten mit Python einzulesen und als .bin zu speichern, aber hat leider nicht auf Anhieb geklappt. Habe es mit COM17 und COM18 versucht, aber beide male war das Bin-File leer. Ich muss mir das morgen nochmal genauer anschauen. 8 MBaud habe ich im Code angegeben. Vllt haben die Leitungen auch keinen guten Kontakt oder mein gebasteltes Framework hat noch einen Fehler.
Mario A. schrieb: > Ich möchte alle Multiplikationen parallel in einem Takt haben. Ja, in der Tat, das könnte klappen. Die Multiplikationen sind ja unabhängig voneinander, die laufen gut in einem Takt. Aber die Summe ist nicht unabhängig von der Summe vorher. Das bedeutet, die Summe müsste ebenfalls in einem Takt gebildet werden und damit das funktioniert natürlich erst wenn die Multiplikationen fertig sind. Wenn du dir in deiner Kette den zweiten Mutliply Adder anguckst. Der bekommt irgendwann ein Startsignal - so wie die neben ihm auch. Was leigt zu diesem Zeitpunkt an seinem C Post an? Das ist noch nicht das Ergebnis der Multiplikation vom ersten Mutliply Adder. Sondern das ist das Ergebnis des ersten Mutliply Adder aus dem vorherigen Takt. Wenn du das wirklich so machen willst, dann würde ich die Summe kombinatorisch bilden. Und damit das tatsächlich funktioniert, das wird ja eine Summe über viele Werte in einem Takt, solltest du das constrainen. Es reicht ja wenn die mit 32 kHz fertig wird. Das ist machbar, aber nicht innerhalb eines Taktes bei 200 MHz. Wenn du das willst musst du die Summe schrittweise berechnen. Ich finde das mit dem Vorbeischieben von Koeffizienten, Abtastwerten oder Summe recht einfach, geht aber auch anders. Du kannst auch jetzt schreiben bei N Koeffizienten:
1 | type sum_array_type is array (0 to N-1) of signed(47 downto 0); |
2 | signal sum_array: sum_array_type; |
3 | |
4 | process begin |
5 | wait until rising_edge(clk); |
6 | for I in 0 to N-1 loop |
7 | sum_array(I) <= Koeffizienten(I) * Abtastwert; |
8 | end loop; |
9 | end process; |
Und dann entweder kombinatorisch eine Summe bilden:
1 | signal Summe: signed(63 downto 0):=(others => '0'); |
2 | |
3 | process(sum_array) |
4 | variable Laufende_Summe: signed(63 downto 0); |
5 | begin
|
6 | Laufende_Summe:= (others => '0'); |
7 | for I in sum_array'range loop |
8 | Laufende_Summe := Laufende_Summe + sum_array(I); |
9 | end loop; |
10 | Summe <= Laufende_Summe; |
11 | end process; |
Das ist dann aber langsam und funktioniert garantiert nicht in einem Takt bei 200 MHz. Oder du machst die Summenbildung getaktet, dauert aber viele Takte. Ich finde das mit der Stückweisen Berechnung einfacher, da wird quasi die Summe geschoben.
1 | type sum_array_type is array (0 to N-1) of signed(47 downto 0); |
2 | signal sum_array: sum_array_type; |
3 | |
4 | signal Ausgabewert: signed(23 downto 0):=(others => '0'); |
5 | |
6 | process begin |
7 | wait until rising_edge(clk); |
8 | sum_array(0) <= Koeffizienten(0) * Abtastwert |
9 | for I in 1 to N-1 loop |
10 | sum_array(I) <= sum_array(I-1) + Koeffizienten(I) * Abtastwert; |
11 | end loop; |
12 | Ausgabewert <= (sum_array(N-1)*ganze_Zahl)/2**exponent; |
13 | end process; |
Wobei ganze Zahl und Exponent so zu wählen sind dass die Amplitude am Ausgang wieder passt. Mario A. schrieb: > aber beide male war das Bin-File leer. Mario A. schrieb: > Ich habe jetzt mal alles angeschlossen: > PMOD Pin 1 (FT2232H_RX_PMOD) geht auf AD1 (RxD) > PMOD Pin 2 (FT2232H_TX_PMOD) geht auf AD0 (TxD) > PMOD Pin 5 auf GND Genau. Vertausche mal die Pins, also verbinde die über Kreuz. Denn der RX Pin auf deinem FT2232H Board will ja die Daten von dem TX Pin des FPGA Boards.
:
Bearbeitet durch User
>>Sondern das ist das Ergebnis des ersten Mutliply Adder aus dem vorherigen Takt. Das würde ja an sich passen? Hab dir das mal in den Anhang gehängt. Der Ansatz müsste doch der transponierten Direktform 2 entsprechen. >>Denn der RX Pin auf deinem FT2232H Board will ja die Daten von dem TX Pin des FPGA Boards. Oh stimmt, vielen Dank!! Scheint jetzt zu funktionieren. Hab mal die beiden Binaries angehängt. Ich schreibe jetzt mal den Pythoncode für die Decodierung um. :)
Mario A. schrieb: > Das würde ja an sich passen? Hab dir das mal in den Anhang gehängt. Der > Ansatz müsste doch der transponierten Direktform 2 entsprechen. Aus dem Bildchen verstehe ich das nicht, aber oben hast du ja das Schematic Bild FIR Zoom gezeigt. Hm, ja das könnte schon passen, bin mir aber nicht sicher. Die Summe wandert da tatsächlich der Reihe nach durch. Hast du das schonmal simuliert? Mario A. schrieb: > Hab mal die > beiden Binaries angehängt. Die gucke ich mir nachher mal an, werde mich melden.
>>Hast du das schonmal simuliert?
Ich hab das schon mal simuliert, aber die Werte könnte ich trotzdem
nochmal prüfen.
Ich setze später einfach mal den Filterwert auf 1 und setze alle
Koeffizienten auch auf 1. Dann sollte man sehr schön sehen, wie sich der
Wert schrittweise erhöht.
Bin gerade dabei die Decodierung umzuschreiben. Da muss ich mich erst
mal noch einlesen.
Das ist das Datenformat?
1 | packet <= '0' & s_audio_l_out(23 downto 18) & '1' |
2 | & s_audio_l_out(17 downto 11) & '0' |
3 | & s_audio_l_out(10 downto 4) & '0' |
4 | & s_audio_l_out(3 downto 0) & |
5 | |
6 | s_audio_l_in(23 downto 21) & '0' |
7 | & s_audio_l_in(20 downto 14) & '0' |
8 | & s_audio_l_in(13 downto 7) & '0' |
9 | & s_audio_l_in(6 downto 0) & '0' & |
10 | |
11 | '0' & s_audio_r_out(23 downto 18) & '0' |
12 | & s_audio_r_out(17 downto 11) & '0' |
13 | & s_audio_r_out(10 downto 4) & '0' |
14 | & s_audio_r_out(3 downto 0) & |
15 | |
16 | s_audio_r_in(23 downto 21) & '0' |
17 | & s_audio_r_in(20 downto 14) & '0' |
18 | & s_audio_r_in(13 downto 7) & '0' |
19 | & s_audio_r_in(6 downto 0) & '0'; |
Was ich nicht verstehe sind die Dateinamen: UART_FT2232H_8MBaud_Signals_Right.bin UART_FT2232H_8MBaud_Signals_Left.bin Dein Datenformat enthält doch schon beide Kanäle, wieso also zwei Dateien? Mario A. schrieb: > Bin gerade dabei die Decodierung umzuschreiben. Da muss ich mich erst > mal noch einlesen. Geduld, Geduld, kommt gleich (-:
Also es ist ja so, dass ich nur immer an einem Kanal die Sweeps machen kann. Deswegen brauche ich 2 Dateien. An sich würde eine reichen, wenn ich für beide Channels sweepen könnte. Muss nur noch rausfinden was du bei L_bits und R_bits machst. :) Der Rest steht schon. Datenformat stimmt ja! Hab ein falsches Binary hochgeladen. Änder ich noch! Da sind keine Sweeps dabei.
:
Bearbeitet durch User
Mario A. schrieb: > Also es ist ja so, dass ich nur immer an einem Kanal die Sweeps machen > kann. Einfach elektrisch verbinden mit einem Draht^^ Mario A. schrieb: > Muss nur noch rausfinden was du bei L_bits und R_bits machst. :) Der > Rest steht schon. Naja, ich fische die jeweiligen Bits raus. #Format: #0AAAAAA1 -- Byte 0 #AAAAAAA0 -- Byte 1 #AAAAAAA0 -- Byte 2 #AAAABBB0 -- Byte 3 Wie hole ich also die Bits für A? Das Vorzeichen ist das MSB, also das Bit 6 aus Byte 0. Das kann man abfragen durch Maskierung, es hat den Wert 64. Wir machen also eine AND Verknüpfung: Byte_0 & 64. Ist das Bit 6 gesetzt dann bekommt man 64 als Wert zurück wenn nicht dann Null. Zwei Beispiele: Byte 0 = 01111001 01111001 & 01000000 = 01000000 Byte 0 = 00111001 00111001 & 01000000 = 00000000 Jetzt will ich aber statt 64 oder 0 die Werte 1 und 0. Also teile ich noch durch 64. A_sign = int((sr[0] & 64)/64) Wie bekomme ich die anderen 23 Bits von A? Die übrigen Bits von A in Byte 0 kann man ebenfalls maskieren mit dem Wert 62. Denn 62 = 00111110 Byte_0 & 62 liefert dann die maskierten Bits zurück. Beispiele: Byte 0 = 01111001 01111001 & 00111110 = 00111001 Byte 0 = 00010111 00010111 & 00111110 = 00010110 Das sind aber 5 mmaskierte Bits, und das LSB wird nicht maskiert, der Wert ist also um Faktor 2 zu hoch. Muss man noch bedenken. Bei den anderen Bytes wie Byte 1 ist das einfacher. #AAAAAAA0 -- Byte 1 Da werden alle Bits für A verwendet bis auf das LSB. Also kann man einfach alle Bits um 1 nach rechts verschieben und dann den 7-Bit-Wert verwenden. Wert = Byte1 >> 1 Bei Byte_3 muss dann um 4 Bits nach rechts verschoben werden. Und dann kommen noch die Zweierpotenzen dazu, die sind nötig um die Bits mit der passenden Wertigkeit innerhalb des 24 Bit Wertes zu darzustellen. Also zusammen: Vorzeichen(A) = (Byte_0 & 64)/64 Wert(Byte_0) = Byte_0 & 62 Wert(Byte_1) = Byte_1 >> 1 Wert(Byte_2) = Byte_2 >> 1 Wert(Byte_3) = Byte_3 >> 4 Gesamtwert = Wert(Byte_0)*2**17 + Wert(Byte_1)*2**11 + Wert(Byte_2)*2**4 + Wert(Byte_3) Und dann mit dem Vorzeichen muss man eben gucken ob das positiv ist oder negativ. So, im Anhang Code und Bildchen, sieht doch gut aus, Gratulation! Aber beachte auch die y-Skala, das ist teilweise ein sehr geringer Wertebereich und wohl eher leise. Edit: Und du hast weiterhin einige Fehler in den Übertragungen. Woran das liegt weiß ich nicht. Es sind 534746 korrekte Pakete und 28904 Fehler. Also grob 5 %, finde ich viel. Kann man Python liegen, da müsstest du öfter mehr vom UART lesen damit der nicht überläuft, kann aber auch an der Elektrik liegen, das würde man mit dem Oszi sehen.
:
Bearbeitet durch User
So hätte ich das jetzt gemacht. Scheint noch etwas falsch zu sein. Ah ich seh grad du warst schneller. :D :D :D Vielen Dank! Danke für die ausführliche Erklärung! Also haben die Binaries gepasst. Ich schaus mir gleich an. Mal schauen wo mein Fehler ist. ;)
:
Bearbeitet durch User
So, jetzt hab ich mal die Fehler geplottet. Sieht sehr periodisch aus. Das könnte also sein, dass der UART Empfangspuffer überläuft weil das Python zu selten/zu wenige Daten abholt.
Hab schon ein paar kleine Fehler im Code gefunden.
>>Das könnte also sein, dass der UART Empfangspuffer überläuft weil das
Python zu selten/zu wenige Daten abholt.
Oh ok. Danke für den Hinweis. Soll ich an den Einstellungen was ändern?
Der/ein Fehler in deinem Python ist, dass das jetzt 14 Bytes sind von Byte 0 bis Byte 13. Rin_bits muss also auch die Bytes 10,11,12 und 13 umfassen. Und: Code am besten als Text anhängen und nicht als Bild. Mario A. schrieb: > Soll ich an den Einstellungen was ändern? Klar, sonst bleiben die Fehler ja weiterhin. Du sollst also häufiger Daten vom UART abholen. Also zwischendurch kürzer schlafen gehen sleep(0.001) oder gar nicht schlafen. Vielleicht geht das auch anders, weiß ich aber nicht. Du kannst das auch in C und vermutlich auch in Matlab machen wenn du die D2XX von FTDI verwendest, hier https://www.ftdichip.com/Support/Documents/ProgramGuides/D2XX_Programmer%27s_Guide(FT_000071).pdf ist die API schön mit Beispielen beschrieben.
Ja habs schon gesehen, danke. :) Ich wusste, dass ich´s ändern muss aber hab versehentlich nur das am Zeilenanfang angepasst. Also die Aufnahmen wurden mit sleep(0.001) gemacht. Dann versuche ich es mal mit sleep(0.0001) oder noch weniger. Danke! Hab nochmal die 2 Binaries angehängt (sleep ist hier noch auf 0.001). Bei dem einen Kanal war leider noch kein Sweep drauf, hab vergessen umzustecken. Deswegen waren die Werte so gering.
:
Bearbeitet durch User
Mario A. schrieb: > Ich wusste, dass ich´s ändern muss aber > hab versehentlich nur das am Zeilenanfang angepasst. Sowas passiert mir auch oft. Da merkt man sich etwas, findet eine weitere Baustelle und kommt dann nicht zurück weil man es vergessen hat. Mario A. schrieb: > Also die Aufnahmen wurden mit sleep(0.001) gemacht. Dann versuche ich es > mal mit sleep(0.0001) oder noch weniger. Danke! Dann nimm das sleep mal komplett raus. Mario A. schrieb: > Hab nochmal die 2 Binaries angehängt Da hast du was anderes hochgeladen ...
:
Bearbeitet durch User
Die neuen haben an jedem Channel 1 Sweep. Also du brauchst beide Dateien damit du dir den linken und rechten Channel ansehen kannst. Habs mir gerade mit deinem Code plotten lassen. :) Danke! Ja ich mach nochmal die Aufnahmen.
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.