【FPGA学习】4-DDS与并行ADC、DAC

2 篇文章 0 订阅
1 篇文章 0 订阅

目录

一、实验目标

二、时钟方案

三、总模块

四、各个模块分析

五、学生实验

 修改代码完成以下任务

1、把DDS的rom改成16比特,高12位送给DAC

2、不要忘记缩放DAC的输出缩放

3、生成不同频率的正弦波

4、使用20MHz的ADC采样频率(保持不变)

5、把数据导入到Matlab(具体操作见上次的文章验证方法)

模块代码

六、思考题


一、实验目标

  • 掌握并行DAC、ADC的接口时序
  • 用DDS合成信号,经过DAC输出
  • 用ADC采集信号
  • 使用SignalTAP在时域观察信号
  • 使用Matlab在频域观察信号

二、时钟方案

  •  使用FPGA片内的锁相环                                                                                                             – 由50MHz晶振的时钟信号                                                                                                         – 倍频得到80MHz的DAC时钟                                                                                                   – 分频得到20MHz的ADC时钟
  • 用FPGA的逻辑对内部的80MHz时钟反相作为DAC 芯片时钟,用于满足DAC数据的建立-保持时序
  • ADC芯片在时钟的上跳锁存数据 
  • ADC时钟同样进行反相,作为ADC接口逻辑的驱动时钟
  • 注意:这种用FPGA的内部逻辑电路进行ADC、 DAC的时钟相位调整的方法,其时钟的抖动和相位 噪声不好。高质量设计中,通常用专门的时钟管理 芯片完成时钟的相位调节

三、总模块

  • 该设计由一个PLL从50MHz晶振生成80MHz的DAC时钟、 20MHzADC时钟
  • 一个单周期的DDS生成补码正弦波,转成无符号后送至DAC
  • 拨码开关SW9 SW8 用于控制DAC的输出幅度 – 其余的SW开关用于控制DDS频率字 

四、各个模块分析

1、pll_DAC_ADC【用于产生dac与adc的clk,与原信号相比,c0为原本的8/5,c1比率为2/5,直流占比均为50%】

2、DAC发生器(数模转换)<1>mc_dds

(1)输入控制

频率输入(FREQIN)低8位由0-7位拨码开关控制,其他32-8=24位接地为0。

使能接高电压一直导通。复位信号接地始终为0,不复位。

 

(2)输出信号

OUTTV用于检测该模块是否正常运行。

DDSOUT是用于产生输出波形。

<2>DAC_interface

DAC 接口模块 转换2补码为无符号数 。输入信号为有符号数,输出符号为无符号数。

(1)输入信号

SCALE比例因子,右移数据

(2)输出信号

数模转换的结果,配置的管脚与仪器运转有关,不更改就好。

 注:为取反信号。

3、ADC发生器(模数转换)

 信号:

CLK_ADC  ,   //  adc clk
DAT_ADC  ,   //  input data, from adc 
OTR_ADC  ,   //  from adc , signal out of range flag(信号超出范围标志)
OTR_OUT  ,   //  output otr flag
STBY_ADC ,   //  adc stand by, set 0 make adc running (ADC待机,设置0使ADC运行)
DOUT        //  data out

五、学生实验

 修改代码完成以下任务

1、把DDS的rom改成16比特,高12位送给DAC

ROM波形数据更改:方法

dds模块:更改输出数据bit数

dac模块输入更改数据bit数:

 rom高12位送给DAC

2、不要忘记缩放DAC的输出缩放

3、生成不同频率的正弦波

        – 仍然保持80MHz的DAC时钟速率    50MHz*8/5=80MHz

        – 用3比特的拨码开关设定输出正弦波频率 (类似3-8译码器)

        – 000~ 0.5MHz、001 ~ 1MHz 、010 ~ 1.5MHz、011 ~ 2MHz – 100~ 2.5MHz、101 ~         3.5MHz、110 ~ 4.5MHz、111 ~ 5.5MHz

4、使用20MHz的ADC采样频率(保持不变)

5、把数据导入到Matlab(具体操作见上次的文章验证方法

        – 观察频谱纯度

        – 确认你生成的信号频率正确

000~ 0.5MHz

001 ~ 1MHz

010 ~ 1.5MHz

011 ~ 2MHz

100~ 2.5MHz

101 ~ 3.5MHz

110 ~ 4.5MHz

111 ~ 5.5MHz

模块代码


// mc_dds
// multi-cycle dds module
module mc_dds(
  CLK   ,   // clock posedge
  RST   ,   // reset posedge
  FREQIN,   // input frequency word
  FREQEN,   // frequency word input enable
  DDSEN ,   // multi-cycle dds work enable
  OUTVD ,   // dds output valid
  DDSOUT);  // dds  output wave

input           CLK   ;
input           RST   ;
input  [32-1:0] FREQIN;
input           FREQEN;
input           DDSEN ;
output          OUTVD ;
output [16-1 :0]  DDSOUT;

// work enable delay line
reg ddsen_R1, ddsen_R2, ddsen_R3;

reg  [32-1:0]  freqin_R     ;
reg  [32-1:0]  phase_acc_R  ;
reg   [16-1:0]  DDSOUT       ;
wire  [16-1:0]  rom_rdW      ;   // rom read data 
wire  [7-1:0]  rom_raW      ;   // rom read address
// code template
// always @ (posedge CLK or posedge RST) begin
//   if(RST) begin
//   end
//   else begin
//   end
// end

always @ (posedge CLK or posedge RST) begin
  if(RST) begin
    ddsen_R1 <= 1'b0; 
    ddsen_R2 <= 1'b0;
    ddsen_R3 <= 1'b0;
  end
  else begin
    ddsen_R1 <= DDSEN   ; 
    ddsen_R2 <= ddsen_R1;
    ddsen_R3 <= ddsen_R2;
  end
end
assign OUTVD = ddsen_R3;


// dds working pipeline
//                                       OUTVD   
// DDSEN    | ddsen_R1     |ddsen_R2    |ddsen_R3    
//          | phase_acc_R  |
//          | rom_raW      | rom_rdW    | DDSOUT
always @ (posedge CLK or posedge RST) begin
  if(RST) begin
    phase_acc_R <= 0;
    freqin_R    <= 0;
  end
  else begin
    freqin_R[31:30] <= FREQIN[31:30];
    freqin_R[29:28] <= 0;
    case(FREQIN[24:22])
		3'b 000:freqin_R[27:0] <= 32'b0000_0001_1001_1001_1001_1001_1001_1010;
		3'b 001:freqin_R[27:0] <= 32'b0000_0011_0011_0011_0011_0011_0011_0011;
		3'b 010:freqin_R[27:0] <= 32'b0000_0100_1100_1100_1100_1100_1100_1101;
		3'b 011:freqin_R[27:0] <= 32'b0000_0110_0110_0110_0110_0110_0110_0110;
		3'b 100:freqin_R[27:0] <= 32'b0000_1000_0000_0000_0000_0000_0000_0000;
		3'b 101:freqin_R[27:0] <= 32'b0000_1011_0011_0011_0011_0011_0011_0011;
		3'b 110:freqin_R[27:0] <= 32'b0000_1110_0110_0110_0110_0110_0110_0110;
		3'b 111:freqin_R[28:0] <= 32'b0001_0001_1001_1001_1001_1001_1001_1010;
	endcase // if(FREQEN) 
    if(DDSEN) begin
      phase_acc_R <= phase_acc_R + freqin_R;
    end // if(DDSEN) 
    if(ddsen_R2) begin
      DDSOUT <= rom_rdW;
    end
  end
end
assign rom_raW = phase_acc_R[32-1: 32-1-7+1];

sine_rom U_sine_rom(
  .CLK    (CLK        ),  // clock
  .RA     (rom_raW    ),  // read address
  .RD     (rom_rdW    )); // read data

endmodule //  mc_dds();
module ADC_interface(
  CLK_ADC  ,   //  adc clk
  DAT_ADC  ,   //  input data, from adc 
  OTR_ADC  ,   //  from adc , signal out of range flag
  OTR_OUT  ,   //  output otr flag
  STBY_ADC ,   //  adc stand by, set 0 make adc running 
  DOUT     );   //  data out


input        CLK_ADC  ;  
input  [9:0] DAT_ADC  ;  
input        OTR_ADC  ;
output       OTR_OUT  ;
output       STBY_ADC ;

output [9:0] DOUT     ; 


reg [9:0] DOUT   ; 

reg       OTR_OUT;

always @ (posedge CLK_ADC) begin  
  DOUT    <= DAT_ADC   ; 
  OTR_OUT <= OTR_ADC;
end

assign STBY_ADC = 1'b0;

endmodule


 DAC 接口模块 转换2补码为无符号数 /
// input is signed , output is unsigned
module DAC_interface(
  CLKIN   ,   //  input clk
  DATIN   ,   //  input data
  SCALE   ,   //  scale factor, right shift the data
  DAT2DAC );   //  data to dac


input           CLKIN;
input  [12-1:0]  DATIN   ;
input  [2-1:0]  SCALE   ;
output [12-1:0] DAT2DAC ;


reg [12-1:0]  DAT2DAC ;
reg [12-1:0]  datin_R1;

always @ (posedge CLKIN) begin
  datin_R1 [11]    <= ~ DATIN[11]; // inverse the msb to unsigned
  datin_R1 [10: 0] <= DATIN[10:0];
  DAT2DAC          <= (datin_R1 >> SCALE);
end


endmodule

六、思考题

  • 在本例中,ADC的20MHz时钟和DAC的 80MHz时钟,是从一个晶振用PLL分出来的。 这种时钟叫做同步时钟
  • 现在的问题是,出于提高计算密度和需求, 我们想用那个80MHz的时钟处理ADC送入的20MHz的数据流。 应该怎么做?

        用时间基准电路从80M 的时钟里产生20M的时钟用于产生ADC的时钟,使整个电路都使用同一个时钟,保证电路的准确。

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值