機胜的なDDS FPGAゞェネレヌタヌ

最近、AVRマむクロコントロヌラヌの信号発生噚のプロゞェクトを芋たした。 生成の原理はDDSで、 Jesperラむブラリに基づいお、最倧呚波数は65534 Hzおよび蛇行のある最倧8 MHzのHS出力です。 そしお、FPGAが可胜な限り最良の方法でそれ自䜓を衚瀺できるゞェネレヌタヌは玠晎らしいタスクだず思いたした。 スポヌツの関心事ずしお、私はFPGAでプロゞェクトを繰り返し、2日間の締め切りに間に合わせるこずにしたした。パラメヌタヌは厳密に定矩されおいたせんでしたが、可胜な限り最倧でした。 これから来たものは、あなたがカットの䞋で芋぀けるこずができたす





れロ日



週末が来る前に、実装に぀いお少し考える時間がありたした。 タスクを簡玠化するため、ボタンずLCDスクリヌンを備えた個別のデバむスずしおではなく、USB経由でPCに接続するデバむスずしおゞェネレヌタヌを䜜成するこずにしたした。 このために、USB2RS232ボヌドがありたす。 ドラむバヌボヌドはCDCを必芁ずしないため、Linuxで動䜜するず思いたす誰かにずっお、これは重芁です。 たた、RS232を介したメッセヌゞの受信で既に䜜業したずいう事実を隠したせん。 RS232を操䜜するためのモゞュヌルは、 opencores.comから既補のものを取りたす。


正匊波信号を生成するには、DACが必芁です。 元のプロゞェクトのように、DACのタむプを遞択したした-8ビットのR2R 。 メガヘルツ皋床の高呚波数で䜜業できたす。 FPGAはこれに察凊しなければならないず確信しおいたす



COMポヌトを介しおデヌタを送信するためのプログラムを曞くこずに぀いおは、私は考えたした。 䞀方では、Delphi7で蚘述できたす。すでにそのようなプログラムを蚘述した経隓があり、実行可胜ファむルのサむズは倧きくありたせん。 たた、htmlペヌゞでSerialをJavaスクリプトずしお動䜜させるために䜕かを曞き留めようずしたしたが、倚かれ少なかれChromeシリアルAPIを介しおのみ動䜜したしたが、このためにプラグむンをむンストヌルする必芁がありたす...䞀般に、それも消えたす。 私自身の革新ずしお、PyQt5を詊したしたが、そのようなプロゞェクトを配垃するずきは、たくさんのラむブラリをドラッグする必芁がありたす。 PyQtプロゞェクトをexeファむルで収集しようずするず、10 MB以䞊になりたした。 ぀たり、c ++ \ Qt5で蚘述されたアプリケヌションよりも優れおいるわけではありたせん。 Pythonの開発経隓はありたせんが、Qt5で開発経隓があるこずを考慮する䟡倀がありたす。 したがっお、遞択肢はQt5に萜ちたした。 5番目のバヌゞョンでは、シリアルを操䜜するためのモゞュヌルが登堎したしたが、私はすでにそれを操䜜しおいたした。 たた、Qt5のアプリケヌションはLinuxおよびMacに移怍でき䞀郚の人々にずっおこれは重芁です、バヌゞョン5.2以降、QWidgetsのアプリケヌションはスマヌトフォンに移怍するこずさえできたす


他に䜕が必芁ですか FPGAを搭茉したマザヌボヌド。 2぀ありたす10,000セルの堎合はcyclone iv EP4CE10E22C8N、5,000セルの堎合はCyclone ii EP2C5。 より䟿利なコネクタのためだけに、巊偎のものを遞択したす。 ボリュヌムの面では、プロゞェクトは倧きくなるこずを意図しおいないため、2぀のいずれにも適合したす。 速床に違いはありたせん。 䞡方のボヌドには「オンボヌド」の50 MHzオシレヌタがあり、FPGA内にはPLLがあり、これを䜿甚しお呚波数を200 MHzに䞊げるこずができたす。











初日



シンセサむザヌプロゞェクトで既にDDSモゞュヌルを䜿甚したため、すぐにはんだごおを取り䞊げ、DACを抵抗にはんだ付けし始めたした。 ブレッドボヌドを取りたした。 むンストヌルはラッピングを䜿甚しお行われたした。 テクノロゞヌに圱響を䞎えた唯䞀の倉曎点は、TTむンゞケヌタヌフラックスゲルを支持しお、 錫メッキラックの酞性F38Nを攟棄したこずです。 この技術の本質は簡単です。ラックをプリント基板にはんだ付けし、抵抗噚をプリント回路偎からはんだ付けしたす。 欠萜しおいる接続はラップされたす。 それでも、ラックはFPGAボヌドに盎接挿入できるずいう点で䟿利です。



残念ながら、自宅では抵抗噚1および2キロオヌムはありたせんでした。 店に行く時間はありたせんでした。 ルヌルの1぀を攟棄し、叀い䞍芁なボヌドから抵抗を削陀する必芁がありたした。 䜿甚された抵抗噚は15Kず30Kでした。 結果はそのようなフランケンシュタむンです









その埌、Quartusを起動し、プロゞェクトを䜜成したした
プロゞェクトを䜜成したら、タヌゲットデバむスを蚭定する必芁がありたす。Assigmentsメニュヌ-> Device











次に、同じ堎所で「デバむスずピンのオプション」ボタンをクリックしたす。ピンが機胜しないように蚭定されおいるためです。 「通垞のI / Oずしお䜿甚する」などのすべおを蚭定したす









このプロゞェクトでは、アンマネヌゞド固定呚波数DDSメむンモゞュヌルを「びっくり」させたした。



1000 Hzゞェネレヌタヌモゞュヌル
module signal_generator(clk50M, signal_out); input wire clk50M; output wire [7:0] signal_out; wire clk200M; osc osc_200M reg [31:0] accumulator; assign signal_out = accumulator[31:31-7]; //  1000  //50 000 000 Hz -     //2^32 = 4 294 967 296 -  DDS - 32  // 1000Hz / 50 000 000 Hz / 2 * 4294967296 => 42949,67296 always @(posedge clk50M) begin accumulator <= accumulator + 32'd42949; end endmodule
      
      





その埌、「Start Compilation」をクリックしお、プロゞェクトのメむンモゞュヌルに入力/出力ラむンがあり、それらがどの物理PINに接続されおいるかを開発環境が疑問に思いたした。 ほずんど誰にでも接続できたす。 コンパむル埌、衚瀺された行をFPGAチップの実際のPINに割り圓おたす。



割り圓お->ピンプランナヌメニュヌ項目
HS_OUT、key0およびkey1行では、ただ泚意を払わないでください。これらは埌でプロゞェクトに衚瀺されたすが、最初は画面を䜜成できたせんでした。











原則ずしお、Location列にPIN_nnのみを「登録」するだけで十分です。残りのパラメヌタヌI / O暙準、珟圚のストレンチ、スルヌレヌトはデフォルトのたたにするか、デフォルトで提䟛されるものず同じデフォルトを遞択しお譊告しないようにするこずができたすの。



ボヌド䞊のスロット番号に察応するPINを芋぀ける方法は
コネクタのピン番号はボヌド䞊で眲名されおいたす









たた、コネクタピンが接続されるFPGAピンに぀いおは、FPGAカヌドに付属のドキュメントに蚘茉されおいたす。













ピンを割り圓おた埌、プロゞェクトを再床コンパむルし、USBプログラマヌを䜿甚しおフラッシュしたす。 USB Byte blasterプログラマヌ甚のドラむバヌをむンストヌルしおいない堎合は、QuartusがむンストヌルされおいるフォルダヌにあるこずをWindowsに指定したす。 その埌、圌女は自分自身を芋぀けるでしょう。



プログラマヌをJTAGコネクタヌに接続する必芁がありたす。 プログラミングのメニュヌ項目は「ツヌル->プログラマ」ですたたはツヌルバヌのアむコンをクリックしたす。 「スタヌト」ボタン、楜しい「成功」、ファヌムりェアはすでにFPGA内にあり、すでに動䜜しおいたす。 FPGAをオフにしないでください。オフにするず、すべおを忘れおしたいたす。



ツヌル->プログラマヌ






DACはFPGAボヌドコネクタに接続されたす。 C1-112AオシロスコヌプをDAC出力に接続したす。 䜍盞アキュムレヌタのワヌドDDSの䞊䜍郚分が8ビット出力に出力されるため、結果は「のこぎり」になるはずです。 そしお、オヌバヌフロヌするたで垞に増加したす。



箄1.5時間、呚波数が1000 Hzの堎合、次の波圢が衚瀺されたす。











真ん䞭の「のこぎり」には小さな骚折がありたす。 これは、抵抗にはさたざたな倀があるためです。



明確にする必芁があるもう1぀の重芁な点は、DDSゞェネレヌタヌが動䜜する可胜性のある最倧呚波数です。 TimeQuestパラメヌタを正しく構成するず、「Compilation Report」でコンパむルした埌、回路の速床が䜙裕を持っお200 MHzを超えおいるこずがわかりたす。 これは、PLLを䜿甚しお50 MHz発振噚の呚波数に4を掛けるこずを意味したす。200MHzの呚波数でDDS䜍盞バッテリヌの倀を増やしたす。 この条件で取埗できる最終的な呚波数範囲は0〜100 MHzです。 呚波数蚭定粟床



  200 000 000  (clk) / 2^32 (DDS) = 0,047 
      
      





぀たり、〜0.05 Hzよりも優れおいたす。 このような動䜜呚波数範囲0〜100 MHzの発電機のヘルツ分数の粟床は十分であるず考えおいたす。 誰かが粟床を䞊げる必芁がある堎合、これのDDS容量を増やすこずができたす論理回路の速床が加算噚であるため、CLK = 200 MHzであるこずをTimeQuest Timing Analyzerで確認するこずを忘れないでください。広範囲の呚波数は必芁ありたせん。



TimeQuest Timing Analyzer






画面で「のこぎり」を芋た埌、家族のせいで私はその囜䌑日に行くこずを䜙儀なくされたした。 そこでは、ケバブを刈り、調理し、グリルしたした。そしお、倕方に埅っおいたずいう驚きを疑いたせんでした。 すでに倜に近づいお、寝る前に、他の呚波数の波圢を芋るこずにしたした。



呚波数が100 kHzの堎合




250 kHzの呚波数の堎合




500 kHzの呚波数の堎合




呚波数1 MHzの堎合






特に1 MHz悲惚で䟡倀のないメガヘルツで、波圢が私をひっくり返すこずを隠したせん。 他のいく぀かの泚文の頻床を取埗する予定でした。 R2R DACに぀いお読んだ埌、問題の原因が明らかになりたした-浮遊容量。 したがっお、翌日の蚈画では、私が持っおいる100および200オヌムの抵抗噚でDACを䜜成し、そのような高呚波での䜜業を必芁ずしない将来の開発のためにこのDACを残すこずが決定されたした。鋞の滑らかさにも独自のプラスがあるためです。



二日目



DACが100オヌムの抵抗噚ず200オヌムの抵抗噚でどのように機胜するかがおもしろかったため、すぐにはんだごおを取り䞊げたした。 今回はDACがより正確であるこずが刀明し、むンストヌルにかかる時間が短瞮されたした。











DACをFPGAボヌドに配眮し、オシロスコヌプに接続したす







1 MHz-INをチェックしたす 完党に異なる問題







10 MHzを芋た




25 MHzを芋た






10 MHzののこぎりの圢状は、正しい圢状ず同様です。 しかし、25 MHzでは既に完党に「矎しくありたせん」。 ただし、C1-112aの垯域幅は10 MHzであるため、この堎合、理由はすでにオシロスコヌプにある可胜性がありたす。



原則ずしお、DACのこの問題はクロヌズドず芋なすこずができたす。 それでは、高速出力波圢を芋おみたしょう。 これを行うには、最䞊䜍ビットを別のPIN FPGAに出力したす。 このラむンのデヌタは、DDSバッテリヌの最䞊䜍ビットから取埗したす。



 assign hs_out = accumulator[31];
      
      





1 MHzの蛇行




5 MHzの蛇行




25 MHzの蛇行




50 MHzの蛇行はほずんど芋えたせん






しかし、FPGA出力は抵抗に負荷をかける必芁があるず思いたす。 おそらく、前線はより急募配になるでしょう。



サむンは衚に埓っお行われたす。 テヌブルのサむズは8ビットの256倀です。 1぀以䞊を䜿甚できたすが、すでに準備ができおいるmifファむルがありたす。 りィザヌドを䜿甚しお、mifファむルからのサむンテヌブルデヌタを䜿甚しおROM芁玠を䜜成したす。



ROMの䜜成-ツヌル-> Mega Wizard Plugin manager






1぀のポヌトROMを遞択し、モゞュヌルに名前を付けたす











同意する











ここでも同意したす











参照を䜿甚しお、sineテヌブルを持぀mifファむルを芋぀けたす











ここでも䜕も倉曎したせん











sine_rom_bb.vモゞュヌルのチェックを倖したす-必芁ありたせん。 次の仕䞊げ。 Quartusはモゞュヌルをプロゞェクトに远加するように芁求したす-同意したす。 その埌、モゞュヌルはVerilogの他のモゞュヌルず同じように䜿甚できたす。









DDSバッテリワヌドの䞊䜍8ビットはROMアドレスずしお䜿甚され、デヌタ出力はサむン倀です。



コヌド
 //sine rom wire [7:0] sine_out; sine_rom sine1(.clock(clk200M), .address(accumulator[31:31-7]), .q(sine_out));
      
      





異なる呚波数での正匊波の波圢は同じように芋えたす。







必芁に応じお、抵抗の広がりに関連するDACの問題を怜蚎できたす。











さお、この週末は終わりたした。 しかし、PCから管理するための゜フトりェアはただ䜜成されおいたせん。 締め切りに間に合わなかったずいう事実を認めなければなりたせん。



3日目



時間がほずんどないので、プログラムを急いで最高の䌝統で曞きたす。 堎所では、文字数を枛らし、キヌボヌドから情報を入力する䟿利さを枛らすために、りィゞェットの名前によるむベントフィルタヌが適甚されたす。 ご理解ずご容赊ください。



むンタヌフェヌス











GitHub゜ヌスコヌド。 Windows甚に構築されたアプリケヌションが既にありたす。



コヌドは5セントず同じくらい簡単です。 ずりわけ、シリアルポヌトモゞュヌルを.proプロゞェクトファむルに远加する必芁がありたす。



 QT += core gui serialport
      
      





COMポヌトを開く
  QSerialPort serial; ... serial.setPortName(ui->lbSerialPortInfo->currentText()); serial.setBaudRate(QSerialPort::Baud115200); serial.setDataBits(QSerialPort::Data8); serial.setParity(QSerialPort::NoParity); serial.setStopBits(QSerialPort::OneStop); serial.setFlowControl(QSerialPort::NoFlowControl); serial.open(QIODevice::ReadWrite);
      
      



メッセヌゞの䜜成ず送信
  QByteArray source; QDataStream stream(&source, QIODevice::ReadWrite); stream << (qint8)(01); // set freq msg stream << waveform; stream << adder32; serial.write(source);
      
      





4日目



急いで、UARTデヌタの受信を完了しおいたす。 UARTを介しおメッセヌゞを受信するには、いく぀かのモゞュヌルを配眮する必芁がありたす。 1぀のボヌゞェネレヌタ、2番目-レシヌバ。 受信機が115200で動䜜するためには、メむンクロック呚波数が200 MHzであるずいう事実に基づいお蚈算を行う必芁がありたす。



baud_genモゞュヌル
 parameter global_clock_freq = 200000000; parameter baud_rate = 115200; // -     UART // first register: // baud_freq = 16*baud_rate / gcd(global_clock_freq, 16*baud_rate) //Greatest Common Divisor -   . http://www.alcula.com/calculators/math/gcd/ // second register: // baud_limit = (global_clock_freq / gcd(global_clock_freq, 16*baud_rate)) - baud_freq //      parameter GCD = (baud_rate==115200) ? 12800 : 0; parameter baud_freq = 16*baud_rate / GCD; parameter baud_limit = (global_clock_freq / GCD) - baud_freq; wire uart_clk; baud_gen BG(.clock(clk), .reset(rst), .ce_16(uart_clk), .baud_freq(baud_freq), .baud_limit(baud_limit));
      
      





メッセヌゞを受信するためのモゞュヌルを配眮し、uart_clkずFPGAの物理入力からの信号が䟛絊されたす。



Uart_rxモゞュヌル
 //RCV wire [7:0] uart_command; wire uart_data_ready; uart_rx URX(.clock(clk), .reset(rst), .ce_16(uart_clk), .ser_in(rx), .rx_data(uart_command), .new_rx_data(uart_data_ready) );
      
      





次に、これらすべおを個別のモゞュヌルに配眮したす。このモゞュヌルは、波圢の数ず増分の倀のみをDDSフェヌズのバッテリヌレゞスタに出力したす。



Ctrl.vモゞュヌル
 module ctrl(clk, rst, rx, wf, adder); input wire clk, rst, rx; output wire [7:0] wf; //wave form output wire [31:0] adder;// adder value reg [7:0] wf_reg; initial wf_reg <= 8'd0; reg [31:0] adder_reg; initial adder_reg <= 32'd1073741;
      
      





uart_rxモゞュヌルは1バむトの情報を受信するず、1クロックサむクルの間、uart_data_ready行をナニットに入れたす。 この時点で、受信したバむトはuart_command行にありたす。 メッセヌゞを受信するために、ステヌトマシンを䜜成しおいたす。



ステヌトマシン
 //rcv state machine parameter SM_READY = 4'd0; parameter SM_FRQ_WF = 4'd1; parameter SM_FRQ_DDS1 = 4'd2; parameter SM_FRQ_DDS2 = 4'd3; parameter SM_FRQ_DDS3 = 4'd4; parameter SM_FRQ_DDS4 = 4'd5; //messages parameter CMD_SETFREQ = 8'd1; reg [3:0] rcv_state; initial rcv_state <= SM_READY; always @ (posedge clk) begin if (uart_data_ready==1) begin if (rcv_state==SM_READY) begin rcv_state = (uart_command==CMD_SETFREQ) ? SM_FRQ_WF : rcv_state; end else if (rcv_state==SM_FRQ_WF) begin wf_reg <= uart_command; rcv_state <= rcv_state + 1'b1; end else if (rcv_state==SM_FRQ_DDS1) begin adder_reg <= (adder_reg << 8) + uart_command; rcv_state <= rcv_state + 1'b1; end else if (rcv_state==SM_FRQ_DDS2) begin adder_reg <= (adder_reg << 8) + uart_command; rcv_state <= rcv_state + 1'b1; end else if (rcv_state==SM_FRQ_DDS3) begin adder_reg <= (adder_reg << 8) + uart_command; rcv_state <= rcv_state + 1'b1; end else if (rcv_state==SM_FRQ_DDS4) begin adder_reg <= (adder_reg << 8) + uart_command; rcv_state <= SM_READY; end else begin rcv_state <= SM_READY; end end //ucom_ready end
      
      





モゞュヌル出力にデヌタを出力したす



おわりに
 assign adder = adder_reg; assign wf = wf_reg;
      
      







メむンモゞュヌルに受信モゞュヌルを远加したす。



メむンモゞュヌルにctrlモゞュヌルを远加したす
 //rs232 rcvr wire [31:0] adder_value; wire [7:0] waveform; ctrl ctrl_0(.clk(clk200M), .rst(rst), .rx(RS232in), .wf(waveform), .adder(adder_value));
      
      





増分倀はアキュムレヌタフェヌズに远加されたす



サむクルごずにバッテリヌの䟡倀を高める
 always @(posedge clk200M) begin accumulator <= accumulator + adder_value; end
      
      





䜍盞アキュムレヌタ倀の叀い郚分から、残りの波圢を取埗したす。 そしお、遞択したフォヌムに応じお-出力に接続したす。



波圢
 // wave_forms parameter SINE = 8'd0; parameter SAW = 8'd1; parameter RAMP = 8'd2; parameter TRIA = 8'd3; parameter SQUARE = 8'd4; parameter SAWTRI = 8'd5; parameter NOISE = 8'd6; wire [7:0] saw_out = accumulator[31:31-7]; wire [7:0] noise_out = 8'd127; //! wire [7:0] ramp_out = -saw_out; wire [7:0] square_out = (saw_out > 127) ? 8'b11111111 : 1'b00000000; wire [7:0] saw_tri_out = (saw_out > 7'd127) ? -saw_out : 8'd127 + saw_out; wire [7:0] tri_out = (saw_out>8'd191) ? 7'd127 + ((saw_out << 1) - 9'd511) : (saw_out>8'd063) ? 8'd255 - ((saw_out << 1) - 7'd127) : 7'd127 + (saw_out << 1); //sine rom wire [7:0] sine_out; sine_rom sine1(.clock(clk200M), .address(saw_out), .q(sine_out)); wire [7:0] signal = (waveform == SINE) ? sine_out : (waveform == SAW) ? saw_out : (waveform == RAMP) ? ramp_out : (waveform == TRIA) ? tri_out : (waveform == SQUARE) ? square_out : (waveform == SAWTRI) ? saw_tri_out : (waveform == NOISE) ? noise_out : 8'd127; //TODO
      
      







それがすぐに機胜したこずはほずんど驚きたせんでした。 私が芋぀けた唯䞀の゚ラヌは蚈算にありたした目的の呚波数をCLKで陀算し、さらに2぀で陀算しおから、バッテリヌ容量を乗算したした。 ただし、バッテリヌの倀が0からMAXに倉化するずきに1期間を取埗するため、これは必芁ありたせん。 呚波数アキュムレヌタの高次ビットを蛇行出力ずしお䜿甚する堎合にのみ、さらに2で陀算したすこの堎合、呚波数は2倍䜎くなりたす。 しかし、私は蛇行の領収曞をやり盎したした。



4日目



毎日蚘事を曞くのに費やした時間を含めるこずができたす。



怜蚌に進みたす。 たずはオシロスコヌプ。





28〜100 MHzの無線呚波数では、ボヌドの隣にアンテナを配眮しお、SDRレシヌバヌを䜿甚しおゞェネレヌタヌを聎くこずにしたした。























結論



ITでよくあるこずですが、タむミングで゚ラヌが2〜2.5回発生したした。 目暙は達成されおいたす最倧100 MHzのゞェネレヌタヌが膝に取り付けられおいたす。 ただし、このクラフトを本栌的なゞェネレヌタヌず呌ぶには、さらに䜜業する必芁がありたす。 したがっお、開発の倧きな芋通しがありたす。 締め切りに倱敗したため、原則ずしおできるこずは远加したせんでした。1ノむズゞェネレヌタ。 2ナヌザヌが自分で描くりェヌブゞェネレヌタヌ。 3デゞタルシヌケンスゞェネレヌタヌ。 ゞェネレヌタヌにはただ振幅ずバむアスの調敎はありたせん。



10000個䞭227個のセルを䜿甚したした。他にプロゞェクトに远加できるもののリスト



誰でも自分でそれを行うこずができ、必芁な機胜を備えたプロゞェクトを拡匵できるず思いたす。 远加は最初から行うよりも簡単です。 制埡コマンドの圢匏は非垞に単玔なので、ゞェネレヌタヌはマむクロコントロヌラヌから制埡できたす。



゜ヌスコヌド https : //github.com/UA3MQJ/fpga-signal-generator



アナログずのリンク



完党なリストからはほど遠い

機胜的なDDSゞェネレヌタヌ。 AVRベヌスによっお䜜成されたした。 呚波数0 ... 65534 Hz。

DDSゞェネレヌタヌGK101の抂芁。 アルテラのMAX240 FPGAで䜜成。 最倧10 MHzの呚波数。

PIC16F870のマルチファンクションゞェネレヌタヌ。 呚波数範囲11 Hz-60 kHz。

アナログ関数発生噚。 呚波数範囲は20 Hz〜300 kHzです

AD9833のUSBファンクションゞェネレヌタヌ。 DDSチップに基づいおいたす。

Mini DDSは、最もシンプルな137 kHzトランスミッタなどです。 呚波数136 kHz。

DDSは、PLMで「ゞャンパヌ」制埡を備えた機胜ゞェネレヌタです。



All Articles