微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 旧帖重提 oserdes 暂时性结论 并转串

旧帖重提 oserdes 暂时性结论 并转串

时间:10-02 整理:3721RD 点击:






目前还有一点问题:不过我会在后续讨论中完成,欢迎大家留帖发言,对我进行指导,大家可以一起讨论。
原帖网址:
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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top