3241 views|0 replies

164

Posts

2

Resources
The OP
 

[Domestic FPGA Evaluation] Anlu (Model SF1S60CG121I) 04 Parallel DAC DDS Module Design [Copy link]

 This post was last edited by EPTmachine on 2023-3-21 15:02

1.1 Hardware Introduction

On one side of the Demo board, there are 16 IOs available for output, and 3.3V power supply output is provided. The schematic diagram of user expanded IO is shown in the figure.

SF1S60CG121I Pin Location

SF1S60CG121I Pin Name

IO power domain

IO Name

IO number

H9

IO_R1P_0,GCLK3

2.5V

USER_IO0_N

3

G9

IO_R1N_0,GCLK2

2.5V

USER_IO0_P

4

H8

IO_R0N_0,GCLK0

2.5V

USER_IO1_N

5

H7

IO_R0P,GCLK1

2.5V

USER_IO1_P

6

D11

IO_R7N_0

2.5V

USER_IO2_N

7

D10

IO_R7P_0

2.5V

USER_IO2_P

8

C11

IO_R8N_0,GCLK10,D3

2.5V

USER_IO3_N

9

C10

IO_R8P_0,GCLK11,D2

2.5V

USER_IO3_P

10

B11

IO_R9N_0

2.5V

USER_IO4_N

11

B10

IO_R9P_0

2.5V

BUZZER

12

A11

IO_R10N_0,GCLK12,D1

2.5V

USER_IO5_N

13

A10

IO_R10P_0,GCLK13,D0

2.5V

USER_IO5_P

14

B8

IO_R11N_0

2.5V

USER_IO6_N

15

B9

IO_R11P_0

2.5V

USER_IO6_P

16

A8

IO_R12N_0,GCLK14,USRCLK

2.5V

USER_IO7_N

17

A9

IO_R12P_0,GCLK15,SCLK

2.5V

USER_IO7_P

18

The above resources can be used with the 10-bit high-speed DAC chip on the electric race training board of HardHe Academy to realize the DDS function. The schematic diagram of the electric race training board is as follows

The actual wiring diagram is as follows. The power supply of the electric race training board is provided by the 3.3V output terminal of the Demo board.

The button circuits and corresponding control pins on the Demo board are as follows:

The button is connected to an external pull-up resistor, which is high level by default. The mapping relationship between the button control pin and the FPGA pin is:

SF1S60CG121I Pin Location

SF1S60CG121I Pin Name

IO power domain

Button Name

H3

IO_B2N_2,GCLK2

1.2V

KEY0

H2

IO_B4P_2

1.2V

KEY1

G3

IO_B2P_2

1.2V

KEY2

1.2 ROM IP core usage and implementation of sine wave table

The SF1 device supports ERAM9K type embedded memory modules (ERAM), which can implement ROM, RAM, FIFO and other modules. The configuration is very convenient to use.

The DDS demonstrated this time uses a quarter of a 10-bit sine wave table, with a data width of 16 bits and a table depth of 64. The complete wave table can be obtained through phase transformation, which is based on symmetry.

However, the following compilation error occurred during actual use, and the specific reason is unknown.

Here I choose to use the LUT implementation. The code is as follows

module sin_table(address,sin);
output [8:0] sin;         //实际波形表为9位分辨率(1/4周期)
input  [5:0] address;     //64个点来生成1/4个周期的波形,完整的一个周期为256个点
 
reg    [8:0] sin;
 
always @(address)
	begin
                  case(address)	
                      6'h0: sin=9'h0;
                      6'h1: sin=9'hC;
                      6'h2: sin=9'h19;
                      6'h3: sin=9'h25;
                      6'h4: sin=9'h32;
                      6'h5: sin=9'h3E;
                      6'h6: sin=9'h4B;
                      6'h7: sin=9'h57;
                      6'h8: sin=9'h63;
                      6'h9: sin=9'h70;
                      6'ha: sin=9'h7C;
                      6'hb: sin=9'h88;
                      6'hc: sin=9'h94;
                      6'hd: sin=9'hA0;
                      6'he: sin=9'hAC;
                      6'hf: sin=9'hB8;
                      6'h10: sin=9'hC3;
                      6'h11: sin=9'hCF;
                      6'h12: sin=9'hDA;
                      6'h13: sin=9'hE6;
                      6'h14: sin=9'hF1;
                      6'h15: sin=9'hFC;
                      6'h16: sin=9'h107;
                      6'h17: sin=9'h111;
                      6'h18: sin=9'h11C;
                      6'h19: sin=9'h126;
                      6'h1a: sin=9'h130;
                      6'h1b: sin=9'h13A;
                      6'h1c: sin=9'h144;
                      6'h1d: sin=9'h14E;
                      6'h1e: sin=9'h157;
                      6'h1f: sin=9'h161;
                      6'h20: sin=9'h16A;
                      6'h21: sin=9'h172;
                      6'h22: sin=9'h17B;
                      6'h23: sin=9'h183;
                      6'h24: sin=9'h18B;
                      6'h25: sin=9'h193;
                      6'h26: sin=9'h19B;
                      6'h27: sin=9'h1A2;
                      6'h28: sin=9'h1A9;
                      6'h29: sin=9'h1B0;
                      6'h2a: sin=9'h1B7;
                      6'h2b: sin=9'h1BD;
                      6'h2c: sin=9'h1C3;
                      6'h2d: sin=9'h1C9;
                      6'h2e: sin=9'h1CE;
                      6'h2f: sin=9'h1D4;
                      6'h30: sin=9'h1D9;
                      6'h31: sin=9'h1DD;
                      6'h32: sin=9'h1E2;
                      6'h33: sin=9'h1E6;
                      6'h34: sin=9'h1E9;
                      6'h35: sin=9'h1ED;
                      6'h36: sin=9'h1F0;
                      6'h37: sin=9'h1F3;
                      6'h38: sin=9'h1F6;
                      6'h39: sin=9'h1F8;
                      6'h3a: sin=9'h1FA;
                      6'h3b: sin=9'h1FC;
                      6'h3c: sin=9'h1FD;
                      6'h3d: sin=9'h1FE;
                      6'h3e: sin=9'h1FF;
                      6'h3f: sin=9'h1FF;
                   endcase
              end
endmodule

1.3 DDS waveform frequency and type control module

Regarding the frequency control of the waveform, the core formula is as follows: fout is the output frequency, fmclk is the master clock of the DDS, Nmax is the maximum value of the n-bit counter, and m is the phase accumulation value of each clock cycle. The DDS generator introduced in this article uses a 28-bit phase accumulator to achieve outputs of different frequencies by changing the step size m.

The key codes are as follows:

	reg [27:0] dds_phase;
	wire [27:0] dds_phase_add;
	assign dds_phase_add = wave_step;
	always@(posedge sys_clk or negedge rst_n)begin
		if(!rst_n)begin
			dds_phase <= 28'd0;
		end else begin
			dds_phase <= dds_phase + dds_phase_add;
		end
	end

The types of waveforms output by DDS, such as square wave, triangle wave, and sawtooth wave, are controlled by the upper ten bits of the phase accumulator.

The square wave uses the highest bit of the phase accumulator as the output data. In the process of the phase accumulator from 0 to the upper limit, the highest bit is 0 in half of the time and 1 in the other half of the time. Since the square wave only needs two quantization values of the DAC, all data is 0 for the minimum value and all data is 1 for the maximum value. The corresponding DAC data pin can output the corresponding data bit. The key code is as follows:

	assign square_dac = {10{dds_phase[27]}};

For the sawtooth wave, its output voltage signal changes from the minimum value of the DAC to the maximum value. Taking the high 10 bits of the phase accumulator as the data source of the data pin of the DAC chip, the sawtooth wave can be generated. The key code is as follows:

assign saw_dac = dds_phase[27:18];

The triangle wave is similar to the sawtooth wave, but because the quantized data of the DAC goes from 0 to 1023 and then from 1023 to 0 in a single cycle, the counting overflow cycle is twice as fast as the sawtooth wave under the same cycle, and the counting direction will change. Therefore, on the basis of generating the sawtooth waveform, the highest bit of the phase accumulator is used as the selection flag of the triangle wave phase, and the 10 bits following it are used as the data source of the DAC data port. The data is inverted or not inverted according to different phases, so as to realize the output of the triangle wave. The key code is as follows:

assign trig_dac = dds_phase[27] ? ~dds_phase[26:17] : dds_phase[26:17];

The sine wave uses the high eight bits of the phase accumulator as the address of the sine wave table, and obtains the corresponding 10-bit DAC quantization value by looking up the table. The relationship between the address of one quarter of the sine wave table and the output DAC quantization value is realized above. The sine wave is similar to the triangle wave, except that it has four quadrants, so when using it, two bits of data are needed to determine which quadrant the waveform is in. The high two bits of the phase accumulator are used to determine the quadrant, and the following six bits are used as the addressing control bits of the wave table. The two are combined to obtain a complete sine wave output. The key code is as follows:

//查找表调用
	lookup_tables u_lut(
	.phase(dds_phase[27:20]),
	.sin_out(sin_dac)
	);


//////////////////////////////
//查找表实现
module lookup_tables(//sys_clk,rst_n,
	phase, sin_out);

//input sys_clk;
//input rst_n;
input  	[7:0] 	phase;
output 	[9:0] 	sin_out;
 
wire     [9:0]   sin_out;
 
reg   	[5:0] 	address;
wire   	[1:0] 	sel;
wire   	[11:0] 	sine_table_out;
 
reg     [9:0]   sine_onecycle_amp;
 
assign sin_out = sine_onecycle_amp[9:0];
 
assign sel = phase[7:6];
 
sin_table u_sin_table(address,sine_table_out);

always @(sel or sine_table_out)
begin
	case(sel)
	2'b00: 	begin
			sine_onecycle_amp = 9'h1ff + sine_table_out[8:0];
			address = phase[5:0];
	     	end
  	2'b01: 	begin
			sine_onecycle_amp = 9'h1ff + sine_table_out[8:0];
			address = ~phase[5:0];
	     	end
  	2'b10: 	begin
			sine_onecycle_amp = 9'h1ff - sine_table_out[8:0];
			address = phase[5:0];
     		end
  	2'b11: 	begin
			sine_onecycle_amp = 9'h1ff - sine_table_out[8:0];
			address = ~ phase[5:0];
     		end
	endcase
end
 
endmodule

1.4 DDS Amplitude Control Module

When the waveform is output through the DAC chip, the number of input bits at the input end of the DAC chip determines the quantization value range of the output signal. The output signal above uses 0 to 1023, which is the full scale of the DAC chip. If you want to control the peak-to-peak value of the output signal, you need to divide the output data. Direct division will lose a lot of precision. Here, the output quantization value is multiplied by a value x (0-255), and then divided by 255 to get an output signal that is attenuated proportionally. The output range of the DAC used in the test is 2.56V-0V, and each value of x above can correspond to a voltage value of 0.01V. The key code for amplitude control is as follows:

module dds_amp_adjust(
	clk,
	rst_n,
	wave_amp,
	signal_dat,
	
	dac_dat
);

	input clk,rst_n;
	input [7:0] wave_amp;//用于调幅的因数
	input [9:0] signal_dat;//未调幅的波形数据
	
	output [9:0] dac_dat;//输出给DAC的数据
	
	reg [17:0] amp_dat;//调幅后的波形数据
		
	always @(posedge clk) begin
		amp_dat<=signal_dat*wave_amp;//波形数据乘以调幅系数
	end

	assign dac_dat=amp_dat[17:8];//取高十位,相当于右移8位,除256

endmodule

1.5 Key input detection module

There are three buttons on the demo board, which can be used to control the type, frequency, and amplitude of the signal. The button debounce procedure is as follows:

module debounce(
    //input
	clk,
    rst_n,
    key,
    //output
    key_pluse);
    
    parameter N=1;			//要消除的按键数量

	input		clk;
    input 		rst_n;
    input [N-1:0]	key;		//输入的按键
    output [N-1:0]	key_pluse;	//按键动作产生的脉冲
    
    reg		[N-1:0] key_signal_pre;
    reg		[N-1:0]	key_signal;
    
    wire 	[N-1:0]	key_edge;
    

    always @(posedge clk or negedge rst_n)
    	begin
        	if(!rst_n)begin
            	key_signal<={N{1'b1}};
                key_signal_pre<={N{1'b1}};
            end	
        	else begin
            	key_signal<=key;
                key_signal_pre<=key_signal;
            end
        end	

	assign key_edge = key_signal_pre&(~key_signal);

	reg [17:0] cnt;
    
    always @(posedge clk or negedge rst_n)
    	begin
        	if(!rst_n)
            	cnt<=18'h0;
			else if(key_edge)
            	cnt<=18'h0;
            else
            	cnt<=cnt+1'b1;	
        end

	reg [N-1:0] key_sec_pre;
    reg [N-1:0] key_sec;

	always @(posedge clk or negedge rst_n)
    	begin
        	if(!rst_n)
            	key_sec<={N{1'b1}};
            else if(cnt==18'h3ffff)
            	key_sec<=key;
        end
        
   	always @(posedge clk or negedge rst_n)
       begin
			if(!rst_n)
            	key_sec_pre<={N{1'b1}};
            else
            	key_sec_pre<=key_sec;
       end

	assign	key_pluse = key_sec_pre & (~key_sec);

endmodule

After confirming a valid input, the debounce module sends a pulse signal, which is used by other modules to detect the rising edge of the key. After detecting the rising edge, different output types, frequencies and amplitudes are switched. The key codes are as follows:

module dds_waveparactrl(
    input clk,
    input rst_n,
    input wave_type_ctrl,
    input wave_freq_ctrl,
    input wave_amp_ctrl,
    output reg [2:0]    wave_type,
    output reg [27:0] wave_freqm,
    output reg [7:0] wave_amp
);


//波形输出形态控制
reg wave_type_ctrlr;//滤波后输出的按键脉冲为低电平

always@(posedge clk,negedge rst_n)begin
    if(!rst_n)begin
		wave_type_ctrlr <= 1'b0;
    end      
    else begin
    	wave_type_ctrlr<=wave_type_ctrl;
    end            
end

wire wave_type_ctrl_pos;
assign wave_type_ctrl_pos=!wave_type_ctrlr&&wave_type_ctrl;

reg [1:0]type_cnt;

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin					   
		wave_type <= 3'b000;
		type_cnt<=2'd1;
	end
    else if(wave_type_ctrl_pos)begin
		case(type_cnt)
			2'd0:begin wave_type <= 3'b000; type_cnt<=type_cnt+1'b1;end
			2'd1:begin wave_type <= 3'b001; type_cnt<=type_cnt+1'b1;end
			2'd2:begin wave_type <= 3'b010; type_cnt<=type_cnt+1'b1;end
			2'd3:begin wave_type <= 3'b011; type_cnt<=type_cnt+1'b1;end
		endcase
		
	end
end

//波形输出频率控制
reg wave_freq_ctrlr;//滤波后输出的按键脉冲为低电平

always@(posedge clk,negedge rst_n)begin
    if(!rst_n)begin
		wave_freq_ctrlr <= 1'b0;
    end      
    else begin
    	wave_freq_ctrlr<=wave_freq_ctrl;
    end            
end

wire wave_freq_ctrl_pos;
assign wave_freq_ctrl_pos=!wave_freq_ctrlr&&wave_freq_ctrl;

reg [2:0]freqm_cnt;

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)begin				   
    	wave_freqm <= 28'd5369;	//50M时钟频率下,1KHz信号的步进值m
		freqm_cnt <=3'd0;
    end		
    else if(wave_freq_ctrl_pos)begin
        case(freqm_cnt)
		3'd0:begin wave_freqm <= 28'd5369;	freqm_cnt<=freqm_cnt+1'd1;end					//1KHz
        3'd1:begin wave_freqm <= 28'd53690;	freqm_cnt<=freqm_cnt+1'd1;end					//10KHz
        3'd2:begin wave_freqm <= 28'd268450;freqm_cnt<=freqm_cnt+1'd1;end					//50KHz
        3'd3:begin wave_freqm <= 28'd536900;freqm_cnt<=freqm_cnt+1'd1;end					//100KHz
        3'd4:begin wave_freqm <= 28'd5369000;	freqm_cnt<=freqm_cnt+1'd1;end				//1MHz
        3'd5:begin wave_freqm <= 28'd10738000;	freqm_cnt<=freqm_cnt+1'd1;end					//2MHz
        3'd6:begin wave_freqm <= 28'd26845000;	freqm_cnt<=freqm_cnt+1'd1;end					//5MHz
		3'd7:begin wave_freqm <= 28'd10738;	freqm_cnt<=freqm_cnt+1'd1;end					//2KHz
        default:;
        endcase
	end
end

//波形输出幅度控制
reg wave_amp_ctrlr;//滤波后输出的按键脉冲为低电平

always@(posedge clk,negedge rst_n)begin
    if(!rst_n)begin
		wave_amp_ctrlr <= 1'b0;
    end      
    else begin
    	wave_amp_ctrlr<=wave_amp_ctrl;
    end            
end

wire wave_amp_ctrl_pos;
assign wave_amp_ctrl_pos=!wave_amp_ctrlr&&wave_amp_ctrl;

reg [2:0] amp_cnt;

always@(posedge clk or negedge rst_n)
begin
    if(!rst_n)begin				   
    	wave_amp <= 8'd255;	//48M时钟频率下,1KHz信号的步进值m
		amp_cnt <=3'd0;
    end		
    else if(wave_amp_ctrl_pos)begin
        case(amp_cnt)
		3'd0:begin wave_amp <= 8'd255;	amp_cnt<=amp_cnt+1'd1;end					//2.56V
        3'd1:begin wave_amp <= 8'd200;	amp_cnt<=amp_cnt+1'd1;end					//2.00V
        3'd2:begin wave_amp <= 8'd180;	amp_cnt<=amp_cnt+1'd1;end					//1.8V
        3'd3:begin wave_amp <= 8'd170;	amp_cnt<=amp_cnt+1'd1;end					//1.7V
        3'd4:begin wave_amp <= 8'd150;	amp_cnt<=amp_cnt+1'd1;end				//1.5V
        3'd5:begin wave_amp <= 8'd140;	amp_cnt<=amp_cnt+1'd1;end					//1.4V
        3'd6:begin wave_amp <= 8'd130;	amp_cnt<=amp_cnt+1'd1;end					//1.3V
		3'd7:begin wave_amp <= 8'd100;	amp_cnt<=amp_cnt+1'd1;end					//1.0V
        default:;
        endcase
	end
end

endmodule

1.6 Experimental Demonstration

dds演示

1.7 Summary

This experiment occupied a total of 11 user IOs, while the Demo board has a total of 16 user IOs. The original plan was to use LCD to set parameters. Of course, the board comes with a 128x32 OLED screen, which is sufficient for setting DDS parameters, but may not be enough for ADC sampling. However, there is a 128x64 OLED on the e-sports training board in the experiment, which is sufficient for displaying waveforms. The OLED screen will be used for subsequent information display.

Project attachment DDS_Parallel_DAC.7z (966.22 KB, downloads: 5)

This post is from Domestic Chip Exchange
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list