概述
目录
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多的等待期。原语模块代码:
`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上的四篇文章合并一篇到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 BRAM的使用1 IODELAY微调时钟相位2 ODDR使用与仿真3 BUFGMUX使用4 vivado BRAM IP的配置选项所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复