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

📄 mem_interface_top_phy_calib_0.v

📁 sata_device_model,对做硬盘控制器的朋友有帮助
💻 V
📖 第 1 页 / 共 4 页
字号:
      cal2_dqs_count          <= {DQS_WIDTH{1'bx}};
      cal2_state              <= CAL2_IDLE;
      cal2_rd_data_fall_last  <= 1'd0;
      cal2_rd_data_rise_last  <= 1'd0;
      cal2_rd_valid           <= 1'd0;
    end else begin
      cal2_inc_tap <= 1'd0;
      cal2_dec_tap <= 1'd0;
      
      case (cal2_state)

        CAL2_IDLE: begin
          cal2_dqs_count <= {DQS_WIDTH{1'b0}};
          if (calib_start[1]) begin
            cal2_state    <= CAL2_INIT;
          end
        end

        CAL2_INIT: begin
          cal2_first_edge_detect <= 1'b0;
          cal2_inc_count <= 6'd0;          
          cal2_tap_count <= cal2_tap_count_cp1;
	  cal2_state <= CAL2_EDGE_DETECT;

        end

        CAL2_EDGE_DETECT:begin
           if ((cal2_detect_edge_r)) begin
              cal2_first_edge_detect <= 1'd1;
              if ((cal2_first_edge_detect) && (cal2_inc_count > 10))
                cal2_state <= CAL2_CASE1; // two edges found
              else if ((cal2_inc_count >= MIN_WIN_SIZE+1))
                cal2_state <= CAL2_CASE2;
              else begin
                 cal2_inc_tap <= 1'd1;
                 cal2_state <= CAL2_EDGE_DETECT_WAIT;
                 cal2_inc_count <= 6'd0;
              end
           end else if (cal2_tap_count == MAX_TAPS)  // if (cal2_detect_edge)
             cal2_state <= CAL2_CASE3;
           else begin
              cal2_inc_tap <= cal2_rd_valid;// increment only when there is valid data
              cal2_state <= CAL2_EDGE_DETECT_WAIT;
           end
        end // case: CAL2_EDGE_DETECT

        CAL2_EDGE_DETECT_WAIT:begin
          if (!idel_set_wait)begin
            cal2_state <= CAL2_EDGE_DETECT;
            cal2_rd_valid <= 1'd1;
            cal2_tap_count <= cal2_tap_count + cal2_rd_valid;
            cal2_inc_count <= cal2_inc_count + cal2_rd_valid;
            cal2_rd_data_fall_last <= cal2_rd_data_fall_r;
            cal2_rd_data_rise_last <= cal2_rd_data_rise_r;
          end
        end

      // case where the first edge was found with not enough taps and have to
      // move over to the next edge.
      // Two edges found
      CAL2_CASE1:begin
            cal2_dec_count <= cal2_dec_count_c1;
            cal2_state <= CAL2_TAP_DEC;
      end

      // where the window size was > MIN_WIN_SIZE before the
      // first edge

      CAL2_CASE2:begin
         cal2_state <= CAL2_TAP_DEC;
         cal2_dec_count <= MIN_WIN_SIZE+1;
      end

      // where the first edge did not have enough taps and second edge
      // not found.

      CAL2_CASE3:begin
         cal2_state <= CAL2_TAP_DEC;
         cal2_dec_count <= cal2_dec_count_c3;
      end

      CAL2_TAP_DEC:begin
         if(cal2_dec_count > 6'd0) begin
            cal2_dec_count <= cal2_dec_count -1;
            cal2_dec_tap <= 1'd1;
         end
         else begin
           cal2_state <= CAL2_DONE;
           cal2_dec_tap <= 1'd0;
         end
      end

      CAL2_DONE:begin
          if (!idel_set_wait) begin
            if (cal2_dqs_count_check) begin
              calib_done[1] <= 1'b1;
              cal2_state <= CAL2_IDLE;
            end else begin
              cal2_state <= CAL2_INIT;
              cal2_rd_valid <= 1'd0;
              cal2_dqs_count <= cal2_dqs_count + 1;
            end
          end
       end
      endcase
    end // else: !if(rst90)
  end // always @ (posedge clk90)


  //***************************************************************************
  // Stage 3 calibration: Read Enable
  //***************************************************************************

  // CLK0 -> CLK90 (well CLK270, but we'll eventually get to CLK90) sync
  always @(negedge clk90) begin
    ctrl_rden_270 <= ctrl_rden_0;
    phy_init_rden_270 <= phy_init_rden_0;
  end

  // don't start calibrating until told to do so, need this if initialization
  // logic will assert RDEN at times prior to start of Stage 2 calibration
  always @(posedge clk90)
    if (rst90)
      cal3_en <= 1'b0;
    else if (calib_start[2])
      cal3_en <= 1'b1;
    else if (calib_done[2])
      cal3_en <= 1'b0;

  always @(posedge clk90) begin
    // long delay chain to delay read enable signal from controller/
    // initialization logic (i.e. this is used for both initialization and
    // during normal controller operation). Stage 3 calibration logic decides
    // which delayed version is appropriate to use (which is affected by the
    // round trip delay of DQ/DQS) as a "valid" signal to tell rest of logic
    // when the captured data output from ISERDES is valid. NOTE: Note all of
    // these taps will be used - depends also on ADDITIVE_CAS_LATENCY, and
    // whether various optional features (which result in extra pipeline
    // delay) are enabled
        rden_stages_r[0]  <= ctrl_rden_270 | phy_init_rden_270;
        rden_stages_r[1]  <= rden_stages_r[0];
        rden_stages_r[2]  <= rden_stages_r[1];
        rden_stages_r[3]  <= rden_stages_r[2];
        rden_stages_r[4]  <= rden_stages_r[3];
        rden_stages_r[5]  <= rden_stages_r[4];
        rden_stages_r[6]  <= rden_stages_r[5];
        rden_stages_r[7]  <= rden_stages_r[6];
        rden_stages_r[8]  <= rden_stages_r[7];
        rden_stages_r[9]  <= rden_stages_r[8];
        rden_stages_r[10] <= rden_stages_r[9];
        rden_stages_r[11] <= rden_stages_r[10];
        rden_stages_r[12] <= rden_stages_r[11];
        rden_stages_r[13] <= rden_stages_r[12];
        rden_stages_r[14] <= rden_stages_r[13];
        rden_stages_r[15] <= rden_stages_r[14];
        rden_stages_r[16] <= rden_stages_r[15];
        rden_stages_r[17] <= rden_stages_r[16];
        rden_stages_r[18] <= rden_stages_r[17];
        rden_stages_r[19] <= rden_stages_r[18];
        rden_stages_r[20] <= rden_stages_r[19];
        rden_stages_r[21] <= rden_stages_r[20];
        rden_stages_r[22] <= rden_stages_r[21];
        rden_stages_r[23] <= rden_stages_r[22];
        // read_en_r is the range of possible taps - one of which will ultimately
        // be used to generate the read valid for each DQS. READ_EN_R[0] is the
        // MINIMUM possible delay from issuance of read command until when
        // captured data at ISERDES output is valid
        rden_r[0] <= rden_stages_r[ADDITIVE_LAT + ECC_ENABLE + REG_ENABLE + CAS_LAT + 5];
        rden_r[1] <= rden_r[0];
        rden_r[2] <= rden_r[1];
        rden_r[3] <= rden_r[2];
        rden_r[4] <= rden_r[3];
        rden_r[5] <= rden_r[4];
        rden_r[6] <= rden_r[5];
        rden_r[7] <= rden_r[6];
        rden_r[8] <= rden_r[7];
       // used to determine one which clock cycle valid data is returned
        rden_edge <= {rden_r[7] & ~rden_r[8],
                      rden_r[6] & ~rden_r[7],
                      rden_r[5] & ~rden_r[6],
                      rden_r[4] & ~rden_r[5],
                      rden_r[3] & ~rden_r[4],
                      rden_r[2] & ~rden_r[3],
                      rden_r[1] & ~rden_r[2],
                      rden_r[0] & ~rden_r[1]};
  end

  //*****************************************************************
  // indicates that current received data is the correct pattern. Check both
  // rising and falling data for first 2 DQ's in each DQS group. Note that
  // we're checking using registered, and twice-registered version of ISERDES
  // output, so need to take this delay into account in determining final
  // read valid delay.
  // Expect data in sequence (in binary): 11, 10, 01, 00
  // We check for the presence of the two middle words (10, 01), and
  // compensate read valid delay accordingly
  // NOTE: Original read enable calibration data checking compared using more
  //       bits. Check if this is required.
  //*****************************************************************

  always @(posedge clk90) begin
    cal3_data <=
      {rd_data_rise_r[(rden_cnt_r2*DQ_PER_DQS+1)],
       rd_data_rise_r[(rden_cnt_r2*DQ_PER_DQS)],
       rd_data_rise_chk_r1[(2*rden_cnt_r2)+1],
       rd_data_rise_chk_r1[(2*rden_cnt_r2)],
       rd_data_fall_r[(rden_cnt_r2*DQ_PER_DQS)+1],
       rd_data_fall_r[(rden_cnt_r2*DQ_PER_DQS)],
       rd_data_fall_chk_r1[(2*rden_cnt_r2)+1],
       rd_data_fall_chk_r1[(2*rden_cnt_r2)]};
  end

 always @(posedge clk90)
    cal3_data_match <= (cal3_data == 8'b01100110);

  // when calibrating, check to see which clock cycle (after the read is
  // issued) does the expected data pattern arrive. Record this result

  //synthesis attribute max_fanout of rden_cnt is 5
  //synthesis attribute max_fanout of rden_cnt_r1 is 5
  //synthesis attribute max_fanout of rden_cnt_r2 is 5
  //synthesis attribute max_fanout of calib3_done 2
  //synthesis attribute max_fanout of rden_dly 2
  always @(posedge clk90) begin
    if (rst90) begin
      calib_done[2]     <= 1'b0;
      calib3_done       <= 1'd0;
      rden_cnt          <= {DQS_WIDTH{1'b0}};
      rden_cnt_r1       <= {DQS_WIDTH{1'bx}};
      rden_cnt_r2       <= {DQS_WIDTH{1'bx}};
      rden_dly_cnt      <= {DQS_BITS_FIX+3{1'b0}};
      rden_dly_tmp      <= 3'd0;
      rden_dly          <= {3*DQS_WIDTH{1'b0}};
      rden_dly_r1       <= {3*DQS_WIDTH{1'b0}};
    end else begin
      calib3_done <= calib_done[2];

      // increment count when data match
      if( cal3_data_match && cal3_en) begin
      // assert done when count reached
      if (rden_cnt_r1 == DQS_WIDTH-1)
              calib_done[2] <= 1'b1;

        if (rden_cnt != DQS_WIDTH-1)
          rden_cnt <= rden_cnt + 1;
         rden_dly_tmp[0] <= rden_edge[6] | rden_edge[4]
           | rden_edge[2] | rden_edge[0];
         rden_dly_tmp[1] <= rden_edge[6] | rden_edge[5]
           |rden_edge[2] | rden_edge[1];
         rden_dly_tmp[2] <= | rden_edge[6:3];

    end

       rden_cnt_r1 <= rden_cnt;
       rden_cnt_r2 <= rden_cnt_r1;
       // index calulation pipelined for timing
       rden_dly_cnt <= (rden_cnt_r1*3);
       rden_dly[rden_dly_cnt+2]    <= rden_dly_tmp[2];
       rden_dly[rden_dly_cnt+1]  <= rden_dly_tmp[1];
       rden_dly[rden_dly_cnt]  <= rden_dly_tmp[0];
       rden_dly_r1 <= rden_dly;
     end
  end

  // generate read valid signal for each DQS group
  // keep CALIB_RDEN deasserted until calibration complete (i.e. stage 3
  // finished), otherwise, user will get rogue RDEN pulses during calibration
  // calib_rden calculation is pipelined for timing.
  // synthesis attribute max_fanout of calib_rden is 1

  genvar rden_i;
  generate
    for(rden_i = 0; rden_i < DQS_WIDTH; rden_i = rden_i + 1) begin: gen_rden
      always @(posedge clk90)begin
        calib_rden[rden_i] <= calib_rden_tmp_1[rden_i];
        calib_rden_tmp_1[rden_i] <= calib3_done && calib_rden_tmp[rden_i];
        calib_rden_tmp[rden_i] <= rden_stages_r[ADDITIVE_LAT + ECC_ENABLE
                  + REG_ENABLE + CAS_LAT + {rden_dly_r1[(rden_i*3)+2],
                  rden_dly_r1[(rden_i*3)+1], rden_dly_r1[(rden_i*3)]}-2];
      end // always @ (posedge clk90)
    end
  endgenerate

endmodule

⌨️ 快捷键说明

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