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

📄 mem_interface_top_phy_init_0.v

📁 sata_device_model,对做硬盘控制器的朋友有帮助
💻 V
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
// Copyright (c) 2006 Xilinx, Inc.
// This design is confidential and proprietary of Xilinx, Inc.
// All Rights Reserved
//*****************************************************************************
//   ____  ____
//  /   /\/   /
// /___/  \  /    Vendor: Xilinx
// \   \   \/     Version: $Name: i+IP+125372 $
//  \   \         Application: MIG
//  /   /         Filename: mem_interface_top_phy_init_0.v
// /___/   /\     Date Last Modified: $Date: 2007/04/18 13:49:32 $
// \   \  /  \    Date Created: Thu Aug 24 2006
//  \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//Reference:
//   This module is the intialization control logic of the memory interface.
//   All commands are issued from here acoording to the burst, CAS Latency and
//   the user commands.
//Revision History:
//*****************************************************************************

`timescale 1ns/1ps

module mem_interface_top_phy_init_0 #
  (
   parameter BANK_WIDTH    = 3,
   parameter CKE_WIDTH     = 1,
   parameter COL_WIDTH     = 10,
   parameter CS_NUM        = 1,
   parameter DQ_WIDTH      = 72,
   parameter ODT_WIDTH     = 1,
   parameter ROW_WIDTH     = 14,
   parameter ADDITIVE_LAT  = 0,
   parameter BURST_LEN     = 4,
   parameter BURST_TYPE    = 0,
   parameter CAS_LAT       = 3,
   parameter ODT_TYPE      = 0,
   parameter REDUCE_DRV    = 0,
   parameter REG_ENABLE    = 1,
   parameter DDR2_ENABLE   = 1,
   parameter DQS_GATE_EN   = 0,
   parameter SIM_ONLY      = 0
   )
  (
   input                                   clk0,
   input                                   rst0,
   input [3:0]                             calib_done,
   input                                   ctrl_ref_flag,
   output reg [3:0]                        calib_start,
   output reg                              phy_init_wren,
   output reg                              phy_init_rden,
   output                                  phy_init_wdf_wren,
   output [63:0]                           phy_init_wdf_data,
   output [ROW_WIDTH-1:0]                  phy_init_addr,
   output [BANK_WIDTH-1:0]                 phy_init_ba,
   output                                  phy_init_ras_n,
   output                                  phy_init_cas_n,
   output                                  phy_init_we_n,
   output [CS_NUM-1:0]                     phy_init_cs_n,
   output [CKE_WIDTH-1:0]                  phy_init_cke,
   output reg                              phy_init_done /* synthesis syn_maxfan = 1 */
   );

  // time to wait after initialization-related writes and reads (used as a
  // generic delay - exact number doesn't matter as long as it's large enough)
  localparam  CNTNEXT   =  6'b101011;

  localparam  INIT_IDLE                = 5'h00;
  localparam  INIT_CNT_200             = 5'h01;
  localparam  INIT_CNT_200_WAIT        = 5'h02;
  localparam  INIT_PRECHARGE           = 5'h03;
  localparam  INIT_PRECHARGE_WAIT      = 5'h04;
  localparam  INIT_LOAD_MODE           = 5'h05;
  localparam  INIT_MODE_REGISTER_WAIT  = 5'h06;
  localparam  INIT_AUTO_REFRESH        = 5'h07;
  localparam  INIT_AUTO_REFRESH_WAIT   = 5'h08;
  localparam  INIT_DEEP_MEMORY_ST      = 5'h09;
  localparam  INIT_DUMMY_ACTIVE        = 5'h0A;
  localparam  INIT_DUMMY_ACTIVE_WAIT   = 5'h0B;
  localparam  INIT_CAL1_WRITE          = 5'h0C;
  localparam  INIT_CAL1_WRITE_READ     = 5'h0D;
  localparam  INIT_CAL1_READ           = 5'h0E;
  localparam  INIT_CAL1_READ_WAIT      = 5'h0F;
  localparam  INIT_CAL2_WRITE          = 5'h10;
  localparam  INIT_CAL2_WRITE_READ     = 5'h11;
  localparam  INIT_CAL2_READ           = 5'h12;
  localparam  INIT_CAL2_READ_WAIT      = 5'h13;
  localparam  INIT_CAL3_WRITE          = 5'h14;
  localparam  INIT_CAL3_WRITE_READ     = 5'h15;
  localparam  INIT_CAL3_READ           = 5'h16;
  localparam  INIT_CAL3_READ_WAIT      = 5'h17;
  localparam  INIT_CAL4_READ           = 5'h18;
  localparam  INIT_CAL4_READ_WAIT      = 5'h19;

  reg [1:0]             burst_addr_r;
  reg [1:0]             burst_cnt_r;
  wire [1:0]            burst_val;
  wire                  cal_read;
  wire                  cal_write;
  wire                  cal_write_read;
  reg [15:0]            calib_start_shift0_r;
  reg [15:0]            calib_start_shift1_r;
  reg [15:0]            calib_start_shift2_r;
  reg [15:0]            calib_start_shift3_r;
  reg [1:0]             chip_cnt_r;
  reg [4:0]             cke_200us_cnt_r;
  reg [7:0]             cnt_200_cycle_r;
  reg                   cnt_200_cycle_done_r;
  reg [5:0]             cnt6_r;
  reg                   done_200us_r;
  reg [ROW_WIDTH-1:0]   ddr_addr_r;
  reg [ROW_WIDTH-1:0]   ddr_addr_r1;
  reg [BANK_WIDTH-1:0]  ddr_ba_r;
  reg [BANK_WIDTH-1:0]  ddr_ba_r1;
  reg                   ddr_cas_n_r;
  reg                   ddr_cas_n_r1;
  reg [CKE_WIDTH-1:0]   ddr_cke_r;
  reg [CS_NUM-1:0]      ddr_cs_n_r;
  reg                   ddr_ras_n_r;
  reg                   ddr_ras_n_r1;
  reg                   ddr_we_n_r;
  reg                   ddr_we_n_r1;
  wire [15:0]           ext_mode_reg;
  reg [3:0]             init_cnt_r /* synthesis syn_maxfan = 1 */;
  reg [4:0]             init_next_state;
  reg [4:0]             init_state_r  /* synthesis syn_maxfan = 3 */;
  reg [4:0]             init_state_r1 /* synthesis syn_maxfan = 3 */;
  reg [4:0]             init_state_r2 /* synthesis syn_maxfan = 3 */;
  wire [15:0]           load_mode_reg;
  wire [3:0]            start_cal;

  reg [3:0]             init_wdf_cnt_r;
  reg [63:0]            init_data_r;
  reg                   init_done_r;
  reg                   init_wren_r;
  reg [3:0]             calib_done_r;

  reg                   phy_init_done_r;

  //***************************************************************************

  //*****************************************************************
  // Mode Register (MR):
  //   [15:14] - unused          - 00
  //   [13]    - reserved        - 0
  //   [12]    - Power-down mode - 0 (normal)
  //   [11:9]  - write recovery  - same value as written to CAS LAT
  //   [8]     - DLL reset       - 0 or 1
  //   [7]     - Test Mode       - 0 (normal)
  //   [6:4]   - CAS latency     - CAS_LAT
  //   [3]     - Burst Type      - BURST_TYPE
  //   [2:0]   - Burst Length    - BURST_LEN
  //*****************************************************************

  generate
    if (DDR2_ENABLE) begin: gen_load_mode_reg_ddr2
      assign load_mode_reg[2:0]   = (BURST_LEN == 8) ? 3'b011 :
                                    ((BURST_LEN == 4) ? 3'b010 : 3'b111);
      assign load_mode_reg[3]     = BURST_TYPE;
      assign load_mode_reg[6:4]   = (CAS_LAT == 3) ? 3'b011 :
                                    ((CAS_LAT == 4) ? 3'b100 :
                                     ((CAS_LAT == 5) ? 3'b101 : 3'b111));
      assign load_mode_reg[7]     = 1'b0;
      assign load_mode_reg[8]     = 1'b0;    // init value only (DLL not reset)
      assign load_mode_reg[11:9]  = load_mode_reg[6:4];
      assign load_mode_reg[15:12] = 4'b000;
    end else begin: gen_load_mode_reg_ddr1
      assign load_mode_reg[2:0]   = (BURST_LEN == 8) ? 3'b011 :
                                    ((BURST_LEN == 4) ? 3'b010 :
                                     ((BURST_LEN == 2) ? 3'b001 : 3'b111));
      assign load_mode_reg[3]     = BURST_TYPE;
      assign load_mode_reg[6:4]   = (CAS_LAT == 2) ? 3'b010 :
                                    ((CAS_LAT == 3) ? 3'b011 :
                                     ((CAS_LAT == 25) ? 3'b110 : 3'b111));
      assign load_mode_reg[12:7]  = 6'b000000; // init value only
      assign load_mode_reg[15:13]  = 3'b000;
    end
  endgenerate

  //*****************************************************************
  // Extended Mode Register (MR):
  //   [15:14] - unused          - 00
  //   [13]    - reserved        - 0
  //   [12]    - output enable   - 0 (enabled)
  //   [11]    - RDQS enable     - 0 (disabled)
  //   [10]    - DQS# enable     - 0 (enabled)
  //   [9:7]   - OCD Program     - 111 or 000 (first 111, then 000 during init)
  //   [6]     - RTT[1]          - RTT[1:0] = 0(no ODT), 1(75), 2(150), 3(50)
  //   [5:3]   - Additive CAS    - ADDITIVE_CAS
  //   [2]     - RTT[0]
  //   [1]     - Output drive    - REDUCE_DRV (= 0(full), = 1 (reduced)
  //   [0]     - DLL enable      - 0 (normal)
  //*****************************************************************

  generate
    if (DDR2_ENABLE) begin: gen_ext_mode_reg_ddr2
      assign ext_mode_reg[0]     = 1'b0;
      assign ext_mode_reg[1]     = REDUCE_DRV;
      assign ext_mode_reg[2]     = ((ODT_TYPE == 1) || (ODT_TYPE == 3)) ?
                                   1'b1 : 1'b0;
      assign ext_mode_reg[5:3]   = (ADDITIVE_LAT == 0) ? 3'b000 :
                                   ((ADDITIVE_LAT == 1) ? 3'b001 :
                                    ((ADDITIVE_LAT == 2) ? 3'b010 :
                                     ((ADDITIVE_LAT == 3) ? 3'b011 :
                                      ((ADDITIVE_LAT == 4) ? 3'b100 :
                                      3'b111))));
      assign ext_mode_reg[6]     = ((ODT_TYPE == 2) || (ODT_TYPE == 3)) ?
                                   1'b1 : 1'b0;
      assign ext_mode_reg[9:7]   = 3'b000;
      assign ext_mode_reg[10]    = 1'b0;
      assign ext_mode_reg[15:10] = 6'b000000;
    end else begin: gen_ext_mode_reg_ddr1
      assign ext_mode_reg[0]     = 1'b0;
      assign ext_mode_reg[1]     = REDUCE_DRV;
      assign ext_mode_reg[12:2]  = 11'b00000000000;
      assign ext_mode_reg[15:13] = 3'b000;
    end
  endgenerate

  //***************************************************************************

  // 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_CAL3_READ_WAIT));

  // 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.
  always @(posedge clk0) 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];
    calib_start[1]       <= calib_start_shift1_r[15];
    calib_start[2]       <= calib_start_shift2_r[15];
    calib_start[3]       <= 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 clk0) 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,
      INIT_CAL3_READ_WAIT,
      INIT_CAL4_READ_WAIT:
        cnt6_r <= cnt6_r + 1;
      default:
        cnt6_r <= 6'b000000;
    endcase
  end

  //***************************************************************************
  // Initial delay after power-on
  //***************************************************************************

  // 200us counter for cke
  always @(posedge clk0)
    if (rst0) begin
      // skip power-up count if only simulating
      if (SIM_ONLY)
        cke_200us_cnt_r <= 5'b00001;
      else
        cke_200us_cnt_r <= 5'b11011;
    end else if (ctrl_ref_flag)
      cke_200us_cnt_r <= cke_200us_cnt_r - 1;

  // refresh detect in 266 MHz clock
  always @(posedge clk0)
    if (rst0)
      done_200us_r <= 1'b0;
    else if (!done_200us_r)
      done_200us_r <= (cke_200us_cnt_r == 5'b00000);

  // 200 clocks counter - count value : C8 required for initialization
  always @(posedge clk0)
    if (rst0 || (init_state_r == INIT_CNT_200))
      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 clk0)
    if (rst0 || (init_state_r == INIT_CNT_200))
      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 clk0)
    if (rst0) 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 clk0)
    if (rst0)
      ddr_cs_n_r <= {CS_NUM{1'b1}};
    else begin
      ddr_cs_n_r <= {CS_NUM{1'b1}};
      ddr_cs_n_r[chip_cnt_r] <= 1'b0;
    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 = cal_write | cal_read;

  assign burst_val = (BURST_LEN == 4) ? 2'b01 :
                     (BURST_LEN == 8) ? 2'b11 : 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 clk0)
    if (cal_write_read)
      burst_addr_r <= burst_addr_r + 1;
    else
      burst_addr_r <= 3'b000;

  // write/read burst count
  always @(posedge clk0)
    if (cal_write_read)
      if (burst_cnt_r == 2'b00)
        burst_cnt_r <= burst_val;
      else
        burst_cnt_r <= burst_cnt_r - 1;
    else
      burst_cnt_r <= 2'b00;

  // indicate when a write is occurring
  always @(posedge clk0)
    phy_init_wren      <= cal_write;

  // used for read enable calibration, pulse to indicate when read issued
  always @(posedge clk0)
    phy_init_rden <= cal_read;

⌨️ 快捷键说明

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