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

📄 mem_interface_top_ctrl_0.v

📁 sata_device_model,对做硬盘控制器的朋友有帮助
💻 V
📖 第 1 页 / 共 3 页
字号:
        bank_conf_r          <= bank_conf;
        conflict_detect_r    <= conflict_detect;
      end

      always @(*) begin
        // If there's a spare open bank: then don't need to precharge after
        // the current burst, we can keep that row open. Otherwise, if the
        // max # of banks are open, then we do need to precharge at the end
        // of the current burst (since that address gets kicked out of the
        // open bank list), but we don't need to wait at the end of that
        // precharge, because the next activate command will be to a
        // different bank
        no_precharge_r = conflict_detect_r & ~bank_valid_r[3] & ~(|bank_hit_r);
        bank_conf      = conflict_detect_r;

        case ({conflict_detect_r, bank_hit_r})
          // first four cases check cover case when we've already matched
          // banks. Now check to see if row matches as well. If not, then we
          // have a conflict - need to precharge, and kick out the old address.
          // Otherwise, if the row matches, we don't have a conflict, since
          // that bank/row is already open
          5'b10001:
            bank_conf = row_miss_r[0];
          5'b10010:
            bank_conf = row_miss_r[1];
          5'b10100:
            bank_conf = row_miss_r[2];
          5'b11000:
            bank_conf = row_miss_r[3];
        endcase
      end

      // synthesis attribute max_fanout of bank_cmp_addr_r is 1
      always @(posedge clk) begin
        // Clear all bank valid bits during AR (i.e. since all banks get
        // precharged during auto-refresh)
        if (rst || (state_r1 == CTRL_AUTO_REFRESH)) begin
          bank_valid_r    <= {(OPEN_BANK_NUM-1){1'b0}};
          bank_cmp_addr_r <= {(OPEN_BANK_NUM*CMP_WIDTH-1){1'bx}};
        end else begin
          if (state_r == CTRL_ACTIVE) begin
            // 00 is always going to have the latest bank and row.
            bank_cmp_addr_r[CMP_WIDTH-1:0]
              <= af_addr_r[CS_RANGE_END:ROW_RANGE_START];
            // This indicates the bank was activated
            bank_valid_r[0] <= 1'b1;

            // Check to see where bank hit occurred, and handle new locations
            // of the various banks.
            if (bank_hit_r[1]) begin
              // bank 1 hit (b0->b1)
              bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
                <= bank_cmp_addr_r[CMP_WIDTH-1:0];
              bank_valid_r[1] <= bank_valid_r[0];
            end else if (bank_hit_r[2]) begin
              // bank 2 hit (b0->b1, b1->b2)
              bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
                <= bank_cmp_addr_r[CMP_WIDTH-1:0];
              bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
                <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
              bank_valid_r[1] <= bank_valid_r[0];
              bank_valid_r[2] <= bank_valid_r[1];
            end else if (!bank_hit_any_r || bank_hit_r[3]) begin
              // if no bank hit or bank3 hit (b0->b1, b1->b2, b2->b3)
              bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH]
                <= bank_cmp_addr_r[CMP_WIDTH-1:0];
              bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH]
                <= bank_cmp_addr_r[(2*CMP_WIDTH)-1:CMP_WIDTH];
              bank_cmp_addr_r[(4*CMP_WIDTH)-1:3*CMP_WIDTH]
                <= bank_cmp_addr_r[(3*CMP_WIDTH)-1:2*CMP_WIDTH];
              bank_valid_r[1] <= bank_valid_r[0];
              bank_valid_r[2] <= bank_valid_r[1];
              bank_valid_r[3] <= bank_valid_r[2];
            end
          end
        end
      end
    end else begin: gen_single_bank_open // single bank option

      always @(*) begin
          // if bank and row not open, set the conflict bit
          bank_conf = (open_bank_r[CMP_WIDTH-1:0] !=
          af_addr_r[CS_RANGE_END:ROW_RANGE_START]) &&
                       conflict_detect_r;
      end

      always @(posedge clk) begin
        if (state_r == CTRL_ACTIVE) // storing the open bank and row
            open_bank_r[CMP_WIDTH-1:0]
           <= af_addr_r[CS_RANGE_END:ROW_RANGE_START];
        conflict_detect_r    <= conflict_detect;
        bank_conf_r          <= bank_conf;
        no_precharge_r       <= 1'd0;
        no_precharge_wait_r  <= 1'd0;
      end
    end
  endgenerate

  //***************************************************************************
  // Timing counters
  //***************************************************************************

  //*****************************************************************
  // Write and read enable generation for PHY
  //*****************************************************************

  // write burst count. Counts from (BL/2 to 1).
  // Also logic for controller write enable.
  always @(posedge clk)
    if (rst) begin
      ctrl_wren   <= 1'b0;
      wrburst_cnt_r <= 3'bxxx;
    end else if (state_r == CTRL_BURST_WRITE) begin
      ctrl_wren   <= 1'b1;
      wrburst_cnt_r <= BURST_LEN_DIV2;
    end else if (wrburst_cnt_r == 3'd1)
      ctrl_wren   <= 1'b0;
    else
      wrburst_cnt_r <= wrburst_cnt_r - 1;

  // read burst count. Counts from (BL/2 to 1)
  always @(posedge clk)
    if (rst) begin
      ctrl_rden   <= 1'b0;
      rdburst_cnt_r <= 3'bxxx;
    end else if (state_r == CTRL_BURST_READ) begin
      ctrl_rden   <= 1'b1;
      rdburst_cnt_r <= BURST_LEN_DIV2;
    end else if (rdburst_cnt_r == 3'd1)
      ctrl_rden   <= 1'b0;
    else
      rdburst_cnt_r <= rdburst_cnt_r - 1;

  //*****************************************************************
  // Various delay counters
  //*****************************************************************

  // tRP count - precharge command period
  always @(posedge clk)
    if (state_r == CTRL_PRECHARGE)
      rp_cnt_r <= TRP_COUNT;
    else if (rp_cnt_r != 3'd0)
      rp_cnt_r <= rp_cnt_r - 1;

  // tRFC count - refresh-refresh, refresh-active
  always @(posedge clk)
    if (state_r == CTRL_AUTO_REFRESH)
      rfc_cnt_r <= TRFC_COUNT;
    else if (rfc_cnt_r != 6'd0)
      rfc_cnt_r <= rfc_cnt_r - 1;

  // tRCD count - active to read/write
  always @(posedge clk)
    if (state_r == CTRL_ACTIVE)
      rcd_cnt_r <= TRCD_COUNT;
    else if (rcd_cnt_r != 3'd0)
      rcd_cnt_r <= rcd_cnt_r - 1;

  // tRAS count - active to precharge
  always @(posedge clk)
    if (state_r == CTRL_ACTIVE)
      ras_cnt_r <= TRAS_COUNT;
    else if (ras_cnt_r != 4'd0)
      ras_cnt_r <= ras_cnt_r - 1;

  // tRTP count - read to precharge
  always @(posedge clk)
    if (state_r == CTRL_BURST_READ)
      rtp_cnt_r <= TRTP_COUNT;
    else if (rtp_cnt_r != 5'd0)
      rtp_cnt_r <= rtp_cnt_r - 1;

  // wtp count - write to precharge
  always @(posedge clk)
    if (state_r == CTRL_BURST_WRITE)
      wtp_cnt_r <= TWR_COUNT  ;
    else if (wtp_cnt_r != 5'd0)
      wtp_cnt_r <= wtp_cnt_r - 1;

  // write to read counter
  // write to read includes : write latency + burst time + tWTR
  always @(posedge clk)
    if (state_r == CTRL_BURST_WRITE)
      wr_to_rd_cnt_r <= (TWTR_COUNT + BURST_LEN_DIV2 + CAS_LAT + ADDITIVE_LAT);
    else if (wr_to_rd_cnt_r != 5'd0)
      wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;

  // read to write counter
  always @(posedge clk)
    if (state_r == CTRL_BURST_READ)
      rd_to_wr_cnt_r <= (ADDITIVE_LAT + REG_ENABLE + BURST_LEN_DIV2 + 2);
    else if (rd_to_wr_cnt_r != 4'd0)
      rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;

  // auto refresh interval counter in refresh_clk domain
  always @(posedge clk)
    if (rst) begin
      refi_cnt_r <= 12'd0;
      ref_flag_r <= 1'b0;
    end else if (refi_cnt_r == TREFI_COUNT) begin
      refi_cnt_r <= 12'd0;
      ref_flag_r <= 1'b1;
    end else begin
      refi_cnt_r <= refi_cnt_r + 1;
      ref_flag_r <= 1'b0;
    end

  assign ctrl_ref_flag = ref_flag_r;

  //refresh flag detect
  //auto_ref high indicates auto_refresh requirement
  //auto_ref is held high until auto refresh command is issued.
  always @(posedge clk)
    if (ref_flag_r && phy_init_done)
      auto_ref_r <= 1'b1;
    else if (state_r == CTRL_AUTO_REFRESH)
      auto_ref_r <= 1'b0;

  // keep track of which chip selects got auto-refreshed (avoid auto-refreshing
  // all CS's at once to avoid current spike)
  always @(posedge clk)
    if (rst || (state_r == CTRL_PRECHARGE))
      auto_cnt_r <= 'd0;
    else if (state_r == CTRL_AUTO_REFRESH)
      auto_cnt_r <= auto_cnt_r + 1;

  // register for timing purposes. Extra delay doesn't really matter
  // synthesis attribute equivalent_register_removal of phy_init_done_r is "no";
  always @(posedge clk)
    phy_init_done_r <= phy_init_done;

// synthesis attribute max_fanout of state_r is 5
  always @(posedge clk)
    if (rst) begin
      state_r    <= CTRL_IDLE;
      state_r1 <= CTRL_IDLE;
    end else begin
      state_r    <= next_state;
      state_r1 <= state_r;
    end

  //***************************************************************************
  // main control state machine
  //***************************************************************************

  always @(*) begin
    next_state = state_r;

    case (state_r)

      CTRL_IDLE: begin
        // stay in this state until initializaton/calibration done. Can
        // service auto refresh requests during this time as well (not
        // required w/ current code, since IDLE is one-time-only state, but
        // useful if we later change code to return to IDLE for any reason)
        if (phy_init_done_r)
          if (auto_ref_r)
            next_state = CTRL_PRECHARGE;
          else if (wr_flag_r || rd_flag_r)
            next_state = CTRL_ACTIVE;
      end

      CTRL_PRECHARGE: begin
        if (auto_ref_r)
          next_state = CTRL_PRECHARGE_WAIT1;
        // when precharging an LRU bank, do not have to go to wait state
        // since we can't possibly be activating row in same bank next
        else if (no_precharge_wait_r)
          next_state = CTRL_ACTIVE;
        else
          next_state = CTRL_PRECHARGE_WAIT;

⌨️ 快捷键说明

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