OpenCores
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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.