我在做数字IO卡。 IO卡的功能包括32路单端数字I/O输出。
32路单端I/O的数据速率为200Mbps,并使用100MHz时钟,通过ODDR实现此功能。 ODDR可以实现两倍时钟的数据速率。 时钟上升沿输出一方的数据,时钟下降沿输出另一方的数据。 ODDR的工作模式有两种:相同的边和不同的边。 该方式通过延迟1个时钟,能够节约时钟和CLB资源,提高性能。
ODDR# (
. DDR_clk_edge(opposite_edge )、//(opposite _ edge ) or'same_edge )。
. init(1'B0 ),//initialvalueofq :1 ' b0or1' B1 ) ) ) ) )。
. Srtype(sync )//set/reset type : (sync ' or ' async ) ) ) )。
) ODDR_inst (
. q(q ),//1-bit DDR output
. c(c ),//1-bit时钟输入
. ce(ce ),//1-bit时钟启用输入
. D1(D1 ),//1 -比特数据输入) (定位边缘) ) ) ) )。
. D2(D2 ),//1 -字节边缘(否定边缘) ) ) ) ) ) ) ) )。
. r(r ),//1 -位重置
. s(s )//1位集
);
我的使用方法是:
wire[63:0] do32;
wire[31:0] do_o;
wiredo_clk_sel;
wire[31:0] do_en;
genvar dq_o;
生成
for(dq_o=0; dq_o 32; dq_o=dq_o 1) begin: gen_do
ODDR # (
. DDR_clk_edge(same_edge )、
. init(1'B0 )表示:
. Sr type (同步) ) )。
) do_oddr (
. q(do_o[dq_o] )、
. c(do_clk_sel )、
. ce(1) B1 )、
. D1 ) do32(dq_o ),//64位
. D2(do32 ) dq_o32 )、
. r(do_en[dq_o] )、
. s(1) B0 ) )。
);
p> endassign 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.