集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
楼主: lcytms

FPGA初级课程第十七讲 任意波形发生器DDS

[复制链接]
 楼主| lcytms 发表于 2016-11-21 18:13:28 | 显示全部楼层
同时修改dds模块。
在dds模块里面增加一个相位控制字pword参数的调用。
修改dds模块代码如下。
module dds (clk, rst_n, num);

        input clk, rst_n;
       
        output [7:0] num;
       
        wire [7:0] addr;

        control #(.pword(64))
                control_inst (
                                .clk(clk),
                                .rst_n(rst_n),
                                .addr(addr)
                        );
       
        rom        rom_inst (
                        .address ( addr ),
                        .clock ( clk ),
                        .q ( num )
                );
       
endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:15:17 | 显示全部楼层
仿真运行结果

设置好仿真之后,可以看到仿真结果。
将输出的数据格式(radix一项)设置成模拟的数据。
可以看到复位完成后,输出相位为90°的正弦波,周期为195.31 kHz,依次循环。
可见设置pword=64时,相当于相移90°。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:18:00 | 显示全部楼层
2)波形发生器(可以调频,可以调相)
        经过前面两小节的分析,我们了解到,如果采用本地时钟是50M的话,那么频率就是195.31KHZ,根据我们的公式:
                频率 = 50M / 256

        设想:如果想要改变输出的频率,我们可以选择改变时钟或者输出点的个数!显而易见,我们的设计不能够时时刻刻去改变时钟的频率,那么想要输出别的频率,我们只能改变输出的点的个数,也就是改变有效地址的数量。         

        之前的设计是每个时钟沿地址增加1,频率是195.31KHz;如果我们每个时钟沿地址增加2,根据公式,输出频率应该是390.62KHz。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:19:05 | 显示全部楼层
我们来修改control模块。
在control模块里面再增加一个频率控制字fword。
修改control模块代码如下。
module control (clk, rst_n, addr);

        input clk, rst_n;
       
        output reg [7:0] addr;
       
        parameter pword = 0;                // phase control word
        parameter fword = 1;                // frequency control word

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                addr <= pword;
                        else
                                addr <= addr + fword;
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:20:18 | 显示全部楼层
同时修改dds模块。
在dds模块里面再增加一个频率控制字fword参数的调用。
修改dds模块代码如下。
module dds (clk, rst_n, num);

        input clk, rst_n;
       
        output [7:0] num;
       
        wire [7:0] addr;

        control #(.pword(64), .fword(2))
                control_inst (
                                .clk(clk),
                                .rst_n(rst_n),
                                .addr(addr)
                        );
       
        rom        rom_inst (
                        .address ( addr ),
                        .clock ( clk ),
                        .q ( num )
                );
       
Endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:21:20 | 显示全部楼层
仿真运行结果

设置好仿真之后,可以看到仿真结果。
将输出的数据格式(radix一项)设置成模拟的数据。
可以看到复位完成后,输出相位为90°的正弦波,周期为390.62 kHz,依次循环。
可见设置fword=2时,相当于频率*2。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:22:22 | 显示全部楼层
3)最终设计
        上一小节的设计,只能设定195.31KHz的整数倍,那就失去了我们设计的意义。为了提高精度,我们可以定义一个位宽为N(N>8)的地址计数器,让地址计数器每次增加一定的值,然后把高八位当作有效地址输送给rom,这样的话,就实现了降低地址改变的频率,进而达到降低输出波形的频率。
        地址计数器的原理就是先将地址变量pword的值作为地址的初值,然后每来一个时钟,地址计数器的值就等于地址当前值加上频率控制字fword,( pword = pword + fword )如此循环。例如刚开始fword = 1(假设pword=0),那么第一个时钟周期地址计数器的输出就是1,第二个时钟周期输出的就是2,第三个时钟周期输出的就是3。再例如,我们的频率控制字fword 刚开始等于2,那么地址计数器输出的就依次是0,2,4.....

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:24:28 | 显示全部楼层
        也就是说频率控制字fword 越大,地址计数器的输出值间隔也就越大,那么我们假设地址计数器的输出是32位的,如果fword越大,那么地址计数值到2^32 的时间就越短。
        我们使用的是50MHz的晶振,周期为20ns,假设fword为1,地址计数器的输出为N位的,那么每20ns,地址计数器加1,要加到2^N,需要20ns x 2^N 时间,这个时间就是输出一个完整信号的周期,那么我们可以知道,输出信号的频率为 Fout = Fclk /2^N,其中,Fclk为我们的晶振频率,再假如,fword = B的时候,地址间隔提高 B 倍,因此计满一个周期的时间缩小了 B 倍,频率提高的 B 倍。综上所述,我们得出了输出信号的频率计算公式:
                        Fout = B * Fclk / 2^N

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:25:32 | 显示全部楼层
        我们来计算一下:当B=1,F大约是0.012Hz。所以我们改变fword的值就基本实现了所有的低于最快频率以下所有的频率值(频率值只能是0.012的倍数,因为0.012太小了,所以基本可以实现所有的频率,若这个精度还是达不到要求的话,大家可以继续增大N的值,根据公式就可以得出最小精度,也可以根据最小精度计算N的值)。
        我们取地址计数器的前八位,相当于把一个波形的相位分成了256个点,每个点对应一个数据,正好和我们的波形数据点的个数是一样的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
 楼主| lcytms 发表于 2016-11-21 18:27:23 | 显示全部楼层
我们来修改control模块。
在control模块里面再增加一个32位的地址计数器addr_cnt变量。
修改control模块代码如下。
module control (clk, rst_n, addr);

        input clk, rst_n;
       
        output [7:0] addr;
       
        parameter pword = 0;                // phase control word
        parameter fword = 100;                // frequency control word
       
        reg [31:0] addr_cnt;                // address counter
       
        assign addr = addr_cnt[31:24];

        always @ (posedge clk or negedge rst_n)
                begin
                        if (!rst_n)
                                begin
                                        addr_cnt[31:24] <= pword;
                                        addr_cnt[23:0] <= 24'd0;
                                end
                        else
                                addr_cnt <= addr_cnt + fword;
                end

endmodule

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?我要注册

x
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2024-11-23 11:56 , Processed in 0.064179 second(s), 17 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表