ODDR

来源:互联网 发布:dxv解码器 for mac 编辑:程序博客网 时间:2024/06/09 20:58

我在做一块数字IO卡,IO卡的功能包括32路单端数字I/O输出。

32路单端I/O的数据速率为200Mbps,利用100MHz时钟,使用ODDR实现此功能。ODDR能实现双倍时钟的数据速率。在时钟上升沿输出一个数据,在时钟下降沿输出另一个数据。ODDR的工作模式有2种:同沿和不同沿。同沿方式通过延迟一个时钟,能节省时钟和CLB资源,提高性能。

ODDR#(

      .DDR_CLK_EDGE("OPPOSITE_EDGE"),//"OPPOSITE_EDGE" or "SAME_EDGE"

      .INIT(1'b0),    // Initial value of Q: 1'b0 or 1'b1

      .SRTYPE("SYNC") // Set/Resettype: "SYNC" or "ASYNC"

   ) ODDR_inst (

      .Q    (Q),   // 1-bit DDR output

      .C    (C),  // 1-bit clock input

      .CE  (CE),// 1-bit clock enable input

      .D1  (D1),// 1-bit data input (positive edge)

      .D2  (D2),// 1-bit data input (negative edge)

      .R    (R),   // 1-bit reset

      .S     (S)    // 1-bit set

   );

我的使用方法为:

wire[63:0] do32;

wire[31:0]    do_o;

wiredo_clk_sel;

wire[31:0]    do_en;

genvar  dq_o;

generate

             for(dq_o= 0; dq_o < 32; dq_o = dq_o+1) begin: gen_do

                                     ODDR #(

                                                                .DDR_CLK_EDGE("SAME_EDGE"),

                                                                 .INIT(1'b0),

                                                                 .SRTYPE("SYNC")

                                                      ) do_oddr (

                                                                 .Q           (do_o[dq_o]                      ),

                                                                 .C           (do_clk_sel                        ),

                                                                 .CE  (1'b1                                  ),

                                                                 .D1  (do32[dq_o]               ),//64位

                                                                 .D2  (do32[dq_o+ 32] ),

                                                                 .R    (do_en[dq_o]                           ),

                                                                 .S     (1'b0                                  )

                                                              );

             end

assign dio[dq_o]=do_if_ctrl[dq_o]? (do_reg_vld[dq_o]?do_reg[dq_o]: do_dout_vld? do_dout[dq_o] : do_df_out_en[ dq_o ] &(~do_df_out_en_iv[dq_o]) ?  do_df[dq_o ]: 1'bz ) :1’bz;

 

endgenerate

dio信号是顶层的inout类型双向端口。数字I/O卡的输出数据有三种类型:寄存器静态数据;动态数据;Flash数据。综合可以通过,但是在MAP过程中,出现了32个错误:

 

Thedual data rate register "gen_do[0].do_oddr" failed to  join an OLOGIC component as required.

Thedual data rate register "gen_do[1].do_oddr" failed to  join an OLOGIC component as required.

Thedual data rate register "gen_do[31].do_oddr" failed to  join an OLOGIC component as required.

 

错误的原因是ODDR的输出必须直接连到输出pad上,不可以再引进逻辑内部。因此会出现do_oddr的输出无法连入OLOGIC中。

我的解决办法是:

通过IOBUF将双向dio数据分离成要输入到FPGA中的di_d和从FPGA获得do_o. IOBUF的控制位T为高时FPGA输入I端口数据使能,为低时输出O使能。

IOBUF#(

                                               .DRIVE(12), // Specify the output drivestrength

                                               .IOSTANDARD("DEFAULT"), //Specify the I/O standard

                                               .SLEW("SLOW") // Specify theoutput slew rate

                                            ) IOBUF_inst (

                                               .O            (di_d[dq_o]  ),    // Buffer output to fpga

                                               .IO           (dio[dq_o]    ),  // Buffer inout port (connect directly to top-level port)

                                               .I              (do_o[dq_o]),     // Buffer input from fpga

                                               .T             (dir_o[dq_o/8 ])      // 3-state enableinput, high=input, low=output

                                            );

将数据端口准备输出的数据准备好后,再赋值给ODDR的D端口,将Q输出连接IOBUF的O上。MAP成功。

看来学习下Xilinx的器件手册还是很有用的。UG190.

0 0