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

📄 phy_init.v

📁 DDR2源代码 DDR2源代码 DDR2源代码
💻 V
📖 第 1 页 / 共 3 页
字号:
      // RZQ/6      assign load_mode_reg1[5]     = 1'b0;      assign load_mode_reg1[6]     = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?                                   1'b1 : 1'b0;      // Make zero WRITE_LEVEL      assign load_mode_reg1[7]   = 0;      assign load_mode_reg1[8]   = 1'b0;      assign load_mode_reg1[9]   = 1'b0;      assign load_mode_reg1[10]    = 1'b0;      assign load_mode_reg1[15:11] = 5'b00000;    end  endgenerate  //*****************************************************************  // DDR3 Load mode reg2  // Mode Register (MR2):  //   [15:11] - unused     - 00  //   [10:9]  - RTT_WR     - 00 (Dynamic ODT off)  //   [8]     - reserved   - 0 (must be '0')  //   [7]     - self-refresh temperature range -  //               0 (normal), 1 (extended)  //   [6]     - Auto Self-Refresh - 0 (manual), 1(auto)  //   [5:3]   - CAS Write Latency (CWL) -  //               000 (5 for 400 MHz device),  //               001 (6 for 400 MHz to 533 MHz devices),  //               010 (7 for 533 MHz to 667 MHz devices),  //               011 (8 for 667 MHz to 800 MHz)  //   [2:0]   - Partial Array Self-Refresh (Optional)      -  //               000 (full array)  //*****************************************************************  generate    if (DDR_TYPE == DDR3) begin: gen_ext_mode_reg2_ddr3      assign load_mode_reg2[2:0]     = 3'b000;      assign load_mode_reg2[5:3]   = (CAS_LAT == 5) ? 3'b000 :                                     (CAS_LAT == 6) ? 3'b001 : 3'b111;      assign load_mode_reg2[6]     = 1'b0; // Manual Self-Refresh      assign load_mode_reg2[7]   = 1'b0;      assign load_mode_reg2[8]   = 1'b0;      assign load_mode_reg2[10:9]  = 2'b00;      assign load_mode_reg2[15:11] = 5'b00000;    end  endgenerate  //*****************************************************************  // DDR3 Load mode reg3  // Mode Register (MR3):  //   [15:3] - unused          - All zeros  //   [2]     - MPR Operation - 0(normal operation), 1(data flow from MPR)  //   [1:0]   - MPR location     - 00 (Predefined pattern)  //*****************************************************************  generate    if (DDR_TYPE == DDR3)begin: gen_ext_mode_reg3_ddr3      assign load_mode_reg3[1:0]   = 2'b00;      assign load_mode_reg3[2]     = 1'b0;      assign load_mode_reg3[15:3] = 13'b0000000000000;    end  endgenerate  //***************************************************************************  // Logic for calibration start, and for auto-refresh during cal request  // CALIB_REF_REQ is used by calibration logic to request auto-refresh  // durign calibration (used to avoid tRAS violation is certain calibration  // stages take a long time). Once the auto-refresh is complete and cal can  // be resumed, CALIB_REF_DONE is asserted by PHY_INIT.  //***************************************************************************  // generate pulse for each of calibration start controls  assign start_cal[0] = ((init_state_r1 == INIT_CAL1_READ) &&                         (init_state_r2 != INIT_CAL1_READ));  assign start_cal[1] = ((init_state_r1 == INIT_CAL2_READ) &&                         (init_state_r2 != INIT_CAL2_READ));  assign start_cal[2] = ((init_state_r1 == INIT_CAL3_READ) &&                         (init_state_r2 == INIT_CAL3_WRITE_READ));  assign start_cal[3] = ((init_state_r1 == INIT_CAL4_READ) &&                         (init_state_r2 == INIT_DUMMY_ACTIVE_WAIT));  // Generate positive-edge triggered, latched signal to force initialization  // to pause calibration, and to issue auto-refresh. Clear flag as soon as  // refresh initiated  always @(posedge clkdiv0)    if (rstdiv0) begin      calib_ref_req_r       <= 1'b0;      calib_ref_req_posedge <= 1'b0;      refresh_req           <= 1'b0;    end else begin      calib_ref_req_r       <= calib_ref_req;      calib_ref_req_posedge <= calib_ref_req & ~calib_ref_req_r;      if (init_state_r1 == INIT_AUTO_REFRESH)        refresh_req <= 1'b0;      else if (calib_ref_req_posedge)        refresh_req <= 1'b1;    end  // flag to tell cal1 calibration was started.  // This flag is used for cal1 auto refreshes  // some of these bits may not be needed - only needed for those stages that  // need refreshes within the stage (i.e. very long stages)  always @(posedge clkdiv0)    if (rstdiv0) begin      cal1_started_r <= 1'b0;      cal2_started_r <= 1'b0;      cal4_started_r <= 1'b0;    end else begin      if (calib_start[0])        cal1_started_r <= 1'b1;      if (calib_start[1])        cal2_started_r <= 1'b1;      if (calib_start[3])        cal4_started_r <= 1'b1;    end  // Delay start of each calibration by 16 clock cycles to  // ensure that when calibration logic begins, that read data is already  // appearing on the bus. Don't really need it, it's more for simulation  // purposes. Each circuit should synthesize using an SRL16.  // In first stage of calibration  periodic auto refreshes  // will be issued to meet memory timing. calib_start_shift0_r[15] will be  // asserted more than once.calib_start[0] is anded with cal1_started_r so  // that it is asserted only once. cal1_refresh_done is anded with  // cal1_started_r so that it is asserted after the auto refreshes.  always @(posedge clkdiv0) begin    calib_start_shift0_r <= {calib_start_shift0_r[14:0], start_cal[0]};    calib_start_shift1_r <= {calib_start_shift1_r[14:0], start_cal[1]};    calib_start_shift2_r <= {calib_start_shift2_r[14:0], start_cal[2]};    calib_start_shift3_r <= {calib_start_shift3_r[14:0], start_cal[3]};    calib_start[0]       <= calib_start_shift0_r[15] & ~cal1_started_r;    calib_start[1]       <= calib_start_shift1_r[15] & ~cal2_started_r;    calib_start[2]       <= calib_start_shift2_r[15];    calib_start[3]       <= calib_start_shift3_r[15] & ~cal4_started_r;    calib_ref_done       <= calib_start_shift0_r[15] |                            calib_start_shift1_r[15] |                            calib_start_shift3_r[15];  end  // generate delay for various states that require it (no maximum delay  // requirement, make sure that terminal count is large enough to cover  // all cases)  always @(posedge clkdiv0) begin    case (init_state_r)      INIT_PRECHARGE_WAIT,      INIT_MODE_REGISTER_WAIT,      INIT_AUTO_REFRESH_WAIT,      INIT_DUMMY_ACTIVE_WAIT,      INIT_CAL1_WRITE_READ,      INIT_CAL1_READ_WAIT,      INIT_CAL2_WRITE_READ,      INIT_CAL2_READ_WAIT,      INIT_CAL3_WRITE_READ:        cnt_cmd_r <= cnt_cmd_r + 1;      default:        cnt_cmd_r <= 7'b0000000;    endcase  end  // assert when count reaches the value  always @(posedge clkdiv0) begin    if(cnt_cmd_r == CNTNEXT_CMD)      cnt_cmd_ok_r <= 1'b1;    else      cnt_cmd_ok_r <= 1'b0;  end  always @(posedge clkdiv0) begin    case (init_state_r)      INIT_CAL3_READ_WAIT,      INIT_CAL4_READ_WAIT:        cnt_rd_r <= cnt_rd_r + 1;      default:        cnt_rd_r <= 4'b0000;    endcase  end  always @(posedge clkdiv0) begin    if(cnt_rd_r == CNTNEXT_RD)      cnt_rd_ok_r <= 1'b1;    else      cnt_rd_ok_r <= 1'b0;  end  //***************************************************************************  // Initial delay after power-on  //***************************************************************************  // register the refresh flag from the controller.  // The refresh flag is in full frequency domain - so a pulsed version must  // be generated for half freq domain using 2 consecutive full clk cycles  // The registered version is used for the 200us counter  always @(posedge clk0)    ctrl_ref_flag_r <= ctrl_ref_flag;  always @(posedge clkdiv0)    cke_200us_cnt_en_r <= ctrl_ref_flag || ctrl_ref_flag_r;  // 200us counter for cke  always @(posedge clkdiv0)    if (rstdiv0) begin      // skip power-up count if only simulating      if (SIM_ONLY)        cke_200us_cnt_r <= 5'b00001;      else        cke_200us_cnt_r <= 5'd27;    end else if (cke_200us_cnt_en_r)      cke_200us_cnt_r <= cke_200us_cnt_r - 1;  always @(posedge clkdiv0)    if (rstdiv0)      done_200us_r <= 1'b0;    else if (!done_200us_r)      done_200us_r <= (cke_200us_cnt_r == 5'b00000);  // 200 clocks counter - count value : h'64 required for initialization  // Counts 100 divided by two clocks  always @(posedge clkdiv0)    if (rstdiv0 || (init_state_r == INIT_CNT_200))      cnt_200_cycle_r <= 8'h64;    else if  (init_state_r == INIT_ZQCL) // ddr3      cnt_200_cycle_r <= 8'hC8;    else if (cnt_200_cycle_r != 8'h00)      cnt_200_cycle_r <= cnt_200_cycle_r - 1;  always @(posedge clkdiv0)    if (rstdiv0 || (init_state_r == INIT_CNT_200)        || (init_state_r == INIT_ZQCL))      cnt_200_cycle_done_r <= 1'b0;    else if (cnt_200_cycle_r == 8'h00)      cnt_200_cycle_done_r <= 1'b1;  //*****************************************************************  //   handle deep memory configuration:  //   During initialization: Repeat initialization sequence once for each  //   chip select. Note that we could perform initalization for all chip  //   selects simulataneously. Probably fine - any potential SI issues with  //   auto refreshing all chip selects at once?  //   Once initialization complete, assert only CS[0] for calibration.  //*****************************************************************  always @(posedge clkdiv0)    if (rstdiv0) begin      chip_cnt_r <= 2'b00;    end else if (init_state_r == INIT_DEEP_MEMORY_ST) begin      if (chip_cnt_r != CS_NUM)        chip_cnt_r <= chip_cnt_r + 1;      else        chip_cnt_r <= 2'b00;    end  always @(posedge clkdiv0)    if (rstdiv0) begin      ddr_cs_n_r <= {CS_NUM{1'b1}};    end else begin      ddr_cs_n_r <= {CS_NUM{1'b1}};      if ((init_state_r == INIT_DUMMY_ACTIVE) ||          (init_state_r == INIT_PRECHARGE) ||          (init_state_r == INIT_LOAD_MODE) ||          (init_state_r == INIT_AUTO_REFRESH) ||          (init_state_r  == INIT_ZQCL    ) ||          (((init_state_r == INIT_CAL1_READ) ||            (init_state_r == INIT_CAL2_READ) ||            (init_state_r == INIT_CAL3_READ) ||            (init_state_r == INIT_CAL4_READ) ||            (init_state_r == INIT_CAL1_WRITE) ||            (init_state_r == INIT_CAL2_WRITE) ||            (init_state_r == INIT_CAL3_WRITE)) && (burst_cnt_r == 2'b00)))        ddr_cs_n_r[chip_cnt_r] <= 1'b0;      else        ddr_cs_n_r[chip_cnt_r] <= 1'b1;    end  //***************************************************************************  // Write/read burst logic  //***************************************************************************  assign cal_write = ((init_state_r == INIT_CAL1_WRITE) ||                      (init_state_r == INIT_CAL2_WRITE) ||                      (init_state_r == INIT_CAL3_WRITE));  assign cal_read = ((init_state_r == INIT_CAL1_READ) ||                     (init_state_r == INIT_CAL2_READ) ||                     (init_state_r == INIT_CAL3_READ) ||                     (init_state_r == INIT_CAL4_READ));  assign cal_write_read = ((init_state_r == INIT_CAL1_READ) ||                           (init_state_r == INIT_CAL2_READ) ||                           (init_state_r == INIT_CAL3_READ) ||                           (init_state_r == INIT_CAL4_READ) ||                           (init_state_r == INIT_CAL1_WRITE) ||                           (init_state_r == INIT_CAL2_WRITE) ||                           (init_state_r == INIT_CAL3_WRITE));  assign burst_val = (BURST_LEN == 4) ? 2'b00 :                     (BURST_LEN == 8) ? 2'b01 : 2'b00;  // keep track of current address - need this if burst length < 8 for  // stage 2-4 calibration writes and reads. Make sure value always gets  // initialized to 0 before we enter write/read state. This is used to  // keep track of when another burst must be issued  always @(posedge clkdiv0)    if (cal_write_read)      burst_addr_r <= burst_addr_r + 2;    else      burst_addr_r <= 2'b00;  // write/read burst count  always @(posedge clkdiv0)    if (cal_write_read)      if (burst_cnt_r == 2'b00)        burst_cnt_r <= burst_val;      else // SHOULD THIS BE -2 CHECK THIS LOGIC        burst_cnt_r <= burst_cnt_r - 1;    else      burst_cnt_r <= 2'b00;  // indicate when a write is occurring  always @(posedge clkdiv0)    // MIG 2.1: Remove (burst_addr_r<4) term - not used     // phy_init_wren <= cal_write && (burst_addr_r < 3'd4);    phy_init_wren <= cal_write;      // used for read enable calibration, pulse to indicate when read issued  always @(posedge clkdiv0)    // MIG 2.1: Remove (burst_addr_r<4) term - not used     // phy_init_rden <= cal_read && (burst_addr_r < 3'd4);    phy_init_rden <= cal_read;  //***************************************************************************  // Initialization state machine  //***************************************************************************  always @(posedge clkdiv0)    // every time we need to initialize another rank of memory, need to    // reset init count, and repeat the entire initialization (but not    // calibration) sequence    if (rstdiv0 || (init_state_r == INIT_DEEP_MEMORY_ST))      init_cnt_r <= INIT_CNTR_INIT;    else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_PRECHARGE) &&             (init_cnt_r == INIT_CNTR_PRECH_1))      // skip EMR(2) and EMR(3) register loads      init_cnt_r <= INIT_CNTR_EMR_EN_DLL;    else if ((DDR_TYPE == DDR1) && (init_state_r == INIT_LOAD_MODE) &&             (init_cnt_r == INIT_CNTR_MR_ACT_DLL))      // skip OCD calibration for DDR1      init_cnt_r <= INIT_CNTR_DEEP_MEM;    else if ((DDR_TYPE == DDR3) && (init_state_r ==  INIT_ZQCL))      // skip states for DDR3      init_cnt_r <= INIT_CNTR_DEEP_MEM;    else if ((init_state_r == INIT_LOAD_MODE) ||             ((init_state_r == INIT_PRECHARGE)              && (init_state_r1 != INIT_CALIB_REF))||             ((init_state_r == INIT_AUTO_REFRESH)              && (~init_done_r))||             (init_state_r == INIT_CNT_200))      init_cnt_r <= init_cnt_r + 1;  always @(posedge clkdiv0) begin    if ((init_state_r == INIT_IDLE) && (init_cnt_r == INIT_CNTR_DONE)) begin      phy_init_done_r <= 1'b1;    end else      phy_init_done_r <= 1'b0;  end  // phy_init_done to the controller and the user interface.  // It is delayed by four clocks to account for the  // multi cycle path constraint to the (phy_init_data_sel)  // to the phy layer.  always @(posedge clkdiv0)begin    phy_init_done_r1 <= phy_init_done_r;    phy_init_done_r2 <= phy_init_done_r1;    phy_init_done_r3 <= phy_init_done_r2;    phy_init_done <= phy_init_done_r3;  end  // Instantiate primitive to allow this flop to be attached to multicycle  // path constraint in UCF. This signal goes to PHY_WRITE and PHY_CTL_IO  // datapath logic only. Because it is a multi-cycle path, it can be  // clocked by either CLKDIV0 or CLK0.  FD u_ff_phy_init_data_sel    (     .Q (phy_init_data_sel),     .C (clkdiv0),     .D (phy_init_done_r1)

⌨️ 快捷键说明

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