我是靠谱客的博主 忐忑野狼,这篇文章主要介绍FPGA原语IODELAY、ODDR、BUFGMUX和VIVADO BRAM的使用1 IODELAY微调时钟相位2 ODDR使用与仿真3 BUFGMUX使用4 vivado BRAM IP的配置选项,现在分享给大家,希望可以做个参考。

目录

1 IODELAY微调时钟相位

2 ODDR使用与仿真

3 BUFGMUX使用

4 vivado BRAM IP的配置选项


1 IODELAY微调时钟相位

 #To Adjust GMII Tx Input Setup/Hold Timing

#set_property IDELAY_VALUE 16 [get_cells *_i/gmii_to_rgmii_0/U0/i_gmii_to_rgmii_block/*_gmii_to_rgmii_0_0_core/i_gmii_to_rgmii/i_gmii_to_rgmii/gen_rgmii_rx_zq.delay_rgmii_rx_ctl]

#set_property IDELAY_VALUE 16 [get_cells -hier -filter {name =~ *_i/gmii_to_rgmii_0/U0/*_gmii_to_rgmii_0_0_core/*delay_rgmii_rxd*}]

#set_property IODELAY_GROUP tri_mode_ethernet_mac_iodelay_grp1 [get_cells *_i/gmii_to_rgmii_0/U0/i_gmii_to_rgmii_block/*_gmii_to_rgmii_0_0_core/i_gmii_to_rgmii/i_gmii_to_rgmii/gen_rgmii_rx_zq.delay_rgmii_rx_ctl]

#set_property IODELAY_GROUP tri_mode_ethernet_mac_iodelay_grp1 [get_cells -hier -filter {name =~ *_i/gmii_to_rgmii_0/U0/*_gmii_to_rgmii_0_0_core/*delay_rgmii_rxd*}]

#set_property IODELAY_GROUP tri_mode_ethernet_mac_iodelay_grp1 [get_cells *_i/gmii_to_rgmii_0/U0/i_*_gmii_to_rgmii_0_0_idelayctrl]

2 ODDR使用与仿真

1)使用方法

在DDR接口中ODDR用于发送时钟和数据;

在SDR接口中仅用ODDR转发时钟(仍在时钟树内),输出端要直连到输出port,不可加逻辑;

使用时钟专用输入管脚输出时钟=使用GPIO输出时钟,必须使用ODDR

发送多位数据时需要用generate语句例化多个ODDR原语,参见如下链接(ODDR的使用错误):

ODDR的使用错误_christne1225i的专栏-CSDN博客 主要内容引用如下:

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

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

我的解决办法是:

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

2)数据输入捕获模式

      OPPOSITE_EDGE模式、SAME_EDGE模式区别在于前者先后使用上升下降沿捕获数据到ODDR内部,后者同时在上升沿捕获两个端口的数据到ODDR内部。两者的输出相同,都是在不同的沿输出各自数据。

 3)仿真

输出端口在CE=1后并不是立即工作,大约有105ns多的等待期。原语模块代码:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
`timescale 1ns / 1ps module oddr( output wire Q, input wire C, input wire CE, input wire D1, input wire D2, input wire R, input wire S ); 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/Reset type: "SYNC" or "ASYNC" ) ODDR_clk ( .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 ); endmodule

简单的仿真代码: 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
`timescale 1ns / 1ps module oddr_tb(); wire Q; reg C; reg CE; reg D1; reg D2; reg R; reg S ; initial begin C = 0; CE= 1; D1= 0; D2= 1; R=0; S=0; end initial begin #2 R=0; #2 R=1; end //时钟 always #15 C=~C; oddr i1 ( .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 ); endmodule

Q端输出比端的延时大约为0.1ns 

 IDDR也存在等待周期:见下图

在以下文章中也提到了在IDDR使用时也存在等待周期:

IDDR仿真_猜猜_新浪博客 文中提到:

需要注意的几点

1. IDDR模块在CE信号变高之后会有一些设定时间,所以在CE信号变高的同时给出data不是一个很好的选择。我在data输出代码里加入了10个cycle的延迟。

2.IDDR对clk是边缘敏感,图中的红色线箭头可以看出,IDDR根据clk_ddr_t信号的上升下降的边缘得到data再输出。之前使用过图中的ds_low来作为IDDR驱动时钟,可是data输出不正常。

3 BUFGMUX使用

1)在多个时钟选择输出1个时,使用BUFGMUX,xilinx官方手册UG382 (38页);

2)参数Clk type: "SYNC" or "ASYNC"

SYNC:两个输入时钟必须都有效,在切换信号变化后,输出保持无效(0 or 1都可能)直到后一个clk的变化沿(上下沿)时输出时钟;The primitive guarantees that when the select line S is toggled to choose the other clock source, the output remains in the inactive state until the next active clock edge on either input.

ASYNC:切换信号变化后,立即输出下一个时钟。

 3)例化代码

BUFGMUX #(

   .CLK_SEL_TYPE("ASYNC" )// Clk type: "SYNC" or "ASYNC" (原语模版中没有注明)

     )

     BUFGMUX_1M_8M (

        .O(clk_out_i),   // 1-bit output: Clock output

        .I0(clk_divider[4]), // 1-bit input: Clock input (S=0)

        .I1(clk_divider[1]), // 1-bit input: Clock input (S=1)

        .S(s[0])    // 1-bit input: Clock select

     );

4)MUX上电后的输出有110ns左右的等待期,之后才正常用S端控制。在此期间控制端口为默认值0,输出端口输出I0默认值。

4 vivado BRAM IP的配置选项

BRAM设置界面的配置,如下入中三个框内:

1)Oprating Mode有读优先、写优先、NO_change三种模式,根据实际需求配置。NO_change功耗低;

2)输出的寄存器配置,绿色框内为BRAM内部的reg,蓝色框内为BRAM外部Slice中reg,两个都使用时数据延时3clk输出,能够获得更好的时序和性能。

3)不要使用异步复位;

4) 可通过vivado自带的仿真功能进行仿真验证。

 

把我在AET blog上的四篇文章合并一篇到CSDN,方便查看。

IODELAY微调时钟相位-Bryan-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台

 BUFGMUX使用-Bryan-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台

ODDR使用与仿真-Bryan-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台

 BRAM IP的配置选项-Bryan-电子技术应用-AET-中国科技核心期刊-最丰富的电子设计资源平台

最后

以上就是忐忑野狼最近收集整理的关于FPGA原语IODELAY、ODDR、BUFGMUX和VIVADO BRAM的使用1 IODELAY微调时钟相位2 ODDR使用与仿真3 BUFGMUX使用4 vivado BRAM IP的配置选项的全部内容,更多相关FPGA原语IODELAY、ODDR、BUFGMUX和VIVADO内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部