国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于AD9833的信號(hào)發(fā)生器

這篇具有很好參考價(jià)值的文章主要介紹了基于AD9833的信號(hào)發(fā)生器。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本文利用FPGA控制AD9833,實(shí)現(xiàn)信號(hào)發(fā)生器的功能。本文將對(duì)AD9833的手冊(cè)進(jìn)行詳細(xì)的解讀,并對(duì)其配置方法進(jìn)行解析,最后在Verilog中進(jìn)行編碼,將代碼燒錄置FPGA中,F(xiàn)PGA通過(guò)外部引腳控制AD9833輸出所需要的正弦波、方波和三角波。三種波形能夠輸出的頻率范圍為0~12.5Mhz。


前言

AD9833是一種低功率可編程波形發(fā)生器,能夠產(chǎn)生正弦、三角形和方波輸出。在各種類型的傳感、驅(qū)動(dòng)和時(shí)域反射測(cè)量應(yīng)用中,都需要產(chǎn)生波形。輸出頻率和相位是軟件可編程的,允許易于調(diào)整。不需要任何外部組件。頻率寄存器為28位;以25MHz的時(shí)鐘速率,可以達(dá)到0.1 Hz的分辨率。類似地,使用1MHz的時(shí)鐘速率,AD9833可以被調(diào)諧到0.004 Hz的分辨率。

AD9833是通過(guò)三線串行接口寫入的。該串行接口以時(shí)鐘速率高達(dá)40MHz,并與DSP和微控制器標(biāo)準(zhǔn)兼容。該設(shè)備的電源供電范圍為2.3V至5.5V。


一、AD9833數(shù)據(jù)手冊(cè)分析

博主將首先分析AD9833的數(shù)據(jù)手冊(cè),并列出博主認(rèn)為手冊(cè)中需要著重注意的點(diǎn),以便于后續(xù)代碼的提出。

1.1 AD9833特性分析

在AD9833的規(guī)格中,我們可以知道,其 V o u t V_{out} Vout? 也就是最大輸出電壓可以達(dá)到0.65V,其具體的表達(dá)式如下:
V O U T = V R E F × 18 × R LOAD / R S E T × ( 1 + ( S I N ( 2 π ( F R E Q R E G × f M C L K × t / 2 28 + P H A S E R E G / 2 12 ) ) ) ) V_{\mathsf{OUT}}=V_{\mathsf{REF}}\times18\times\mathsf{R}_\text{LOAD}/{ \mathsf{R}_{\mathsf{SET}}}\times(1+(\mathsf{SIN}(2\pi(\mathsf{FREQREG}\times\mathbf{f}_{\mathsf{MCLK}}\times\mathbf{t}_{/2}28+\mathsf{PHASEREG}_{/2}12)))) VOUT?=VREF?×18×RLOAD?/RSET?×(1+(SIN(2π(FREQREG×fMCLK?×t/2?28+PHASEREG/2?12))))

即:輸出電壓的大小跟參考電壓和負(fù)載電阻密切相關(guān),同時(shí)隨著設(shè)置波形頻率的變化而變化。

另外,AD9833的VDD的范圍為2.3V-5.5V,也就是說(shuō)你需要提供一定數(shù)值的電源電壓。

1.2 AD9833時(shí)鐘分析

在手冊(cè)中,我們可以看到AD9833的時(shí)鐘圖如圖1所示:
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖1 AD9833時(shí)鐘

在圖1中,我們需要著重關(guān)注的是AD9833的MCLK周期最小為40ns,也就是說(shuō)你需要提供25Mhz的激勵(lì)時(shí)鐘信號(hào),用于驅(qū)動(dòng)AD9833進(jìn)行內(nèi)部數(shù)據(jù)操作。

基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖2 AD9833操作時(shí)序

觀察圖2,我們可知:如何需要寫入AD9833的控制字,我們首先需要將FSYNC拉低,在SCLK操作時(shí)鐘的周期性變化下,將SDATA也就是操作字逐一寫入。需要注意的是,SCLK的操作時(shí)鐘周期最小需要25ns,高低電平的維持時(shí)間最小需要10ns,在最后一個(gè)下降沿?cái)?shù)據(jù)寫入后需要在10ns-20ns的時(shí)間內(nèi)將FSYNC的電平拉高,否則寫入無(wú)效。

1.3 AD9833引腳分析

AD9833的引腳圖如圖3所示:
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖3 AD9833引腳圖

在AD9833的引腳中,MCLK為激勵(lì)時(shí)鐘,我們采用25Mhz;FSYNC在拉低后進(jìn)行寫入操作,隨著SCLK的電平變化將SDATA的值讀入。另外,VDD和AGND之間應(yīng)連接一個(gè)0.1uF和一個(gè)10uF的解耦電容。

1.4 AD9833操作原理分析

要想講清楚AD9833的控制方式,我們需要重點(diǎn)觀察其操作字是如何定義的。
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖4 AD9833操作字

在上述的16個(gè)控制位中,博主將講解需要著重觀察的控制位,其他控制位請(qǐng)讀者自行查看手冊(cè)。

  • B28
    當(dāng)B28 = 1時(shí)允許連續(xù)兩次寫入將完整單詞加載到頻率寄存器中。第一次寫包含頻率單詞的14個(gè)LSB,下一次寫將包含14個(gè)MSB。每個(gè)16位字的前兩位定義了該字被加載到的頻率寄存器,因此,對(duì)于這兩個(gè)連續(xù)的寫操作,前兩位應(yīng)該是相同的。
    當(dāng)B28 = 0時(shí),28位頻率寄存器作為兩個(gè)14位寄存器運(yùn)行,一個(gè)包含14個(gè)MSB,另一個(gè)包含14個(gè)LSB。這意味著頻率詞的14個(gè)MSB可以獨(dú)立于14個(gè)LSB進(jìn)行改變,反之亦然。為了改變14個(gè)MSB或14個(gè)LSB,需要對(duì)適當(dāng)?shù)念l率地址進(jìn)行一次寫入??刂莆籇12(HLB)通知AD9833,要改變的位是14個(gè)MSB還是14個(gè)LSB。
    博主在后文中將B28 = 1,也就是連續(xù)寫入兩個(gè)16位字對(duì)頻率寄存器進(jìn)行更改。
  • RESET
    RESET = 1將內(nèi)部寄存器重置為0,這對(duì)應(yīng)于中度的模擬輸出。
    RESET = 0將禁用重置。
    需要注意的是,RESET將不重置相位、頻率和控制寄存器。另外,為了避免AD9833在初始化的時(shí)候出現(xiàn)虛假的DAC輸出,需要在進(jìn)行寫入操作時(shí)也就是B28 = 1時(shí)將RESET位置1。
  • MODE
    MODE位與OPBITEN(D5)一起使用。這個(gè)位的功能是控制芯片上DAC連接到VOUT時(shí)VOUT引腳的輸出。
    當(dāng)MODE = 1時(shí)三角波將從DAC中輸出。
    當(dāng)MODE = 0時(shí)正弦波將輸出。

接下來(lái)我們將利用代碼來(lái)詳細(xì)論述操作字的寫入流程。

二、FPGA控制代碼

我們將利用Verilog語(yǔ)言編寫FPGA的代碼,并用FPGA控制AD9833的SCLK、SDATA、FSYNC引腳,進(jìn)行寫入操作。

2.1 主函數(shù)

主函數(shù)中主要包含了各個(gè)模塊,并將模塊之間的變量聯(lián)系起來(lái)。

module Signal_Generate(
	input sys_clk,
	input sys_rst_n,
	
	input key0,				// 按鍵檢測(cè)切換波形狀態(tài)
	input key1,
	
	output MCP_CS,			// MCP使能標(biāo)志 		低電平有效
	output SCK,				// MCP輸入信號(hào)狀態(tài)	低電平信號(hào)變化 下降沿讀信號(hào)
	output SI,				// MCP輸入信號(hào)
	output AD_FSYNC			// AD使能標(biāo)志
	
    );

// parameter define
parameter   CLK_FREQ   = 26'd50_000_000;	// MCP模塊的驅(qū)動(dòng)時(shí)鐘頻率
parameter	MCP_FREQ   = 18'd25_000_000;	// MCP的SCK時(shí)鐘頻率

// wire define
wire 		MCP_CLK;						// MCP時(shí)鐘信號(hào)	
wire 		locked;						
wire [15:0] TxData;							// 寫入AD的操作數(shù)
wire 		TxData_en;						// 開始寫入標(biāo)志位
wire        TxData_done;					// 寫入完成標(biāo)志位			
wire [ 7:0] counter_rem;					// 實(shí)時(shí)觀察寫入情況
wire [ 7:0] counter_rem_driver;				// 實(shí)時(shí)觀察驅(qū)動(dòng)情況

//***************************************************
//**** main code ****
//***************************************************

// 例化按鍵消抖模塊
key_debounce u_key0_debounce(
	.clk		(sys_clk),
	.rst_n		(sys_rst_n),
	
	.key		(key0),
	.key_value	(key0_value),		// 按下后為低電平 	輸出
	.key_flag	(key0_flag)			// 按下后標(biāo)志位拉高	輸出
	);
	
key_debounce u_key1_debounce(
	.clk		(sys_clk),
	.rst_n		(sys_rst_n),
	
	.key		(key1),
	.key_value	(key1_value),		// 按下后為低電平 	輸出
	.key_flag	(key1_flag)			// 按下后標(biāo)志位拉高	輸出
	);	

// AD根據(jù)操作數(shù)寫入16bits模塊
AD_Write u_AD_Write(
	.clk		(sys_clk),
	.rst_n		(sys_rst_n),
	
	.TxData		(TxData),			// 寫入16位二進(jìn)制操作數(shù)
	.TxData_en	(TxData_en),		// 開始寫入標(biāo)志位 輸入
	.TxData_done(TxData_done),		// 寫入完成標(biāo)志位 輸出
	.counter_rem(counter_rem),		// 實(shí)時(shí)檢查寫入位置
	
	.AD_SCK		(SCK),				// AD操作時(shí)鐘
	.AD_FSYNC	(AD_FSYNC),			// AD使能標(biāo)志位
	.AD_SI		(SI)				// AD寫入數(shù)據(jù)
	);
	
// AD驅(qū)動(dòng)模塊
AD_Driver u_AD_Driver(
	.clk		(sys_clk),
	.rst_n		(sys_rst_n),
	
	.key0_value	(key0_value),
	.key0_flag	(key0_flag),
	.key1_value	(key1_value),
	.key1_flag	(key1_flag),
	
	.counter_rem_driver	(counter_rem_driver),	// 實(shí)時(shí)檢查驅(qū)動(dòng)位置
	.TxData_done		(TxData_done),			// 寫入完成標(biāo)志位 輸入	
	.TxData				(TxData),				// 寫入操作數(shù)
	.TxData_en			(TxData_en)				// 開始寫入標(biāo)志位 輸出
	);

// ILA檢測(cè)模塊
ila_0 u_ila_0(
	.clk	(sys_clk), 					// input wire clk

	.probe0	(AD_FSYNC), 				// input wire [0:0]  probe0  
	.probe1	(SCK), 						// input wire [0:0]  probe1 
	.probe2	(SI), 						// input wire [0:0]  probe2 
	.probe3	(TxData_en), 				// input wire [0:0]  probe3 
	.probe4	(TxData_done), 				// input wire [0:0]  probe4 
	.probe5	(TxData), 					// input wire [15:0] probe5
	.probe6	(counter_rem_driver) 		// input wire [7:0]  probe6
);   
	
endmodule

接下來(lái),我將對(duì)函數(shù)的主要功能進(jìn)行介紹。

  • key_debounce
    此函數(shù)的主要功能是對(duì)外部按鍵KEY0和KEY1是否按下進(jìn)行判斷,當(dāng)KEY0按下后,將進(jìn)行波形變換操作,當(dāng)KEY1按下后,將進(jìn)行頻率變換操作。后文會(huì)有提及。
  • AD_Write
    此函數(shù)主要功能是將一個(gè)16位的操作字根據(jù)一定的時(shí)序?qū)懭氲紸D9833中,在寫入完成后將TxData_done置位,AD_Driver接收到置位信息后,將后續(xù)需要寫入的操作字賦值給TxData中,并將開始寫入標(biāo)志位TxData_en置位。
  • AD_Driver
    此函數(shù)的主要功能是根據(jù)當(dāng)前狀態(tài)變更狀態(tài)字,以及控制AD9833需要輸出的波形和頻率。
  • ILA
    檢測(cè)模塊ILA用于實(shí)時(shí)檢測(cè)。

2.2 按鍵檢測(cè)模塊

按鍵檢測(cè)模塊通過(guò)延時(shí)消抖來(lái)檢測(cè)按鍵值變化是否有效。

module key_debounce(
	input clk,
	input rst_n,
	input key,				// 外部輸入按鍵值
	output reg key_value,	// 消抖后的按鍵值
	output reg key_flag		// 消抖后的按鍵值有效標(biāo)志
	);

reg [19:0] cnt;
reg key_reg;

// 按鍵值消抖
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		cnt 	<= 20'd0;
		key_reg <= 1'b1;
	end
	else begin
		key_reg <= key;
		if(key_reg != key) begin	// 檢測(cè)到按鍵值變化
			cnt <= 20'd100_0000;	// 開啟延時(shí)
		end
		else begin
			if(cnt > 20'd0)			// 延時(shí)過(guò)程
				cnt <= cnt - 1'b1;
			else
				cnt <= 20'd0;
		end
	end
end

// 輸出最終值
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		key_value <= 1'b1;			// 沒有按下時(shí)默認(rèn)為高電平
		key_flag  <= 1'b0;			// 標(biāo)志位為無(wú)效標(biāo)志
	end
	// 計(jì)時(shí)器遞減到1時(shí)輸出按鍵值
	else if(cnt == 20'd1) begin	
		key_value <= key;			// 將消抖后的數(shù)值保存
		key_flag  <= 1'b1;			// 標(biāo)志位為有效標(biāo)志
	end
	else begin
		key_value <= key_value;		// 計(jì)時(shí)器為結(jié)束則保持原有數(shù)值
		key_flag  <= 1'b0;
	end


end	
	
endmodule

KEY0和KEY1在復(fù)位狀態(tài)下為高電平,當(dāng)按鍵按下后變更為低電平。在此模塊中,我們用key_reg寄存器來(lái)存儲(chǔ)上一時(shí)刻KEY的狀態(tài),當(dāng)檢測(cè)到其與當(dāng)前時(shí)刻的KEY狀態(tài)不一致時(shí)進(jìn)行100_0000個(gè)時(shí)鐘周期的延時(shí),也就是20ns*100_0000=20ms的延時(shí),如果按鍵狀態(tài)在該時(shí)間內(nèi)為發(fā)生變化說(shuō)明按下有效。將key_valuekey_flag位變更。

2.3 操作寫入模塊

此模塊,用于將操作字根據(jù)一定的時(shí)序?qū)懭搿?/p>

module AD_Write(
	input clk,
	input rst_n,
	
	input [15:0] 	TxData,						// 寫入16位二進(jìn)制操作數(shù)
	input 			TxData_en,					// 開始寫入標(biāo)志位
	output reg 		TxData_done,				// 寫入完成標(biāo)志位	
	output 			counter_rem,				// 實(shí)時(shí)檢查寫入位置
	output reg 		AD_SCK,						// AD操作時(shí)鐘
	output reg 		AD_FSYNC,					// AD使能標(biāo)志位
	output reg 		AD_SI						// AD寫入數(shù)據(jù)
    );
	
// reg define
reg [15:0] 	data;								// 寫入的16位操作數(shù)
reg [ 7:0] 	counter;							// 寫入時(shí)序		
reg 		tx_en;								// 保存寫入標(biāo)志位

// wire define

	
//***************************************************
//**** main code ****
//***************************************************

assign counter_rem = counter;

// 使能后頻數(shù)計(jì)數(shù)器
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		counter 	<= 8'd0;
		TxData_done <= 1'b0;
		tx_en 		<= 1'b0;
	end
	else begin
		// 接收到發(fā)送信號(hào)
		if(TxData_en) begin
			tx_en <= 1'b1;						// 保存開始寫入標(biāo)志位
		end
		else begin
			if(tx_en) begin						// 數(shù)據(jù)發(fā)送時(shí)使能計(jì)數(shù)器
				if(counter < 8'd33) begin
					counter 	<= counter + 1'b1;
					TxData_done <= 1'b0;
				end else begin					// 在counter計(jì)數(shù)到完成操作后重置
					counter 	<= 8'd0;
					tx_en 		<= 1'b0;		// 結(jié)束發(fā)送
					TxData_done <= 1'b1;		// 置位操作完成位
				end
			end	
			else begin
				counter 	<= 8'd0;
				TxData_done <= 1'b0;
				tx_en 		<= tx_en;
			end
		end
	end

end

// Control the AD_SCK, AD_FSYNC, and DAT pins based on the TxData input
// AD在SCK為高電平時(shí)改變狀態(tài) 在SCK下降沿時(shí)寫入數(shù)據(jù)
always @ (posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        AD_SCK 		<= 1;
        AD_FSYNC 	<= 1;
        AD_SI 		<= 0;
    end else begin
		// 開始發(fā)送16bits數(shù)據(jù)
		if(tx_en) begin
			case(counter)
				// 準(zhǔn)備工作
				8'd0: begin
					data 		<= TxData;			// 寄存數(shù)據(jù)
					AD_SCK 		<= 1;				// FSYNC拉低時(shí)SCK為高
					AD_FSYNC 	<= 0;				// 使能發(fā)送
					AD_SI 		<= 0;				// 默認(rèn)
				end
				// first 16bits
				8'd1: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[15];			// SI取數(shù)據(jù)最高位
				end
				8'd2: begin
					AD_SCK 	<= 0;
				end
				8'd3: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[14];			
				end
				8'd4: begin
					AD_SCK 	<= 0;
				end
				8'd5: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[13];			
				end
				8'd6: begin
					AD_SCK 	<= 0;
				end
				8'd7: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[12];			
				end
				8'd8: begin
					AD_SCK 	<= 0;
				end
				8'd9: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[11];			
				end
				8'd10: begin
					AD_SCK 	<= 0;
				end
				8'd11: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[10];			
				end
				8'd12: begin
					AD_SCK 	<= 0;
				end
				8'd13: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[9];			
				end
				8'd14: begin
					AD_SCK 	<= 0;
				end
				8'd15: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[8];			
				end
				8'd16: begin
					AD_SCK 	<= 0;
				end
				8'd17: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[7];			
				end
				8'd18: begin
					AD_SCK 	<= 0;
				end
				8'd19: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[6];			
				end
				8'd20: begin
					AD_SCK 	<= 0;
				end
				8'd21: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[5];			
				end
				8'd22: begin
					AD_SCK 	<= 0;
				end
				8'd23: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[4];			
				end
				8'd24: begin
					AD_SCK 	<= 0;
				end
				8'd25: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[3];			
				end
				8'd26: begin
					AD_SCK 	<= 0;
				end
				8'd27: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[2];			
				end
				8'd28: begin
					AD_SCK 	<= 0;
				end
				8'd29: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[1];			
				end
				8'd30: begin
					AD_SCK 	<= 0;
				end
				8'd31: begin
					AD_SCK 	<= 1;
					AD_SI 	<= data[0];			// SI取數(shù)據(jù)最低位	
				end
				8'd32: begin
					AD_SCK 	<= 0;				// 寫入最后一位數(shù)據(jù)			
				end
				// the end
				8'd33: begin
					AD_SCK 		<= 1;
					AD_FSYNC 	<= 1;
					AD_SI 		<= 0;
				end
				default: begin
					AD_SCK 		<= 1;
					AD_FSYNC 	<= 1;
					AD_SI 		<= 0;
				end
			endcase
		end
		else begin
			AD_SCK 		<= 1;
			AD_FSYNC 	<= 1;
			AD_SI 		<= 0;
		end
    end
end
	
endmodule

當(dāng)檢測(cè)到操作寫入信號(hào)TxData_en被置位時(shí),將模塊內(nèi)寄存器tx_en置位,用于保存置位信號(hào),因?yàn)?code>TxData_en將在一個(gè)時(shí)鐘周期后被拉低。
當(dāng)置位信號(hào)保存完成后,將開始寫入操作,counter作為寫入的寄存器用于寄存當(dāng)前寫入的位置。當(dāng)counter為0時(shí),將需要寫入的數(shù)據(jù)保存到data中,并將FSYNC拉低,表示我們將要開始寫入操作。注意:在FSYNC拉低時(shí),我們需要確保SCK為高電平,否則FSYNC的拉低無(wú)效。
FSYNC拉低后,我們?cè)?code>SCK為高電平時(shí),變更SI為需要寫入數(shù)據(jù)的位次,保持一個(gè)時(shí)鐘周期20ns后,將SCK拉低,AD9833在SCK為下降沿時(shí)將SI的數(shù)據(jù)讀入。以此往復(fù)直至寫入完成的操作字。
在寫入完成后,我們需要在10ns-20ns的時(shí)間內(nèi)將FSYNC拉高,否則寫入無(wú)效。并將TxData_done置位,表示寫入完成了,可以進(jìn)行后續(xù)操作。

2.4 驅(qū)動(dòng)操作模塊

驅(qū)動(dòng)模塊,主要對(duì)寫入的操作字進(jìn)行變更,通過(guò)選擇合適的波形和頻率控制AD9833輸出。

module AD_Driver(
	input 	clk,
	input 	rst_n,
	
	input  	key0_value,
	input  	key0_flag,
	input  	key1_value,
	input  	key1_flag,
	
	output 	   [ 7:0] 	counter_rem_driver,
	
	input 				TxData_done,	// 寫入完成標(biāo)志位 	輸入	
	output reg [15:0] 	TxData,			// 寫入操作數(shù) 		輸出
	output reg 			TxData_en		// 開始寫入標(biāo)志位 	輸出
    );
	
// local parameter define
localparam [15:0] reset_add 		= 16'h0100;
localparam [15:0] write_freq 		= 16'h2100;
// 為了避免在AD9833被初始化時(shí)出現(xiàn)虛假的DAC輸出
// 復(fù)位位應(yīng)該被設(shè)置為1 直到部件準(zhǔn)備好開始生成輸出為止

// fMck=25Mhz
// (fMclk/2^28/fwanted)^(-1)=FREQREG; fwanted(min)=0.0931, fwanted(max)=25M
localparam [15:0] write_freq_lsb_3M = 16'h70b7;		// 輸出3M信號(hào)
localparam [15:0] write_freq_msb_3M = 16'h47ae;
localparam [15:0] write_freq_lsb_1M = 16'h6592;		// 輸出1M信號(hào)
localparam [15:0] write_freq_msb_1M = 16'h428f;
localparam [15:0] write_freq_lsb_1k = 16'h69f1;		// 輸出1k信號(hào)
localparam [15:0] write_freq_msb_1k = 16'h4000;
localparam [15:0] write_phase_c0 	= 16'hc000;		// 相位配置

localparam [15:0] write_sin 		= 16'h2000;		// 正弦波
localparam [15:0] write_traingle 	= 16'h2002;		// 三角波
localparam [15:0] write_square  	= 16'h2028;		// 方波

// reg define
reg [ 7:0] counter;				// 寫入操作開始后的位置
reg [31:0] delay_counter;		// 開始寫入操作前的延遲	
reg 	   delay_start;			// 延遲開始標(biāo)志位
reg        delay_end;			// 延遲結(jié)束標(biāo)志位

reg [ 2:0] waveform_select;		// 選擇波形
reg [ 2:0] freq_select;			// 選擇頻率
reg [15:0] write_waveform;		// 寫入的波形類型
reg [15:0] write_freq_lsb_c0;	// 寫入頻率數(shù)據(jù)的低位
reg [15:0] write_freq_msb_c0;	// 寫入頻率數(shù)據(jù)的高位

// wire define

//***************************************************
//**** main code ****
//***************************************************

assign counter_rem_driver = counter;

// 開始延遲計(jì)數(shù)器
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		delay_counter 	<= 32'b0;
		delay_start 	<= 1'b1;
		delay_end 		<= 1'b0;
		waveform_select <= 2'd0;
		freq_select 	<= 2'd0;
	end
	else begin
		// 初始化和波形頻率選擇后根據(jù)delay_start開啟延遲
		if(delay_start) begin
			if(delay_counter < 10'd1000) begin
				delay_counter = delay_counter + 1'b1;
			end
			else begin
				delay_counter 	<= 32'b0;
				delay_start 	<= 1'b0;
				// 將delay_end作為延遲結(jié)束的標(biāo)志 置1只存在一個(gè)周期
				delay_end 		<= 1'b1;
			end
		end
		// 根據(jù)按鍵調(diào)整波形和頻率
		else begin
			// key0按下調(diào)整輸出波形
			if((key0_flag == 1) && (key0_value == 0)) begin
				waveform_select <= waveform_select + 1'd1;
				delay_start 	<= 1'b1;
				delay_counter 	<= 32'b0;
				delay_end 		<= 1'b0;
			end
			// key1按下調(diào)整輸出頻率
			else if((key1_flag == 1) && (key1_value == 0)) begin
				freq_select 	<= freq_select + 1'd1;
				delay_start 	<= 1'b1;
				delay_counter 	<= 32'b0;
				delay_end 		<= 1'b0;
			end
			else begin
			// default波形和頻率不變化
				waveform_select <= waveform_select;
				freq_select 	<= freq_select;
				delay_counter 	<= 32'b0;
				delay_end 		<= 1'b0;
			end
		end
		
	end
end

// 切換波形種類
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		write_waveform <= write_sin;
	end
	else begin
		case(waveform_select) 
			2'd0: begin
				write_waveform <= write_sin;
			end
			2'd1: begin
				write_waveform <= write_traingle;
			end
			2'd2: begin
				write_waveform <= write_square;
			end
			default: begin
				write_waveform <= write_sin;
			end
		endcase
	end
end

// 切換頻率
always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		write_freq_lsb_c0 <= write_freq_lsb_1M;
		write_freq_msb_c0 <= write_freq_msb_1M;
	end
	else begin
		case(freq_select)
			2'd0: begin
				write_freq_lsb_c0 <= write_freq_lsb_1M;
				write_freq_msb_c0 <= write_freq_msb_1M;
			end
			2'd1: begin
				write_freq_lsb_c0 <= write_freq_lsb_3M;
				write_freq_msb_c0 <= write_freq_msb_3M;			
			end
			2'd2: begin
				write_freq_lsb_c0 <= write_freq_lsb_1k;
				write_freq_msb_c0 <= write_freq_msb_1k;			
			end
			default: begin
				write_freq_lsb_c0 <= write_freq_lsb_1M;
				write_freq_msb_c0 <= write_freq_msb_1M;			
			end
		endcase
	end
end

always @ (posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		TxData 		<= 16'd0;
		TxData_en 	<= 1'b0;
		counter 	<= 8'd12;
	end
	else begin
		// delay_end被置位后 將counter的值歸零 開始寫入操作數(shù)
		// 否則寫入操作會(huì)在結(jié)束處不斷循環(huán)
		if(delay_end) begin 			
			counter <= 8'd0;
		end
		else begin
			case(counter) 
				// 重置寄存器
				8'd0: begin
					TxData 		<= reset_add;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd1: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 選擇數(shù)據(jù)一次寫入
				8'd2: begin
					TxData 		<= write_freq;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd3: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 寫入頻率寄存器低148'd4: begin
					TxData 		<= write_freq_lsb_c0;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd5: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 寫入頻率寄存器高148'd6: begin
					TxData 		<= write_freq_msb_c0;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd7: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 寫入相位寄存器12// 不確定相位寄存器是否同時(shí)寫入 在圖例中相位寄存器無(wú)任何寫入的使能標(biāo)志位
				8'd8: begin
					TxData 		<= write_phase_c0;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd9: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 選擇波形輸出器
				8'd10: begin
					TxData 		<= write_waveform;
					TxData_en 	<= 1'b1;
					counter 	<= counter + 1'b1;
				end
				8'd11: begin
					TxData 		<= TxData;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
					if(TxData_done) begin
						counter <= counter + 1'b1;
					end
				end
				// 結(jié)束 將使能位TxData_en拉低
				8'd12: begin
					TxData 		<= 16'd0;
					TxData_en 	<= 1'b0;
					counter 	<= counter;
				end
				default: begin
					counter 	<= counter;
				end
			endcase
			
		end
	end
end

endmodule

FPGA重置后,delay_start置位,經(jīng)過(guò)一定的延時(shí)后,開始初始化寫入1Mhz的正弦波信號(hào)。寫入的過(guò)程如下:

  1. 重置寄存器
  2. 選擇數(shù)據(jù)一次寫入
  3. 寫入頻率寄存器低14位
  4. 寫入頻率寄存器高14位
  5. 寫入相位寄存器12位
  6. 選擇波形輸出
  7. 循環(huán)等待按鍵按下重置上述流程

當(dāng)檢測(cè)到按鍵按下時(shí),即key_flagkey_value變化時(shí),波形選擇寄存器和頻率選擇寄存器會(huì)發(fā)生變化。以此來(lái)選擇正弦波、三角波、方波和1M、3M和1K的頻率信號(hào)。

三、結(jié)果展示

FPGA引腳輸出。
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖5 FPGA引腳輸出

圖5是FPGA的引腳輸出狀態(tài)??梢钥吹?code>FSYNC為低電平時(shí)開始寫入操作,TxData為寫入操作字,SI逐一讀取寫入位,跟隨著SCK的變化寫入。

3M的正弦波。
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖6 AD9833輸出圖 3M正弦波

可以觀察到周期是333ns,也就是3M,輸出頻率很精準(zhǔn)。另外是436mV的峰峰值(經(jīng)過(guò)外部運(yùn)放放大后的,放大倍數(shù)為6.1倍),不超過(guò)手冊(cè)中的650mV。

1K的正弦波。
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖7 AD9833輸出圖 1K正弦波

其余波形和頻率,博主忘記拍了=.=,但確實(shí)完整輸出了三角波和方波(只要按一下按鍵就行)。就不重新連了,有點(diǎn)懶。
最后的最后,展示一下AD9833在原理圖中的連接圖。
基于AD9833的信號(hào)發(fā)生器,FPGA,fpga開發(fā),信號(hào)處理

圖8 AD9833原理圖

總結(jié)

本文,首先分析了AD9833的芯片手冊(cè),根據(jù)其芯片手冊(cè)的內(nèi)容,我們用Verilog語(yǔ)言編寫了控制程序,并燒錄至FPGA中用于控制AD9833。最后得到不同波形和頻率的輸出結(jié)果。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-777017.html

到了這里,關(guān)于基于AD9833的信號(hào)發(fā)生器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 基于FPGA的DDS信號(hào)發(fā)生器

    基于FPGA的DDS信號(hào)發(fā)生器

    ? ? 兩個(gè)禮拜前就像寫這個(gè)文檔了,但是一直鴿到現(xiàn)在,主要是人擺了。還有個(gè)技術(shù)上的原因是,我想用串口屏顯示波形,在串口調(diào)試助手上返回的數(shù)據(jù)是對(duì)的,但是發(fā)到串口屏上啥反應(yīng)沒有,人就很麻,如果這個(gè)弄不出來(lái),前面 HMI 串口屏的工程、人機(jī)交互界面就白做了。

    2024年02月06日
    瀏覽(21)
  • 基于FPGA的簡(jiǎn)易 DDS 信號(hào)發(fā)生器的設(shè)計(jì)

    基于FPGA的簡(jiǎn)易 DDS 信號(hào)發(fā)生器的設(shè)計(jì)

    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ì)人員,我們

    2024年02月07日
    瀏覽(41)
  • 基于FPGA的信號(hào)發(fā)生器(三角波、方波、正弦波)

    基于FPGA的信號(hào)發(fā)生器(三角波、方波、正弦波)

    目錄 DDS實(shí)現(xiàn)原理 DDS整體設(shè)計(jì)框圖? Quartus II 仿真? modelsim仿真 頂層代碼 DDS(Direct Digital ?Frequency Synthesizer) 直接數(shù)字頻率合成器 ,也可叫DDFS。? DDS是從相位的概念直接合成所需波形的 一種頻率合成技術(shù) 。? 不僅可以產(chǎn)生不同頻率的正弦波,而且可以控制波形的初始相位。? 主

    2024年02月04日
    瀏覽(20)
  • FPGA學(xué)習(xí)任意波函數(shù)信號(hào)發(fā)生器的設(shè)計(jì)(基于quartus II13.0)

    FPGA學(xué)習(xí)任意波函數(shù)信號(hào)發(fā)生器的設(shè)計(jì)(基于quartus II13.0)

    平臺(tái): quartus II 13.0 仿真:signal tap II 語(yǔ)言:VHDL 方式:原理圖bdf輸入 芯片:Cyclone IV E: EP4CE6E22C8 設(shè)計(jì)一任意波函數(shù)信號(hào)發(fā)生器,具備以下兩功能: ①能輸出標(biāo)準(zhǔn)正弦波波形。 ②能輸出任意函數(shù)波形。 首先明確實(shí)驗(yàn)用到的宏模塊操作是在tool——MeGaWizard Plug-In Manager中(如下圖)

    2024年02月03日
    瀏覽(46)
  • DDS信號(hào)發(fā)生器Verilog波形發(fā)生器FPGA

    DDS信號(hào)發(fā)生器Verilog波形發(fā)生器FPGA

    名稱:DDS信號(hào)發(fā)生器Verilog波形發(fā)生器 軟件:Quartus 語(yǔ)言:Verilog 要求: ?1.可產(chǎn)生正弦波,鋸齒波,三角波,方波4種波形,頻率可調(diào) ?2.具有波形選擇、起動(dòng)、停止功能。 代碼下載:DDS信號(hào)發(fā)生器Verilog波形發(fā)生器_Verilog/VHDL資源下載 代碼網(wǎng):hdlcode.com 部分代碼展示 設(shè)計(jì)文檔

    2024年02月07日
    瀏覽(25)
  • FPGA實(shí)驗(yàn)五:信號(hào)發(fā)生器設(shè)計(jì)

    目錄 一、實(shí)驗(yàn)?zāi)康?二、設(shè)計(jì)要求 三、實(shí)驗(yàn)代碼 1.代碼原理分析 2.代碼設(shè)計(jì)思路

    2024年02月12日
    瀏覽(28)
  • FPGA實(shí)驗(yàn)筆記_Vivado:DDS信號(hào)發(fā)生器;數(shù)碼管;基于DHT11的溫濕度傳感器

    FPGA實(shí)驗(yàn)筆記_Vivado:DDS信號(hào)發(fā)生器;數(shù)碼管;基于DHT11的溫濕度傳感器

    目錄 1、 FPGA的DDS信號(hào)發(fā)生器 1.1、DDS簡(jiǎn)介 1.2、ROM IP核的生成 1.3、波形數(shù)據(jù)的生成 1.4、 ROM的調(diào)用 1.5、 完整代碼(包括拓展部分) 2、數(shù)碼管顯示 2.1、數(shù)碼管簡(jiǎn)要說(shuō)明 2.2、SM410564 3、基于DHT11的溫濕度傳感器 3.1、DHT11 3.2、基本思路 3.3、數(shù)據(jù)分離模塊(BTD) 3.4、數(shù)據(jù)轉(zhuǎn)換模塊(

    2024年02月04日
    瀏覽(98)
  • fpga課設(shè)-多功能信號(hào)發(fā)生器

    1緒論 1.1 背景 信號(hào)發(fā)生器作為一種歷史悠久的測(cè)量?jī)x器,早在20年代電子設(shè)備剛出現(xiàn)時(shí)就產(chǎn)生了。隨著通信和雷達(dá)技術(shù)的發(fā)展,40年代出現(xiàn)了主要用于測(cè)試各種接收機(jī)的標(biāo)準(zhǔn)信號(hào)發(fā)生器,使得信號(hào)發(fā)生器從定性分析的測(cè)試儀器發(fā)展成定量分析的測(cè)量?jī)x器。同時(shí)還出現(xiàn)了可用來(lái)

    2024年02月05日
    瀏覽(25)
  • 基于FPGA的DDS原理信號(hào)發(fā)生器設(shè)計(jì) quartusII 9.1平臺(tái) Verilog HDL語(yǔ)言編程 可產(chǎn)生正弦波

    基于FPGA的DDS原理信號(hào)發(fā)生器設(shè)計(jì) quartusII 9.1平臺(tái) Verilog HDL語(yǔ)言編程 可產(chǎn)生正弦波

    基于FPGA的DDS原理信號(hào)發(fā)生器設(shè)計(jì) quartusII 9.1平臺(tái) Verilog HDL語(yǔ)言編程 ?可產(chǎn)生正弦波、方波、鋸齒波以及三角波 ? 頻率幅度可調(diào)節(jié) ? 代碼+原理圖 在現(xiàn)代電子技術(shù)領(lǐng)域,針對(duì)各種應(yīng)用的信號(hào)發(fā)生器是一種非常核心的設(shè)備,而基于現(xiàn)場(chǎng)可編程邏輯門陣列(FPGA)的直接數(shù)字合成(

    2024年04月27日
    瀏覽(30)
  • FPGA之簡(jiǎn)易DDS信號(hào)發(fā)生器設(shè)計(jì)

    FPGA之簡(jiǎn)易DDS信號(hào)發(fā)生器設(shè)計(jì)

    設(shè)計(jì)一個(gè)能產(chǎn)生頻率可變、相位可調(diào)的能產(chǎn)生正弦波、三角波、方波、鋸齒波的信號(hào)發(fā)生器。 DDS 是直接數(shù)字式頻率合成器(Direct Digital Synthesizer)的英文縮寫,是一項(xiàng)關(guān)鍵的數(shù)字化技術(shù)。與傳統(tǒng)的頻率合成器相比,DDS 具有低成本、低功耗、高分辨率和快速轉(zhuǎn)換時(shí)間等優(yōu)點(diǎn),

    2024年02月02日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包