XILINX FPGA IP之DDS Compiler_ip例化仿真

描述

之前的文章对dds ip 的结构、精度、参数、接口进行了详细的说明,本文通过例化仿真对该IP的实际使用进行演示。本文例化固定模式和可配置模式两种模式分别例化ip并仿真,说明该IP的应用。

1、固定模式:

该模式下IP的参数设置如下图,时钟频率设置为100Mhz,两个通道时分复用,SFDR 60dB.

FPGA

然后相位、相位偏差全部选择固定模式,

FPGA

输出频率配置为1Mhz和2Mhz:

FPGA

设置完之后再summary这里可以看到该IP的实现细节,输出位宽10bit,2ch,没ch的时钟速率是50Mhz,使用一个M18K的BROM实现查找表等等的一些细节。

FPGA

在additional summary里边可以看到相应的频率控制字和实际精度,因为当前设置的时标准模式不是栅格(rasterized)模式,所以输出是有频偏的。

FPGA

上述设置生成的IP端口如下,输入端口为时钟复位信号,输出sin cos和phase值。

dds_compiler_0 your_instance_name (
  .aclk(aclk),                                // input wire aclk
  .aresetn(aresetn),                          // input wire aresetn
  .m_axis_data_tvalid(m_axis_data_tvalid),    // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata),      // output wire [31 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid(m_axis_phase_tvalid),  // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata(m_axis_phase_tdata)    // output wire [31 : 0] m_axis_phase_tdata
);

这个IP的tb就非常简单了,只有提供时钟复位即可,但是输出时时分复用的,所以tb对输出信号进行了处理将两路输出分开了,方便波形观察,如下:

`timescale 1ns/100ps
module tb_dds_fix_normal ;


reg             aclk                = 'd0;
reg             aresetn             = 'd0;
wire            m_axis_data_tvalid  ;
wire [31 : 0]   m_axis_data_tdata   ;
wire            m_axis_phase_tvalid ;
wire [31 : 0]   m_axis_phase_tdata  ;


always #1 aclk = ~aclk;




initial
    begin
        #100;
        aresetn =1'b1;
    end




dds_compiler_0 dds_compiler_0 (
  .aclk                     (aclk                   ), // input wire aclk
  .aresetn                  (aresetn                ), // input wire aresetn
  .m_axis_data_tvalid       (m_axis_data_tvalid     ), // output wire m_axis_data_tvalid
  .m_axis_data_tdata        (m_axis_data_tdata      ), // output wire [31 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid      (m_axis_phase_tvalid    ), // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata       (m_axis_phase_tdata     )  // output wire [31 : 0] m_axis_phase_tdata
);


reg             S_ch0_valid ;
reg   [15:0]    S_ch0_cos   ;
reg   [15:0]    S_ch0_sin   ;
reg   [31:0]    S_ch0_pha   ;
reg   [15:0]    S_ch1_cos   ;
reg   [15:0]    S_ch1_sin   ;
reg   [31:0]    S_ch1_pha   ;


always @(posedge aclk)
    if(!aresetn)
        S_ch0_valid <= 1'b1;
    else if(m_axis_data_tvalid)
        S_ch0_valid <= ~S_ch0_valid;


always @(posedge aclk)
    if(S_ch0_valid)
        begin
            S_ch0_cos <= m_axis_data_tdata[15:0]  ;
            S_ch0_sin <= m_axis_data_tdata[31:16] ;
            S_ch0_pha <= m_axis_phase_tdata       ;
            S_ch1_cos <= S_ch1_cos                ;
            S_ch1_sin <= S_ch1_sin                ;
            S_ch1_pha <= S_ch1_pha                ;
        end
    else
        begin
            S_ch0_cos <= S_ch0_cos                ;
            S_ch0_sin <= S_ch0_sin                ;
            S_ch0_pha <= S_ch0_pha                ;
            S_ch1_cos <= m_axis_data_tdata[15:0]  ;
            S_ch1_sin <= m_axis_data_tdata[31:16] ;
            S_ch1_pha <= m_axis_phase_tdata       ;
        end
    
endmodule

仿真波形如下:

FPGA

2、相位可配置模式:

该模式将相位偏差和相位步进设置为axi配置模式,如下图,其它配置保持不变:

FPGA

生成的端口如下,该模式下增加了config端口,用于phase信息的配置:

dds_compiler_cfg your_instance_name (
  .aclk(aclk),                                                        // input wire aclk
  .aresetn(aresetn),                                                  // input wire aresetn
  .s_axis_config_tvalid(s_axis_config_tvalid),                        // input wire s_axis_config_tvalid
  .s_axis_config_tdata(s_axis_config_tdata),                          // input wire [31 : 0] s_axis_config_tdata
  .s_axis_config_tlast(s_axis_config_tlast),                          // input wire s_axis_config_tlast
  .m_axis_data_tvalid(m_axis_data_tvalid),                            // output wire m_axis_data_tvalid
  .m_axis_data_tdata(m_axis_data_tdata),                              // output wire [31 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid(m_axis_phase_tvalid),                          // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata(m_axis_phase_tdata),                            // output wire [15 : 0] m_axis_phase_tdata
  .event_s_config_tlast_missing(event_s_config_tlast_missing),        // output wire event_s_config_tlast_missing
  .event_s_config_tlast_unexpected(event_s_config_tlast_unexpected)  // output wire event_s_config_tlast_unexpected
);

这时,需要对tb进行相应的修改,增加config的配置,如下,新增一个11bit的计数器,计满后对两个通道的phase值进行翻倍:

reg             aclk                = 'd0;
reg             aresetn             = 'd0;
reg             s_axis_config_tvalid= 'd0;
reg  [31 : 0]   s_axis_config_tdata = {{16'd1310},{16'd1310}};
reg             s_axis_config_tlast = 'd0;


wire            m_axis_data_tvalid  ;
wire [31 : 0]   m_axis_data_tdata   ;
wire            m_axis_phase_tvalid ;
wire [15 : 0]   m_axis_phase_tdata  ;


always #1 aclk = ~aclk;




initial
    begin
        #100;
        aresetn =1'b1;
    end


reg  [10:0] S_clk_cnt   ;


always @(posedge aclk)
    if(!aresetn)
        S_clk_cnt <= 'd3;
    else
        S_clk_cnt <= S_clk_cnt + 'd1;


always @(posedge aclk)
    s_axis_config_tvalid <= ((S_clk_cnt==0)||(S_clk_cnt==1));


always @(posedge aclk)
    s_axis_config_tlast <= (S_clk_cnt==1);


always @(posedge aclk)
    if(s_axis_config_tvalid)
        s_axis_config_tdata <= s_axis_config_tdata + s_axis_config_tdata;




dds_compiler_cfg your_instance_name (
  .aclk                             (aclk                           ), // input wire aclk
  .aresetn                          (aresetn                        ), // input wire aresetn
  .s_axis_config_tvalid             (s_axis_config_tvalid           ), // input wire s_axis_config_tvalid
  .s_axis_config_tdata              (s_axis_config_tdata            ), // input wire [31 : 0] s_axis_config_tdata
  .s_axis_config_tlast              (s_axis_config_tlast            ), // input wire s_axis_config_tlast
  .m_axis_data_tvalid               (m_axis_data_tvalid             ), // output wire m_axis_data_tvalid
  .m_axis_data_tdata                (m_axis_data_tdata              ), // output wire [31 : 0] m_axis_data_tdata
  .m_axis_phase_tvalid              (m_axis_phase_tvalid            ), // output wire m_axis_phase_tvalid
  .m_axis_phase_tdata               (m_axis_phase_tdata             ), // output wire [15 : 0] m_axis_phase_tdata
  .event_s_config_tlast_missing     (event_s_config_tlast_missing   ), // output wire event_s_config_tlast_missing
  .event_s_config_tlast_unexpected  (event_s_config_tlast_unexpected)  // output wire event_s_config_tlast_unexpected 
);

仿真结果如下如,可以看到随着phase步进的不断累加,两个通道的输出频率也在不断增加.

FPGA

好了,本文就写的这里,希望通着这一系列的文章能帮助大家深入理解并正确使用DDS IP,详细的仿真过程可参考B站视频。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分