📄 mem_interface_top_ctrl_0.v
字号:
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 + -