📄 mem_interface_top_ctrl_0.v
字号:
end
CTRL_PRECHARGE_WAIT:
if (rp_cnt_r == 3'b000)
if (auto_ref_r)
// precharge again to make sure we close all the banks
next_state = CTRL_PRECHARGE;
else
next_state = CTRL_ACTIVE;
CTRL_PRECHARGE_WAIT1:
if (rp_cnt_r == 3'b000)
next_state = CTRL_AUTO_REFRESH;
CTRL_AUTO_REFRESH:
next_state = CTRL_AUTO_REFRESH_WAIT;
CTRL_AUTO_REFRESH_WAIT:
if (rfc_cnt_r == 3'd0)
next_state = CTRL_ACTIVE;
CTRL_ACTIVE:
next_state = CTRL_ACTIVE_WAIT;
CTRL_ACTIVE_WAIT:
if (rcd_cnt_r == 3'd0)
next_state = CTRL_COMMAND_WAIT;
CTRL_COMMAND_WAIT: begin
if (auto_ref_r) begin
if (ras_cnt_r == 4'd0)
next_state = CTRL_PRECHARGE;
end else if ((((conflict_detect_r)
&&(wr_flag_r || rd_flag_r)) && ~MULTI_BANK_EN)
|| (MULTI_BANK_EN && conflict_detect_r))
next_state = CTRL_COMMAND_WAIT_CONF;
else if (wr_flag_r)
next_state = CTRL_BURST_WRITE;
else if (rd_flag_r)
next_state = CTRL_BURST_READ;
end
// beginning of write burst
CTRL_BURST_WRITE:
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (wr_flag)
// if we have another non-conflict write command right after the
// current write, then stay in this state
next_state = CTRL_BURST_WRITE;
else
// otherwise, if we're done with this burst, and have no write
// immediately scheduled after this one, wait until write-read
// delay has passed
next_state = CTRL_WRITE_WAIT;
end else
// otherwise BL > 2, and we have at least one more write cycle for
// current burst
next_state = CTRL_WRITE_WAIT;
// continuation of write burst (also covers waiting after write burst
// has completed for write-read delay to pass)
CTRL_WRITE_WAIT: begin
if (conflict_detect || auto_ref_r)
next_state = CTRL_WRITE_BANK_CONF;
// if current burst is finished, and another non-conflict write is
// already queued up
else if (wr_flag && (wrburst_cnt_r <= 3'b010))
next_state = CTRL_BURST_WRITE;
// otherwise, if current write has completed, wait for wr-rd delay
else if ((wrburst_cnt_r <= 3'b010) && (wr_to_rd_cnt_r == 5'b00000))
next_state = CTRL_COMMAND_WAIT;
end
CTRL_BURST_READ:
if (BURST_LEN_DIV2 == 1) begin
// special case if BL = 2 (i.e. burst lasts only one clk cycle)
if (rd_flag)
next_state = CTRL_BURST_READ;
else
next_state = CTRL_READ_WAIT;
end else
next_state = CTRL_READ_WAIT;
CTRL_READ_WAIT: begin
if (conflict_detect || auto_ref_r)
next_state = CTRL_READ_BANK_CONF;
else if (rd_flag && (rdburst_cnt_r <= 3'b010))
next_state = CTRL_BURST_READ;
else if ((rdburst_cnt_r <= 3'b010) && (rd_to_wr_cnt_r == 4'b0000))
next_state = CTRL_COMMAND_WAIT;
end
CTRL_WRITE_BANK_CONF: begin
if (auto_ref_r) begin
if((wtp_cnt_r == 5'd0) && (ras_cnt_r == 4'b0000))
next_state = CTRL_PRECHARGE;
end else if ((bank_conf && MULTI_BANK_EN) ||
((conflict_detect_r && (rd_flag_r || wr_flag_r)
&& ~MULTI_BANK_EN)))begin
if (no_precharge_r)
next_state = CTRL_ACTIVE;
else if ((wtp_cnt_r == 5'd0) && (ras_cnt_r == 4'b0000))
next_state = CTRL_PRECHARGE;
end else if (wr_flag_r && (wrburst_cnt_r < 3'b010)) begin
next_state = CTRL_BURST_WRITE;
end else if (wr_flag_r && (wrburst_cnt_r == 3'b010))
next_state = CTRL_BURST_WRITE;
else if ((wrburst_cnt_r <= 3'b010) && (wr_to_rd_cnt_r == 5'b00000))
next_state = CTRL_COMMAND_WAIT;
end
CTRL_READ_BANK_CONF: begin
if (auto_ref_r) begin
if ((rtp_cnt_r == 5'd0) && (ras_cnt_r == 4'b0000))
next_state = CTRL_PRECHARGE;
end else if ((bank_conf && MULTI_BANK_EN) ||
((conflict_detect_r && (rd_flag_r || wr_flag_r)
&& ~MULTI_BANK_EN)))begin
if (no_precharge_r)
next_state = CTRL_ACTIVE;
else if ((rtp_cnt_r == 5'd0) && (ras_cnt_r == 4'b0000))
next_state = CTRL_PRECHARGE;
end else if (rd_flag_r && (rdburst_cnt_r == 3'b010)) begin
next_state = CTRL_BURST_READ;
end else if (rd_flag_r && (rdburst_cnt_r < 3'b010))
next_state = CTRL_BURST_READ;
else if ((rdburst_cnt_r <= 3'b010) && (rd_to_wr_cnt_r == 4'b0000))
next_state = CTRL_COMMAND_WAIT;
end
CTRL_COMMAND_WAIT_CONF: begin
if ((bank_conf && MULTI_BANK_EN) ||
(bank_conf_r && ~MULTI_BANK_EN))begin
if (no_precharge_r)
next_state = CTRL_ACTIVE;
else if (ras_cnt_r == 4'd0)
next_state = CTRL_PRECHARGE;
end else if (wr_flag_r)
next_state = CTRL_BURST_WRITE;
else if (rd_flag_r)
next_state = CTRL_BURST_READ;
else
next_state = CTRL_COMMAND_WAIT;
end
endcase
end
//***************************************************************************
// control signals to memory
//***************************************************************************
always @(posedge clk)
if ((state_r1 == CTRL_AUTO_REFRESH) ||
(state_r1 == CTRL_ACTIVE) ||
(state_r1 == CTRL_PRECHARGE))
ddr_ras_n_r <= 1'b0;
else
ddr_ras_n_r <= 1'b1;
always @(posedge clk)
if ((state_r1 == CTRL_BURST_WRITE) ||
(state_r1 == CTRL_BURST_READ) ||
(state_r1 == CTRL_AUTO_REFRESH))
ddr_cas_n_r <= 1'b0;
else
ddr_cas_n_r <= 1'b1;
always @(posedge clk)
if ((state_r1 == CTRL_BURST_WRITE) || (state_r1 == CTRL_PRECHARGE))
ddr_we_n_r <= 1'b0;
else
ddr_we_n_r <= 1'b1;
// turn off auto-precharge when issuing commands (A10 = 0)
// mapping the col add for linear addressing.
generate
if (COL_WIDTH == ROW_WIDTH-1) begin: gen_ddr_addr_col_0
assign ddr_addr_col = {af_addr_r1[COL_WIDTH-1:10], 1'b0,
af_addr_r1[9:0]};
end
if (COL_WIDTH > 10) begin: gen_ddr_addr_col_1
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}},
af_addr_r1[COL_WIDTH-1:10], 1'b0,
af_addr_r1[9:0]};
end else begin: gen_ddr_addr_col_2
assign ddr_addr_col = {{(ROW_WIDTH-COL_WIDTH-1){1'b0}}, 1'b0,
af_addr_r1[COL_WIDTH-1:0]};
end
endgenerate
// Assign address during row activate
assign ddr_addr_row = af_addr_r1[ROW_RANGE_END:ROW_RANGE_START];
always @(posedge clk)
if ((state_r1 == CTRL_ACTIVE))
ddr_addr_r <= ddr_addr_row;
else if ((state_r1 == CTRL_BURST_WRITE) ||
(state_r1 == CTRL_BURST_READ))
ddr_addr_r <= ddr_addr_col;
else if ((state_r1 == CTRL_PRECHARGE) && auto_ref_r) begin
// if we're precharging as a result of AUTO-REFRESH, precharge all banks
ddr_addr_r <= {ROW_WIDTH{1'b0}};
ddr_addr_r[10] <= 1'b1;
end else if (state_r1 == CTRL_PRECHARGE)
// if we're precharging to close a specific bank/row, set A10=0
ddr_addr_r <= {ROW_WIDTH{1'b0}};
else
ddr_addr_r <= {ROW_WIDTH{1'bx}};
always @(posedge clk)
// whenever we're precharging, we're either: (1) precharging all banks (in
// which case banks bits are don't care, (2) precharging the LRU bank,
// b/c we've exceeded the limit of # of banks open (need to close the LRU
// bank to make room for a new one), (3) we haven't exceed the maximum #
// of banks open, but we trying to open a different row in a bank that's
// already open
if ((state_r1 == CTRL_PRECHARGE) && bank_conf_r && MULTI_BANK_EN &&
!bank_hit_any_r)
// When LRU bank needs to be closed
ddr_ba_r <= bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_BANK_RANGE_END:
(3*CMP_WIDTH)+CMP_BANK_RANGE_START];
else
// Either precharge due to refresh or bank hit case
ddr_ba_r <= af_addr_r1[BANK_RANGE_END:BANK_RANGE_START];
// chip enable generation logic
generate
// if only one chip select, always assert it after reset
if (CS_BITS == 0) begin: gen_ddr_cs_0
always @(posedge clk)
if (rst)
ddr_cs_n_r[0] <= 1'b1;
else
ddr_cs_n_r[0] <= 1'b0;
// otherwise if we have multiple chip selects
end else begin: gen_ddr_cs_1
always @(posedge clk)
if (rst)
ddr_cs_n_r <= {CS_NUM{1'b1}};
else if (state_r1 == CTRL_AUTO_REFRESH) begin
// if auto-refreshing, only auto-refresh one CS at any time (avoid
// beating on the ground plane by refreshing all CS's at same time)
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[auto_cnt_r] <= 1'b0;
end else if ((state_r1 == CTRL_PRECHARGE) && bank_conf_r &&
MULTI_BANK_EN && !bank_hit_any_r) begin
// precharging the LRU bank
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[bank_cmp_addr_r[(3*CMP_WIDTH)+CMP_CS_RANGE_END:
(3*CMP_WIDTH)+CMP_CS_RANGE_START]] <= 1'b0;
end else begin
// otherwise, check the upper address bits to see which CS to assert
ddr_cs_n_r <= {CS_NUM{1'b1}};
ddr_cs_n_r[af_addr_r1[CS_RANGE_END:CS_RANGE_START]] <= 1'b0;
end
end
endgenerate
assign ctrl_addr = ddr_addr_r;
assign ctrl_ba = ddr_ba_r;
assign ctrl_ras_n = ddr_ras_n_r;
assign ctrl_cas_n = ddr_cas_n_r;
assign ctrl_we_n = ddr_we_n_r;
assign ctrl_cs_n = ddr_cs_n_r;
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -