Line 153... |
Line 153... |
reg [3:0] reset_address;
|
reg [3:0] reset_address;
|
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd_a, cmd_b, cmd_c, cmd_d,
|
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd_a, cmd_b, cmd_c, cmd_d,
|
refresh_cmd, maintenance_cmd;
|
refresh_cmd, maintenance_cmd;
|
reg [24:0] reset_instruction;
|
reg [24:0] reset_instruction;
|
reg [16:0] reset_timer;
|
reg [16:0] reset_timer;
|
reg r_move;
|
|
initial reset_override = 1'b1;
|
initial reset_override = 1'b1;
|
initial reset_address = 4'h0;
|
initial reset_address = 4'h0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
if (i_reset)
|
if (i_reset)
|
begin
|
begin
|
Line 380... |
Line 379... |
|
|
// Can we preload the next bank?
|
// Can we preload the next bank?
|
reg [13:0] r_nxt_row;
|
reg [13:0] r_nxt_row;
|
reg [2:0] r_nxt_bank;
|
reg [2:0] r_nxt_bank;
|
|
|
reg need_close_bank, need_close_this_bank,
|
|
last_close_bank, maybe_close_next_bank,
|
|
last_maybe_close,
|
|
need_open_bank, last_open_bank, maybe_open_next_bank,
|
|
last_maybe_open,
|
|
valid_bank;
|
|
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd,
|
|
maybe_close_cmd, maybe_open_cmd, rw_cmd;
|
|
reg rw_we;
|
|
|
|
wire w_this_closing_bank, w_this_opening_bank,
|
|
w_this_maybe_close, w_this_maybe_open,
|
|
w_this_rw_move;
|
|
reg last_closing_bank, last_opening_bank;
|
|
wire w_need_close_this_bank, w_need_open_bank,
|
|
w_r_valid, w_s_valid;
|
|
|
|
//////////
|
//////////
|
//
|
//
|
//
|
//
|
// Open Banks
|
// Open Banks
|
Line 420... |
Line 403... |
//
|
//
|
//
|
//
|
wire w_precharge_all;
|
wire w_precharge_all;
|
reg [CKRP:0] bank_status [0:7];
|
reg [CKRP:0] bank_status [0:7];
|
reg [13:0] bank_address [0:7];
|
reg [13:0] bank_address [0:7];
|
reg [1:0] bank_wr_ck [0:7]; // tWTR
|
|
reg bank_wr_ckzro [0:7]; // tWTR
|
|
wire [7:0] bank_open;
|
|
wire [7:0] bank_closed;
|
|
|
|
wire [1:0] write_recycle_clocks;
|
|
assign write_recycle_clocks = 2'h3;
|
|
|
|
genvar k;
|
|
generate
|
|
for(k=0; k<8; k=k+1)
|
|
assign bank_open[k] = bank_status[k][0];
|
|
for(k=0; k<8; k=k+1)
|
|
assign bank_closed[k] = !bank_status[k][0];
|
|
endgenerate
|
|
|
|
initial bank_open = 0;
|
|
initial bank_closed = 8'hff;
|
|
always @(posedge i_clk)
|
|
begin
|
|
bank_wr_ck[0] <= (|bank_wr_ck[0])?(bank_wr_ck[0]-2'h1):2'h0;
|
|
bank_wr_ck[1] <= (|bank_wr_ck[1])?(bank_wr_ck[1]-2'h1):2'h0;
|
|
bank_wr_ck[2] <= (|bank_wr_ck[2])?(bank_wr_ck[2]-2'h1):2'h0;
|
|
bank_wr_ck[3] <= (|bank_wr_ck[3])?(bank_wr_ck[3]-2'h1):2'h0;
|
|
bank_wr_ck[4] <= (|bank_wr_ck[4])?(bank_wr_ck[4]-2'h1):2'h0;
|
|
bank_wr_ck[5] <= (|bank_wr_ck[5])?(bank_wr_ck[5]-2'h1):2'h0;
|
|
bank_wr_ck[6] <= (|bank_wr_ck[6])?(bank_wr_ck[6]-2'h1):2'h0;
|
|
bank_wr_ck[7] <= (|bank_wr_ck[7])?(bank_wr_ck[7]-2'h1):2'h0;
|
|
|
|
bank_wr_ckzro[0] <= (bank_wr_ck[0][1]==1'b0);
|
|
bank_wr_ckzro[1] <= (bank_wr_ck[1][1]==1'b0);
|
|
bank_wr_ckzro[2] <= (bank_wr_ck[2][1]==1'b0);
|
|
bank_wr_ckzro[3] <= (bank_wr_ck[3][1]==1'b0);
|
|
bank_wr_ckzro[4] <= (bank_wr_ck[4][1]==1'b0);
|
|
bank_wr_ckzro[5] <= (bank_wr_ck[5][1]==1'b0);
|
|
bank_wr_ckzro[6] <= (bank_wr_ck[6][1]==1'b0);
|
|
bank_wr_ckzro[7] <= (bank_wr_ck[7][1]==1'b0);
|
|
|
|
// bank_open[0] <= (bank_status[0][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[1] <= (bank_status[1][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[2] <= (bank_status[2][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[3] <= (bank_status[3][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[4] <= (bank_status[4][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[5] <= (bank_status[5][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[6] <= (bank_status[6][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
// bank_open[7] <= (bank_status[7][(CKRP-2):0] =={(CKRP-1){1'b1}});
|
|
|
|
// bank_closed[0] <= (bank_status[0][(CKRP-3):0] == 0);
|
|
// bank_closed[1] <= (bank_status[1][(CKRP-3):0] == 0);
|
|
// bank_closed[2] <= (bank_status[2][(CKRP-3):0] == 0);
|
|
// bank_closed[3] <= (bank_status[3][(CKRP-3):0] == 0);
|
|
// bank_closed[4] <= (bank_status[4][(CKRP-3):0] == 0);
|
|
// bank_closed[5] <= (bank_status[5][(CKRP-3):0] == 0);
|
|
// bank_closed[6] <= (bank_status[6][(CKRP-3):0] == 0);
|
|
// bank_closed[7] <= (bank_status[7][(CKRP-3):0] == 0);
|
|
|
|
if (w_this_rw_move)
|
|
bank_wr_ck[rw_cmd[16:14]] <= (rw_cmd[`DDR_WEBIT])? 2'h0
|
|
: write_recycle_clocks;
|
|
|
|
|
always @(posedge i_clk)
|
|
begin
|
if (cmd_pipe[0])
|
if (cmd_pipe[0])
|
begin
|
begin
|
bank_status[s_bank] <= 1'b0;
|
bank_status[s_bank] <= 1'b0;
|
if (nxt_pipe[1])
|
if (nxt_pipe[1])
|
bank_status[s_nxt_bank] <= 1'b1;
|
bank_status[s_nxt_bank] <= 1'b1;
|
Line 534... |
Line 460... |
// moves forward when data moves onto the bus.
|
// moves forward when data moves onto the bus.
|
//
|
//
|
//
|
//
|
|
|
reg [BUSNOW:0] bus_active, bus_read, bus_ack;
|
reg [BUSNOW:0] bus_active, bus_read, bus_ack;
|
reg [BUSNOW:0] bus_subaddr;
|
|
initial bus_active = 0;
|
initial bus_active = 0;
|
initial bus_ack = 0;
|
initial bus_ack = 0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
bus_active[BUSNOW:0] <= { bus_active[(BUSNOW-1):0], 1'b0 };
|
bus_active[BUSNOW:0] <= { bus_active[(BUSNOW-1):0], 1'b0 };
|
// Drive the d-bus?
|
// Drive the d-bus?
|
bus_read[BUSNOW:0] <= { bus_read[(BUSNOW-1):0], 1'b0 };
|
bus_read[BUSNOW:0] <= { bus_read[(BUSNOW-1):0], 1'b0 };
|
// Will this position on the bus get a wishbone acknowledgement?
|
// Will this position on the bus get a wishbone acknowledgement?
|
bus_ack[BUSNOW:0] <= { bus_ack[(BUSNOW-1):0], 1'b0 };
|
bus_ack[BUSNOW:0] <= { bus_ack[(BUSNOW-1):0], 1'b0 };
|
//
|
|
bus_subaddr[BUSNOW:0] <= { bus_subaddr[(BUSNOW-1):0], 1'b1 };
|
|
|
|
if (cmd_pipe[2])
|
if (cmd_pipe[2])
|
begin
|
begin
|
bus_active[0]<= 1'b1; // Data transfers in one clocks
|
bus_active[0]<= 1'b1; // Data transfers in one clocks
|
bus_ack[0] <= 1'b1;
|
bus_ack[0] <= 1'b1;
|
bus_ack[0] <= 1'b1;
|
bus_ack[0] <= 1'b1;
|
|
|
bus_read[0] <= !(rw_we);
|
bus_read[0] <= !s_we;
|
end
|
end
|
end
|
end
|
|
|
//
|
//
|
//
|
//
|
Line 566... |
Line 489... |
//
|
//
|
wire pre_valid;
|
wire pre_valid;
|
assign pre_valid = !maintenance_override;
|
assign pre_valid = !maintenance_override;
|
|
|
reg pipe_stall;
|
reg pipe_stall;
|
assign w_r_valid = (pre_valid)&&(r_pending)
|
|
&&(bank_status[r_bank][0])
|
|
&&(bank_address[r_bank]==r_row)
|
|
&&((r_we)||(bank_wr_ckzro[r_bank]));
|
|
assign w_s_valid = ((pre_valid)&&(s_pending)&&(pipe_stall)
|
|
&&(bank_status[s_bank][0])
|
|
&&(bank_address[s_bank]==s_row)
|
|
&&((s_we)||(bank_wr_ckzro[s_bank])));
|
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
r_pending <= (i_wb_stb)&&(~o_wb_stall)
|
r_pending <= (i_wb_stb)&&(~o_wb_stall)
|
||(r_pending)&&(pipe_stall);
|
||(r_pending)&&(pipe_stall);
|
Line 660... |
Line 575... |
s_nxt_row <= r_nxt_row;
|
s_nxt_row <= r_nxt_row;
|
s_nxt_bank <= r_nxt_bank;
|
s_nxt_bank <= r_nxt_bank;
|
end
|
end
|
end
|
end
|
|
|
wire [2:0] this_bank;
|
|
wire [13:0] this_row;
|
|
wire [9:0] this_col;
|
|
assign this_bank = (pipe_stall)?s_bank : r_bank;
|
|
assign this_row = (pipe_stall)?s_row : r_row;
|
|
assign this_col = (pipe_stall)?s_col : r_col;
|
|
|
|
assign w_need_close_this_bank = (cmd_pipe == 3'b000);
|
|
wire w_this_bank_valid;
|
|
assign w_this_bank_valid = (cmd_pipe[2]);
|
|
|
|
//
|
//
|
//
|
//
|
// Okay, let's look at the last assignment in our chain. It should look
|
// Okay, let's look at the last assignment in our chain. It should look
|
// something like:
|
// something like:
|
Line 699... |
Line 604... |
if (i_reset)
|
if (i_reset)
|
maintenance_cmd <= { `DDR_NOOP, 17'h00 };
|
maintenance_cmd <= { `DDR_NOOP, 17'h00 };
|
else
|
else
|
maintenance_cmd <= (reset_override)?reset_cmd:refresh_cmd;
|
maintenance_cmd <= (reset_override)?reset_cmd:refresh_cmd;
|
|
|
assign w_need_open_bank = ((r_pending)||(s_pending))
|
|
&&(bank_closed[this_bank])
|
|
||((pipe_stall)&&(!cmd_b[20]));
|
|
|
|
assign w_this_closing_bank = (!maintenance_override)&&(cmd_pipe[0]);
|
|
assign w_this_opening_bank = (!maintenance_override)&&(cmd_pipe[1]);
|
|
assign w_this_rw_move = (!maintenance_override)&&(cmd_pipe[2]);
|
|
assign w_this_maybe_close = (!maintenance_override)&&(!cmd_pipe[0])&&(nxt_pipe[0]);
|
|
assign w_this_maybe_open = (!maintenance_override)&&(!cmd_pipe[1])&&(nxt_pipe[1]);
|
|
reg [2:0] r_odt;
|
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
last_opening_bank <= 1'b0;
|
|
last_closing_bank <= 1'b0;
|
|
last_maybe_open <= 1'b0;
|
|
last_maybe_close <= 1'b0;
|
|
|
|
|
|
// We run our commands by timeslots, A, B, C, and D in that
|
// We run our commands by timeslots, A, B, C, and D in that
|
// order.
|
// order.
|
|
|
// Timeslot A always contains any maintenance commands we might
|
// Timeslot A always contains any maintenance commands we might
|
// have.
|
// have.
|
Line 737... |
Line 626... |
// into a deselect command that the chip will ignore.
|
// into a deselect command that the chip will ignore.
|
//
|
//
|
cmd_a <= maintenance_cmd;
|
cmd_a <= maintenance_cmd;
|
|
|
cmd_b <= { `DDR_PRECHARGE, s_nxt_bank, s_nxt_row[13:11], 1'b0, s_nxt_row[9:0] };
|
cmd_b <= { `DDR_PRECHARGE, s_nxt_bank, s_nxt_row[13:11], 1'b0, s_nxt_row[9:0] };
|
cmd_b[20] <= 1'b1; // Deactivate, unless ...
|
cmd_b[`DDR_CSBIT] <= 1'b1; // Deactivate, unless ...
|
if (cmd_pipe[0])
|
if (cmd_pipe[0])
|
cmd_b <= { `DDR_PRECHARGE, s_bank, s_row[13:11], 1'b0, s_row[9:0] };
|
cmd_b <= { `DDR_PRECHARGE, s_bank, s_row[13:11], 1'b0, s_row[9:0] };
|
cmd_b[20] <= (!cmd_pipe[0])&&(!nxt_pipe[0]);
|
cmd_b[`DDR_CSBIT] <= (!cmd_pipe[0])&&(!nxt_pipe[0]);
|
|
|
cmd_c <= { `DDR_ACTIVATE, s_nxt_bank, s_nxt_row[13:11], 1'b0, s_nxt_row[9:0] };
|
cmd_c <= { `DDR_ACTIVATE, s_nxt_bank, s_nxt_row[13:11], 1'b0, s_nxt_row[9:0] };
|
cmd_c[20] <= 1'b1; // Disable command, unless ...
|
cmd_c[`DDR_CSBIT] <= 1'b1; // Disable command, unless ...
|
if (cmd_pipe[1])
|
if (cmd_pipe[1])
|
cmd_c <= { `DDR_ACTIVATE, r_bank, r_row[13:0] };
|
cmd_c <= { `DDR_ACTIVATE, s_bank, s_row[13:0] };
|
else if (nxt_pipe[1])
|
else if (nxt_pipe[1])
|
cmd_c[20] <= 1'b0;
|
cmd_c[`DDR_CSBIT] <= 1'b0;
|
|
|
if (cmd_pipe[2])
|
if (cmd_pipe[2])
|
begin
|
begin
|
cmd_d[`DDR_CSBIT:`DDR_WEBIT] <= (s_we)?`DDR_WRITE:`DDR_READ;
|
cmd_d[`DDR_CSBIT:`DDR_WEBIT] <= (s_we)?`DDR_WRITE:`DDR_READ;
|
cmd_d[(`DDR_WEBIT-1):0] <= { s_bank, 3'h0, 1'b0, s_col };
|
cmd_d[(`DDR_WEBIT-1):0] <= { s_bank, 3'h0, 1'b0, s_col };
|
end
|
end
|
cmd_d[20] <= !(cmd_pipe[2]);
|
cmd_d[`DDR_CSBIT] <= !(cmd_pipe[2]);
|
|
|
|
|
if ((s_pending)&&(pipe_stall))
|
|
rw_we <= s_we;
|
|
else
|
|
rw_we <= r_we;
|
|
|
|
r_odt <= { r_odt[2:1], (cmd_pipe[2])&&(s_we) };
|
|
// cmd_d <= rw_cmd;
|
|
r_move <= (!cmd_pipe[2]);
|
|
|
|
// Now, if the maintenance mode must override whatever we are
|
// Now, if the maintenance mode must override whatever we are
|
// doing, we only need to apply this more complicated logic
|
// doing, we only need to apply this more complicated logic
|
// to the CS_N bit, or bit[20], since this will activate or
|
// to the CS_N bit, or bit[20], since this will activate or
|
// deactivate the rest of the command--making the rest
|
// deactivate the rest of the command--making the rest
|
// either relevant (CS_N=0) or irrelevant (CS_N=1) as we need.
|
// either relevant (CS_N=0) or irrelevant (CS_N=1) as we need.
|
if (maintenance_override)
|
if (maintenance_override)
|
begin // Over-ride all commands. Make them deselect commands,
|
begin // Over-ride all commands. Make them deselect commands,
|
// save for the maintenance timeslot.
|
// save for the maintenance timeslot.
|
cmd_a[20] <= 1'b0;
|
cmd_a[`DDR_CSBIT] <= 1'b0;
|
cmd_b[20] <= 1'b1;
|
cmd_b[`DDR_CSBIT] <= 1'b1;
|
cmd_c[20] <= 1'b1;
|
cmd_c[`DDR_CSBIT] <= 1'b1;
|
cmd_d[20] <= 1'b1;
|
cmd_d[`DDR_CSBIT] <= 1'b1;
|
end else
|
end else
|
cmd_a[20] <= 1'b1; // Disable maintenance timeslot
|
cmd_a[`DDR_CSBIT] <= 1'b1; // Disable maintenance timeslot
|
end
|
end
|
|
|
`define LGFIFOLN 3
|
`define LGFIFOLN 3
|
`define FIFOLEN 8
|
`define FIFOLEN 8
|
reg [(`LGFIFOLN-1):0] bus_fifo_head, bus_fifo_tail;
|
reg [(`LGFIFOLN-1):0] bus_fifo_head, bus_fifo_tail;
|