URL
https://opencores.org/ocsvn/wbddr3/wbddr3/trunk
Subversion Repositories wbddr3
Compare Revisions
- This comparison shows the changes necessary to convert path
/wbddr3/trunk/rtl
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/wbddrsdram.v
6,6 → 6,24
// |
// Purpose: |
// |
/* |
Stall logic: |
1. First clock sets r_* variables. |
2. Second clock sets need_* variables. If need_open, need_close, or |
need_refresh are true, that should also set the o_wb_stall |
variable. Well also move r_* info to s_* (think s=stall) |
3. If stalled, the next command comes from s_*. Otherwise, from r_*. |
4. Bus FIFO fills from s_* |
// |
// |
For every transaction, one of 4 possibilities: |
1. Wait for refresh to complete |
2. Wait for precharge and activate to complete |
3. Wait for activate to complete |
4. Issue RW cmd |
5. Wait for bus transaction to complete |
6. ACK |
*/ |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
124,9 → 142,20
reg [1:0] r_sub; |
reg r_move; // It was accepted, and can move to next stage |
|
// The pending transaction, one further into the pipeline. This is |
// the stage where the read/write command is actually given to the |
// interface if we haven't stalled. |
reg [31:0] s_data; |
reg s_pending, s_we, s_match; |
reg [25:0] s_addr; |
reg [13:0] s_row, s_nxt_row; |
reg [2:0] s_bank, s_nxt_bank; |
reg [9:0] s_col; |
reg [1:0] s_sub; |
|
// Can the pending transaction be satisfied with the current (ongoing) |
// transaction? |
reg m_move, m_match, m_continue, m_pending, m_we; |
reg m_move, m_match, m_pending, m_we; |
reg [25:0] m_addr; |
reg [13:0] m_row; |
reg [2:0] m_bank; |
145,10 → 174,12
valid_bank, last_valid_bank; |
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd, |
maybe_close_cmd, maybe_open_cmd, rw_cmd; |
reg [1:0] rw_sub; |
reg rw_we; |
|
wire w_this_closing_bank, w_this_opening_bank, |
w_this_maybe_close, w_this_maybe_open, |
w_this_rw_move, w_this_refresh; |
w_this_rw_move; |
reg last_closing_bank, last_opening_bank; |
// |
// tWTR = 7.5 |
188,9 → 219,10
// the DDR3 SDRAM, or a timer to wait until the next command. Further, the |
// timer commands indicate whether or not the command during the timer is to |
// be set to idle, or whether the command is instead left as it was. |
reg reset_override, reset_ztimer; |
reg reset_override, reset_ztimer, maintenance_override; |
reg [4:0] reset_address; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd, |
maintenance_cmd; |
reg [24:0] reset_instruction; |
reg [16:0] reset_timer; |
initial reset_override = 1'b1; |
512,7 → 544,8
begin |
bus_active[`BUSNOW:0] <= { bus_active[(`BUSNOW-1):0], 1'b0 }; |
bus_read[`BUSNOW:0] <= { bus_read[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus? |
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus? |
// Is this a new command? i.e., the start of a transaction? |
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 }; |
//bus_mask[8:0] <= { bus_mask[7:0], 1'b1 }; // Write this value? |
bus_subaddr[8] <= bus_subaddr[7]; |
bus_subaddr[7] <= bus_subaddr[6]; |
530,9 → 563,9
bus_subaddr[3] <= 2'h0; |
bus_subaddr[2] <= 2'h1; |
bus_subaddr[1] <= 2'h2; |
bus_new[{ 2'b0, (2'h3-r_sub) }] <= 1'b1; |
bus_new[{ 2'b0, rw_sub }] <= 1'b1; |
|
bus_read[3:0] <= (r_we)? 4'h0:4'hf; |
bus_read[3:0] <= (rw_we)? 4'h0:4'hf; |
end |
end |
|
544,19 → 577,30
// Now, let's see, can we issue a read command? |
// |
// |
wire w_s_match; |
assign w_s_match = (s_pending)&&(r_pending)&&(r_we == s_we) |
&&(r_row == s_row)&&(r_bank == s_bank) |
&&(r_col == s_col) |
&&(r_sub > s_sub); |
reg pipe_stall; |
always @(posedge i_clk) |
begin |
if ((i_wb_stb)&&(~o_wb_stall)) |
r_pending <= (i_wb_stb)&&(~o_wb_stall) |
||(r_pending)&&(pipe_stall); |
if (~pipe_stall) |
s_pending <= r_pending; |
if (~pipe_stall) |
begin |
r_pending <= 1'b1; |
pipe_stall <= (r_pending)&&(((!w_r_valid)||(valid_bank))&&(!w_s_match)); |
o_wb_stall <= (r_pending)&&(((!w_r_valid)||(valid_bank))&&(!w_s_match)); |
end else begin // if (pipe_stall) |
pipe_stall <= (s_pending)&&((!w_s_valid)||(valid_bank)||(r_move)||(last_valid_bank)); |
o_wb_stall <= (s_pending)&&((!w_s_valid)||(valid_bank)||(r_move)||(last_valid_bank)); |
end |
if (need_refresh) |
o_wb_stall <= 1'b1; |
end else if ((m_move)||(w_this_rw_move)) |
begin |
r_pending <= 1'b0; |
o_wb_stall <= 1'b0; |
end |
|
if (~o_wb_stall) |
if (~pipe_stall) |
begin |
r_we <= i_wb_we; |
r_addr <= i_wb_addr; |
570,12 → 614,42
r_nxt_row <= (i_wb_addr[11:9]==3'h7)?i_wb_addr[25:12]+14'h1:i_wb_addr[25:12]; |
r_nxt_bank <= i_wb_addr[11:9]+3'h1; |
end |
|
if (~pipe_stall) |
begin |
// Moving one down the pipeline |
s_we <= r_we; |
s_addr <= r_addr; |
s_data <= r_data; |
s_row <= r_row; |
s_bank <= r_bank; |
s_col <= r_col; |
s_sub <= r_sub; |
|
// pre-emptive work |
s_nxt_row <= r_nxt_row; |
s_nxt_bank <= r_nxt_bank; |
|
s_match <= w_s_match; |
end |
end |
|
wire w_need_close_this_bank, w_need_open_bank; |
wire w_need_close_this_bank, w_need_open_bank, |
w_r_valid, w_s_valid; |
assign w_need_close_this_bank = (r_pending)&&(bank_status[r_bank][0]) |
&&(r_row != bank_address[r_bank]); |
assign w_need_open_bank = (r_pending)&&(bank_status[r_bank][1:0]==2'b00); |
&&(r_row != bank_address[r_bank]) |
||(pipe_stall)&&(s_pending)&&(bank_status[s_bank][0]) |
&&(s_row != bank_address[s_bank]); |
assign w_need_open_bank = (r_pending)&&(bank_status[r_bank][1:0]==2'b00) |
||(pipe_stall)&&(s_pending)&&(bank_status[s_bank][1:0]==2'b00); |
assign w_r_valid = (!need_refresh)&&(r_pending) |
&&(bank_status[r_bank][3]) |
&&(bank_address[r_bank]==r_row) |
&&(!bus_active[0]); |
assign w_s_valid = (!need_refresh)&&(s_pending) |
&&(bank_status[s_bank][3]) |
&&(bank_address[s_bank]==s_row) |
&&(!bus_active[0]); |
|
always @(posedge i_clk) |
begin |
606,52 → 680,31
|
|
|
valid_bank <= (r_pending)&&(bank_status[r_bank][3]) |
&&(bank_address[r_bank]==r_row) |
&&(!last_valid_bank)&&(!r_move) |
&&(!bus_active[0]); |
valid_bank <= ((w_r_valid)||(pipe_stall)&&(w_s_valid)) |
&&(!last_valid_bank)&&(!r_move); |
last_valid_bank <= r_move; |
|
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (~r_pending)?`DDR_NOOP:((r_we)?`DDR_WRITE:`DDR_READ); |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 3'h0, 1'b0, r_col }; |
if ((s_pending)&&(pipe_stall)) |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (s_we)?`DDR_WRITE:`DDR_READ; |
else if (r_pending) |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (r_we)?`DDR_WRITE:`DDR_READ; |
else |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= `DDR_NOOP; |
if ((s_pending)&&(pipe_stall)) |
rw_cmd[`DDR_WEBIT-1:0] <= { s_bank, 3'h0, 1'b0, s_col }; |
else |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 3'h0, 1'b0, r_col }; |
if ((s_pending)&&(pipe_stall)) |
rw_sub <= 2'b11 - s_sub; |
else |
rw_sub <= 2'b11 - r_sub; |
if ((s_pending)&&(pipe_stall)) |
rw_we <= s_we; |
else |
rw_we <= r_we; |
|
end |
|
|
// Match registers, to see if we can move forward without sending a |
// new command |
reg [2:0] m_clock; |
reg m_timeout; |
always @(posedge i_clk) |
begin |
if (|m_clock) |
m_clock <= m_clock - 3'h1; |
if (!m_timeout) |
m_timeout <= (m_clock[2:1] == 2'b00); |
if (w_this_rw_move) |
begin |
m_pending <= r_pending; |
m_we <= r_we; |
m_addr <= r_addr; |
m_row <= r_row; |
m_bank <= r_bank; |
m_col <= r_col; |
m_sub <= r_sub; |
m_clock<= 3'h7; |
m_timeout <= 1'b0; |
end else if ((m_match)&&(!m_timeout)) |
m_sub <= r_sub; |
|
m_match <= (m_pending)&&(r_pending)&&(r_we == m_we) |
&&(r_row == m_row)&&(r_bank == m_bank) |
&&(r_col == m_col) |
&&(r_sub > m_sub); |
m_continue <= (m_pending)&&(r_pending)&&(r_we == m_we) |
&&(r_row == m_row)&&(r_bank == m_bank) |
&&(r_col == m_col+10'h1); |
// m_nextbank <= (m_pending)&&(r_pending)&&(r_we == m_we) |
// &&(r_row == m_row)&&(r_bank == m_bank); |
end |
|
// |
// |
// Okay, let's look at the last assignment in our chain. It should look |
667,21 → 720,31
else if (reset_ztimer) |
o_ddr_cke <= reset_instruction[`DDR_CKEBIT]; |
|
assign w_this_refresh = (!reset_override)&&(need_refresh) |
&&(refresh_cmd[`DDR_CSBIT:`DDR_WEBIT] == `DDR_REFRESH); |
always @(posedge i_clk) |
if (i_reset) |
maintenance_override <= 1'b1; |
else |
maintenance_override <= (reset_override)||(need_refresh); |
|
assign w_this_closing_bank = (!reset_override)&&(!need_refresh) |
initial maintenance_cmd = { `DDR_NOOP, 17'h00 }; |
always @(posedge i_clk) |
if (i_reset) |
maintenance_cmd <= { `DDR_NOOP, 17'h00 }; |
else |
maintenance_cmd <= (reset_override)?reset_cmd:refresh_cmd; |
|
assign w_this_closing_bank = (!maintenance_override) |
&&(need_close_bank); |
assign w_this_opening_bank = (!reset_override)&&(!need_refresh) |
assign w_this_opening_bank = (!maintenance_override) |
&&(!need_close_bank)&&(need_open_bank); |
assign w_this_rw_move = (!reset_override)&&(!need_refresh) |
assign w_this_rw_move = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&(valid_bank)&&(!r_move); |
assign w_this_maybe_close = (!reset_override)&&(!need_refresh) |
assign w_this_maybe_close = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(maybe_close_next_bank); |
assign w_this_maybe_open = (!reset_override)&&(!need_refresh) |
assign w_this_maybe_open = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(!maybe_close_next_bank) |
693,13 → 756,10
last_maybe_open <= 1'b0; |
last_maybe_close <= 1'b0; |
r_move <= 1'b0; |
if (reset_override) |
cmd <= reset_cmd[`DDR_CSBIT:0]; |
else if (need_refresh) |
if (maintenance_override) // Command from either reset or |
cmd <= maintenance_cmd; // refresh logic |
else if (need_close_bank) |
begin |
cmd <= refresh_cmd; // The command from the refresh logc |
end else if (need_close_bank) |
begin |
cmd <= close_bank_cmd; |
last_closing_bank <= 1'b1; |
end else if (need_open_bank) |
732,7 → 792,11
|
// The bus R/W FIFO |
wire w_bus_fifo_read_next_transaction; |
assign w_bus_fifo_read_next_transaction = (bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG])&&(bus_active[`BUSREG])&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]); |
assign w_bus_fifo_read_next_transaction = |
(bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG]) |
&&(bus_fifo_tail != bus_fifo_head) |
&&(bus_active[`BUSREG]) |
&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]); |
always @(posedge i_clk) |
begin |
pre_ack <= 1'b0; |
743,7 → 807,7
bus_fifo_tail <= 4'h0; |
o_ddr_dm <= 1'b0; |
end else begin |
if ((w_this_rw_move)||(m_move)) |
if ((w_this_rw_move)||((s_pending)&&(s_match)&&(!pipe_stall))) |
bus_fifo_head <= bus_fifo_head + 4'h1; |
|
o_ddr_dm <= (bus_active[`BUSREG])&&(!bus_read[`BUSREG]); |
754,8 → 818,8
o_ddr_dm <= 1'b0; |
end |
end |
bus_fifo_data[bus_fifo_head] <= r_data; |
bus_fifo_sub[bus_fifo_head] <= r_sub; |
bus_fifo_data[bus_fifo_head] <= s_data; |
bus_fifo_sub[bus_fifo_head] <= s_sub; |
bus_fifo_new[bus_fifo_head] <= w_this_rw_move; |
end |
|