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

📄 ctrl.v

📁 DDR2源代码 DDR2源代码 DDR2源代码
💻 V
📖 第 1 页 / 共 3 页
字号:
  // register stage. The data is fetched from the second  // register stage whenever the state machine can accept new  // addr. The conflict flags are also generated based on the  // second register stage and updated when the new address  // is loaded for the state machine.  always@(posedge clk) begin    if (rst_r1)begin      af_valid_r2 <= 1'd0;      af_addr_r2 <= {31{1'bx}};      af_cmd_r2 <= {3{1'bx}};      bank_hit_r <= {OPEN_BANK_NUM{1'bx}};      bank_conflict_r <= 1'bx;      row_conflict_r <= 4'bx;    end else if(sm_rden || ~af_valid_r2)begin      af_valid_r2 <= af_valid_r1;      af_addr_r2 <= af_addr_r1;      af_cmd_r2 <= af_cmd_r1;      if(MULTI_BANK_EN)begin        bank_hit_r <= bank_hit;        row_conflict_r <= row_miss;        bank_conflict_r <= (~(|bank_hit));      end else begin        bank_hit_r <= {OPEN_BANK_NUM{1'b0}};        bank_conflict_r <= 1'd0;        row_conflict_r[0] <= (af_addr_r1[CS_RANGE_END:ROW_RANGE_START]                              != sb_open_add_r[CMP_WIDTH-1:0]);      end    end  end  assign conflict_detect = (MULTI_BANK_EN) ?                           ((|(row_conflict_r[3:0] & bank_hit_r[3:0]))                            | bank_conflict_r) & af_valid_r2 :                           row_conflict_r[0] & af_valid_r2;  always @(posedge clk) begin    conflict_detect_r <= conflict_detect;    sm_rden_r <= sm_rden;    af_addr_r3 <= af_addr_r2;    ctrl_af_rden_r <= ctrl_af_rden & ~af_empty;  end  // conflict resolved signal. When this signal is asserted  // the conflict is resolved. The address to be compared  // for the conflict_resolved_r will be stored in act_add_r  // when the bank is opened.  always @(posedge clk) begin   conflict_resolved_r <= (act_addr_r ==                           af_addr_r2[CS_RANGE_END:ROW_RANGE_START]);    if((state_r == CTRL_ACTIVE))      act_addr_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];  end  //***************************************************************************  // Bank management logic  // Semi-hardcoded for now for 4 banks  // will keep multiple banks open if MULTI_BANK_EN is true.  //***************************************************************************  genvar bank_i;  generate // if multiple bank option chosen    if(MULTI_BANK_EN) begin: gen_multi_bank_open      for (bank_i = 0; bank_i < OPEN_BANK_NUM;           bank_i = bank_i + 1) begin: gen_bank_hit1        // asserted if bank address match + open bank entry is valid        always @(*) begin          bank_hit[bank_i]            = ((bank_cmp_addr_r[(CMP_WIDTH*(bank_i+1))-1:                                (CMP_WIDTH*bank_i)+ROW_WIDTH] ==                af_addr_r1[CS_RANGE_END:BANK_RANGE_START]) &&               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[bank_i]            = (bank_cmp_addr_r[(CMP_WIDTH*bank_i)+ROW_WIDTH-1:                               (CMP_WIDTH*bank_i)] !=               af_addr_r1[ROW_RANGE_END:ROW_RANGE_START]);        end      end      always @(posedge clk) begin        no_precharge_wait_r  <= bank_valid_r[3] & bank_conflict_r;        bank_hit_r1 <= bank_hit_r;      end      always@(*)        no_precharge_r = ~bank_valid_r[3] & bank_conflict_r;      always@(posedge clk)        no_precharge_r1 <= no_precharge_r;      always @(posedge clk) begin        // Clear all bank valid bits during AR (i.e. since all banks get        // precharged during auto-refresh)        if ((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'b0}};        end else begin          if (state_r1 == CTRL_ACTIVE) begin            // 00 is always going to have the latest bank and row.            bank_cmp_addr_r[CMP_WIDTH-1:0]              <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];            // This indicates the bank was activated            bank_valid_r[0] <= 1'b1;            case ({bank_hit_r1[2:0]})              3'b001: begin                bank_cmp_addr_r[CMP_WIDTH-1:0]                  <= af_addr_r3[CS_RANGE_END:ROW_RANGE_START];                // This indicates the bank was activated                bank_valid_r[0] <= 1'b1;              end              3'b010: begin //(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              3'b100:begin //(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              default: begin //(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            endcase          end        end      end    end else begin: gen_single_bank_open // single bank option      always @(posedge clk) begin        no_precharge_r       <= 1'd0;        no_precharge_r1      <= 1'd0;        no_precharge_wait_r  <= 1'd0;        if (rst_r1)          sb_open_add_r <= {CMP_WIDTH{1'b0}};        else if (state_r == CTRL_ACTIVE)          sb_open_add_r <= af_addr_r2[CS_RANGE_END:ROW_RANGE_START];      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) begin    if (state_r == CTRL_BURST_WRITE) begin      wrburst_cnt_r <= BURST_LEN_DIV2;    end else if (wrburst_cnt_r >= 3'd1)      wrburst_cnt_r <= wrburst_cnt_r - 1;  end // always @ (posedge clk)  always @(posedge clk) begin    if (rst_r1) begin      ctrl_wren   <= 1'b0;    end else if (state_r == CTRL_BURST_WRITE) begin      ctrl_wren   <= 1'b1;    end else if (wrburst_wren_ok_r)      ctrl_wren   <= 1'b0;  end  always @(posedge clk) begin    if ((state_r == CTRL_BURST_WRITE)        && (BURST_LEN_DIV2 > 2))      wrburst_ok_r <= 1'd0;    else if ((wrburst_cnt_r <= 3'd3) ||             (BURST_LEN_DIV2 <= 2))      wrburst_ok_r <= 1'b1;  end  // flag to check when wrburst count has reached  // a value of 1. This flag is used in the ctrl_wren  // logic  always @(posedge clk) begin     if(wrburst_cnt_r == 3'd2)       wrburst_wren_ok_r <=1'b1;     else       wrburst_wren_ok_r <= 1'b0;  end  // read burst count. Counts from (BL/2 to 1)  always @(posedge clk) begin   if (state_r == CTRL_BURST_READ) begin      rdburst_cnt_r <= BURST_LEN_DIV2;    end else if (rdburst_cnt_r >= 3'd1)      rdburst_cnt_r <= rdburst_cnt_r - 1;  end // always @ (posedge clk)   always @(posedge clk) begin    if (rst_r1) begin      ctrl_rden   <= 1'b0;    end else if (state_r == CTRL_BURST_READ) begin      ctrl_rden   <= 1'b1;    end else if (rdburst_rden_ok_r)      ctrl_rden   <= 1'b0;   end  always @(posedge clk) begin    if ((state_r == CTRL_BURST_READ)        && (BURST_LEN_DIV2 > 2))      rdburst_ok_r <= 1'd0;    else if ((rdburst_cnt_r <= 3'd3) ||             (BURST_LEN_DIV2 <= 2))      rdburst_ok_r <= 1'b1;  end  // flag to check when rdburst count has reached  // a value of 1. This flag is used in the ctrl_rden  // logic  always @(posedge clk) begin     if (rdburst_cnt_r == 3'd2)       rdburst_rden_ok_r <= 1'b1;     else       rdburst_rden_ok_r <= 1'b0;  end  //*****************************************************************  // Various delay counters  // The counters are checked for value of <= 3 to determine the  // if the count values are reached during different commands.  // It is checked for 3 because  // 1. The counters are loaded during the state when the command  //    state is reached (+1)  // 2. After the <= 3 condition is reached the sm takes two cycles  //    to transition to the new command state (+2)  //*****************************************************************  // tRP count - precharge command period  always @(posedge clk) begin    if (state_r == CTRL_PRECHARGE)      rp_cnt_r <= TRP_COUNT;    else if (rp_cnt_r != 4'd0)      rp_cnt_r <= rp_cnt_r - 1;  end  always @(posedge clk) begin    if (state_r == CTRL_PRECHARGE)      rp_cnt_ok_r <= 1'd0;    else if (rp_cnt_r <= 4'd3)      rp_cnt_ok_r <= 1'd1;  end  // tRFC count - refresh-refresh, refresh-active  always @(posedge clk) begin    if (state_r == CTRL_AUTO_REFRESH)      rfc_cnt_r <= TRFC_COUNT;    else if (rfc_cnt_r != 8'd0)      rfc_cnt_r <= rfc_cnt_r - 1;  end  always @(posedge clk) begin    if (state_r == CTRL_AUTO_REFRESH)      rfc_ok_r <= 1'b0;    else if(rfc_cnt_r <= 8'd3)      rfc_ok_r <= 1'b1;  end  // tRCD count - active to read/write  always @(posedge clk) begin    if (state_r == CTRL_ACTIVE)      rcd_cnt_r <= TRCD_COUNT;    else if (rcd_cnt_r != 4'd0)      rcd_cnt_r <= rcd_cnt_r - 1;  end  always @(posedge clk) begin    if ((state_r == CTRL_ACTIVE)        && (TRCD_COUNT > 2))      rcd_cnt_ok_r <= 1'd0;    else if (rcd_cnt_r <= 4'd3)      rcd_cnt_ok_r <= 1;  end  // tRRD count - active to active  always @(posedge clk) begin    if (state_r == CTRL_ACTIVE)      trrd_cnt_r <= TRRD_COUNT;    else if (trrd_cnt_r != 3'd0)      trrd_cnt_r <= trrd_cnt_r - 1;  end  always @(posedge clk) begin    if (state_r == CTRL_ACTIVE)      trrd_cnt_ok_r <= 1'd0;    else if (trrd_cnt_r <= 3'd3)      trrd_cnt_ok_r <= 1;  end  // tRAS count - active to precharge  always @(posedge clk) begin    if (state_r == CTRL_ACTIVE)      ras_cnt_r <= TRAS_COUNT;    else if (ras_cnt_r != 5'd0)      ras_cnt_r <= ras_cnt_r - 1;  end  // counter for write to prcharge  // read to precharge and  // activate to precharge  // precharge_ok_cnt_r is added with trtp count,  // there can be cases where the sm can go from  // activate to read and the act->pre count time  // would not have been satisfied. The rd->pre   // time is very less. wr->pre time is almost the   // same as act-> pre  always @(posedge clk) begin    if (state_r == CTRL_BURST_READ) begin      // assign only if the cnt is < TRTP_COUNT      if (precharge_ok_cnt_r < TRTP_COUNT)        precharge_ok_cnt_r <= TRTP_COUNT;    end else if (state_r == CTRL_BURST_WRITE)      precharge_ok_cnt_r <= TWR_COUNT;    else if (state_r == CTRL_ACTIVE)      precharge_ok_cnt_r <= TRAS_COUNT;    else if (precharge_ok_cnt_r != 5'd0)      precharge_ok_cnt_r <= precharge_ok_cnt_r - 1;  end  always @(posedge clk) begin    if ((state_r == CTRL_BURST_READ) ||        (state_r == CTRL_BURST_WRITE)||        (state_r == CTRL_ACTIVE))      precharge_ok_r <= 1'd0;    else if(precharge_ok_cnt_r <= 5'd3)      precharge_ok_r <=1'd1;  end  // write to read counter  // write to read includes : write latency + burst time + tWTR  always @(posedge clk) begin    if (rst_r1)      wr_to_rd_cnt_r <= 5'd0;    else if (state_r == CTRL_BURST_WRITE)      wr_to_rd_cnt_r <= (TWTR_COUNT);    else if (wr_to_rd_cnt_r != 5'd0)      wr_to_rd_cnt_r <= wr_to_rd_cnt_r - 1;  end  always @(posedge clk) begin    if (state_r == CTRL_BURST_WRITE)      wr_to_rd_ok_r <= 1'd0;    else if (wr_to_rd_cnt_r <= 5'd3)      wr_to_rd_ok_r <= 1'd1;  end  // read to write counter  always @(posedge clk) begin    if (rst_r1)      rd_to_wr_cnt_r <= 5'd0;    else if (state_r == CTRL_BURST_READ)      rd_to_wr_cnt_r <= (TRTW_COUNT);    else if (rd_to_wr_cnt_r != 5'd0)      rd_to_wr_cnt_r <= rd_to_wr_cnt_r - 1;  end  always @(posedge clk) begin    if (state_r == CTRL_BURST_READ)      rd_to_wr_ok_r <= 1'b0;    else if (rd_to_wr_cnt_r <= 5'd3)      rd_to_wr_ok_r <= 1'b1;  end  always @(posedge clk) begin     if(refi_cnt_r == (TREFI_COUNT -1))

⌨️ 快捷键说明

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