使用OSERDESE2原语实现多个dds合成一个波形,达到面积换速度的目的

如何使用OSERDESE2原语实现多个dds合成一个波形

在这里插入图片描述

  • 要实现一个高频波形的数字呈现时,可以将其拆分成4个甚至8个相同频率不同初始相位的低频波形,多个低频dds生成的波形使用OSERDESE2原语合成最终的高频波形,这样占用了更多资源,但是降低了运行速度。
  • 如图所示彩色的波形由四个不同颜色构成,一共由36个点构成一个完整的正弦波。当使用一个dds生成时,必然运行时钟频率要求更高。当我们将其拆成四个小的波形,每个波形由9个点构成,相当于四分之一倍低频频率的dds;或者说在原本单位周期要完成36个点的计算,现在只需要完成9个点的计算,只不过这样的计算模块有四个。相当于同样一件事原先交给一个人完成,那他就需要焦头烂额地在固定周期内完成工作;如果将工作拆成4个小任务交由四个人分别完成,那么每个人的压力就会很小,工作也会很悠闲。这种方式通常称为面积换速度。
  • 在FPGA(Field-Programmable Gate Array)中,“面积”(Area)、“功耗”(Power)和"速度"(Performance)是 FPGA 设计的关键指标,通常被称为 “Area, Power, Speed”(APS)三角。
  • 面积(Area): 指的是 FPGA 芯片上被设计电路占据的物理空间。在FPGA中,资源包括逻辑单元(Lookup
    Tables)、寄存器、布线资源等。更大的面积通常表示能够容纳更多的逻辑元素,但也可能会增加功耗和成本。
  • 功耗(Power): FPGA 设计中的功耗是指电路在运行时所消耗的电能。功耗与 FPGA
    设计的电路结构、时钟频率、电压等因素有关。在一些功耗敏感的应用中,需要设计者在满足性能要求的前提下尽量降低功耗。
  • 速度(Speed): 在 FPGA
    设计中,速度通常指的是电路在运行时的时钟频率。更高的时钟频率允许电路更快地执行操作,但同时也可能增加功耗和面积。
  • 这三个指标之间存在权衡关系,通常被描述为 “Area, Power, Speed” 三角。设计者需要在这三者之间做出取舍,根据具体的应用需求和设计约束做出权衡。例如,提高时钟频率可能会导致更大的功耗,而减小面积可能会限制电路的复杂性。

在这里插入图片描述

OSERDESE2原语的应用

如下方程序所示:

`timescale 1ns / 1ps
///////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:  		jiangquan
// 
// Design Name: 
// Module Name:		txdata_oserd_e2
// Project Name:    
// Target Devices:  Kintex-7
// Tool Versions:   Vivado 2019.1
// Description: 
// OSERDESE2,DAC data output interface
//
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Create Date: 2021/03/09
// Additional Comments:
//
//
// Revision 0.02 - File update
// Update Date: year/mounth/date
// Additional Comments:
//
// 
///////////////////////////////////////////////////////////////////////
module txdata_oserd_e2 #(
    parameter  BUS_W   = 8'd16,
    parameter  SERD_W  = 4'd4,
    parameter  DCI_SEQ = 5'b01010,  // DCI SEQUENCE: 0 1 0 1 0
    parameter  SERD_MD = "DDR",     // DDR Mode support Data_Width:2,4,6,8,10,14
                                    // SDR Mode support Data_Width:2,3,4,5,6,7,8
    parameter  DAT_W   = 8'd224     //14 * BUS_W
    
    )
(
    // Global Clock And Reset
    input               i_rst,
    input               i_tx_clk,
    input               i_tx_clkdiv,
    // dac external interface
    output  [15:0]      o_tx_dout_p,
    output  [15:0]      o_tx_dout_n,
    output              o_tx_dci_p,
    output              o_tx_dci_n,
    // dac fpga internal interface
    input  [223:0]      i_tx_data
    );

//====================================================================//
//-------------------------- 变量声明 --------------------------------//
//====================================================================//
    wire                              dci_sf1;
    wire                              dci_sf2; 
    wire    [BUS_W -1 : 0]            dat_sf1;
    wire    [BUS_W -1 : 0]            dat_sf2;
                      
    wire    [BUS_W -1 : 0]            tx_dout;
    wire                              tx_dci;
                      
    wire    [BUS_W -1 : 0]            tx_d1;
    wire    [BUS_W -1 : 0]            tx_d2;
    wire    [BUS_W -1 : 0]            tx_d3;
    wire    [BUS_W -1 : 0]            tx_d4;
    wire    [BUS_W -1 : 0]            tx_d5;
    wire    [BUS_W -1 : 0]            tx_d6;
    wire    [BUS_W -1 : 0]            tx_d7;
    wire    [BUS_W -1 : 0]            tx_d8; 
    wire    [BUS_W -1 : 0]            tx_d9; 
    wire    [BUS_W -1 : 0]            tx_d10;
    wire    [BUS_W -1 : 0]            tx_d11;
    wire    [BUS_W -1 : 0]            tx_d12;
    wire    [BUS_W -1 : 0]            tx_d13;
    wire    [BUS_W -1 : 0]            tx_d14;

//====================================================================//
//-------------------------   核心逻辑   -----------------------------//
//====================================================================//
    
    assign  tx_d1   = i_tx_data[   BUS_W -1 : 0       ];
    assign  tx_d2   = i_tx_data[ 2*BUS_W -1 : BUS_W   ];
    assign  tx_d3   = i_tx_data[ 3*BUS_W -1 : 2*BUS_W ];
    assign  tx_d4   = i_tx_data[ 4*BUS_W -1 : 3*BUS_W ];
    assign  tx_d5   = i_tx_data[ 5*BUS_W -1 : 4*BUS_W ];
    assign  tx_d6   = i_tx_data[ 6*BUS_W -1 : 5*BUS_W ];
    assign  tx_d7   = i_tx_data[ 7*BUS_W -1 : 6*BUS_W ];
    assign  tx_d8   = i_tx_data[ 8*BUS_W -1 : 7*BUS_W ];
    assign  tx_d9   = i_tx_data[ 9*BUS_W -1 : 8*BUS_W ];
    assign  tx_d10  = i_tx_data[10*BUS_W -1 : 9*BUS_W ];
    assign  tx_d11  = i_tx_data[11*BUS_W -1 : 10*BUS_W ];
    assign  tx_d12  = i_tx_data[12*BUS_W -1 : 11*BUS_W ];
    assign  tx_d13  = i_tx_data[13*BUS_W -1 : 12*BUS_W ];
    assign  tx_d14  = i_tx_data[14*BUS_W -1 : 13*BUS_W ];

/////////////////////////////////////
// Sync Reset to CLKDIV
    (* KEEP="TRUE" *)wire   sync_rst;
    reg  [3:0]  rst_cnt;

    always @(posedge i_tx_clkdiv or posedge i_rst)begin
        if(i_rst)
            rst_cnt     <= 0;
        else
            if(rst_cnt == 4'b1000)
                rst_cnt <= rst_cnt;
            else
                rst_cnt <= rst_cnt + 1;
    end // eng always
    
    assign  sync_rst = rst_cnt[1]; 
 
/////////////////////////////////////    
// DCI
generate
    if(SERD_W > 8)
        begin:width_expansion_mode
               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   DCI_SEQ[0]                  ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "MASTER"                    ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   4                           )
               )
               u_oserdes1_dci (
                  .OFB                      (                               ),
                  .OQ                       (   tx_dci                      ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (                               ),
                  .SHIFTOUT2                (                               ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (   DCI_SEQ[1]                  ),
                  .D2                       (   DCI_SEQ[2]                  ),
                  .D3                       (   DCI_SEQ[3]                  ),
                  .D4                       (   DCI_SEQ[4]                  ),
                  .D5                       (   DCI_SEQ[1]                  ),
                  .D6                       (   DCI_SEQ[2]                  ),
                  .D7                       (   DCI_SEQ[3]                  ),
                  .D8                       (   DCI_SEQ[4]                  ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   dci_sf1                     ),
                  .SHIFTIN2                 (   dci_sf2                     ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );

               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   DCI_SEQ[0]                  ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "SLAVE"                     ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   4                           )
               )
               u_oserdes2_dci (
                  .OFB                      (                               ),
                  .OQ                       (                               ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (   dci_sf1                     ),
                  .SHIFTOUT2                (   dci_sf2                     ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (                               ),
                  .D2                       (                               ),
                  .D3                       (   DCI_SEQ[1]                  ),
                  .D4                       (   DCI_SEQ[2]                  ),
                  .D5                       (   DCI_SEQ[3]                  ),
                  .D6                       (   DCI_SEQ[4]                  ),
                  .D7                       (   DCI_SEQ[1]                  ),
                  .D8                       (   DCI_SEQ[2]                  ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   1'b0                        ),
                  .SHIFTIN2                 (   1'b0                        ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );
               
                OBUFDS #(
                    .IOSTANDARD             (   "LVDS"                      ),  // Specify the output I/O standard
                    .SLEW                   (   "FAST"                      )   // "SLOW"
                )
                u_obufds_dci(
                    .I                      (   tx_dci              ), // Buffer input
                    .O                      (   o_tx_dci_p          ), // Diff_p output (connect directly to top-level port)
                    .OB                     (   o_tx_dci_n          )  // Diff_n output (connect directly to top-level port)
                );
        end // 
    else
        begin:normal_mode
               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   DCI_SEQ[0]                  ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "MASTER"                    ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   1                           )
               )
               u_oserdes_dci (
                  .OFB                      (                               ),
                  .OQ                       (   tx_dci                      ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (                               ),
                  .SHIFTOUT2                (                               ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (   DCI_SEQ[1]                  ),
                  .D2                       (   DCI_SEQ[2]                  ),
                  .D3                       (   DCI_SEQ[3]                  ),
                  .D4                       (   DCI_SEQ[4]                  ),
                  .D5                       (   DCI_SEQ[1]                  ),
                  .D6                       (   DCI_SEQ[2]                  ),
                  .D7                       (   DCI_SEQ[3]                  ),
                  .D8                       (   DCI_SEQ[4]                  ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   1'b0                        ),
                  .SHIFTIN2                 (   1'b0                        ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );
             
                OBUFDS #(
                    .IOSTANDARD             (   "LVDS"                      ),  // Specify the output I/O standard
                    .SLEW                   (   "FAST"                      )   // "SLOW"
                )
                u_obufds_dci(
                    .I                      (   tx_dci              ), // Buffer input
                    .O                      (   o_tx_dci_p          ), // Diff_p output (connect directly to top-level port)
                    .OB                     (   o_tx_dci_n          )  // Diff_n output (connect directly to top-level port)
                );
        end
endgenerate
        
// DATA
genvar DAT_GEN;
generate
    if(SERD_W > 8)
        begin:width_expansion_mode
            for (DAT_GEN = 0; DAT_GEN < BUS_W; DAT_GEN = DAT_GEN + 1) 
            begin: u_dat_gen
               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   1'b0                        ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "MASTER"                    ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   1                           )
               )
               u_oserdes1_dat (
                  .OFB                      (                               ),
                  .OQ                       (   tx_dout[DAT_GEN]            ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (                               ),
                  .SHIFTOUT2                (                               ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (   tx_d1[DAT_GEN]              ),
                  .D2                       (   tx_d2[DAT_GEN]              ),
                  .D3                       (   tx_d3[DAT_GEN]              ),
                  .D4                       (   tx_d4[DAT_GEN]              ),
                  .D5                       (   tx_d5[DAT_GEN]              ),
                  .D6                       (   tx_d6[DAT_GEN]              ),
                  .D7                       (   tx_d7[DAT_GEN]              ),
                  .D8                       (   tx_d8[DAT_GEN]              ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   dat_sf1[DAT_GEN]            ),
                  .SHIFTIN2                 (   dat_sf2[DAT_GEN]            ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );

               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   1'b0                        ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "SLAVE"                     ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   1                           )
               )
               u_oserdes2_dat (
                  .OFB                      (                               ),
                  .OQ                       (                               ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (   dat_sf1[DAT_GEN]            ),
                  .SHIFTOUT2                (   dat_sf2[DAT_GEN]            ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (                               ),
                  .D2                       (                               ),
                  .D3                       (   tx_d9 [DAT_GEN]             ),
                  .D4                       (   tx_d10[DAT_GEN]             ),
                  .D5                       (   tx_d11[DAT_GEN]             ),
                  .D6                       (   tx_d12[DAT_GEN]             ),
                  .D7                       (   tx_d13[DAT_GEN]             ),
                  .D8                       (   tx_d14[DAT_GEN]             ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   1'b0                        ),
                  .SHIFTIN2                 (   1'b0                        ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );

                OBUFDS #(
                    .IOSTANDARD             (   "LVDS"                      ),  // Specify the output I/O standard
                    .SLEW                   (   "FAST"                      )   // "SLOW"
                )
                u_obufds_dat(
                    .I                      (   tx_dout  [DAT_GEN]      ),
                    .O                      (   o_tx_dout_p[DAT_GEN]    ),
                    .OB                     (   o_tx_dout_n[DAT_GEN]    ) 
                );
            end
        end
    else
        begin:normal_mode
            for (DAT_GEN = 0; DAT_GEN < BUS_W; DAT_GEN = DAT_GEN + 1) 
            begin: u_dat_gen
               OSERDESE2 #(
                  .DATA_RATE_OQ             (   SERD_MD                     ),  // DDR, SDR
                  .DATA_RATE_TQ             (   "DDR"                       ),  // DDR, BUF, SDR
                  .DATA_WIDTH               (   SERD_W                      ),  // Parallel data width (2-8,10,14)
                  .INIT_OQ                  (   1'b0                        ),
                  .INIT_TQ                  (   1'b0                        ),
                  .SERDES_MODE              (   "MASTER"                    ),  // MASTER, SLAVE
                  .SRVAL_OQ                 (   1'b0                        ),
                  .SRVAL_TQ                 (   1'b0                        ),
                  .TBYTE_CTL                (   "FALSE"                     ),  // Enable tristate byte operation (FALSE, TRUE)
                  .TBYTE_SRC                (   "FALSE"                     ),  // Tristate byte source (FALSE, TRUE)
                  .TRISTATE_WIDTH           (   1                           )
               )
               u_oserdes_dat (
                  .OFB                      (                               ),
                  .OQ                       (   tx_dout[DAT_GEN]            ),
                  // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
                  .SHIFTOUT1                (                               ),
                  .SHIFTOUT2                (                               ),
                  .TBYTEOUT                 (                               ),
                  .TFB                      (                               ),
                  .TQ                       (                               ),
                  .CLK                      (   i_tx_clk                    ),
                  .CLKDIV                   (   i_tx_clkdiv                 ),
                  // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
                  .D1                       (   tx_d1[DAT_GEN]              ),
                  .D2                       (   tx_d2[DAT_GEN]              ),
                  .D3                       (   tx_d3[DAT_GEN]              ),
                  .D4                       (   tx_d4[DAT_GEN]              ),
                  .D5                       (   tx_d5[DAT_GEN]              ),
                  .D6                       (   tx_d6[DAT_GEN]              ),
                  .D7                       (   tx_d7[DAT_GEN]              ),
                  .D8                       (   tx_d8[DAT_GEN]              ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
                  // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
                  .SHIFTIN1                 (   1'b0                        ),
                  .SHIFTIN2                 (   1'b0                        ),
                  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
                  .T1                       (   1'b0                        ),
                  .T2                       (   1'b0                        ),
                  .T3                       (   1'b0                        ),
                  .T4                       (   1'b0                        ),
                  .TBYTEIN                  (   1'b0                        ),
                  .TCE                      (   1'b0                        )
               );
             
                OBUFDS #(
                    .IOSTANDARD             (   "LVDS"                      ),  // Specify the output I/O standard
                    .SLEW                   (   "FAST"                      )   // "SLOW"
                )
                u_obufds_dat(
                    .I                      (   tx_dout  [DAT_GEN]      ),
                    .O                      (   o_tx_dout_p[DAT_GEN]    ),
                    .OB                     (   o_tx_dout_n[DAT_GEN]    ) 
                );
            end
        end     
endgenerate

/////////////////////////////////////    
    
endmodule


此程序实现了多DDS模块生成数据在多个通道进行的,并转串的合并输出。需要理解以下两点:

  1. 理解generate模块复用例化
  2. OSERDESE2 原语

详细的OSERDESE2 原语解释请自行查阅,如xilinx原语详解及仿真——OSERDESE2
generate的使用方法如Verilog中generate的用法

注意事项

  1. 使用OSERDESE2原语的时候,是将四个低频dds的数据合成一个,那么合成模块就是将四个dds的值一次穿插,其最终的输出频率无法降低,和使用一个dds输出波形时所用的时钟频率一致或至少其一半,但无法降低至每个小dds的低频率去运行。如果硬件如DAC无法在这么高的频率下输出,那么还是无法合成高频率的波形。也就是说此方法只是为了减轻系统计算庞大数据时候的速度压力,最终合成波形的频率上限是由硬件条件尤其是DAC决定的。
  2. OSERDESE2原语可以做到时钟上升沿和下降沿都输出数据,利用ddr模式可以生成两倍频率的数据。如10MHz的波形用一个dds实现,如果44个点为一个周期,那么时钟频率为440Mhz,而利用OSERDESE2原语只需要220MHz就可以合成。
  3. 再考虑多少个dds合成一个最终的波形时,不仅限于4个或者8,具体根据实际情况考量,可以利用OSERDESE2原语的级联做到14个DDS合成一个。
  4. 此程序使用的是8个dds的数据,但最终选出其第1、3、5、7个dds进行波形合成,第2、4、6、8个dds并未进行计算,但是在OSERDESE2模块里仍然按照8个通道去合并的。如果8个dds的数据全部并转串输出,那么最终波形一个周期就由11个点组成,而现在这种四个11/8个dds合成的波形,每个周期其实只有5或6个点。这里只是阐述D1、D2通道的数据为何一样,详细可查看此文:DDS的步进值计算
    在这里插入图片描述

代码要点

  1. 此代码里虽然使用了ddr模式,但是时钟上升沿和下降沿的数据是一样的,等同于仍然是每个时钟上升沿才输出一次。
  2. 虽然D1-D8通道全部使用了,但D1和D2、D3和D4、D5和D6、D7和D8的数据是一样的。
  3. 要注意并转串是倒着输出的,因此最终输出的结果等于是D7通道的第一个数据排第1输出,D5通道的第一个数据排在第2个输出,D3排第3,D1排第4;然后是D7通道的第二个数据,依次类推。
  4. 在如下图所示程序里 ,tx_d1值得不是数组,而是一个变量,这里不是利用数组的多维元素进行拼接,而是tx_d1这个变量的某一位进行generate的模块复用。要知道的是这些复用的模块是同时进行的,也就是单位时钟周期内,tx_d1这个变量的每一位都赋值成功了
                   D1                       (   tx_d1[DAT_GEN]              ),
                  .D2                       (   tx_d2[DAT_GEN]              ),
                  .D3                       (   tx_d3[DAT_GEN]              ),
                  .D4                       (   tx_d4[DAT_GEN]              ),
                  .D5                       (   tx_d5[DAT_GEN]              ),
                  .D6                       (   tx_d6[DAT_GEN]              ),
                  .D7                       (   tx_d7[DAT_GEN]              ),
                  .D8                       (   tx_d8[DAT_GEN]              ),
                  .OCE                      (   1'b1                        ),
                  .RST                      (   sync_rst                    ), 
  1. 如下表所示,复用的模块对每一位单独进行赋值,每个模块都是并行同时进行赋值的;也就是同一时间输出端tx_dout的A、B、C、D变量就已经赋值完成了,再依次按照AABBCCDD顺序输出即可。
    切勿理解为tx_dout[15:0]=0000 0000 0000 000A0

在这里插入图片描述

  • 42
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值