基于FPGA的DDS信號(hào)發(fā)生器
? ? 兩個(gè)禮拜前就像寫這個(gè)文檔了,但是一直鴿到現(xiàn)在,主要是人擺了。還有個(gè)技術(shù)上的原因是,我想用串口屏顯示波形,在串口調(diào)試助手上返回的數(shù)據(jù)是對(duì)的,但是發(fā)到串口屏上啥反應(yīng)沒有,人就很麻,如果這個(gè)弄不出來,前面HMI串口屏的工程、人機(jī)交互界面就白做了?;貧w正題,下面開始講DDS信號(hào)發(fā)生器的理論和代碼實(shí)現(xiàn)。
一、理論部分
? ? 理論部分主要是從野火的簡易DDS信號(hào)發(fā)生器的設(shè)計(jì)與驗(yàn)證課程中學(xué)習(xí)而來,加入了大量的我的理解,代碼部分對(duì)野火的代碼做了很多擴(kuò)展,使得其更加完善。
1、DDS是啥
? ? 隨便從某個(gè)地方摘了一點(diǎn):
DDS 是直接數(shù)字式頻率合成器(Direct Digital Synthesizer)的英文縮寫,是一項(xiàng)關(guān)鍵的數(shù)字化技術(shù)。與傳統(tǒng)的頻率合成器相比,DDS 具有低成本、低功耗、高分辨率和快速轉(zhuǎn)換時(shí)間等優(yōu)點(diǎn),廣泛使用在電信與電子儀器領(lǐng)域,是實(shí)現(xiàn)設(shè)備全數(shù)字化的一個(gè)關(guān)鍵技術(shù)。作為設(shè)計(jì)人員,我們習(xí)慣稱它為信號(hào)發(fā)生器,一般用它產(chǎn)生正弦波、鋸齒波、方波等不同波形或不同頻率的信號(hào)波形,在電子設(shè)計(jì)和測試中得到廣泛應(yīng)用。
總之DDS就是一個(gè)信號(hào)發(fā)生器,能夠產(chǎn)生不同種類、不同頻率和不同初相的波形。
2、總體框圖
? ? 上圖為DDS的基本結(jié)構(gòu),主要由相位累加器、相位調(diào)制器、波形數(shù)據(jù)表 ROM 、D/A轉(zhuǎn)換器四大結(jié)構(gòu)組成。CLK是系統(tǒng)工作時(shí)鐘,頻率為
f
C
L
K
f_{CLK}
fCLK?;頻率字輸入F_WORD,為整數(shù),控制輸出信號(hào)的頻率大小,它可以理解為一個(gè)步進(jìn)值(后面具體說明);相位字輸入P_WORD,為整數(shù),控制輸出信號(hào)的相位偏移;由于我沒有D/A轉(zhuǎn)換器,所以直接輸出8位的數(shù)字信號(hào),設(shè)其頻率為
f
O
U
T
f_{OUT}
fOUT?。
? ? 另外提一句,之前我想用串口屏當(dāng)作示波器用顯示波形,但是串口屏本身仍然還是一個(gè)數(shù)字器件,不是模擬器件,它也是根據(jù)0~255的量化電平值作為電壓值,顯示出高低不同的像素點(diǎn)從而形成曲線,與示波器接收D/A轉(zhuǎn)換器轉(zhuǎn)后后的模擬電壓值(像0.2V,1.4V等等)是不同的。
3、模塊介紹
- 輸入緩存器:在將頻率字和相位字輸入之后,有一個(gè)累加寄存器,是在系統(tǒng)時(shí)鐘同步下做數(shù)據(jù)寄存,使得數(shù)據(jù)改變時(shí)不會(huì)干擾后續(xù)相位累加器和相位調(diào)制器的正常工作。
-
相位累加器:
- 該部分是DDS的核心部分,在這里完成相位累加,生成相位碼。為什么叫相位累加器呢,我的想法是,DDS產(chǎn)生信號(hào)的本質(zhì)即為從ROM中讀取一個(gè)周期的一個(gè)個(gè)信號(hào)點(diǎn)的值進(jìn)行循環(huán)輸出,在這一個(gè)周期內(nèi),從讀一個(gè)點(diǎn)的值到讀下一個(gè)點(diǎn)的值即為相位的偏移??偟南辔淮a即對(duì)應(yīng)ROM地址中的一個(gè)周期的所有數(shù)據(jù)(事實(shí)上只取了相位碼的高位部分)。
- 相位累加器的的輸入為頻率字輸入F_WORD,表示相位累加在每個(gè)時(shí)鐘周期的增量,也可以理解為一個(gè)步進(jìn)值,我在代碼中用
fre_step
表示。當(dāng)相位碼(我在代碼中用fre_add
表示)累加溢出之后,表示一個(gè)周期的信號(hào)輸出完畢。 - 工作時(shí)鐘信號(hào)頻率
f
C
L
K
f_{CLK}
fCLK?,輸出信號(hào)頻率與頻率字輸入F_WORD之間的關(guān)系式為
f
O
U
T
=
F
W
O
R
D
?
f
C
L
K
/
2
N
f_{OUT} = F_{WORD} * f_{CLK} / 2^N
fOUT?=FWORD??fCLK?/2N。其中N為頻率字輸入F_WORD和相位碼的位寬,我在代碼中設(shè)置為32,可以通過
parameter
進(jìn)行更改。上式可以這樣理解,從硬件角度理解,當(dāng)頻率字輸入F_WORD為1時(shí),有關(guān)系式 f O U T = f C L K / 2 N f_{OUT} = f_{CLK} / 2^N fOUT?=fCLK?/2N,在 2 N 2^N 2N計(jì)數(shù)容量內(nèi),每個(gè)時(shí)鐘周期增加1,記滿 2 N 2^N 2N后輸出一個(gè)ROM中的信號(hào)值;也可從數(shù)學(xué)角度理解為輸出頻率為系統(tǒng)時(shí)鐘頻率除以 2 N 2^N 2N。此時(shí)的 f O U T f_{OUT} fOUT?為DDS的最小分辨率,輸出信號(hào)頻率最低。當(dāng)頻率字輸入F_WORD增大時(shí),每個(gè)時(shí)鐘周期的累加增量擴(kuò)大了F_WORD倍,因此輸出頻率是在最小分辨率的基礎(chǔ)上乘以了這個(gè)倍數(shù)。
-
相位調(diào)制器:相位調(diào)制器接收相位累加器輸出的相位碼,同時(shí)加上相位偏移值(相位字輸入)P_WORD,用于信號(hào)的相位調(diào)制。和相位字輸入P_WORD有關(guān)的關(guān)系式為
θ
=
P
W
O
R
D
?
2
π
/
2
M
\theta = P_{WORD} * 2\pi / 2^M
θ=PWORD??2π/2M。其中
θ
\theta
θ為波形初相位,M為ROM地址位寬,在代碼中相位字輸入為
pha_step
,含義為一步相位偏移。上式可以這樣理解,一個(gè)周期信號(hào)對(duì)應(yīng)角度 2 π 2\pi 2π對(duì)應(yīng)ROM中的4096個(gè)數(shù)據(jù),因此 2 π / 2 M 2\pi / 2^M 2π/2M則表示了每個(gè)數(shù)據(jù)的輸出對(duì)應(yīng)的相位增加值,乘以相位偏移值后得到總的偏移初相。 -
波形數(shù)據(jù)表:
- 波形數(shù)據(jù)表為一個(gè)ROM IP核,其中存有一個(gè)完整周期的正弦波信號(hào)。代碼中我設(shè)置的ROM IP核深度為4096,地址位寬即為12,數(shù)據(jù)存儲(chǔ)位寬為8位。用MATLAB產(chǎn)生ROM IP核所需要的 .mif文件,將一個(gè)周期的正弦波信號(hào)(還有方波,鋸齒波和三角波信號(hào)),沿橫軸等間隔采樣4096次,每次采集的信號(hào)幅度用一字節(jié)數(shù)據(jù)表示,最大值為255,最小值為0。將4096次采樣結(jié)果按順序?qū)懭?em>ROM的4096個(gè)存儲(chǔ)單元,則一個(gè)完整周期的正弦波的數(shù)字幅度信號(hào)寫入了波形數(shù)據(jù)表ROM中。波形數(shù)據(jù)表ROM以相位調(diào)制器傳入的相位碼為ROM讀地址,將地址對(duì)應(yīng)的存儲(chǔ)單元中的電壓幅值數(shù)字量輸出。
- 關(guān)于從相位累加器得到的相位碼對(duì)ROM進(jìn)行尋址的問題。由上文所說,N為相位累加器的位寬,M為ROM地址位寬,M由一個(gè)信號(hào)周期的采樣點(diǎn)數(shù)決定,怎樣決定N的大小我還不知道。對(duì)于N位的相位累加器,相位碼的最大值為 2 N 2^N 2N,如果ROM中存儲(chǔ)單元的個(gè)數(shù)也為 2 N 2^N 2N的話,這個(gè)問題就很好解決,但是這對(duì)ROM存儲(chǔ)容量的要求就較高。在實(shí)際中可以采用相位碼的高幾位對(duì)ROM進(jìn)行尋址,也就是說不是每個(gè)系統(tǒng)時(shí)鐘周期都對(duì)ROM進(jìn)行數(shù)據(jù)讀取,而是多個(gè)時(shí)鐘讀取一次。
4、對(duì)上述的理論舉個(gè)栗子
? ? 設(shè):ROM存儲(chǔ)單元深度為4096,則ROM地址位寬為12位,每個(gè)數(shù)據(jù)存儲(chǔ)單元位寬為8位,相位累加器位寬為32位。
? ? 由上述條件,根據(jù)DDS原理,相位累加器的32位與頻率控制字不斷累加;而在相位調(diào)制器中與相位控制字進(jìn)行累加時(shí),應(yīng)用相位累加器的高12位。由于采用相位累加器的高12位作為ROM尋址,當(dāng)?shù)?0位溢出向高12位加一時(shí),向ROM尋址一次輸出一個(gè)數(shù)據(jù)表中的數(shù)據(jù)。
? ? 以頻率控制字F_WORD=1為例,相位累加器的低20位會(huì)在每一個(gè)時(shí)鐘周期不斷加一,直到低20位溢出向高12位進(jìn)位,在溢出之前,讀取ROM的地址一直為0,也就是說ROM的0地址中的數(shù)據(jù)被讀了
2
20
2^{20}
220次。繼續(xù)下去在溢出后地址加一,讀向ROM地址1,這個(gè)數(shù)據(jù)被再次讀
2
20
2^{20}
220次。接下來的所有點(diǎn)都是如此。最終輸出的波形頻率應(yīng)該是工作時(shí)鐘頻率的
1
/
2
20
1/2^{20}
1/220,周期被擴(kuò)大了
2
20
2^{20}
220倍。
? ? 同樣當(dāng)頻率控制字F_WORD=100時(shí),相位累加器的低20位會(huì)一直加100,那么,相位累加器的低20位溢出的時(shí)間比上面會(huì)快100倍,則ROM中的每個(gè)點(diǎn)相比于上面會(huì)少讀100次,所以最終輸出頻率是上述的100倍。
二、代碼部分
1、波形控制部分代碼
module wave_ctrl #(
parameter DATA_WIDTH_ROM = 8, //輸出數(shù)據(jù)位寬
parameter N = 32, //相位累加器位寬
parameter M = 12, //相位調(diào)制器位寬
parameter ADDR = 12 //ROM數(shù)據(jù)表位寬
) (
input wire clk,
input wire rstn,
input wire [3:0] wave_sel, //波形選擇
input wire [N-1:0] fre_step, //頻率字輸入,相當(dāng)于一個(gè)步進(jìn)值,每個(gè)時(shí)鐘周期增加的值
input wire [M-1:0] pha_step, //相位字輸入,相當(dāng)于一個(gè)步進(jìn)值,每個(gè)時(shí)鐘周期增加的值
output wire [2*DATA_WIDTH_ROM-1:0] data_out
);
//四種波形信號(hào)選擇參數(shù)定義
parameter sin_wave = 4'b0001; //正弦波
parameter squ_wave = 4'b0010; //方波
parameter tri_wave = 4'b0100; //三角波
parameter saw_wave = 4'b1000; //鋸齒波
//頻率字和相位字輸入緩存
reg [N-1:0] fre_step_reg;
reg [M-1:0] pha_step_reg;
//相位累加信號(hào)和相位調(diào)制后信號(hào)
reg [N-1:0] fre_add; //相位碼
reg [M-1:0] pha_add;
//四種波形的ROM讀使能信號(hào)
reg [0:0] sin_wave_en;
reg [0:0] squ_wave_en;
reg [0:0] tri_wave_en;
reg [0:0] saw_wave_en;
//ROM讀地址
reg [ADDR-1:0] rom_addr;
reg [ADDR-1:0] sin_wave_rom_addr;
reg [ADDR-1:0] squ_wave_rom_addr;
reg [ADDR-1:0] tri_wave_rom_addr;
reg [ADDR-1:0] saw_wave_rom_addr;
//四種波形的ROM輸出信號(hào)
wire [DATA_WIDTH_ROM-1:0] sin_wave_data_out;
wire [DATA_WIDTH_ROM-1:0] squ_wave_data_out;
wire [DATA_WIDTH_ROM-1:0] tri_wave_data_out;
wire [DATA_WIDTH_ROM-1:0] saw_wave_data_out;
//波形選擇
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
sin_wave_en <= 1'b0;
squ_wave_en <= 1'b0;
tri_wave_en <= 1'b0;
saw_wave_en <= 1'b0;
sin_wave_rom_addr <= 0;
squ_wave_rom_addr <= 0;
tri_wave_rom_addr <= 0;
saw_wave_rom_addr <= 0;
end
case (wave_sel)
sin_wave: begin
sin_wave_en <= 1'b1;
squ_wave_en <= 1'b0;
tri_wave_en <= 1'b0;
saw_wave_en <= 1'b0;
sin_wave_rom_addr <= rom_addr;
end
squ_wave: begin
sin_wave_en <= 1'b0;
squ_wave_en <= 1'b1;
tri_wave_en <= 1'b0;
saw_wave_en <= 1'b0;
squ_wave_rom_addr <= rom_addr;
end
tri_wave: begin
sin_wave_en <= 1'b0;
squ_wave_en <= 1'b0;
tri_wave_en <= 1'b1;
saw_wave_en <= 1'b0;
tri_wave_rom_addr <= rom_addr;
end
saw_wave: begin
sin_wave_en <= 1'b0;
squ_wave_en <= 1'b0;
tri_wave_en <= 1'b0;
saw_wave_en <= 1'b1;
saw_wave_rom_addr <= rom_addr;
end
endcase
end
//頻率字輸入緩存器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
fre_step_reg <= 0;
end else begin
fre_step_reg <= fre_step;
end
end
//相位字輸入緩存器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
pha_step_reg <= 0;
end else begin
pha_step_reg <= pha_step;
end
end
//相位累加器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
fre_add <= 0;
end else begin
fre_add <= fre_add + fre_step_reg;
end
end
//相位調(diào)制器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
pha_add <= 0;
end else begin
pha_add <= fre_add[N-1:N-M] + pha_step_reg;
end
end
//將相位調(diào)制后信號(hào)作為ROM讀地址輸入
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
rom_addr <= 0;
end else begin
rom_addr <= pha_add;
end
end
sin_wave_rom_8x4096 sin_wave_rom_8x4096_inst (
.address(sin_wave_rom_addr),
.clock (clk),
.rden (sin_wave_en),
.q (sin_wave_data_out)
);
squ_wave_rom_8x4096 squ_wave_rom_8x4096_inst (
.address(squ_wave_rom_addr),
.clock (clk),
.rden (squ_wave_en),
.q (squ_wave_data_out)
);
tri_wave_rom_8x4096 tri_wave_rom_8x4096_inst (
.address(tri_wave_rom_addr),
.clock (clk),
.rden (tri_wave_en),
.q (tri_wave_data_out)
);
saw_wave_rom_8x4096 saw_wave_rom_8x4096_inst (
.address(saw_wave_rom_addr),
.clock (clk),
.rden (saw_wave_en),
.q (saw_wave_data_out)
);
assign data_out = (sin_wave_en ? sin_wave_data_out : 0) + (squ_wave_en ? squ_wave_data_out : 0) + (tri_wave_en ? tri_wave_data_out : 0) + (saw_wave_en ? saw_wave_data_out : 0);
endmodule //dds_ctrl
2、頻率、相位字控制代碼:
? ? 以下這份代碼的功能是可以分別輸入 fre_x
MHz, fre_y
kHz和 fre_z
Hz的頻率以及 pha_x
π
\pi
π和
(
1
/
p
h
a
_
y
)
?
π
(1/pha\_y)*\pi
(1/pha_y)?π的初相,并將以上的輸入數(shù)據(jù)通過公式轉(zhuǎn)換成頻率和相位字的代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-460483.html
module fre_pha_data_ctrl #(
parameter N = 32, //相位累加器位寬
parameter M = 12, //相位調(diào)制器位寬
parameter FRE_WIDTH = 10, //三路頻率輸入的位寬,三路頻率的單位分別為MHz,kHz,Hz
parameter PHA_WIDTH = 8, //兩路相位輸入的位寬,(x+1/y)pi
parameter DATA_WIDTH = 64
) (
input wire clk,
input wire rstn,
input wire [FRE_WIDTH-1:0] fre_x, //MHz
input wire [FRE_WIDTH-1:0] fre_y, //kHz
input wire [FRE_WIDTH-1:0] fre_z, //Hz
input wire [PHA_WIDTH-1:0] pha_x, //x*pi
input wire [PHA_WIDTH-1:0] pha_y, //(1/y)*pi
output wire [N-1:0] fre_step, //頻率字輸入,相當(dāng)于一個(gè)步進(jìn)值,每個(gè)時(shí)鐘周期增加的值
output wire [M-1:0] pha_step //相位字輸入,相當(dāng)于一個(gè)步進(jìn)值,每個(gè)時(shí)鐘周期增加的值
);
/* ----------頻率數(shù)據(jù)處理 fre_step---------- */
parameter _1MHZ = 1_000_000;
parameter _1KHZ = 1_000;
parameter CLK_IN = 64'd50 * _1MHZ;
wire [DATA_WIDTH-1:0] fre_out; //實(shí)際輸出信號(hào)頻率
wire [DATA_WIDTH-1:0] temp; //中間值,fre_out*(2^N)的值
reg [DATA_WIDTH-1:0] fre_reg_x; //頻率輸入x緩存信號(hào)
reg [DATA_WIDTH-1:0] fre_reg_y; //頻率輸入y緩存信號(hào)
reg [DATA_WIDTH-1:0] fre_reg_z; //頻率輸入z緩存信號(hào)
wire [DATA_WIDTH-1:0] fre_step_temp;
//單位MHz,化為Hz
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
fre_reg_x <= 64'd0;
end else begin
fre_reg_x <= fre_x * _1MHZ;
end
end
//單位kHz,化為Hz
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
fre_reg_y <= 64'd0;
end else begin
fre_reg_y <= fre_y * _1KHZ;
end
end
//單位Hz,寄存器緩存
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
fre_reg_z <= 64'd0;
end else begin
fre_reg_z <= fre_z;
end
end
//將三者相加得到實(shí)際輸出頻率
assign fre_out = fre_reg_x + fre_reg_y + fre_reg_z;
//將實(shí)際輸出頻率乘以2^N次方,即左移N位
assign temp = fre_out << N;
//將temp除以時(shí)鐘頻率CLK_IN
div_64_64_inst #(
.DATA_WIDTH(DATA_WIDTH)
) u_div_64_64_inst1 (
.numer_sig (temp),
.denom_sig (CLK_IN),
.quotient_sig(fre_step_temp),
.remain_sig ()
);
assign fre_step = fre_step_temp[N-1:0];
/* ----------相位數(shù)據(jù)處理 pha_step---------- */
reg [DATA_WIDTH-1:0] pha_reg_x; //相位輸入x緩存信號(hào)
reg [DATA_WIDTH-1:0] pha_reg_y; //相位輸入y緩存信號(hào)
wire [DATA_WIDTH-1:0] temp_x;
wire [DATA_WIDTH-1:0] temp_y;
wire [DATA_WIDTH-1:0] pha_step_temp;
//相位輸入x緩存器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
pha_reg_x <= 1'd1;
end else begin
pha_reg_x <= pha_x;
end
end
//相位輸入y緩存器
always @(posedge clk or negedge rstn) begin
if (rstn == 1'b0) begin
pha_reg_y <= 64'd1;
end else begin
pha_reg_y <= pha_y;
end
end
//計(jì)算X*2^(M-1)
assign temp_x = pha_reg_x << (M - 1);
//計(jì)算(1/Y)*2^(M-1)
div_64_64_inst #(
.DATA_WIDTH(DATA_WIDTH)
) u_div_64_64_inst (
.numer_sig (64'd2048),
.denom_sig (pha_reg_y),
.quotient_sig(temp_y),
.remain_sig ()
);
//計(jì)算pha_step,總表達(dá)式為(X+1/Y)*2^(M-1)
assign pha_step_temp = temp_x + temp_y;
assign pha_step = pha_step_temp[M-1:0];
endmodule //fre_pha_data_ctrl
3、合并以上兩個(gè)模塊的頂層文件:
module wave_ctrl_fre_pha_data_ctrl #(
parameter N = 32, //相位累加器位寬
parameter M = 12, //相位調(diào)制器位寬
parameter FRE_WIDTH = 10, //三路頻率輸入的位寬,三路頻率的單位分別為MHz,kHz,Hz
parameter PHA_WIDTH = 8, //兩路相位輸入的位寬,(x+1/y)pi
parameter DATA_WIDTH = 64,
parameter DATA_WIDTH_ROM = 8, //輸出數(shù)據(jù)位寬
parameter ADDR = 12 //ROM數(shù)據(jù)表位寬
) (
input wire [0:0] clk,
input wire [0:0] rstn,
input wire [FRE_WIDTH-1:0] fre_x, //MHz
input wire [FRE_WIDTH-1:0] fre_y, //kHz
input wire [FRE_WIDTH-1:0] fre_z, //Hz
input wire [PHA_WIDTH-1:0] pha_x, //x*pi
input wire [PHA_WIDTH-1:0] pha_y, //(1/y)*pi
input wire [3:0] wave_sel, //波形選擇
output wire [2*DATA_WIDTH_ROM-1:0] data_out
);
wire [N-1:0] fre_step;
wire [M-1:0] pha_step;
fre_pha_data_ctrl #(
.N (N),
.M (M),
.FRE_WIDTH (FRE_WIDTH),
.PHA_WIDTH (PHA_WIDTH),
.DATA_WIDTH(DATA_WIDTH)
) u_fre_pha_data_ctrl (
.clk (clk),
.rstn (rstn),
.fre_x (fre_x),
.fre_y (fre_y),
.fre_z (fre_z),
.pha_x (pha_x),
.pha_y (pha_y),
.fre_step(fre_step),
.pha_step(pha_step)
);
wave_ctrl #(
.DATA_WIDTH_ROM(DATA_WIDTH_ROM),
.N (N),
.M (M),
.ADDR (ADDR)
) u_wave_ctrl (
.clk (clk),
.rstn (rstn),
.wave_sel(wave_sel),
.fre_step(fre_step),
.pha_step(pha_step),
.data_out(data_out)
);
endmodule //tb_wave_ctrl_fre_pha_data_ctrl
4、關(guān)于IP核:
? ? 第一份代碼中實(shí)例化的四個(gè)單端口8x4096的ROM IP核,配置、調(diào)用及實(shí)例化IP核的過程這里不再描述,生成 .mif配置數(shù)據(jù)文件的MATLAB代碼將放在其他文章中給出,將會(huì)放在MATLAB數(shù)字信號(hào)處理專欄中。
? ? 第二份代碼中實(shí)例化了除法器,用于數(shù)據(jù)運(yùn)算。文章來源地址http://www.zghlxwxcb.cn/news/detail-460483.html
5、頂層代碼的testbench代碼:
`timescale 1ns / 1ns
module tb_wave_ctrl_fre_pha_data_ctrl;
// wave_ctrl_fre_pha_data_ctrl Parameters
parameter PERIOD = 10;
parameter N = 32;
parameter M = 12;
parameter FRE_WIDTH = 10;
parameter PHA_WIDTH = 8;
parameter DATA_WIDTH = 64;
parameter DATA_WIDTH_ROM = 8;
// wave_ctrl_fre_pha_data_ctrl Inputs
reg [ 0:0] clk = 0;
reg [ 0:0] rstn = 0;
reg [ FRE_WIDTH-1:0] fre_x = 0;
reg [ FRE_WIDTH-1:0] fre_y = 0;
reg [ FRE_WIDTH-1:0] fre_z = 0;
reg [ PHA_WIDTH-1:0] pha_x = 0;
reg [ PHA_WIDTH-1:0] pha_y = 0;
reg [ 3:0] wave_sel = 4'b001;
// wave_ctrl_fre_pha_data_ctrl Outputs
wire [2*DATA_WIDTH-1:0] data_out;
always #PERIOD clk = ~clk;
initial begin
#(PERIOD * 2 + PERIOD / 2) rstn = 1;
#(PERIOD) wave_sel = 4'b0001;
fre_x = 10;
pha_x = 0;
pha_y = 2;
#(PERIOD * 1000) wave_sel = 4'b0001;
fre_x = 2;
pha_x = 0;
pha_y = 2;
#(PERIOD * 1000) wave_sel = 4'b0010;
fre_x = 1;
pha_x = 1;
pha_y = 1;
#(PERIOD * 1000) wave_sel = 4'b0100;
fre_x = 1;
pha_x = 1;
pha_y = 1;
#(PERIOD * 1000) wave_sel = 4'b1000;
fre_x = 1;
pha_x = 1;
pha_y = 1;
end
wave_ctrl_fre_pha_data_ctrl #(
.N (N),
.M (M),
.FRE_WIDTH (FRE_WIDTH),
.PHA_WIDTH (PHA_WIDTH),
.DATA_WIDTH (DATA_WIDTH),
.DATA_WIDTH_ROM(DATA_WIDTH_ROM)
) u_wave_ctrl_fre_pha_data_ctrl (
.clk (clk[0:0]),
.rstn (rstn[0:0]),
.fre_x (fre_x[FRE_WIDTH-1:0]),
.fre_y (fre_y[FRE_WIDTH-1:0]),
.fre_z (fre_z[FRE_WIDTH-1:0]),
.pha_x (pha_x[PHA_WIDTH-1:0]),
.pha_y (pha_y[PHA_WIDTH-1:0]),
.wave_sel(wave_sel[3:0]),
.data_out(data_out[2*DATA_WIDTH-1:0])
);
initial begin
end
endmodule
到了這里,關(guān)于基于FPGA的DDS信號(hào)發(fā)生器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!