Skip to content

Commit

Permalink
more sdram64 testings for cyc1000. restored rb5 de10lite
Browse files Browse the repository at this point in the history
  • Loading branch information
somhi committed May 10, 2023
1 parent ba7b9b1 commit e090c01
Show file tree
Hide file tree
Showing 3 changed files with 656 additions and 312 deletions.
266 changes: 266 additions & 0 deletions hdl/sdram/jtframe_sdram64_bank_cyc2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/* This file is part of JTFRAME.
JTFRAME program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
JTFRAME program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
Author: Jose Tejada Gomez. Twitter: @topapate
Version: 1.0
Date: 29-4-2021 */

// SDRAM is set to burst=2 (64 bits)

module jtframe_sdram64_bank #(
parameter AW=22,
HF=1, // 1 for HF operation (idle cycles), 0 for LF operation
// HF operation starts at 66.6MHz (1/15ns)
SHIFTED =0,
AUTOPRECH =0,
PRECHARGE_ALL=0,
BALEN =64, // 16, 32 or 64 bits
BURSTLEN =64,
READONLY =0 // set to 1 if ALL BANKS can only read
// this will make dbusy64 match dbusy
)(
input rst,
input clk,

// requests
input [AW-1:0] addr,
input rd,
input wr,

output ack,
output dst, // data starts
output reg dok, // data ok
output rdy,
input set_prech,

output dbusy, // DQ bus busy (read values only)
output dbusy64, // DQ bus busy (the full four clock cycles)
output reg dqm_busy, // DQM lines are used
output reg wr_busy, // output access to DQ bus
input all_dbusy,
input all_dbusy64,
input all_dqm,
output idle,

output reg post_act, // cycles banned for activate (tRRD)
input all_act,

// row matching
output reg [12:0] row,
input match,

// SDRAM interface
output reg br, // bus request
input bg, // bus grant

// SDRAM_A[12:11] and SDRAM_DQML/H are controlled in a way
// that can be joined together thru an OR operation at a
// higher level. This makes it possible to short the pins
// of the SDRAM, as done in the MiSTer 128MB module
output reg [12:0] sdram_a, // SDRAM Address bus 13 Bits
output reg [ 3:0] cmd
);

localparam ROW=13,
COW= AW==22 ? 9 : 10; // 9 for 32MB SDRAM, 10 for 64MB

// states
localparam IDLE = 0,
// AUTOPRECH 1+2(1)
PRE_ACT = HF ? 3:2,
ACT = PRE_ACT+1,
PRE_RD = PRE_ACT + (HF ? 3:2),
READ = PRE_RD+1,
DST = READ + (SHIFTED ? 1 : 2) ,
DTICKS = BURSTLEN==64 ? 4 : (BURSTLEN==32?2:1),
BUSY = DST+(DTICKS-1),
RDY = DST + (BALEN==16 ? 0 : (BALEN==32? 1 : 3)),
STW = BUSY + 1 + {2'd0,AUTOPRECH[0]};

// /CS /RAS /CAS /WE
localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0
CMD_REFRESH = 4'b0___0____0____1, // 1
CMD_PRECHARGE = 4'b0___0____1____0, // 2
CMD_ACTIVE = 4'b0___0____1____1, // 3
CMD_WRITE = 4'b0___1____0____0, // 4
CMD_READ = 4'b0___1____0____1, // 5
CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate
CMD_NOP = 4'b0___1____1____1, // 7
CMD_INHIBIT = 4'b1___0____0____0; // 8

localparam [STW-1:0] ONE = 1;
/*
`ifdef SIMULATION
initial begin
$display("%m\n\tREAD=%2d\n\tDST=%2d\n\tRDY=%2d\n\tSTW=%2d",READ,DST,RDY,STW);
end
`endif
*/
reg actd, prechd;
wire [ROW-1:0] addr_row;
reg [STW-1:0] st, next_st, rot_st;
reg last_act;
wire rd_wr;

reg do_prech, do_act, do_read, written;

// state phases
reg in_busy, in_busy64;

// SDRAM pins
assign ack = st[READ],
dst = st[DST] | (st[READ] & wr),
dbusy = |{in_busy, do_read},
dbusy64 = READONLY ? dbusy : |{in_busy64, do_read},
rdy = (written && !AUTOPRECH) ? st[READ] : st[RDY],
addr_row = AW==22 ? addr[AW-1:AW-ROW] : addr[AW-2:AW-1-ROW],
rd_wr = rd | wr,
idle = st[0];

always @(posedge clk, posedge rst) begin
if( rst ) begin
in_busy <= 0; // |st[ (BALEN==16? READ+1 : RDY-2):READ]
in_busy64 <= 0; // |{st[BUSY:READ], do_read}
dok <= 0; // |st[RDY:DST]
dqm_busy <= 0; // |{st[RDY-2:READ]}
end else begin
if(next_st[READ]) in_busy <= 1;
else if( st[(BALEN==16? READ+1 : RDY-2)] || next_st[READ-1:0]!=0 ) in_busy<=0;

if(next_st[READ]) in_busy64 <= 1;
else if( st[BUSY] || next_st[READ-1:0]!=0 ) in_busy64<=0;

if(next_st[DST]) dok<=1;
else if( st[RDY] || next_st[DST-1:0]!=0 ) dok <= 0;

if(next_st[READ]) dqm_busy<=1;
else if(st[RDY-2] || next_st[READ-1:0]!=0) dqm_busy<=0;

end
end

always @(*) begin
rot_st = { st[STW-2:0], st[STW-1] };
next_st = st;
if( st[IDLE] ) begin
if(do_prech) next_st = rot_st;
if(do_act ) next_st = ONE<<ACT;
if(do_read ) next_st = ONE<<READ;
end
if( ( st[PRE_RD] && bg && !all_dqm ) ||
( st[PRE_ACT] && bg && !all_dqm && !all_act) ||
( !st[IDLE] && !st[PRE_ACT] && !st[PRE_RD] ) )
next_st = rot_st;
if( st[READ] && wr && !AUTOPRECH)
next_st = 1; // writes finish earlier
end

wire row_match = match && actd && !AUTOPRECH[0];

always @(*) begin
do_prech = 0;
do_act = 0;
do_read = 0;
if( bg ) begin
do_prech = !prechd && !row_match // not a good address
&& (st[IDLE]&&rd_wr);

do_act = ((st[IDLE] & rd_wr & prechd & ~actd) | st[PRE_ACT])
& ~all_act & ~all_dqm;

do_read = ((st[IDLE] & rd_wr & row_match) | st[PRE_RD]) &
(~all_dbusy & (~all_dbusy64 | rd) & ~all_dqm);
end
end

generate
if( HF==1 ) begin
always @(posedge clk, posedge rst) begin
if( rst ) begin
br <= 0;
end else begin
br <= 0;
if( (st[IDLE] || next_st[IDLE] || next_st[PRE_ACT] || next_st[PRE_RD]) && rd_wr ) begin
br <= 1;
if( next_st[PRE_RD] & (all_dbusy | (all_dbusy64&wr)) ) br <= 0; // Do not try to request
end
end
end
end else begin
always @(*) begin
br = 0;
if( (st[IDLE] || st[PRE_ACT] || st[PRE_RD]) && rd_wr ) begin
br = 1;
if( st[PRE_RD] & (all_dbusy | (all_dbusy64&wr)) ) br = 0; // Do not try to request
end
end
end
endgenerate

// module outputs
always @(*) begin
wr_busy = do_read & wr;
cmd = do_prech ? CMD_PRECHARGE : (
do_act ? CMD_ACTIVE : (
do_read ? (rd ? CMD_READ : CMD_WRITE ) : CMD_NOP ));
// sdram_a[12:11] = addr_row[12:11];
// sdram_a[10:0] = do_act ? addr_row[10:0] :
// { do_read ? AUTOPRECH[0] : PRECHARGE_ALL[0], addr[AW-1], addr[8:0]};

// sdram_a[12:0] = do_act ? addr_row[12:0] :
// { 2'b00, do_read ? AUTOPRECH[0] : PRECHARGE_ALL[0], addr[AW-1], addr[AW-2], addr[7:0]};

// sdram_a[12:0] = do_act ? addr_row[12:0] :
// { 2'b00, do_read ? AUTOPRECH[0] : PRECHARGE_ALL[0], 2'b00, addr[7:0]};

sdram_a[12:0] = do_act ? addr_row[12:0] :
{ 2'b00, do_read ? AUTOPRECH[0] : PRECHARGE_ALL[0], 1'b0, addr[AW-1], addr[7:0]};

end

always @(posedge clk, posedge rst) begin
if( rst ) begin
prechd <= 0;
actd <= 0;
row <= 0;
st <= 1; // IDLE
last_act <= 0;
written <= 0;
end else begin
st <= next_st;
if( do_act ) begin
post_act <= 1;
last_act <= 1;
end else begin
last_act <= 0;
post_act <= last_act;
end

if( do_act ) begin
row <= addr_row;
prechd <= 0;
actd <= 1;
end

if( do_read ) written <= wr;
else if(st[0]) written<=0;

if( do_prech || set_prech || (do_read && AUTOPRECH)) begin
prechd <= 1;
actd <= 0;
end
end
end

endmodule
100 changes: 100 additions & 0 deletions hdl/sdram/jtframe_sdram64_init_cyc2.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/* This file is part of JTFRAME.
JTFRAME program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
JTFRAME program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JTFRAME. If not, see <http://www.gnu.org/licenses/>.
Author: Jose Tejada Gomez. Twitter: @topapate
Version: 1.0
Date: 29-4-2021 */

module jtframe_sdram64_init #(parameter
HF =1,
BURSTLEN=64
) (
input rst,
input clk,

output reg init,
output reg [3:0] cmd,
output reg [12:0] sdram_a
);

//localparam [13:0] INIT_WAIT = HF ? 14'd10_000 : 14'd5_000; // 100us for 96MHz/48MHz
localparam [14:0] INIT_WAIT = HF ? 15'd20_000 : 15'd10_000; // 200us for 96MHz/48MHz for W9864G6JT (CYC1000)


// /CS /RAS /CAS /WE
localparam CMD_LOAD_MODE = 4'b0___0____0____0, // 0
CMD_REFRESH = 4'b0___0____0____1, // 1
CMD_PRECHARGE = 4'b0___0____1____0, // 2
CMD_ACTIVE = 4'b0___0____1____1, // 3
CMD_WRITE = 4'b0___1____0____0, // 4
CMD_READ = 4'b0___1____0____1, // 5
CMD_STOP = 4'b0___1____1____0, // 6 Burst terminate
CMD_NOP = 4'b0___1____1____1, // 7
CMD_INHIBIT = 4'b1___0____0____0; // 8

// initialization signals
reg [14:0] wait_cnt;
reg [ 2:0] init_st;
reg [ 3:0] init_cmd;

always @(posedge clk, posedge rst) begin
if( rst ) begin
// initialization loop
init <= 1;
wait_cnt <= INIT_WAIT; // wait for 200us
init_st <= 3'd0;
init_cmd <= CMD_NOP;
// SDRAM pins
cmd <= CMD_NOP;
sdram_a <= 13'd0;
end else if( init ) begin
if( |wait_cnt ) begin
wait_cnt <= wait_cnt-15'd1;
init_cmd <= CMD_NOP;
cmd <= init_cmd;
end else begin
sdram_a <= 13'd0;
if(!init_st[2]) init_st <= init_st+3'd1;
case(init_st)
3'd0: begin
init_cmd <= CMD_PRECHARGE;
sdram_a[10]<= 1; // all banks
wait_cnt <= 15'd2;
end
3'd1: begin
init_cmd <= CMD_REFRESH;
wait_cnt <= 15'd11;
end
3'd2: begin
init_cmd <= CMD_REFRESH;
wait_cnt <= 15'd11;
end
3'd3: begin
init_cmd <= CMD_LOAD_MODE;
sdram_a <= {10'b00_1_00_010_0,BURSTLEN==64?3'b010:(BURSTLEN==32?3'b001:3'b000)}; // CAS Latency = 2, burst = 1-4
wait_cnt <= 15'd3;
end
3'd4: begin
init <= 0;
end
default: begin
cmd <= init_cmd;
init <= 0;
end
endcase
end
end
end

endmodule
Loading

0 comments on commit e090c01

Please sign in to comment.