?? ctrl.v
字號:
// 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 + -