Diseño de generador de señal DDS basado en FPGA (frecuencia, amplitud y forma de onda regulables)

Tabla de contenido

 

1. Principio DDS

2. Diseño general del sistema

1. Condiciones existentes

2. Análisis de desempeño experimental

3. Diseño del módulo del sistema

(1) Módulo de configuración de frecuencia (f_word_set.v)

(2) Módulo de configuración de forma de onda (wave_set.v)

(3) Módulo de ajuste de amplitud (amplitude_set.v)

(4) Módulo DDS (DDS.v)

(5) Módulo superior (DDS_top.v)

4. Verificación de la simulación

Tres, resumen


Dirección de descarga del proyecto: https://download.csdn.net/download/qq_33231534/12848911


1. Principio DDS

DDS se denomina síntesis digital directa (síntesis digital directa). Su principio básico es formar una nueva forma de onda seleccionando todos los datos o parte de los datos muestreados en un ciclo de datos de forma de onda. Según el teorema de muestreo de Nyquist, el mínimo de dos muestras Los puntos pueden formar una forma de onda, pero de hecho, se requieren al menos 4 puntos. El diagrama de bloques principal es el siguiente:

Se compone principalmente de palabra de control de fase, palabra de control de frecuencia, acumulador de fase y memoria de forma de onda.

Memoria de forma de onda: almacena una señal discreta de una forma de onda periódica;

Palabra de control de frecuencia: se utiliza para controlar la frecuencia de forma de onda generada.

Acumulador de fase: se utiliza para controlar la acumulación de fase de la forma de onda para formar una pantalla completa de forma de onda.

Palabra de control de fase: se utiliza para controlar la posición inicial de la forma de onda.

2. Diseño general del sistema

1. Condiciones existentes

Esta plataforma experimental es la placa de desarrollo AC620 de Xiaomeige, con chip DAC de precisión de muestreo de 12 bits TLV5618 integrado, con un rango de voltaje de salida de 0V ~ 4.096V, y su frecuencia de reloj más alta es de 20MHz.

2. Análisis de desempeño experimental

Dado que la frecuencia de muestreo más alta del chip DAC integrado es de 20 MHz, para diseñar un margen y solo para verificar la corrección del diseño, la frecuencia de muestreo DAC se establece aquí en 10 MHz, y el chip DAC de TLV5618 usa comunicación SPI, que se transmite una vez. Los datos necesitan casi 16 ciclos de reloj, que aquí se consideran 20 ciclos de reloj, por lo que la frecuencia más alta de recepción de datos es 10/20 = 0,5 MHz. Por lo tanto, la frecuencia más alta generada por el generador de señales en este experimento se establece en 0.5MHz.

3. Diseño del módulo del sistema

Aquí no hay un módulo de controlador DAC. El módulo de controlador DAC es útil en mi sistema de adquisición de datos de blog anterior. Como no tengo un osciloscopio y no puedo medir la forma de onda, solo puedo probar la exactitud del diseño a través del software de simulación, por lo que no hago un módulo de controlador DAC aquí. . Cada módulo se explicará por separado a continuación:

(1) Módulo de configuración de frecuencia (f_word_set.v)

Aquí puede cambiar la frecuencia por turno presionando el botón. Las frecuencias admitidas aquí incluyen 1Hz, 10Hz, 100Hz, 500Hz, 1KHz, 5KHz, 10KHz, 50KHz, 100KHz, 200KHz, 500KHz y 11 opciones diferentes. Presione el botón para cambiar en orden.

Aquí se calculan las palabras de control de frecuencia de diferentes formas de onda de frecuencia. Para obtener señales de baja frecuencia como 1Hz, 10Hz, etc., se deben realizar otros recuentos cuando se realiza la acumulación de fase en ellos. Aquí, se seleccionan 20 bits para la acumulación y hay 12 bits para la acumulación de datos de forma de onda. Se acumula un total de 32 bits de datos. Por ejemplo, fre_acc [31: 0], donde los 20 bits bajos de datos se usan como acumulación suplementaria, y los 12 bits altos se usan como datos de forma de onda para acumular. Para generar una forma de onda de 1Hz, asumiendo que se deben sumar x ciclos de reloj cada vez, el ciclo de 1Hz es T = 1 / f (aquí el ciclo está representado por ns), los datos de 32 bits se completan después de Tns y se usa el reloj del sistema de 50MHz. El ciclo del reloj del sistema es de 20 ns, entonces: (T / 20) * x = 2 ^ 32, entonces la fórmula de cálculo de la palabra de control de frecuencia es: x = (2 ^ 32) * 20 / T = (2 ^ 32) * 20 * f ( hz) / 1000000000;

Los datos finales de la palabra de control de cada frecuencia son:

1Hz ~ 86 ; 10Hz ~ 859 ; 100Hz ~ 8590 ; 500Hz ~ 42950 ; 1000Hz ~ 85899 ; 5000Hz ~ 429497 ; 10KHz ~ 858993 ; 50KHz ~ 4294967 ; 100KHz ~ 8589935 ; 200KHz ~ 17179869 ; 500KHz ~ 42949673。

El código es el siguiente, en el que el módulo anti-vibración del botón interior utiliza el módulo anti-vibración del botón escrito en el blog anterior.


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-04 15:25:53
// Revise Data    : 2020-09-04 17:06:45
// File Name      : F_word_set.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : 频率控制字的生成
 

module F_word_set(
	input				clk		,
	input				rst_n	,
	input				key1_in	,

	output	reg	[25:0]	f_word	
	);
	
	wire		key_flag	;
	wire		key_state	;
	reg	[3:0]	cnt			;

	key_filter fword_key (
			.clk       (clk),
			.rst_n     (rst_n),
			.key_in    (key1_in),
			.key_flag  (key_flag),
			.key_state (key_state)
		);

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			cnt <= 4'd0;
		end
		else if (key_flag) begin
			if (cnt==4'd10) begin
				cnt <= 4'd0;
			end
			else begin
				cnt <= cnt + 1'b1;
			end
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			f_word <= 0;
		end
		else begin
			case(cnt)
				4'd0:f_word = 26'd86;		//1Hz
				4'd1:f_word = 26'd859;		//10Hz
				4'd2:f_word = 26'd8590;		//100Hz
				4'd3:f_word = 26'd42950;	//500Hz
				4'd4:f_word = 26'd85899;	//1kHz
				4'd5:f_word = 26'd429497;	//5kHz
				4'd6:f_word = 26'd858993;	//10kHz
				4'd7:f_word = 26'd4294967;	//50kHz
				4'd8:f_word = 26'd8589935;	//100kHz
				4'd9:f_word = 26'd17179869;	//200kHz
				4'd10:f_word = 26'd42949673;//500kHz
				default:;
			endcase
		end
	end
endmodule

(2) Módulo de configuración de forma de onda (wave_set.v)

Aquí hay cuatro tipos de formas de onda: onda sinusoidal, onda triangular, onda de diente de sierra y onda cuadrada. Aquí, presione la tecla para cambiar los datos de la palabra de control de forma de onda No hay módulo ROM para cada forma de onda, y el módulo ROM se coloca en el módulo DDS para salida de datos.


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-04 15:10:48
// Revise Data    : 2020-09-04 15:23:44
// File Name      : wave_set.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : dds信号发生器的波形选择,按键按下切换波形
 

module wave_set(
	input				clk		,
	input				rst_n	,
	input				key0_in	,

	output	reg	[1:0]	wave_c		//wave_c oo~正弦波  01~三角波  10~锯齿波  11~方波
	);

	wire	key_flag	;
	wire	key_state	;

	key_filter wave_key (
			.clk       (clk),
			.rst_n     (rst_n),
			.key_in    (key0_in),
			.key_flag  (key_flag),
			.key_state (key_state)
		);

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			wave_c <= 0; //默认正弦波
		end
		else if (key_flag) begin
			wave_c <= wave_c + 1'b1;
		end
	end
endmodule

(3) Módulo de ajuste de amplitud (amplitude_set.v)

Presione el botón para controlar la configuración de la amplitud de la forma de onda, aquí se puede establecer en 1 vez, 1/2 veces, 1/4 veces, 1/8 veces, 1/16 veces de la forma de onda original.


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-05 09:35:58
// Revise Data    : 2020-09-05 09:35:58
// File Name      : amplitude_set.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : 信号电压幅度设置 1/2/4/8/16分之一

module amplitude_set(
	input				clk		,
	input				rst_n	,
	input				key2_in	,

	output	reg	[4:0]	amplitude	
	);

	reg	[2:0]	cnt			;
	wire		key_flag	;
	wire		key_state	;


	key_filter amplitude_key (
				.clk       (clk),
				.rst_n     (rst_n),
				.key_in    (key2_in),
				.key_flag  (key_flag),
				.key_state (key_state)
			);

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			cnt <= 3'd0;
		end
		else if (key_flag) begin
			if (cnt == 3'd4) begin
				cnt <= 3'd0;
			end
			else begin
				cnt <= cnt + 1'b1;
			end
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			amplitude <= 0;			
		end
		else begin
			case(cnt)
				3'd0: amplitude <= 5'd1;
				3'd1: amplitude <= 5'd2;
				3'd2: amplitude <= 5'd4;
				3'd3: amplitude <= 5'd8;
				3'd4: amplitude <= 5'd16;
				default:amplitude <= 5'd1;
			endcase
		end
	end
endmodule

(4) Módulo DDS (DDS.v)

Este módulo instancia cuatro módulos ROM de almacenamiento de formas de onda (el módulo ROM es muy simple y también se ha escrito en el sistema de adquisición de datos, por lo que no lo repetiré aquí), y al mismo tiempo realiza la acumulación de fase de DDS, y lee los datos en la ROM a través de la tabla de búsqueda.


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-04 17:09:55
// Revise Data    : 2020-09-04 17:31:29
// File Name      : DDS.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : DDS模块
 
module DDS(
	input				clk			,
	input				rst_n		,
	input		[25:0]	f_word		,
	input		[1:0]	wave_c		,
	input		[11:0]	p_word		,
	input		 	,

	output	reg	[11:0]	dac_data	
	);

	localparam	DATA_WIDTH = 4'd12;
	localparam	ADDR_WIDTH = 4'd12;

	reg		[11:0]	addr	 ;
	wire	[11:0]	dac_data0;
	wire	[11:0]	dac_data1;
	wire	[11:0]	dac_data2;
	wire	[11:0]	dac_data3;


	//波形选择
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			dac_data <= 12'd0;
		end
		else begin
			case(wave_c)
				2'b00:dac_data <= dac_data0/amplitude;	//正弦波
				2'b01:dac_data <= dac_data1/amplitude;	//三角波
				2'b10:dac_data <= dac_data2/amplitude;	//锯齿波
				2'b11:dac_data <= dac_data3/amplitude;	//方波
				default:;
			endcase
		end
	end

	//相位累加器
	reg	[31:0]	fre_acc;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			fre_acc <= 0;
		end
		else begin
			fre_acc <= fre_acc + f_word;
		end
	end

	//生成查找表地址
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			addr <= 0;
		end
		else begin
			addr <= fre_acc[31:20] + p_word;
		end
	end

	//正弦波
	sin_rom #(
		.DATA_WIDTH(DATA_WIDTH),
		.ADDR_WIDTH(ADDR_WIDTH)
	) inst_sin_rom (
		.addr (addr),
		.clk  (clk),
		.q    (dac_data0)
	);

	//三角波
	sanjiao_rom #(
			.DATA_WIDTH(DATA_WIDTH),
			.ADDR_WIDTH(ADDR_WIDTH)
		) inst_sanjiao_rom (
			.addr (addr),
			.clk  (clk),
			.q    (dac_data1)
		);

	//锯齿波
	juchi_rom #(
			.DATA_WIDTH(DATA_WIDTH),
			.ADDR_WIDTH(ADDR_WIDTH)
		) inst_juchi_rom (
			.addr (addr),
			.clk  (clk),
			.q    (dac_data2)
		);

	//方波
	fangbo_rom #(
			.DATA_WIDTH(DATA_WIDTH),
			.ADDR_WIDTH(ADDR_WIDTH)
		) inst_fangbo_rom (
			.addr (addr),
			.clk  (clk),
			.q    (dac_data3)
		);

endmodule

(5) Módulo superior (DDS_top.v)


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-04 18:32:24
// Revise Data    : 2020-09-04 19:03:10
// File Name      : DDS_top.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : 
 
module DDS_top(
	input					clk			,
	input					rst_n		,
	input					key0_in		,
	input					key1_in		,
	input					key2_in		,

	output	wire	[11:0]	dac_data	
	);

	wire	[1:0]	wave_c		;
	wire	[25:0]	f_word		;
	wire	[4:0]	amplitude	;

	DDS inst_DDS
	(
		.clk      (clk),
		.rst_n    (rst_n),
		.f_word   (f_word),
		.wave_c   (wave_c),
		.p_word   (12'd0),
		.amplitude(amplitude),
		.dac_data (dac_data)
	);

	F_word_set inst_F_word_set 
	(
		.clk(clk), 
		.rst_n(rst_n), 
		.key1_in(key1_in), 
		.f_word(f_word)
	);

	wave_set inst_wave_set 
	(
		.clk(clk), 
		.rst_n(rst_n), 
		.key0_in(key0_in), 
		.wave_c(wave_c)
	);

	amplitude_set inst_amplitude_set(
		.clk	(clk)		,
		.rst_n	(rst_n)		,
		.key2_in(key2_in)	,

		.amplitude(amplitude)	
	);

endmodule

4. Verificación de la simulación

Dado que el tiempo de simulación será relativamente largo, diferentes formas de onda y diferentes funciones se prueban por separado. Los códigos principales son los siguientes:


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-04 19:07:11
// Revise Data    : 2020-09-04 22:50:36
// File Name      : DDS_top_tb.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : 


`timescale 1ns/1ns
module DDS_top_tb();

	reg					clk			;
	reg					rst_n		;
	reg					key0_in		;
	reg					key1_in		;
	reg					key2_in		;

	wire	[11:0]		dac_data	;

	localparam	clk_period = 20;

	DDS_top inst_DDS_top
		(
			.clk      (clk),
			.rst_n    (rst_n),
			.key0_in  (key0_in),
			.key1_in  (key1_in),
			.key2_in  (key2_in),
			.dac_data (dac_data)
		);


		initial clk = 0;
		always #(clk_period/2) clk = ~clk;

		initial begin
			#1;
			rst_n = 0;
			key0_in = 1;
			key1_in = 1;
			key2_in = 1;
			#(clk_period*20);
			rst_n = 1;
			#(clk_period*10);

			// key0_in = 0;
			// #30000000;
			// key0_in = 1;
			// #30000000;
			// key0_in = 0;
			// #30000000;
			// key0_in = 1;
			// #30000000;
			// key0_in = 0;
			// #30000000;
			// key0_in = 1;

			//#2000000000;

			key1_in = 0;
			#30000000;
			key1_in = 1;
			#30000000;
			//#200000000;

			key1_in = 0;
			#30000000;
			key1_in = 1;
			#30000000;
			//#20000000;

			key1_in = 0;
			#30000000;
			key1_in = 1;
			#30000000;
			#4000000;

			key2_in = 0;
			#30000000;
			key2_in = 1;
			#30000000;
			#4000000;

			key2_in = 0;
			#30000000;
			key2_in = 1;
			#30000000;
			#4000000;
			
			key2_in = 0;
			#30000000;
			key2_in = 1;
			#30000000;
			#4000000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #2000000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #400000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #200000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #40000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #20000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #10000;

			// key1_in = 0;
			// #30000000;
			// key1_in = 1;
			// #30000000;
			// #4000;

			
			#(clk_period*20);
			$stop;
		end
endmodule

Forma de onda de simulación:

(1) onda sinusoidal de 1 Hz

(2) onda triangular de 1 Hz

(3) onda de diente de sierra de 1Hz

(4) onda cuadrada de 1Hz

(5) Ondas cuadradas de diferentes frecuencias

(6) Ondas cuadradas de diferentes frecuencias

(7) Ondas sinusoidales de diferentes frecuencias

(8) Ondas triangulares de diferentes frecuencias

(9) Ondas de diente de sierra de diferentes frecuencias

(10) Ondas sinusoidales de diferentes amplitudes

Tres, resumen

Desde el punto de vista de la simulación, todo el diseño cumple las condiciones esperadas, pero el módulo DAC no se prueba en la placa. Este diseño básicamente completa el diseño del generador de señal DDS Hay otras deficiencias, por favor corríjame.

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_33231534/article/details/108424647
Recomendado
Clasificación