FPGA原语IODELAY、ODDR、BUFGMUX和VIVADO BRAM的使用

目录

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的专栏-优快云博客 主要内容引用如下:

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多的等待期。原语模块代码:

`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

简单的仿真代码: 

`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上的四篇文章合并一篇到优快云,方便查看。

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

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

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

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

<think>好的,我现在需要回答用户关于Xilinx FPGABUFGMUXBUFGMUX_CTRL的区别的问题。用户已经提供了几个相关的引用,我需要仔细分析这些信息,然后整理出清晰的答案。 首先,我需要确认用户提到的“bufgmux_ctrl”是否是指“BUFGCTRL”,因为在提供的引用中多次提到BUFGCTRL,而BUFGMUX是基于它构建的。可能用户在这里有笔误,或者混淆了名称,所以需要明确这两个组件的关系。 根据引用[1]和引用[2],BUFGMUX是一个时钟缓冲器,有两个输入和一个选择信号,而BUFGCTRL是一个更高级的控制单元,提供更多配置选项。BUFGMUX实际上是在BUFGCTRL的基础上,将某些引脚固定连接到逻辑高或低电平,从而简化了使用方式。例如,引用[4]中的代码示例显示BUFGMUX有I0、I1、S和O引脚,这可能对应于BUFGCTRL的某些输入,但其他控制信号如CE、IGNORE可能被固定了。 接下来,我需要比较两者的主要区别。根据引用[2],BUFG(包括BUFGMUX)是BUFGCTRL的简化版,固定了部分引脚,限制了配置选项。而BUFGCTRL具有更多的控制信号,比如CE(时钟使能)、S(选择信号)、IGNORE(忽略某些条件)等,这使得它更灵活,但使用也更复杂。 另外,功能定位不同。BUFGMUX主要用于时钟切换,而BUFGCTRL功能更全面,可能用于更复杂的时钟管理任务,比如动态切换、使能控制等。结构差异方面,BUFGMUX的结构是基于BUFGCTRL的,但引脚连接不同。例如,引用[1]中的图2-10说明了它们的关系。 应用场景方面,BUFGMUX适合简单的时钟切换,而BUFGCTRL适用于需要动态控制或复杂配置的情况。例如,当需要根据条件动态切换时钟源或调整时钟行为时,BUFGCTRL会更合适。 需要确保回答准确,引用正确的来源。比如引用[1]提到BUFGMUX是基于BUFGCTRL,引用[2]说明BUFG是BUFGCTRL的简化版本。同时,引用[4]中的代码示例展示了BUFGMUX使用方式,但用户的问题可能涉及BUFGCTRL的更多控制信号。 在整理这些信息时,需要分点说明差异,比如功能定位、结构差异、控制信号、应用场景等,确保用户能清晰理解两者的区别。此外,生成的相关问题需要围绕这两个组件展开,比如如何选择、典型应用、配置选项等。 最后,检查是否有遗漏的信息,比如是否有关于时序特性或性能差异的内容,但根据提供的引用,似乎没有这方面的信息,因此可能不需要涉及。确认所有引用正确标注,例如引用[1]、[2]、[4]都涉及两者的关系,而引用[3]提到IODELAY等,可能与当前问题无关,可以忽略。</think>### BUFGMUX与BUFGCTRL的核心区别 在Xilinx FPGA中,**BUFGMUX**和**BUFGCTRL**是两种时钟管理原语,主要差异体现在功能定位、控制信号和配置灵活性上: 1. **功能定位** - **BUFGMUX**:专为时钟切换设计,支持两个输入时钟源(`I0`和`I1`)通过选择信号`S`进行静态或动态切换,输出单一时钟信号`O`。适用于简单的时钟多路复用场景[^1][^4]。 - **BUFGCTRL**:功能更全面的时钟控制单元,支持动态时钟切换、时钟使能(`CE`)控制以及异步/同步切换模式配置,适合需要复杂时钟管理的场景[^2]。 2. **结构差异** - BUFGMUX基于BUFGCTRL实现,但**固定了部分控制信号**。例如: - `IGNORE0`和`IGNORE1`(输入时钟无效条件)被固定为逻辑低电平; - `CE0`和`CE1`(时钟使能)被固定为高电平[^1]。 - BUFGCTRL则**开放所有控制引脚**,允许用户自定义配置,例如动态启用/禁用时钟路径或设置切换条件。 3. **控制信号对比** | 信号 | BUFGMUX | BUFGCTRL | 说明 | |-----------|---------|--------------------|--------------------------| | `S` | 有 | 有(`S0`/`S1`) | 切换选择信号 | | `CE` | 无 | 有(`CE0`/`CE1`) | 时钟使能控制 | | `IGNORE` | 无 | 有(`IGNORE0`/`1`) | 输入时钟有效性忽略条件 | | `I0/I1` | 有 | 有 | 输入时钟源 | | `O` | 有 | 有 | 输出时钟 | 4. **应用场景** - **BUFGMUX**:适合需要简单、低延迟的时钟切换,例如冗余时钟源切换或低功耗模式下的时钟选择[^4]。 - **BUFGCTRL**:用于需要动态控制(如运行时使能/禁用时钟)或复杂切换逻辑(如优先级切换)的场景。 --- ### 示例代码 BUFGMUX原语调用示例(引用自): ```verilog BUFGMUX BUFGMUX_inst ( .O(o_clk_out_2), // 输出时钟 .I0(clk_in2), // S=0时选择的时钟 .I1(clk_in1), // S=1时选择的时钟 .S(clk_10ms_en) // 切换控制信号 ); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值