• 正文
    • 設(shè)計(jì)背景
    • 設(shè)計(jì)原理
    • 設(shè)計(jì)架構(gòu)
    • 設(shè)計(jì)代碼
    • 仿真測(cè)試
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

源碼系列:基于FPGA的任意波形發(fā)生器(DDS)設(shè)計(jì)(附源工程)

2024/11/21
4816
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大俠好,歡迎來(lái)到FPGA技術(shù)江湖,江湖偌大,相見(jiàn)即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。

今天給大俠帶來(lái)基于FPGA的任意波形發(fā)生器設(shè)計(jì),附源碼,獲取源碼,請(qǐng)?jiān)凇癋PGA技術(shù)江湖”公眾號(hào)內(nèi)回復(fù)“? ?DDS設(shè)計(jì)源碼”,可獲取源碼文件。話(huà)不多說(shuō),上貨。

設(shè)計(jì)背景

DDS(Direct Digital Synthesizer)直接數(shù)字式頻率合成器,是一種新型頻率合成技術(shù),具有低成本、低功耗、高分辨率、相對(duì)帶寬大和頻率轉(zhuǎn)換時(shí)間短等優(yōu)點(diǎn)。較容易實(shí)現(xiàn)頻率、相位以及幅度的數(shù)控調(diào)制,廣泛應(yīng)用在電信與電子儀器和通信領(lǐng)域。波形發(fā)生器是一種數(shù)據(jù)信號(hào)發(fā)生器,在調(diào)試硬件時(shí),常常需要加入一些信號(hào),以觀察電路工作是否正常。加入的信號(hào)有:正弦波、三角波、方波和任意波形等。

設(shè)計(jì)原理

相位(phase)是對(duì)于一個(gè)波,特定的時(shí)刻在它循環(huán)周期中的位置:一種它是否在波峰、波谷或它們之間的某點(diǎn)的標(biāo)度。相位描述信號(hào)波形變化的度量,通常以度 (角度)作為單位,也稱(chēng)作相角。當(dāng)信號(hào)波形以周期的方式變化,波形循環(huán)一周即為360°。那么相位可調(diào)也可以簡(jiǎn)單的理解為:改變初始相位。

頻率,是單位時(shí)間內(nèi)完成周期性變化的次數(shù),是描述周期運(yùn)動(dòng)頻繁程度的量,常用符號(hào)f或ν表示,單位為秒分之一,符號(hào)為s-1,頻率可調(diào)也就是改變單位時(shí)間內(nèi)完成周期性變化的次數(shù)。

本設(shè)計(jì)采用DDS技術(shù)設(shè)計(jì)相位頻率可調(diào)的波形發(fā)生器,已經(jīng)知道了相位和頻率可調(diào)分別代表什么,那么接下來(lái)就要知道怎樣依靠DDS技術(shù)實(shí)現(xiàn)波形發(fā)生器,并且相位和頻率可以調(diào)控。DDS的基本結(jié)構(gòu)如下圖所示:

根據(jù)上圖可以看出:DDS主要由相位累加器、波形數(shù)據(jù)表(ROM)、D/A轉(zhuǎn)換器構(gòu)成,本設(shè)計(jì)暫時(shí)不涉及D/A轉(zhuǎn)換部分。相位累加器位寬為N,波形數(shù)據(jù)表的大小為2^P,累加器的高P位則用于尋址波形數(shù)據(jù)表,即ROM,從ROM中輸出的數(shù)據(jù)則是產(chǎn)生的波形。如果累加器在系統(tǒng)時(shí)鐘(CLOCK)的作用下,以步進(jìn)為M累加直至溢出,則M為頻率控制字(即圖中的FWORD),相位控制字(PWORD)則作為累加器的輸入初始值。這里的累加器,也可以理解為ROM的地址發(fā)生器。

上段所述我們可具體理解為:改變地址的初值(PWORD)就可以改變初始的相位,由于我們?cè)O(shè)計(jì)中,ROM的數(shù)據(jù)為256,所以PWORD 的值在0~255之間,PWORD= 256*(初始相位/360度)。

我們?cè)O(shè)計(jì)的系統(tǒng)時(shí)鐘(CLOCK)為50MHz,周期為20ns,而正弦波被分成了256個(gè)點(diǎn),波形發(fā)生器的頻率就是195.31KHz。若想要輸出別的頻率,則可通過(guò)改變輸出的點(diǎn)的個(gè)數(shù),即改變有效地址的數(shù)量。我們用位寬為N位的累加器,假設(shè)FWORD為1,要產(chǎn)生一個(gè)完整波形的周期則為20ns*2^N,則產(chǎn)生波形的頻率=系統(tǒng)時(shí)鐘/2^N,即Fout = Fclk/2^N,如果FWORD為B,每次步進(jìn)的間隔提高了B倍,所以計(jì)滿(mǎn)一個(gè)波形周期的時(shí)間就縮小了B倍,即頻率就提高了B倍。則波形頻率的公式為:Fout = B*(Fclk/2^N)。之后我們?nèi)±奂悠鞯母?位,去尋址波形數(shù)據(jù),對(duì)應(yīng)點(diǎn)的還是個(gè)數(shù)一樣的。本設(shè)計(jì)中我們將N取為32,當(dāng)B=1,F(xiàn)out約為0.012Hz,0.012就相當(dāng)于最小精度,所以我們就實(shí)現(xiàn)了頻率為0.012倍數(shù)的調(diào)制,但因?yàn)?.012值很小了,所以可以說(shuō)基本實(shí)現(xiàn)了所有頻率的調(diào)制。

設(shè)計(jì)架構(gòu)

根據(jù)上述的原理圖分析,本設(shè)計(jì)的架構(gòu)如下圖:

架構(gòu)圖中的端口功能描述如下表:

dds_addr模塊是實(shí)現(xiàn)相位累加器的模塊,這里用參數(shù)來(lái)調(diào)制FWORD和PWORD的值,累加之后,將地址高八位(addr_out)輸出到rom模塊,從而產(chǎn)生波形數(shù)據(jù)。

設(shè)計(jì)代碼

在具體寫(xiě)代碼之前,我們需要先制作載有波形數(shù)據(jù)的mif文件,這時(shí)需要一個(gè)小軟件(Mif_Maker2010),軟件的安裝包和源碼一起,大俠可以去公眾號(hào)內(nèi)獲取。

具體操作步驟如下:

打開(kāi)Mif_Maker2010,在查看中點(diǎn)擊全局參數(shù),如下圖:

將全局參數(shù)設(shè)置如下圖:數(shù)據(jù)長(zhǎng)度為256,數(shù)據(jù)位寬為8,數(shù)據(jù)格式為無(wú)符號(hào)10進(jìn)制,采樣頻率為1000。

點(diǎn)擊設(shè)定波形,選擇想要生成的波形,這里我們以正弦波為例,如需要其他波形,都可進(jìn)行修改:

之后點(diǎn)擊保存,則可生成mif文件,這里我們命名為sin.mif。打開(kāi)sin.mif后,如下圖所示:

dds_addr模塊代碼:

這里我們以初始相位為180度,頻率為5KHz為例:

module dds_addr (clk, rst_n, addr_out);
  input clk, rst_n;   //系統(tǒng)時(shí)鐘復(fù)位  output [7:0] addr_out;  //輸出的地址,對(duì)應(yīng)到ROM內(nèi)的數(shù)據(jù)     parameter N = 32;  parameter PWORD = 128;  //相位控制字 (x/360)*256  parameter FWORD = 429497; //頻率控制字F_out=B*(F_clk/2**32),fword=B  //5KHZ  reg [N-1:0] addr;  //32位累加器    always @ (posedge clk or negedge rst_n)  begin    if (!rst_n)      begin        addr <= 32'd0;  //相位控制字      end    else      begin  /*每隔fword的大小,輸出一位地址,若頻率控制字FWORD等于2,那么地址計(jì)數(shù)器輸出的就依次是0,2,4.....*/            addr <= addr + FWORD;      end      end   /*將累加器器的地址的高八位賦值給輸出的地址(ROM的地址*/  assign addr_out = addr[N-1:N-8] + PWORD;
endmodule 

rom模塊為調(diào)用的IP核,該rom IP核中存儲(chǔ)了sin.mif的數(shù)據(jù)。

dds頂層模塊代碼:

module dds (clk, rst_n, q);
  input clk, rst_n;   //系統(tǒng)時(shí)鐘復(fù)位  output [7:0] q;     //輸出波形數(shù)據(jù)    wire [7:0] addr_out;  //8位地址,對(duì)應(yīng)到ROM內(nèi)的數(shù)據(jù)    /*****相位累加器模塊*****/  dds_addr dds_addr_inst(    .clk(clk),     .rst_n(rst_n),    .addr_out(addr_out)  );    /*****波形數(shù)據(jù)模塊*****/  rom  rom_inst (    .address ( addr_out ),    .clock ( clk ),    .q ( q )  );
endmodule

仿真測(cè)試

dds_tb頂層模塊的測(cè)試模塊:

`timescale 1ns/1ps
module dds_tb;
  reg clk, rst_n;  wire [7:0] q;    initial begin    clk = 1;    rst_n = 0;    #200.1    rst_n = 1;        #50_000_000 $stop;  end 
  dds dds_dut(    .clk(clk),     .rst_n(rst_n),    .q(q)  );    always #10 clk = ~clk;
endmodule 

仿真圖:

根據(jù)上圖可知,我們的設(shè)計(jì)正確。并且可以實(shí)現(xiàn)相位和頻率可調(diào)。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶(hù)資源
  • 寫(xiě)文章/發(fā)需求
立即登錄

任何技術(shù)的學(xué)習(xí)就好比一個(gè)江湖,對(duì)于每一位俠客都需要不斷的歷練,從初入江湖的小白到歸隱山林的隱世高人,需要不斷的自我感悟自己修煉,讓我們一起仗劍闖FPGA乃至更大的江湖。