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

📄 mem_interface_top_ctrl_0.v

📁 sata_device_model,对做硬盘控制器的朋友有帮助
💻 V
📖 第 1 页 / 共 3 页
字号:
//*****************************************************************************
// 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_ctrl_0.v
// /___/   /\     Date Last Modified: $Date: 2007/04/18 13:49:32 $
// \   \  /  \    Date Created: Wed Aug 30 2006
//  \___\/\___\
//
//Device: Virtex-5
//Design Name: DDR2
//Purpose:
//   This module is the main control logic of the memory interface. All
//   commands are issued from here according to the burst, CAS Latency and the
//   user commands.
//Reference:
//Revision History:
//*****************************************************************************

`timescale 1ns/1ps

module mem_interface_top_ctrl_0 #
  (
   parameter BANK_WIDTH    = 3,
   parameter COL_WIDTH     = 10,
   parameter CS_BITS       = 0,
   parameter CS_NUM        = 1,
   parameter ROW_WIDTH     = 14,
   parameter ADDITIVE_LAT  = 0,
   parameter BURST_LEN     = 4,
   parameter CAS_LAT       = 3,
   parameter ECC_ENABLE    = 0,
   parameter REG_ENABLE    = 1,
   parameter TREFI_NS      = 7800,
   parameter TRAS          = 40000,
   parameter TRCD          = 15000,
   parameter TRFC          = 127500,
   parameter TRP           = 15000,
   parameter TRTP          = 7500,
   parameter TWR           = 15000,
   parameter TWTR          = 10000,
   parameter CLK_PERIOD    = 5000,
   parameter MULTI_BANK_EN = 1,
   parameter DDR2_ENABLE   = 1
   )
  (
   input                   clk,
   input                   rst,
   input [1:0]             af_conflict,
   input [2:0]             af_cmd,
   input [30:0]            af_addr,
   input                   af_empty,
   input                   phy_init_done,
   output                  ctrl_ref_flag,
   output                  ctrl_af_rden,
   output reg              ctrl_wren,
   output reg              ctrl_rden,
   output [ROW_WIDTH-1:0]  ctrl_addr,
   output [BANK_WIDTH-1:0] ctrl_ba,
   output                  ctrl_ras_n,
   output                  ctrl_cas_n,
   output                  ctrl_we_n,
   output [CS_NUM-1:0]     ctrl_cs_n
   );

  // input address split into various ranges
  localparam ROW_RANGE_START     = COL_WIDTH;
  localparam ROW_RANGE_END       = ROW_WIDTH + ROW_RANGE_START - 1;
  localparam BANK_RANGE_START    = ROW_RANGE_END + 1;
  localparam BANK_RANGE_END      = BANK_WIDTH + BANK_RANGE_START - 1;
  localparam CS_RANGE_START      = BANK_RANGE_START + BANK_WIDTH;
  localparam CS_RANGE_END        = CS_BITS + CS_RANGE_START - 1;
  // compare address (for determining bank/row hits) split into various ranges
  // (compare address doesn't include column bits)
  localparam CMP_WIDTH            = CS_BITS + BANK_WIDTH + ROW_WIDTH;
  localparam CMP_ROW_RANGE_START  = 0;
  localparam CMP_ROW_RANGE_END    = ROW_WIDTH + CMP_ROW_RANGE_START - 1;
  localparam CMP_BANK_RANGE_START = CMP_ROW_RANGE_END + 1;
  localparam CMP_BANK_RANGE_END   = BANK_WIDTH + CMP_BANK_RANGE_START - 1;
  localparam CMP_CS_RANGE_START   = CMP_BANK_RANGE_END + 1;
  localparam CMP_CS_RANGE_END     = CS_BITS + CMP_CS_RANGE_START - 1;

  localparam BURST_LEN_DIV2      = BURST_LEN / 2;
  localparam OPEN_BANK_NUM       = 4;

  // calculation counters based on clock cycle and memory parameters
  // TRAS: ACTIVE->PRECHARGE interval - 2
  localparam integer TRAS_CYC = (TRAS/CLK_PERIOD)+1;
  // TRCD: ACTIVE->READ/WRITE interval - 3 (for DDR2 factor in ADD_LAT)
  localparam integer TRCD_CYC = ((TRCD/CLK_PERIOD) + 1)-
             ADDITIVE_LAT ;
  // TRFC: REFRESH->REFRESH, REFRESH->ACTIVE interval - 2
  localparam integer TRFC_CYC = TRFC/CLK_PERIOD +1;
  // TRP: PRECHARGE->COMMAND interval - 2
  localparam integer TRP_CYC =  TRP/CLK_PERIOD + 1;
  // TRTP: READ->PRECHARGE interval - 2 (for DDR2, TRTP = 2 clks)
  localparam integer TRTP_TMP_MIN = ((TRTP/CLK_PERIOD) + 1 );
  localparam integer TRTP_CYC = TRTP_TMP_MIN + ADDITIVE_LAT +
             BURST_LEN_DIV2 - 2;
  // TWR: WRITE->PRECHARGE interval - 2
  localparam integer WR_LAT = (DDR2_ENABLE) ? CAS_LAT + ADDITIVE_LAT - 1 : 1;
  localparam integer TWR_CYC = (TWR/CLK_PERIOD) + WR_LAT + BURST_LEN_DIV2 ;
  // TWTR: WRITE->READ interval - 3 (for DDR1, TWTR = 2 clks)
  localparam integer TWTR_TMP_MIN = ((TWTR/CLK_PERIOD)+1);
  localparam integer TWTR_CYC = (DDR2_ENABLE) ? TWTR_TMP_MIN : 2;

  // TRTW: READ->WRITE interval - 3
  //  DDR1: CL + (BL/2) + ECC/REG delays
  //  DDR2: (BL/2) + 2 + ECC/REG delays
  localparam integer CAS_LAT_RD = (CAS_LAT == 25) ? 2 : CAS_LAT;

  // Make sure all values >= 0 (some may be = 0)
  localparam TRAS_COUNT = (TRAS_CYC > 0) ? TRAS_CYC : 0;
  localparam TRCD_COUNT = (TRCD_CYC > 0) ? TRCD_CYC : 0;
  localparam TRFC_COUNT = (TRFC_CYC > 0) ? TRFC_CYC : 0;
  localparam TRP_COUNT  = (TRP_CYC > 0)  ? TRP_CYC : 0;
  localparam TRTP_COUNT = (TRTP_CYC > 0) ? TRTP_CYC : 0;
  localparam TWR_COUNT  = (TWR_CYC > 0)  ? TWR_CYC : 0;
  localparam TWTR_COUNT = (TWTR_CYC > 0) ? TWTR_CYC : 0;

  // Auto refresh interval
  localparam TREFI_COUNT = ((TREFI_NS * 1000)/CLK_PERIOD) - 1;

  // memory controller states
  localparam   CTRL_IDLE                =     5'h00;
  localparam   CTRL_PRECHARGE           =     5'h01;
  localparam   CTRL_PRECHARGE_WAIT      =     5'h02;
  localparam   CTRL_AUTO_REFRESH        =     5'h03;
  localparam   CTRL_AUTO_REFRESH_WAIT   =     5'h04;
  localparam   CTRL_ACTIVE              =     5'h05;
  localparam   CTRL_ACTIVE_WAIT         =     5'h06;
  localparam   CTRL_BURST_READ          =     5'h07;
  localparam   CTRL_READ_WAIT           =     5'h08;
  localparam   CTRL_BURST_WRITE         =     5'h09;
  localparam   CTRL_WRITE_WAIT          =     5'h0A;
  localparam   CTRL_COMMAND_WAIT        =     5'h0B;
  localparam   CTRL_WRITE_BANK_CONF     =     5'h0C;
  localparam   CTRL_READ_BANK_CONF      =     5'h0D;
  localparam   CTRL_COMMAND_WAIT_CONF   =     5'h0E;
  localparam   CTRL_PRECHARGE_WAIT1     =     5'h0F;

  wire [(CS_BITS+BANK_WIDTH)-1:0]          af_addr_bank_cmp;
  reg [30:0]                               af_addr_r
                                          /* synthesis syn_maxfan = 1 */;
  reg [30:0]                               af_addr_r1;
  wire [ROW_WIDTH-1:0]                     af_addr_row_cmp;
  reg [2:0]                                auto_cnt_r;
  reg                                      auto_ref_r;
  reg                                      bank_conf;
  reg                                      bank_conf_r
                                           /* synthesis syn_maxfan = 5 */;
  reg [(OPEN_BANK_NUM*CMP_WIDTH)-1:0]      bank_cmp_addr_r
                                           /* synthesis syn_maxfan = 1 */;
  reg                                      bank_hit_any_r;
  reg [OPEN_BANK_NUM-1:0]                  bank_hit_r
                                           /* synthesis syn_maxfan = 5 */;
  reg [OPEN_BANK_NUM-1:0]                  bank_valid_r;
  reg [CMP_WIDTH-1:0]                      open_bank_r;
  wire                                     conflict_detect;
  reg                                      conflict_detect_r
                                           /* synthesis syn_maxfan = 2 */;
  reg [ROW_WIDTH-1:0]                      ddr_addr_r;
  wire [ROW_WIDTH-1:0]                     ddr_addr_col;
  wire [ROW_WIDTH-1:0]                     ddr_addr_row;
  reg [BANK_WIDTH-1:0]                     ddr_ba_r;
  reg                                      ddr_cas_n_r;
  reg [CS_NUM-1:0]                         ddr_cs_n_r;
  reg                                      ddr_ras_n_r;
  reg                                      ddr_we_n_r;
  reg [4:0]                                next_state;
  reg                                      no_precharge_r;
  reg                                      no_precharge_wait_r;
  reg                                      phy_init_done_r
                                           /* synthesis syn_preserve=1 */;
  reg [3:0]                                ras_cnt_r;
  reg [2:0]                                rcd_cnt_r;
  reg [2:0]                                rdburst_cnt_r;
  wire                                     rd_flag;
  reg                                      rd_flag_r
                                           /* synthesis syn_maxfan = 1 */;
  reg [3:0]                                rd_to_wr_cnt_r;
  reg                                      ref_flag_r;
  reg [11:0]                               refi_cnt_r;
  reg [5:0]                                rfc_cnt_r;
  reg [OPEN_BANK_NUM-1:0]                  row_miss_r
                                           /* synthesis syn_maxfan = 5 */;
  reg [2:0]                                rp_cnt_r;
  reg [4:0]                                rtp_cnt_r;
  reg [4:0]                                state_r
                                           /* synthesis syn_maxfan = 5 */;
  reg [4:0]                                state_r1;
  reg [2:0]                                wrburst_cnt_r;
  wire                                     wr_flag;
  reg                                      wr_flag_r
                                           /* synthesis syn_maxfan = 1 */;
  reg [4:0]                                wr_to_rd_cnt_r;
  reg [4:0]                                wtp_cnt_r;



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

  assign ctrl_af_rden = ((state_r == CTRL_BURST_WRITE) ||
                         (state_r == CTRL_BURST_READ));

  // indicate potential address miss if there is a bank or row change from the
  // previous command
  assign conflict_detect = (| af_conflict);

  //*****************************************************************
  // interpret commands from Command/Address FIFO
  //*****************************************************************

  assign wr_flag = (af_empty) ? 1'b0 : ((af_cmd == 3'b000) ? 1'b1 : 1'b0);
  assign rd_flag = (af_empty) ? 1'b0 : ((af_cmd == 3'b001) ? 1'b1 : 1'b0);

  // synthesis attribute max_fanout of rd_flag_r is 1
  // synthesis attribute max_fanout of wr_flag_r is 1
  always @(posedge clk) begin
    rd_flag_r <= rd_flag;
    wr_flag_r <= wr_flag;
  end

  // register address inputs
  // synthesis attribute max_fanout of af_addr_r is 1
  always @(posedge clk) begin
    af_addr_r <= af_addr;
    af_addr_r1 <= af_addr_r;
  end

  //***************************************************************************
  // Bank management logic
  // Semi-hardcoded for now for 4 banks
  // will keep multiple banks open if MULTI_BANK_EN is true.
  //***************************************************************************

  // synthesis attribute max_fanout of bank_hit_r is 5
  // synthesis attribute max_fanout of row_miss_r is 5
  // synthesis attribute max_fanout of bank_conf_r is 5
  // synthesis attribute max_fanout of conflict_detect_r is 2
  genvar bank_i;
  generate // if multiple bank option chosen
    if(MULTI_BANK_EN) begin: gen_multi_bank_open
      assign af_addr_bank_cmp = af_addr[CS_RANGE_END:BANK_RANGE_START];
      assign af_addr_row_cmp = af_addr[ROW_RANGE_END:ROW_RANGE_START];

    for (bank_i = 0; bank_i < OPEN_BANK_NUM;
         bank_i = bank_i + 1) begin: gen_bank_hit
      // asserted if bank address match + open bank entry is valid
      always @(posedge clk) begin
        bank_hit_r[bank_i]
          = ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:
                              (CMP_WIDTH*bank_i)+ROW_WIDTH] ==
              af_addr_bank_cmp) && bank_valid_r[bank_i]);
        // asserted if row address match (no check for bank entry valid, rely
        // on this term to be used in conjunction with BANK_HIT[])
        row_miss_r[bank_i]
          = (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:
                             (CMP_WIDTH*bank_i)] != af_addr_row_cmp);
        end
      end

      always @(posedge clk) begin
        bank_hit_any_r <= | bank_hit_r;
        no_precharge_wait_r  <= bank_valid_r[3] & ~(|bank_hit_r);

⌨️ 快捷键说明

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