旧帖重提 oserdes 暂时性结论 并转串
目前还有一点问题:不过我会在后续讨论中完成,欢迎大家留帖发言,对我进行指导,大家可以一起讨论。
原帖网址:
http://bbs.eetop.cn/thread-443590-1-1.html
大家可以比较我跟原帖的不同之处,就是下面的一段话:
100MHz钟-->MMCM-->(CLK=500MHz钟,CLK_div=250MHz钟)-->OSERDES(DDR,8:1,并行数据=8'b10100111)-->500MHz数据时钟输出
源码如下:
module oserdes
(
input clk_in,
input reset_pll,
input reset_serdes,
output[7:0] rstdly_show,
//................................................
output clkfbout,
output clkout0,
output clkout1,
output TQ,
output OFB,
output TFB,
output TBYTEOUT,
//................................................
output mmcm_lock,
output CLK_TO_PINS_P,
output CLK_TO_PINS_N
);
assign rstdly_show= rst_dly;
//wire clkfbout;
//wire clkout0;
//wire clkout1;
wire clkfbout_buf;
wire clkin1;
wire highspeed_clk;
wire lowspeed_clk;
reg IO_RESET;
reg [7:0] rst_dly;
wire oserdes_out;
MMCME2_ADV #
(
.BANDWIDTH ("OPTIMIZED"),//
.CLKOUT4_CASCADE ("FALSE"),//
.COMPENSATION ("ZHOLD"),//
.STARTUP_WAIT ("FALSE"),//
.divCLK_divIDE (1),//设置中只能取1'b1;
.CLKFBOUT_MULT_F (10.000),//相乘100M*10=1000M
.CLKFBOUT_PHASE (0.000),//feed back
.CLKFBOUT_USE_FINE_PS ("FALSE"),//相移使能
.CLKOUT0_divIDE_F (2.000),//2分频的意思吗?,多长了个F==500M
.CLKOUT0_PHASE (0.000),//
.CLKOUT0_DUTY_CYCLE (0.500),//
.CLKOUT0_USE_FINE_PS ("FALSE"),//相位移动
.CLKOUT1_divIDE (4.000),//4分频的意思吗?==250M
.CLKOUT1_PHASE (0.000),//
.CLKOUT1_DUTY_CYCLE (0.500),//占空比
.CLKOUT1_USE_FINE_PS ("FALSE"),//
.CLKIN1_PERIOD (10.0),//精度ns-ps
.REF_JITTER1 (0.010)//抖动
)
U1_MMCM
( // Output clocks
.CLKFBOUT (clkfbout),
.CLKFBOUTB (),
.CLKOUT0 (clkout0),
.CLKOUT0B (),
.CLKOUT1 (clkout1),
.CLKOUT1B (),
.CLKOUT2 (),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (),
.CLKOUT5 (),
.CLKOUT6 (),
// Input clock control
.CLKFBIN (clkfbout_buf),
.CLKIN1 (clkin1),
.CLKIN2 (1'b0),
// Tied to always select the primary input clock
.CLKINSEL (1'b1),
// Ports for dynamic reconfiguration
.DADDR (7'h0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'h0),
.DO (),
.DRDY (),
.DWE (1'b0),
// Ports for dynamic phase shift
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE (),
// Other control and status signals
.LOCKED (mmcm_lock),
.CLKINSTOPPED (),//
.CLKFBSTOPPED (),//
.PWRDWN (1'b0),//powerdown
.RST (reset_pll)//
);
BUFG U2_BUFG
(
.O (clkfbout_buf),
.I (clkfbout)
);
BUFG U3_BUFG
(
.O (highspeed_clk),
.I (clkout0)
);
BUFG U4_BUFG
(
.O (lowspeed_clk),
.I (clkout1)
);
IBUFG U5_BUFG
( .I (clk_in),
.O (clkin1)
);
OSERDESE2
#(
.DATA_RATE_OQ ("DDR"),
.DATA_RATE_TQ ("SDR"),
.DATA_WIDTH (8),
.TRISTATE_WIDTH (1),
.SERDES_MODE ("MASTER")
)
U6_SERDES
(
.D1 (1'b1),
.D2 (1'b1),
.D3 (1'b1),
.D4 (1'b0),
.D5 (1'b0),
.D6 (1'b1),
.D7 (1'b0),
.D8 (1'b1),
.T1 (1'b0),
.T2 (1'b0),
.T3 (1'b0),
.T4 (1'b0),
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0),
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.OCE (rst_dly[4]),//output clk enable
.CLK (highspeed_clk),//
.CLKdiv (lowspeed_clk),//
.OQ (oserdes_out),//
.TQ (TQ),//
.OFB (OFB),
.TFB (TFB),
.TBYTEIN (1'b0),//
.TBYTEOUT (TBYTEOUT),//
.TCE (1'b0),//
.RST (IO_RESET)
);
OBUFDS
#(.IOSTANDARD ("LVDS"))
obufds_inst
(.O (CLK_TO_PINS_P),
.OB (CLK_TO_PINS_N),
.I (oserdes_out)
);
always @ (posedge lowspeed_clk or posedge reset_serdes)
begin
if(reset_serdes)
begin
IO_RESET <= 1'b1;
rst_dly <= 8'b0000_0000;
end
else
begin
IO_RESET <= 1'b0;
rst_dly[7:1] <= rst_dly[6:0];
rst_dly[0] <= 1'b1;
end
end
endmodule
仿真激励文件与原帖完全相同:
module sim();
localparam CLK100_PERIOD = 10; //in nSec
reg clk_in;
reg reset_pll;
reg reset_serdes;
wire mmcm_lock;
wire CLK_TO_PINS_P;
wire CLK_TO_PINS_N;
oserdes
SIM (
.clk_in (clk_in),
.reset_pll (reset_pll),
.reset_serdes (reset_serdes),
.mmcm_lock (mmcm_lock),
.CLK_TO_PINS_P (CLK_TO_PINS_P),
.CLK_TO_PINS_N (CLK_TO_PINS_N)
);
// Stimulation Generation
initial
begin
reset_pll = 1'b1;
#200
reset_pll = 1'b0;
end
initial
begin
reset_serdes = 1'b1;
#1200
reset_serdes = 1'b0;
end
// Clock Generation
initial
clk_in = 1'b0;
always #(CLK100_PERIOD/2.0) clk_in = ~clk_in;
endmodule
下面是我的总结与问题:
仿真图中显示:8位的并行数据转成了串行数据,且速率是1000M=clkout0*2,双倍速率采样的缘故。
时钟就三个:clk_in=100M,clkout0=500M,clkout1=250M;
目前的问题只有一个,哪个时钟来驱动输入的并行数据,并转串模块只有两个输入时钟,因此只能是clkout1=250M,它是串行数据速率的1/4,用来驱动并4转串1刚刚好。在本例中并8转串1也成功了,我猜是因为,clkout1上升沿给个8并行数据,然后开始转串,又来上升沿,串行工作只完成了一半,给的并行数据(此例中给的并行数据保持相同,后面的工作我会改正)被丢弃,然后又上升沿,正好串行工作完成。
我下面的工作就是论证我观点的正确与否了。希望大家关注,多多指教我。
列位看官,此问题已经解决,我的猜想是正确的。
将clkout0的分频数由2改为1,clkout0由500M变为1000M,代码如下:
.CLKOUT0_divIDE_F (1.000),
分析:此时clkout1仍然是250M,输出串行数据速率虽然是1000M,但是由于是DDR(上升沿下降沿都采样)双倍速率采样,1000M*2/250M=8,正好进行并8转串1的操作,刚好同步,由clkout1驱动输入并行数据。
为了方便测试验证我的说法,我在主程序中加入小段代码:
reg[7:0]datain;
always @ (posedge lowspeed_clk or posedge reset_serdes)
begin
if(reset_serdes)
begin
datain<=8'h01;
end
else
begin
datain<={datain[6:0],datain[7]};
end
end
很简单哦,为了方便观察嘛。
然后把datain输入D1-D8,代码修改如下:
U6_SERDES
(
.D1 (datain[0]),
.D2 (datain[1]),
.D3 (datain[2]),
.D4 (datain[3]),
.D5 (datain[4]),
.D6 (datain[5]),
.D7 (datain[6]),
.D8 (datain[7]),
下面给出仿真结果:
无疑,结果是正确的。
欢迎大家踊跃参加讨论,还有很多问题值得探讨,并串,串并转换,还有mmcm始终配置模块,还有低压差分信号等等一系列的内容,大家都可以一起讨论。我希望他是一个生长贴,学习进步贴。
自己去看XAPP860