前言
在上篇文章ISERDES2介绍中介绍了该原语的使用以及DDR模式8:1采样的代码与仿真波形,本文对ISERDES2不做过多介绍,直接给出DDR模式的10:1采集,方法与8:1采用一样,引入OSERDES将数据传入ISERDES2模块中进行采样。
代码介绍
代码包括PLL模块,oserdes2_ctrl,iserdes2_ctrl
1. 顶层模块
module top(
sys_clk ,
rst_n ,
o_iserdese2_vld ,
o_iserdese2
);
parameter DATA_WIDTH = 4'd10 ;
parameter CHEEK_SUM1 = 10'h323;
parameter CHEEK_SUM2 = 10'h28c;
input sys_clk ;
input rst_n ;
output o_iserdese2_vld ;
output [DATA_WIDTH-1:0] o_iserdese2 ;
wire rst_wire ;
wire clk ;
wire clk_div ;
wire oserdese_ofb ;
wire locked ;
wire flag_wire ;
clk_wiz_0 u_clk_wiz_0(
.clk_out1 ( clk_div ),//output clk_out1
.clk_out2 ( clk ),//output clk_out2
.reset ( ~rst_n ),//input reset
.locked ( locked ),
.clk_in1 ( sys_clk ) //input clk_in1
);
assign rst_wire = rst_n==0;
//例化并串转换原语;
oserdese2_ctrl u_oserdese2_ctrl(
.clk ( clk ), //系统时钟信号;
.clk_div ( clk_div ),
.rst ( rst_wire ), //系统复位信号,高电平有效;
.ofb ( oserdese_ofb ),
.o_cheeksum_flag ( flag_wire ),
.cheek_sum_first ( CHEEK_SUM1 ), //校验和
.cheek_sum_secord( CHEEK_SUM2 )
);
iserdese2_ctrl u_iserdese2_ctrl(
.clk ( clk ),//系统时钟信号;
.clk_div ( clk_div ),
.rst ( rst_wire ),//系统复位信号,高电平有效;
.ofb ( oserdese_ofb ),
.dout ( o_iserdese2 ),//输出数据
.dout_vld ( o_iserdese2_vld ), //输出数据有效指示信号;
.i_cheeksum_flag (flag_wire ),
.cheek_sum_first (CHEEK_SUM1 ), //校验和
.cheek_sum_secord(CHEEK_SUM2 )
);
endmodule
2. PLL模块
DDR模式10:1数据串并转换CLK:CLKDIV=5:1,本文通过系统时钟50MHz生成一个CLK=250MHz,一个CLKDIV=50MHz用与iserder2原语使用。PLL模块通过软件生成,这里不再介绍。
3. oserdese2_ctrl
module oserdese2_ctrl(
clk ,
clk_div ,
rst ,
cheek_sum_first , //校验和
cheek_sum_secord, //校验和
ofb ,
o_cheeksum_flag
);
parameter PACKAGE_NUM = 32 ; //校验和长度
parameter DATA_WIDTH = 10 ;
input clk ;
input clk_div ;
input rst ;
input [DATA_WIDTH-1:0] cheek_sum_first ; //校验和
input [DATA_WIDTH-1:0] cheek_sum_secord; //校验和
output ofb ;
output o_cheeksum_flag ;
reg o_cheeksum_flag ;
reg [7:0] cnt ;
reg [DATA_WIDTH-1:0] din ;
wire add_cnt ;
wire end_cnt ;
reg [5:0] cnt ;
reg [7:0] cnt_package ;
wire shiftout1 ;
wire shiftout2 ;
//校验和发送完成标志位;
always@(posedge clk_div)begin
if(rst)begin
o_cheeksum_flag <= 1'b0;
end
else if(cnt_package==PACKAGE_NUM-1)begin
o_cheeksum_flag <= 1'b1;
end
end
always@(posedge clk_div)begin
if(rst)begin
cnt <= 0;
end
else if(add_cnt)begin
if(end_cnt)begin
cnt <= 0;
end
else begin
cnt <= cnt + 1;
end
end
end
assign add_cnt = !o_cheeksum_flag ;
assign end_cnt = add_cnt && cnt == 2-1 ;
//校验头计数器计算头部长度
always @(posedge clk_div or posedge rst)begin
if(rst)begin
cnt_package <= 0;
end
else if(cnt_package==PACKAGE_NUM-1)begin
cnt_package <= cnt_package;
end
else if(end_cnt)begin
cnt_package <= cnt_package + 1;
end
end
//校验头部{7C,82}与数据拼接;
always@(posedge clk_div or posedge rst)begin
if(rst)begin
din <= cheek_sum_first;
end
else if(cnt_package==PACKAGE_NUM-1)begin//如果校准序列发送完毕,则发送随机信号用于测试。
din <= {(din[0] ^ din[4] ^ din[5] ^ din[6]),din[9:1]};//M序列公式为x^8+x^4+x^3+x^2+1。
end
else if(cnt==1-1)begin//发送校准序列8'h5c;
din <= cheek_sum_first;
end
else if(cnt==2-1)begin//发送校准序列8'h82.
din <= cheek_sum_secord;
end
end
//例化OSERDESE2原语
OSERDESE2 #(
.DATA_RATE_OQ ( "DDR" ),// DDR, SDR
.DATA_RATE_TQ ( "SDR" ),// DDR, BUF, SDR
.DATA_WIDTH ( 10 ),// Parallel data width (2-8,10,14)
.INIT_OQ ( 1'b0 ),// Initial value of OQ output (1'b0,1'b1)
.INIT_TQ ( 1'b0 ),// Initial value of TQ output (1'b0,1'b1)
.SERDES_MODE ( "MASTER" ),// MASTER, SLAVE
.SRVAL_OQ ( 1'b0 ),// OQ output value when SR is used (1'b0,1'b1)
.SRVAL_TQ ( 1'b0 ),// TQ output value when SR is used (1'b0,1'b1)
.TBYTE_CTL ( "FALSE" ),// Enable tristate byte operation (FALSE, TRUE)
.TBYTE_SRC ( "FALSE" ),// Tristate byte source (FALSE, TRUE)
.TRISTATE_WIDTH ( 1 ) // 3-state converter width (1,4)
)
OSERDESE2_Master (
.OFB ( ofb ),// 1-bit output: Feedback path for data
.OQ ( ),// 1-bit output: Data path output
// SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
.SHIFTOUT1 ( ),
.SHIFTOUT2 ( ),
.TBYTEOUT ( ),// 1-bit output: Byte group tristate
.TFB ( ),// 1-bit output: 3-state control
.TQ ( ),// 1-bit output: 3-state control
.CLK ( clk ),// 1-bit input: High speed clock
.CLKDIV ( clk_div ),// 1-bit input: Divided clock
// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
.D1 ( din[0] ),
.D2 ( din[1] ),
.D3 ( din[2] ),
.D4 ( din[3] ),
.D5 ( din[4] ),
.D6 ( din[5] ),
.D7 ( din[6] ),
.D8 ( din[7] ),
.OCE ( 1'b1 ),// 1-bit input: Output data clock enable
.RST ( rst ),// 1-bit input: Reset
// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
.SHIFTIN1 ( shiftout1 ),
.SHIFTIN2 ( shiftout2 ),
// T1 - T4: 1-bit (each) input: Parallel 3-state inputs
.T1 ( 1'b0 ),
.T2 ( 1'b0 ),
.T3 ( 1'b0 ),
.T4 ( 1'b0 ),
.TBYTEIN ( 1'b0 ),// 1-bit input: Byte group tristate
.TCE ( 1'b0 ) // 1-bit input: 3-state clock enable
);
OSERDESE2 #(
.DATA_RATE_OQ ( "DDR" ),// DDR, SDR
.DATA_RATE_TQ ( "SDR" ),// DDR, BUF, SDR
.DATA_WIDTH ( 10 ),// Parallel data width (2-8,10,14)
.INIT_OQ ( 1'b0 ),// Initial value of OQ output (1'b0,1'b1)
.INIT_TQ ( 1'b0 ),// Initial value of TQ output (1'b0,1'b1)
.SERDES_MODE ( "SLAVE" ),// MASTER, SLAVE
.SRVAL_OQ ( 1'b0 ),// OQ output value when SR is used (1'b0,1'b1)
.SRVAL_TQ ( 1'b0 ),// TQ output value when SR is used (1'b0,1'b1)
.TBYTE_CTL ( "FALSE" ),// Enable tristate byte operation (FALSE, TRUE)
.TBYTE_SRC ( "FALSE" ),// Tristate byte source (FALSE, TRUE)
.TRISTATE_WIDTH ( 1 ) // 3-state converter width (1,4)
)
OSERDESE2_Slave (
.OFB ( ),// 1-bit output: Feedback path for data
.OQ ( ),// 1-bit output: Data path output
// SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
.SHIFTOUT1 ( shiftout1 ),
.SHIFTOUT2 ( shiftout2 ),
.TBYTEOUT ( ),// 1-bit output: Byte group tristate
.TFB ( ),// 1-bit output: 3-state control
.TQ ( ),// 1-bit output: 3-state control
.CLK ( clk ),// 1-bit input: High speed clock
.CLKDIV ( clk_div ),// 1-bit input: Divided clock
// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
.D1 ( 1'b0 ),
.D2 ( 1'b0 ),
.D3 ( din[8] ),
.D4 ( din[9] ),
.D5 ( 1'b0 ),
.D6 ( 1'b0 ),
.D7 ( 1'b0 ),
.D8 (1'b0 ),
.OCE ( 1'b1 ),// 1-bit input: Output data clock enable
.RST ( rst ),// 1-bit input: Reset
// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
.SHIFTIN1 ( ),
.SHIFTIN2 ( ),
// T1 - T4: 1-bit (each) input: Parallel 3-state inputs
.T1 ( 1'b0 ),
.T2 ( 1'b0 ),
.T3 ( 1'b0 ),
.T4 ( 1'b0 ),
.TBYTEIN ( 1'b0 ),// 1-bit input: Byte group tristate
.TCE ( 1'b0 ) // 1-bit input: 3-state clock enable
);
endmodule
在DDR数据OSERDES2原语使用中,位宽大于8的时候,需要用到两个OSERDES2原语进行转换。连接方式如下图,将Slave的SHIFTOUT与Master的SHIFTIN向连,连接方式与ISEDES2的连接相反。
4. iserdese2_ctrl
module iserdese2_ctrl(
clk ,
clk_div ,
rst ,
ofb ,
cheek_sum_first , //校验和
cheek_sum_secord , //校验和
i_cheeksum_flag ,
dout ,
dout_vld
);
parameter CNT_NUM = 5'd16;
parameter DATA_WIDTH = 4'd10;
input clk ;
input clk_div ;
input rst ;
input ofb ;
input i_cheeksum_flag ;
input [DATA_WIDTH-1:0] cheek_sum_first ;
input [DATA_WIDTH-1:0] cheek_sum_secord ;
output [DATA_WIDTH-1:0] dout ;
output dout_vld ;
reg bitslip ;
reg slip_flag ;
wire add_cnt ;
reg [4:0] cnt ;
wire [DATA_WIDTH-1:0] dout ;
reg dout_vld ;
wire [DATA_WIDTH-1:0] q ;
reg flag_cheek ;
reg [2:0] slip_cnt ;
wire add_cnt_slip ;
wire end_cnt_slip ;
reg [2:0] cnt_shift ;
wire add_cnt_shift ;
wire end_cnt_shift ;
wire shiftout1 ;
wire shiftout2 ;
//例化ISERDESE2原语
ISERDESE2 #(
.DATA_RATE ( "DDR" ),// DDR, SDR
.DATA_WIDTH ( 10 ),// Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN ( "FALSE" ),// Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN ( "FALSE" ),// Enable DYNCLKINVSEL inversion (FALSE, TRUE)
.INIT_Q1 ( 1'b0 ),// INIT_Q1 : Initial value on the Q outputs (0/1)
.INIT_Q2 ( 1'b0 ),// INIT_Q2 : Initial value on the Q outputs (0/1)
.INIT_Q3 ( 1'b0 ),// INIT_Q3 : Initial value on the Q outputs (0/1)
.INIT_Q4 ( 1'b0 ),// INIT_Q4 : Initial value on the Q outputs (0/1)
.INTERFACE_TYPE ( "NETWORKING" ),// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY ( "NONE" ),// NONE, BOTH, IBUF, IFD
.NUM_CE ( 2 ),// Number of clock enables (1,2)
.OFB_USED ( "TRUE" ),// Select OFB path (FALSE, TRUE)
.SERDES_MODE ( "MASTER" ),// MASTER, SLAVE
.SRVAL_Q1 ( 1'b0 ),// SRVAL_Q1 : Q output values when SR is used (0/1)
.SRVAL_Q2 ( 1'b0 ),// SRVAL_Q2 : Q output values when SR is used (0/1)
.SRVAL_Q3 ( 1'b0 ),// SRVAL_Q3 : Q output values when SR is used (0/1)
.SRVAL_Q4 ( 1'b0 ) // SRVAL_Q4 : Q output values when SR is used (0/1)
)
ISERDESE2_Master (
.O ( ),// 1-bit output: Combinatorial output
.Q1 ( q[9] ),// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q2 ( q[8] ),
.Q3 ( q[7] ),
.Q4 ( q[6] ),
.Q5 ( q[5] ),
.Q6 ( q[4] ),
.Q7 ( q[3] ),
.Q8 ( q[2] ),
.SHIFTOUT1 ( shiftout1 ),// SHIFTOUT1 : 1-bit (each) output: Data width expansion output ports
.SHIFTOUT2 ( shiftout2 ),// SHIFTOUT2 : 1-bit (each) output: Data width expansion output ports
.BITSLIP ( bitslip ),// 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from SDR).
.CE1 ( 1'b1 ),// CE1: 1-bit (each) input: Data register clock enable inputs
.CE2 ( 1'b1 ),// CE2: 1-bit (each) input: Data register clock enable inputs
.CLKDIVP ( 1'b0 ),// 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK ( clk ),// 1-bit input: High-speed clock
.CLKB ( ~clk ),// 1-bit input: High-speed secondary clock
.CLKDIV ( clk_div ),// 1-bit input: Divided clock
.OCLK ( 1'b0 ),// 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL(1'b0 ),// 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL ( 1'b0 ),// 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D ( 1'b0 ),// 1-bit input: Data input
.DDLY ( 1'b0 ),// 1-bit input: Serial data from IDELAYE2
.OFB ( ofb ),// 1-bit input: Data feedback from OSERDESE2
.OCLKB ( 1'b0 ),// 1-bit input: High speed negative edge output clock
.RST ( rst ),// 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1 ( ),
.SHIFTIN2 ( )
);
ISERDESE2 #(
.DATA_RATE ( "DDR" ),// DDR, SDR
.DATA_WIDTH ( 10 ),// Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN ( "FALSE" ),// Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN ( "FALSE" ),// Enable DYNCLKINVSEL inversion (FALSE, TRUE)
.INIT_Q1 ( 1'b0 ),// INIT_Q1 : Initial value on the Q outputs (0/1)
.INIT_Q2 ( 1'b0 ),// INIT_Q2 : Initial value on the Q outputs (0/1)
.INIT_Q3 ( 1'b0 ),// INIT_Q3 : Initial value on the Q outputs (0/1)
.INIT_Q4 ( 1'b0 ),// INIT_Q4 : Initial value on the Q outputs (0/1)
.INTERFACE_TYPE ( "NETWORKING" ),// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY ( "NONE" ),// NONE, BOTH, IBUF, IFD
.NUM_CE ( 2 ),// Number of clock enables (1,2)
.OFB_USED ( "FALSE" ),// Select OFB path (FALSE, TRUE)
.SERDES_MODE ( "SLAVE" ),// MASTER, SLAVE
.SRVAL_Q1 ( 1'b0 ),// SRVAL_Q1 : Q output values when SR is used (0/1)
.SRVAL_Q2 ( 1'b0 ),// SRVAL_Q2 : Q output values when SR is used (0/1)
.SRVAL_Q3 ( 1'b0 ),// SRVAL_Q3 : Q output values when SR is used (0/1)
.SRVAL_Q4 ( 1'b0 ) // SRVAL_Q4 : Q output values when SR is used (0/1)
)
ISERDESE2_Slave (
.O ( ),// 1-bit output: Combinatorial output
.Q1 ( ),// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q2 ( ),
.Q3 ( q[1] ),
.Q4 ( q[0] ),
.Q5 ( ),
.Q6 ( ),
.Q7 ( ),
.Q8 ( ),
.SHIFTOUT1 ( ),// SHIFTOUT1 : 1-bit (each) output: Data width expansion output ports
.SHIFTOUT2 ( ),// SHIFTOUT2 : 1-bit (each) output: Data width expansion output ports
.BITSLIP ( bitslip ),// 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from SDR).
.CE1 ( 1'b1 ),// CE1: 1-bit (each) input: Data register clock enable inputs
.CE2 ( 1'b1 ),// CE2: 1-bit (each) input: Data register clock enable inputs
.CLKDIVP ( 1'b0 ),// 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK ( clk ),// 1-bit input: High-speed clock
.CLKB ( ~clk ),// 1-bit input: High-speed secondary clock
.CLKDIV ( clk_div ),// 1-bit input: Divided clock
.OCLK ( 1'b0 ),// 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL(1'b0 ),// 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL ( 1'b0 ),// 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D ( 1'b0 ),// 1-bit input: Data input
.DDLY ( 1'b0 ),// 1-bit input: Serial data from IDELAYE2
.OFB ( ),// 1-bit input: Data feedback from OSERDESE2
.OCLKB ( 1'b0 ),// 1-bit input: High speed negative edge output clock
.RST ( rst ),// 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1 ( shiftout1 ),
.SHIFTIN2 ( shiftout2 )
);
//当没有完成校准时,如果检测到转换结果与要求不一致,则把该信号拉高。
always@(posedge clk_div or posedge rst)begin
if(rst)begin
bitslip <= 1'b0;
end//当没有校准,且没有处于校准阶段时检测到串并转换结果不为8'h5c或者8'h82时拉高;
else if(((q != cheek_sum_first) && (q != cheek_sum_secord)) && (~slip_flag) && (~bitslip) && (~dout_vld))begin
bitslip <= 1'b1;
end
else begin
bitslip <= 1'b0;
end
end
//滑块计数器,因为bitslip拉高后,输出需要经过一段时间才会有效,因此这段时间不能对输出数据进行读取判断。
always@(posedge clk_div or posedge rst)begin
if(rst)begin
slip_cnt <= 1'b0;
end
else if(add_cnt_slip)begin
if(end_cnt_slip)begin
slip_cnt <= 1'b0;
end
else begin
slip_cnt <= slip_cnt + 1'd1;
end
end
end
assign add_cnt_slip = slip_flag ;
assign end_cnt_slip = add_cnt_slip && slip_cnt == 4-1;
//bitslip拉高后的标志信号,初始值为0,当bitslip拉高时拉高,当slip_cnt计数器计数到最大值时清零。
always@(posedge clk_div or posedge rst)begin
if(rst)begin
slip_flag <= 1'b0;
end
else if(bitslip)begin
slip_flag <= 1'b1;
end
else if(end_cnt_slip)begin
slip_flag <= 1'b0;
end
end
//转换成功计数器,用于记录校准阶段,当校准阶段检测到固定个连续有效数据时,认为校准成功。
always@(posedge clk_div or posedge rst)begin
if(rst)begin//
cnt <= 0;
end//当在校准阶段时,当bitslip有效时拉高;
else if((slip_flag || bitslip) && (~dout_vld))begin
cnt <= 0;
end
else if(cnt == CNT_NUM - 1)begin//当检测到固定校准数据时,计数器保持该数值。
cnt <= CNT_NUM - 1;
end
else if(add_cnt)begin
cnt <= cnt + 1;
end
end
//当不处于移动滑块状态且检测到输出数据为规定数据时加1.
assign add_cnt = ((q == cheek_sum_first) || (q == cheek_sum_secord)) && (~slip_flag) && (~bitslip) && (cnt != (CNT_NUM - 1));
//将转换后的数据输出,只有当校准完成后,输出有效指示信号磁能拉高,表示输出的数据有效。
always@(posedge clk_div or posedge rst)begin
if(rst)begin
dout_vld <= 0;
end
else begin
dout_vld <= end_cnt_shift;
end
end
assign dout = q;
always@(posedge clk_div or posedge rst)begin //oserdese2采用的DDR(8:1)模式,它有4个CLK_DIV的延时
if(rst)begin
cnt_shift <= 0;
end
else if(add_cnt_shift)begin
if(end_cnt_shift)begin
cnt_shift <= cnt_shift ;
end
else begin
cnt_shift <= cnt_shift + 1;
end
end
end
assign add_cnt_shift = i_cheeksum_flag && flag_cheek ;
assign end_cnt_shift = add_cnt_shift && cnt_shift == 4-1 ;//CLK_DIV的延时计数
always@(posedge clk_div or posedge rst)begin
if(rst)begin
flag_cheek <= 1'd0;
end
else if(cnt == CNT_NUM - 1)begin//对bitslip拉高后的时钟计数。
flag_cheek <= 1'd1;
end
end
endmodule
在DDR数据OSERDES2原语使用中,位宽大于8的时候,需要用到两个OSERDES2原语进行转换。连接方式如下图。
5 测试代码
`timescale 1ns / 1ns
module test ();
localparam CYCLE = 20 ; //系统时钟50M
localparam RST_TIME = 10 ;
reg clk ;
reg rst_n ;
wire [9 : 0] o_iserdese2 ;
wire o_iserdese2_vld ;
top u_top(
.sys_clk ( clk ),
.rst_n ( rst_n ),
.o_iserdese2 ( o_iserdese2 ),
.o_iserdese2_vld ( o_iserdese2_vld )
);
initial begin
clk = 0;
forever #(CYCLE/2) clk = ~clk;
end
initial begin
rst_n = 1;
#2;
rst_n = 0;
#(RST_TIME*CYCLE);
rst_n = 1;
end
endmodule
仿真亲测没有问题,具体方法查看可以上篇文章ISERDESR原语介绍中的DDR模式8:1串并转换,代码只是修改了PLL的采样时钟,ISERDES2与OSERDES2各添加了一个Slave原语模块,其他没有变化。