ROM存储1/4周期正弦信号构造DDS

简单的dds程编写过程中我遇到问题以及一些个人的思考。初次接触FPGA,如有问题请多多指教~

1.几个疑问,解决和没有解决的。

为何采用ROM而不是直接采用DDS核来进行正弦信号的合成?

    实际中如果只需要合成正弦信号,那么DDS核是一个很好的选择,而且DDS核可以选择是否采用泰勒校正以获取更低的杂散。由于ROM表中的数据可以由我们自己选择,采用ROM做DDS具有更强的灵活性。

在使用chipscope时,添加ICON核和.cdc文件的区别?

    ICON核的添加需要改变原有程序的结构,需要重新综合,正是由于这个核在程序内部,我们可以轻易地选择需要观察的信号;

.cdc文件的插入不改变程序结构,只需要重新translate等,由于是对综合后的程序进行插入,所以有些信号会被优化掉或者改名字等。

双口ROM有无缺陷?

    不知道……modelsim反正中表明,无法仿真collision等……Block Ram的手册中没有提到双口ROM,也许看看双口RAM会有帮助。

2.Matlab仿真


注意:由于采用了1/4周期存储,要求整个周期的数值是中心对称的,半个周期的数值是轴对称的。这就意味着采样点中不应该有0值得存在。


Matlab仿真——ROM表存储数据

%% ROM产生 (无符号数)
ROM_N=2^10; %ROM表深度
DATA_L=14;  %ROM位宽
t=1:ROM_N;
y=(2^DATA_L-1)*(sin(2*pi*(t-0.5)/ROM_N/4));%-0.5保证对称性

ROM_DATA=round(y);
View Code

Matlab仿真——DDS程序(请原谅我没有用case……)

%% 正弦波dds产生
F_CLK=10*10^6;  %时钟频率10M
PINC_IN_L=32;   %增量长度
DDS_CLK=10*10^3;    %dds输出频率10k
PHASE_IN=0;    %初始相位
pinc=round(DDS_CLK*2^PINC_IN_L/F_CLK);    %相位增量

SIM_L=4000;    %仿真长度
phase=PHASE_IN+pinc*(0:SIM_L-1);
addr=mod((floor(phase/2^PINC_IN_L*ROM_N)),ROM_N*4);
flag=floor(addr/ROM_N);
dds_out=1:SIM_L;
for i=1:SIM_L
    if(flag(i)==0)
        dds_out(i)=ROM_DATA(addr(i)+1);
    else if(flag(i)==1)
        dds_out(i)=ROM_DATA(2047-addr(i)+1);
        else if(flag(i)==2)
                dds_out(i)=-ROM_DATA(addr(i)-2048+1);
            else
                dds_out(i)=-ROM_DATA(4095-addr(i)+1);
            end 
        end
    end
end

plot(dds_out);
View Code

 

3.DDS的解释

    Xilinx的DDS核的User Guide中队DDS做了很详细的说明,本节不再重复此内容,本节将叙述一种全新的DDS理解方式。这种理解方式解决了频率控制字长于ROM表深度时DDS的理解上的问题。

连续还是离散?

    连续还是离散,在于我们用什么眼光去看待。如下图所示,我们可以理解蓝色的图是离散的,而红色的线是连续的。然而,对于我们要获取的信息而言,这两幅图是完全没有区别的。抽样定理中有理想抽样和平顶抽样(采样保持电路)之分,然而在频域效果上,是并没有很大区别的。untitled

ROM表存储的是连续的数值

    按照上面的理论,可以认为ROM表中存储的是正弦信号的平顶采样结果。如下图所示(一个全周期的ROM表,对称性满足1/4周期存储的要求)

image

    上图的频谱在信号与系统中有提及,上述波形的形成方式可以认为是在乘以周期为T的冲击函数,之后卷积一个宽度为T的窗函数。对应可以求得其频域。(具体可参考平顶抽样

频率控制字

   频率控制字控制对上述的阶梯函数的采样,如果这样理解的话,就没有所谓的相位截取取ROM表的值的疑惑了。频谱图能够清晰的表现这一过程,然而由于blog表达不便,此处不做详细说明。

    此处能够解释DDS产生的杂散。

4.Verilog实现

    从设计设计上来说,Verilog和Matlab代码应该完全一致,包括代码编写的思路,以及命名都应该统一。但是下面的程序没有做到这一点,带改进。

`timescale 1ns / 1ps

module DDS_10k(
    input clk_10M,
    input rst,
    output[13:0] D_SIN,
    output[13:0] D_COS
    );

parameter pinc=32'd4294967;    //10k
reg[31:0] addr_temp=32'd0;
reg[9:0] addra,addrb;
reg mark_a,mark_b;

always@(posedge(clk_10M))    //复位
begin
    if(rst==0)
        addr_temp<=32'd0;
    else
        addr_temp<=addr_temp+pinc;
end

always@(posedge(clk_10M))    //1/4周期控制
begin
    case(addr_temp[31:30])
        2'b00:
            begin
                addra<=addr_temp[29:20];
                mark_a<=0;
                addrb<=~addr_temp[29:20];
                mark_b<=0;
            end
        2'b01:
            begin
                addra<=~addr_temp[29:20];
                mark_a<=0;
                addrb<=addr_temp[29:20];
                mark_b<=1;
            end
        2'b10:
            begin
                addra<=addr_temp[29:20];
                mark_a<=1;
                addrb<=~addr_temp[29:20];
                mark_b<=1;
            end
        2'b11:
            begin
                addra<=~addr_temp[29:20];
                mark_a<=1;
                addrb<=addr_temp[29:20];
                mark_b<=0;
            end
    endcase
end

//ROM表读取
ROM_SIN_1k18 rom_dds (
  .clka(clk_10M), // input clka
  .addra(addra), // input [9 : 0] addra
  .douta(D_SIN[12:0]), // output [12 : 0] douta
  .clkb(clk_10M), // input clkb
  .addrb(addrb), // input [9 : 0] addrb
  .doutb(D_COS[12:0]) // output [12 : 0] doutb
);

reg sin_mark_temp;
reg cos_mark_temp;
assign D_SIN[13]=sin_mark_temp;
assign D_COS[13]=cos_mark_temp;

//此处ROM没有添加register,因此输出和地址有一个周期的延时,故Mark也要有一周期延时
always@(posedge(clk_10M))
begin
    sin_mark_temp<=mark_a;
    cos_mark_temp<=mark_b;
end

endmodule
View Code

 

转载于:https://www.cnblogs.com/sea-wind/p/3950548.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGA是可编程逻辑器件,DDS是直接数字频率合成器,正弦波是一种周期性的波形。1/4周期性指的是正弦波在一个周期内只有1/4的部分是可见的。在FPGA中使用DDS模块可以生成正弦波,并且可以通过控制参数来调整波形的频率和幅度。 FPGA中的DDS模块通过一个相位累加器和一个查表器组成。相位累加器根据所设置的频率参数和时钟信号的频率进行相位累加,查表器则根据相位值输出对应的正弦波幅值。通过不断变化相位累加器的步进值,可以控制正弦波的频率,从而实现频率的可调。 在DDS模块中,相位值和幅值都是以二进制表示的,因此需要将输出的数字值转换为模拟信号。这个数字到模拟的转换过程可以通过一个数字模拟转换器(DAC)来实现。DAC将数字信号转换为模拟电压或电流输出,可以直接驱动音频设备或其他模拟电路。 如果要实现正弦波的1/4周期性,可以通过调节DDS模块的相位累加器的步进值来控制波形的形状。相位累加器的步进值可以设置为正弦波一个周期的1/4,这样在一个周期内只有1/4部分的波形是可见的。这种方式可以实现周期比较短的正弦波,并可以用于一些特定的应用,如频率合成、信号调制等。 综上所述,FPGA中的DDS模块可以生成正弦波,并且可以通过控制参数来调整波形的频率和幅度。1/4周期性指的是在一个周期内只有1/4部分的波形是可见的,可以通过调节DDS模块的相位累加器的步进值来实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值