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 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/wbddrsdram.v
51,16 → 51,16
// In this controller, 24-bit commands tend to be passed around. These |
// 'commands' are bit fields. Here we specify the bits associated with |
// the bit fields. |
`define DDR_RSTDONE 26 // End the reset sequence? |
`define DDR_RSTTIMER 25 // Does this reset command take multiple clocks? |
`define DDR_RSTBIT 24 // Value to place on reset_n |
`define DDR_CKEBIT 23 // Should this reset command set CKE? |
`define DDR_CMDLEN 23 |
`define DDR_CSBIT 22 |
`define DDR_RASBIT 21 |
`define DDR_CASBIT 20 |
`define DDR_WEBIT 19 |
`define DDR_NOPTIMER 18 // Steal this from BA bits |
`define DDR_RSTDONE 24 // End the reset sequence? |
`define DDR_RSTTIMER 23 // Does this reset command take multiple clocks? |
`define DDR_RSTBIT 22 // Value to place on reset_n |
`define DDR_CKEBIT 21 // Should this reset command set CKE? |
`define DDR_CMDLEN 21 |
`define DDR_CSBIT 20 |
`define DDR_RASBIT 19 |
`define DDR_CASBIT 18 |
`define DDR_WEBIT 17 |
`define DDR_NOPTIMER 16 // Steal this from BA bits |
`define DDR_BABITS 3 // BABITS are really from 18:16, they are 3 bits |
`define DDR_ADDR_BITS 14 |
|
109,7 → 109,7
reg [31:0] r_data; |
reg r_pending, r_we; |
reg [25:0] r_addr; |
reg [14:0] r_row; |
reg [13:0] r_row; |
reg [2:0] r_bank; |
reg [9:0] r_col; |
reg [1:0] r_sub; |
119,13 → 119,13
// transaction? |
reg m_move, m_match, m_continue, m_pending, m_we; |
reg [25:0] m_addr; |
reg [14:0] m_row; |
reg [13:0] m_row; |
reg [2:0] m_bank; |
reg [9:0] m_col; |
reg [1:0] m_sub; |
|
// Can we preload the next bank? |
reg [14:0] r_nxt_row; |
reg [13:0] r_nxt_row; |
reg [2:0] r_nxt_bank; |
|
// |
169,7 → 169,7
reg reset_override, reset_ztimer; |
reg [3:0] reset_address; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd; |
reg [26:0] reset_instruction; |
reg [24:0] reset_instruction; |
reg [16:0] reset_timer; |
initial reset_override = 1'b1; |
initial reset_address = 4'h0; |
177,13 → 177,13
if (i_reset) |
begin |
reset_override <= 1'b1; |
reset_cmd <= { `DDR_NOOP, reset_instruction[18:0]}; |
end else if (!reset_ztimer) |
; |
else if (reset_instruction[`DDR_RSTDONE]) |
reset_override <= 1'b0; |
else |
reset_cmd <= reset_instruction[22:0]; |
reset_cmd <= { `DDR_NOOP, reset_instruction[16:0]}; |
end else if (reset_ztimer) |
begin |
if (reset_instruction[`DDR_RSTDONE]) |
reset_override <= 1'b0; |
reset_cmd <= reset_instruction[20:0]; |
end |
always @(posedge i_clk) |
if (i_reset) |
o_ddr_cke <= 1'b0; |
191,12 → 191,12
o_ddr_cke <= reset_instruction[`DDR_CKEBIT]; |
|
initial reset_ztimer = 1'b0; // Is the timer zero? |
initial reset_timer = 17'h01; |
initial reset_timer = 17'h02; |
always @(posedge i_clk) |
if (i_reset) |
begin |
reset_ztimer <= 1'b0; |
reset_timer <= 17'd1; |
reset_timer <= 17'd2; |
end else if (!reset_ztimer) |
begin |
reset_ztimer <= (reset_timer == 17'h01); |
207,26 → 207,26
reset_timer <= reset_instruction[16:0]; |
end |
|
wire [18:0] w_ckXPR = CKXPR, w_ckRST = 4, w_ckRP = 3, |
wire [16:0] w_ckXPR = CKXPR, w_ckRST = 4, w_ckRP = 3, |
w_ckRFC = CKRFC; |
always @(posedge i_clk) |
if (i_reset) |
reset_instruction <= { 4'h4, `DDR_NOOP, 19'd40_000 }; |
else case(reset_address) // RSTDONE, TIMER, CKE, ?? |
reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
else if (reset_ztimer) case(reset_address) // RSTDONE, TIMER, CKE, ?? |
// 1. Reset asserted (active low) for 200 us. (@200MHz) |
4'h0: reset_instruction <= { 4'h4, `DDR_NOOP, 19'd40_000 }; |
4'h0: reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
// 2. Reset de-asserted, wait 500 us before asserting CKE |
4'h1: reset_instruction <= { 4'h6, `DDR_NOOP, 19'd100_000 }; |
4'h1: reset_instruction <= { 4'h6, `DDR_NOOP, 17'd100_000 }; |
// 3. Assert CKE, wait minimum of Reset CKE Exit time |
4'h2: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckXPR }; |
// 4. Look MR2. (1CK, no TIMER) |
4'h3: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h2, |
5'h0, 2'b00, 1'b0, 1'b0, 1'b1, 3'b0, 3'b0 }; // MRS2 |
3'h0, 2'b00, 1'b0, 1'b0, 1'b1, 3'b0, 3'b0 }; // MRS2 |
// 3. Wait 4 clocks (tMRD) |
4'h4: reset_instruction <= { 4'h7, `DDR_NOOP, 19'h04 }; |
4'h4: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
// 5. Set MR1 |
4'h5: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h1, |
3'h0, // Reserved for Future Use (RFU) |
1'h0, // Reserved for Future Use (RFU) |
1'b0, // Qoff - output buffer enabled |
1'b1, // TDQS ... enabled |
1'b0, // RFU |
241,10 → 241,10
1'b1, // DIC set to 2'b01 |
1'b1 }; // MRS1, DLL enable |
// 7. Wait another 4 clocks |
4'h6: reset_instruction <= { 4'h7, `DDR_NOOP, 19'h04 }; |
4'h6: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
// 8. Send MRS0 |
4'h7: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h0, |
3'b0, // Reserved for future use |
1'b0, // Reserved for future use |
1'b0, // PPD control, (slow exit(DLL off)) |
3'b1, // Write recovery for auto precharge |
1'b0, // DLL Reset (No) |
255,22 → 255,22
1'b0, // Low bit of cas latency |
2'b0 }; // Burst length = 8 (Fixed) |
// 9. Wait tMOD, is max(12 clocks, 15ns) |
4'h8: reset_instruction <= { 4'h7, `DDR_NOOP, 19'h0c }; |
4'h8: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h0a }; |
// 10. Issue a ZQCL command to start ZQ calibration, A10 is high |
4'h9: reset_instruction <= { 4'h7, `DDR_ZQS, 8'h0, 1'b1, 10'h0}; |
4'h9: reset_instruction <= { 4'h3, `DDR_ZQS, 6'h0, 1'b1, 10'h0}; |
//11.Wait for both tDLLK and tZQinit completed, both are 512 cks |
4'ha: reset_instruction <= { 4'h7, `DDR_NOOP, 19'd512 }; |
4'ha: reset_instruction <= { 4'h7, `DDR_NOOP, 17'd512 }; |
// 12. Precharge all command |
4'hb: reset_instruction <= { 4'h7, `DDR_PRECHARGE, 8'h0, 1'b1, 10'h0 }; |
4'hb: reset_instruction <= { 4'h3, `DDR_PRECHARGE, 6'h0, 1'b1, 10'h0 }; |
// 13. Wait for the precharge to complete |
4'hc: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRP }; |
// 14. A single Auto Refresh commands |
4'hd: reset_instruction <= { 4'h7, `DDR_REFRESH, 19'h00 }; |
4'hd: reset_instruction <= { 4'h3, `DDR_REFRESH, 17'h00 }; |
// 15. Wait for the auto refresh to complete |
4'he: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRFC }; |
// Two Auto Refresh commands |
default: |
reset_instruction <={4'hb, `DDR_NOOP, 19'd00_000 }; |
reset_instruction <={4'hb, `DDR_NOOP, 17'd00_000 }; |
endcase |
// reset_instruction <= reset_mem[reset_address]; |
|
277,7 → 277,7
initial reset_address = 4'h0; |
always @(posedge i_clk) |
if (i_reset) |
reset_address <= 4'h0; |
reset_address <= 4'h1; |
else if (reset_ztimer) |
reset_address <= reset_address + 4'h1; |
// |
356,8 → 356,8
always @(posedge i_clk) |
// if (cmd[22:19] == `DDR_ACTIVATE) |
if (need_open_bank) |
bank_address[activate_bank_cmd[18:16]] |
<= activate_bank_cmd[14:0]; |
bank_address[activate_bank_cmd[16:14]] |
<= activate_bank_cmd[13:0]; |
|
// |
// |
388,13 → 388,13
need_refresh <= (refresh_clk == 0)||(midrefresh); |
always @(posedge i_clk) |
if (!need_refresh) |
refresh_cmd <= { `DDR_NOOP, 19'h00 }; |
refresh_cmd <= { `DDR_NOOP, 17'h00 }; |
else if (~banks_are_closing) |
refresh_cmd <= { `DDR_PRECHARGE, 3'h0, 5'h0, 1'b1, 10'h00 }; |
refresh_cmd <= { `DDR_PRECHARGE, 3'h0, 3'h0, 1'b1, 10'h00 }; |
else if (~all_banks_closed) |
refresh_cmd <= { `DDR_NOOP, 19'h00 }; |
refresh_cmd <= { `DDR_NOOP, 17'h00 }; |
else |
refresh_cmd <= { `DDR_REFRESH, 19'h00 }; |
refresh_cmd <= { `DDR_REFRESH, 17'h00 }; |
always @(posedge i_clk) |
midrefresh <= (need_refresh)&&(all_banks_closed)&&(~refresh_clear); |
|
481,19 → 481,19
r_we <= i_wb_we; |
r_addr <= i_wb_addr; |
r_data <= i_wb_data; |
r_row <= i_wb_addr[25:11]; |
r_bank <= i_wb_addr[10:8]; |
r_col <= { i_wb_addr[7:0], 2'b00 }; // 9:2 |
r_row <= i_wb_addr[25:12]; |
r_bank <= i_wb_addr[11:9]; |
r_col <= { i_wb_addr[8:2], 3'b000 }; // 9:2 |
r_sub <= i_wb_addr[1:0]; |
|
// pre-emptive work |
r_nxt_row <= i_wb_addr[25:11]+15'h1; |
r_nxt_bank <= i_wb_addr[10:8]+3'h1; |
r_nxt_row <= i_wb_addr[25:12]+14'h1; |
r_nxt_bank <= i_wb_addr[11:9]+3'h1; |
end |
end |
|
reg [2:0] bank_active[7:0]; |
reg [14:0] bank_address[7:0]; |
reg [13:0] bank_address[7:0]; |
|
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd, rw_cmd; |
reg need_close_bank, need_close_this_bank, |
514,8 → 514,8
&&(!need_close_this_bank); |
|
close_bank_cmd <= (maybe_close_next_bank) |
? { `DDR_PRECHARGE, r_nxt_bank, r_nxt_row[14:10], 1'b0, r_nxt_row[9:0] } |
: { `DDR_PRECHARGE, r_bank, r_row[14:10], 1'b0, r_row[9:0] }; |
? { `DDR_PRECHARGE, r_nxt_bank, r_nxt_row[13:11], 1'b0, r_nxt_row[9:0] } |
: { `DDR_PRECHARGE, r_bank, r_row[13:11], 1'b0, r_row[9:0] }; |
|
|
need_open_bank <= (r_pending)&&(bank_active[r_bank][1:0]==2'b00) |
527,8 → 527,8
&&(!need_open_bank)&&(!need_close_bank); |
|
activate_bank_cmd <= (maybe_open_next_bank) |
? { `DDR_ACTIVATE,r_nxt_bank,1'b0,r_nxt_row[14:0] } |
: { `DDR_ACTIVATE, r_bank, 1'b0,r_row[14:0] }; |
? { `DDR_ACTIVATE,r_nxt_bank, r_nxt_row[13:0] } |
: { `DDR_ACTIVATE, r_bank, r_row[13:0] }; |
|
|
|
538,7 → 538,7
last_valid_bank <= valid_bank; |
|
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (~r_pending)?`DDR_NOOP:((r_we)?`DDR_WRITE:`DDR_READ); |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 5'h0, 1'b0, r_col }; |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 3'h0, 1'b0, r_col }; |
end |
|
|