⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem_interface_top_phy_calib_0.v

📁 sata_device_model,对做硬盘控制器的朋友有帮助
💻 V
📖 第 1 页 / 共 4 页
字号:


   genvar dq_cnt_i3;
  generate
    for(dq_cnt_i3 = 0; dq_cnt_i3 < DQ_PER_DQS; dq_cnt_i3 = dq_cnt_i3 + 1)
    begin: gen_dq_cnt3
      always @(posedge clk90)begin
         cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd0;
         cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd0;

        if (cal1_state_r1 == CAL1_DQ_DESKEW)begin
          if(cal1_dq_count[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] > (MIN_WIN_SIZE))
           begin
             cal1_dlyce_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd1;
             cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd1;
             cal1_dq_count_cp3[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] <=
             cal1_dq_count[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] - 1'd1;
           end
        end
      end
   end // block: gen_dq_cnt3
   endgenerate

  //*****************************************************************
  // keep track of the total taps used per byte. It accounts for DQS
  // taps that are used in the first calibration and any dq tap that are
  // used for deskew during first calibration ( dq taps are used here
  // only if it is more than the dqs taps. The difference is added to
  // the counter). Also add the increments done during the second
  // calibration
  //*****************************************************************
  //synthesis attribute max_fanout of dqs_tap_count is 5
  genvar dqs_cnt_i;
  generate
    for(dqs_cnt_i = 0; dqs_cnt_i < DQS_WIDTH; dqs_cnt_i = dqs_cnt_i + 1)
    begin: gen_dqs_cnt
      always @(posedge clk90)
         if (cal1_dqs_count == dqs_cnt_i) begin
              dqs_tap_count[(dqs_cnt_i*6)+5:dqs_cnt_i*6]
                           <= cal1_tp_count;
           end
        end
  endgenerate

  // assignment to the dqs_tap_count is pipelined for timing
  always @(posedge clk90)
    if((cal1_dq_deskew_count > cal1_dqs_inc_count)
       && (cal1_state_r1 == CAL1_DQ_RESET1))
      cal1_tp_count <= cal1_dq_deskew_count;
    else
      cal1_tp_count <= cal1_dqs_inc_count;

   // Extra register stages and pipeline for timing.
   // Used in cal1 state machine 
  always @(posedge clk90) begin
    dqs_tap_count_r1 <= dqs_tap_count;
    cal1_dqs_count_r1    <= cal1_dqs_count;
    cal1_dq_deskew_count_cp <= ((cal1_dqs_inc_count + cal1_dq_inc_count)
                  -MIN_WIN_SIZE);
    cal1_dqs_count_check <= (cal1_dqs_count_r1 >= DQS_WIDTH-1);
    cal1_detect_stable_r <= cal1_detect_stable;
  end


  //synthesis attribute max_fanout of cal1_detect_stable_r is 1
  //synthesis attribute max_fanout of cal1_dqs_count is 3
  //synthesis attribute max_fanout of cal1_dqs_count_r1 is 3
  //synthesis attribute max_fanout of cal1_dqs_inc_count is 5
  //synthesis attribute max_fanout of cal1_dq_inc_count is 5
  //synthesis attribute max_fanout of cal1_dq_deskew_count is 2
  //synthesis attribute max_fanout of cal1_dq_deskew_count_cp is 2
  //synthesis attribute max_fanout of cal1_state is 5
  //synthesis attribute max_fanout of cal1_state_r1 is 5
  //synthesis attribute max_fanout of cal1_state_r2 is 5

  // In simulation mode the first stage calibration is turned off.
  always @(posedge clk90) begin
    if (rst90) begin
      //to avoid simulation issues when sim models have uncertainity
      if(!SIM_ONLY)
         calib_done[0]         <= 1'b0;
      else
        calib_done[0]          <= 1'b1;

      cal1_data_chk_last       <= {2*DQ_PER_DQS{1'bx}};
      cal1_dlyce_dqs           <= 1'bx;
      cal1_dlyinc_dqs          <= 1'bx;
      cal1_dlyrst_dq           <= 1'bx;
      cal1_state               <= CAL1_IDLE;
      cal1_state_r1            <= CAL1_IDLE;
      cal1_state_r2            <= CAL1_IDLE;
      cal1_dqs_count           <= {DQS_WIDTH{1'bx}};
      cal1_dqs_inc_count       <= {6{1'bx}};//cnt dqs inc
      cal1_dq_inc_count        <= {6{1'bx}};// total dq inc
      cal1_dq_deskew_count     <= {6{1'bx}};// dq deskew

    end else begin
      // default values for all "pulse" outputs

      cal1_dlyce_dqs      <= 1'd0;
      cal1_dlyinc_dqs     <= 1'd0;
      cal1_dlyrst_dq      <= 1'd0;      
      cal1_state_r1        <= cal1_state;
      cal1_state_r2        <= cal1_state_r1;

      case (cal1_state)

        CAL1_IDLE: begin
          cal1_dqs_count           <= {DQS_WIDTH{1'b0}};
          if (calib_start[0]) begin
              if(!SIM_ONLY)// in sim mode avoid first stage calibration
                cal1_state    <= CAL1_INIT;
            cal1_data_chk_last <= cal1_data_chk_r;
          end
        end

        CAL1_INIT: begin
          cal1_dq_inc_count    <= 6'd0;
          cal1_state <= CAL1_EDGE_DETECT;
        end

        // look for first edge
        CAL1_EDGE_DETECT: begin
           cal1_data_chk_last <= cal1_data_chk_r;
           if((~|(cal1_detect_stable_r) && (cal1_window_cnt > 6'd0))) begin
              cal1_state <= CAL1_DQ_RESET; // when no dq in valid window
           end else if (|(cal1_detect_stable_r) || (cal1_stable_flag)) begin
              cal1_dq_inc_count <= cal1_dq_inc_count + 1;
              cal1_state <= CAL1_EDGE_DETECT_WAIT;
           end
        end

        // wait for DQ IDELAY to settle
        CAL1_EDGE_DETECT_WAIT: begin
          if (!idel_set_wait) begin
            cal1_state <= CAL1_EDGE_DETECT;

          end

        end

        CAL1_DQS_INC:begin
           if(cal1_dqs_inc_count> 6'd0)begin
              cal1_dlyinc_dqs <= 1'd1;
              cal1_dlyce_dqs <= 1'd1;
              cal1_dqs_inc_count <= cal1_dqs_inc_count - 1;
           end else
              cal1_state <= CAL1_DQ_DESKEW;
        end

       CAL1_DQ_RESET: begin
              cal1_dlyrst_dq <= 1'd1;
              cal1_state <= CAL1_DQ_RESET1;
              if(cal1_window_cnt < (MIN_WIN_SIZE-1))
                 cal1_dqs_inc_count <= (MIN_WIN_SIZE) - cal1_window_cnt;
              else
                 cal1_dqs_inc_count       <= 6'd0;

       end

       CAL1_DQ_RESET1: begin
              cal1_dlyrst_dq <= 1'd1;
              if(CLK_PERIOD < 3800)//deskew only for higer frequency
                   cal1_dq_deskew_count <= cal1_dq_deskew_count_cp;
              else
                   cal1_dq_deskew_count     <= 6'd0;
              if(cal1_window_cnt_r1 >= (MIN_WIN_SIZE-1))
                 cal1_state <= CAL1_DQ_DESKEW;
              else begin
                 cal1_state <= CAL1_DQS_INC;
              end
       end

       CAL1_DQ_DESKEW: begin
              if(cal1_dq_deskew_count > 0)
                 cal1_dq_deskew_count <= cal1_dq_deskew_count - 1'd1;
              else
                 cal1_state <= CAL1_DONE;
       end

       CAL1_DONE:begin
          if (!idel_set_wait) begin
            if (cal1_dqs_count_check) begin
              calib_done[0] <= 1'b1;
              cal1_state <= CAL1_IDLE;
            end else begin
              cal1_state <= CAL1_INIT;
              cal1_dqs_count <= cal1_dqs_count + 1;
            end
         end
        end
      endcase
    end // else: !if(rst90)
  end // always @ (posedge clk90)

  //***************************************************************************
  // Second stage calibration: DQS-FPGA Clock
  // Algorithm Description:
  //  1. Increment DQ and DQS IDEALY to find an edge
  //  2. If edge found and and the window is >= MIN_WIN_SIZE, then
  //     position the DQS/DQ MIN_WIN_SIZE taps from the edge
  //  3. If edge found and the window is < MIN_WIN_SIZE, then increment
  //     until the next edge is found.
  //  3a. If next edge found, move (decrement) DQ/DQS by BIT_PERIOD_TAP
  //      + MIN_WIN_SIZE from the second edge. So that the DQ/DQS is
  //      positioned in the first half of the bit period
  //  3b. If next edge not found and if the number of taps from the first
  //      edge is >= (BIT_PERIOD_TAP + MIN_WIN_SIZE), then move (decrement)
  //      DQ/DQS ((window_after_first_edge) - (BIT_PERIOD_TAP + MIN_WIN_SIZE))
  //      taps.
  //  3c. If next edge not found and if the number of taps from the first edge
  //      edge is < (BIT_PERIOD_TAP + MIN_WIN_SIZE), then leave DQ/DQS at the
  //      current position.
  //  4.  Repeat for each DQS group.
  //***************************************************************************

  //*****************************************************************
  // second stage calibration uses readback pattern of "1100" (i.e.
  // 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
  // only look at the first bit of each DQS group
  //*****************************************************************

  // register for timing purposes
  always @(posedge clk90) begin
    cal2_rd_data_fall_r <= rd_data_fall_r[cal2_dqs_count_r1*DQ_PER_DQS];
    cal2_rd_data_rise_r <= rd_data_rise_r[cal2_dqs_count_r1*DQ_PER_DQS];
  end

  // deasserted when captured data has changed since IDELAY was
  // incremented
  assign cal2_detect_edge =
    ((cal2_rd_data_fall_r != cal2_rd_data_fall_last) ||
      (cal2_rd_data_rise_r != cal2_rd_data_rise_last)) && cal2_rd_valid;

  //*****************************************************************
  //synthesis attribute max_fanout of cal2_dqs_count is 1
  //synthesis attribute max_fanout of cal2_dqs_count_r1 is 3
  //synthesis attribute max_fanout of cal2_tap_count is 5
  //synthesis attribute max_fanout of cal2_tap_count_cp1 is 5
  //synthesis attribute max_fanout of cal2_inc_count is 5
  //synthesis attribute max_fanout of cal2_dec_count is 2
  //synthesis attribute max_fanout of cal2_tap_count_index is 3

  // cal2_tap_count_cp1 assignment is done here and it
  // is assigned to the cal2_tap_count in the state
  // machine. The index is calculation is pipelined
  // for timing.
  always @(posedge clk90) begin
      cal2_tap_count_index  <= cal2_dqs_count*6;
      cal2_tap_count_cp1[0] <= dqs_tap_count_r1[cal2_tap_count_index];
      cal2_tap_count_cp1[1] <= dqs_tap_count_r1[cal2_tap_count_index+1];
      cal2_tap_count_cp1[2] <= dqs_tap_count_r1[cal2_tap_count_index+2];
      cal2_tap_count_cp1[3] <= dqs_tap_count_r1[cal2_tap_count_index+3];
      cal2_tap_count_cp1[4] <= dqs_tap_count_r1[cal2_tap_count_index+4];
      cal2_tap_count_cp1[5] <= dqs_tap_count_r1[cal2_tap_count_index+5];
  end


 // Extra register stages and pipeline for timing.
 // Used in cal2 state machine 
  always @(posedge clk90) begin
     cal2_dec_count_c1 <= ((cal2_inc_count/2) - (MIN_WIN_SIZE-2));
     if(cal2_inc_count > (BIT_PERIOD_TAPS + (MIN_WIN_SIZE-1)))
            cal2_dec_count_c3 <= cal2_inc_count - 
              (BIT_PERIOD_TAPS + (MIN_WIN_SIZE-1));
      else
            cal2_dec_count_c3 <= cal2_inc_count/2;

     cal2_detect_edge_r <= cal2_detect_edge;
     cal2_dqs_count_r1  <= cal2_dqs_count;
     cal2_dqs_count_check <= (cal2_dqs_count_r1 >= DQS_WIDTH-1);
  end
   
     

  //synthesis attribute max_fanout of cal2_state is 5
  always @(posedge clk90) begin
    if (rst90) begin
      calib_done[1]           <= 1'b0;
      cal2_tap_count          <= {6{1'bx}};// holds the total taps used
      cal2_inc_count          <= {6{1'bx}} ;// window cnt
      cal2_dec_count          <= {6{1'bx}};
      cal2_inc_tap            <= 1'd0;// flags for idelay
      cal2_dec_tap            <= 1'd0;// flags for idelay
      cal2_first_edge_detect  <= 1'd0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -