OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /eco32/trunk
    from Rev 312 to Rev 313
    Reverse comparison

Rev 312 → Rev 313

/fpga/experiments/memctrl/sim/memctrl-1/ramtest/ramtest.v
0,0 → 1,262
//
// ramtest.v -- RAM test generator
//
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
`define SIMULATE
`define VERBOSE
 
`define INST_PERIOD 31
`define INST_PHASE 19
`define DATA_PERIOD 17
`define DATA_PHASE 7
 
 
//
// memory test generator
//
// Algorithm: Three independent address/data generators
// produce exactly the same sequence of address/data pairs,
// although at different times: data write, data read, and
// instruction read. Three out of four data cycles are writes,
// one is a read. Instruction reads are also less frequent
// than data writes: 1/31 < 1/17 * 3/4. The writing process
// is therefore always ahead of the reading processes, with
// an increasing gap in between.
//
 
module ramtest(clk, rst,
inst_stb, inst_addr,
inst_din, inst_ack,
data_stb, data_we, data_addr,
data_dout, data_din, data_ack,
test_ended, test_error);
input clk;
input rst;
output reg inst_stb;
output [25:0] inst_addr;
input [63:0] inst_din;
input inst_ack;
output reg data_stb;
output reg data_we;
output [25:0] data_addr;
output [63:0] data_dout;
input [63:0] data_din;
input data_ack;
output test_ended;
output test_error;
 
reg [4:0] inst_timer;
reg [4:0] data_timer;
reg [9:0] data_counter;
 
wire ir_next;
wire [21:0] ir_a;
wire [63:0] ir_d;
 
wire dw_next;
wire [21:0] dw_a;
wire [63:0] dw_d;
 
wire dr_next;
wire [21:0] dr_a;
wire [63:0] dr_d;
 
`ifdef SIMULATE
reg error_1;
reg error_3;
`endif
reg error_2;
reg error_4;
 
always @(posedge clk) begin
if (rst) begin
inst_timer <= 0;
inst_stb <= 0;
`ifdef SIMULATE
error_1 <= 0;
`endif
error_2 <= 0;
end else begin
if (~test_ended) begin
if (~inst_stb) begin
if (inst_timer == `INST_PERIOD - 1) begin
inst_timer <= 0;
end else begin
inst_timer <= inst_timer + 1;
end
if (inst_timer == `INST_PHASE) begin
inst_stb <= 1;
end
end else begin
if (inst_ack) begin
inst_stb <= 0;
`ifdef SIMULATE
`ifdef VERBOSE
$display("%t: inst read @ 0x%h", $realtime, ir_a);
$display(" value = 0x%h", inst_din);
`endif
if (^inst_din[63:0] === 1'bx) begin
$display("Warning: Input data has don't cares at %t",
$realtime);
error_1 <= 1;
end
`endif
if (inst_din[63:0] != ir_d[63:0]) begin
error_2 <= 1;
end
end
end
end
end
end
 
adgen adgen_ir(
.clk(clk),
.rst(rst),
.next(ir_next),
.addr(ir_a),
.data(ir_d)
);
 
assign ir_next = inst_ack;
assign inst_addr[25:0] = { 4'h0, ir_a[21:0] };
 
always @(posedge clk) begin
if (rst) begin
data_timer <= 0;
data_stb <= 0;
data_we <= 0;
data_counter <= 0;
`ifdef SIMULATE
error_3 <= 0;
`endif
error_4 <= 0;
end else begin
if (~test_ended) begin
if (~data_stb) begin
if (data_timer == `DATA_PERIOD - 1) begin
data_timer <= 0;
end else begin
data_timer <= data_timer + 1;
end
if (data_timer == `DATA_PHASE) begin
data_stb <= 1;
data_we <= ~&data_counter[1:0];
end
end else begin
if (data_ack) begin
data_stb <= 0;
data_we <= 0;
data_counter <= data_counter + 1;
`ifdef SIMULATE
`ifdef VERBOSE
if (data_we == 1) begin
$display("%t: data write @ 0x%h", $realtime, dw_a);
$display(" value = 0x%h", dw_d);
end else begin
$display("%t: data read @ 0x%h", $realtime, dr_a);
$display(" value = 0x%h", data_din);
end
`endif
if (data_we == 0 &&
^data_din[63:0] === 1'bx) begin
$display("Warning: Input data has don't cares at %t",
$realtime);
error_3 <= 1;
end
`endif
if (data_we == 0 &&
data_din[63:0] != dr_d[63:0]) begin
error_4 <= 1;
end
end
end
end
end
end
 
adgen adgen_dw(
.clk(clk),
.rst(rst),
.next(dw_next),
.addr(dw_a),
.data(dw_d)
);
 
adgen adgen_dr(
.clk(clk),
.rst(rst),
.next(dr_next),
.addr(dr_a),
.data(dr_d)
);
 
assign dw_next = data_ack & data_we;
assign dr_next = data_ack & ~data_we;
assign data_addr[25:0] = { 4'h0, data_we ? dw_a[21:0] : dr_a[21:0] };
assign data_dout[63:0] = dw_d[63:0];
 
assign test_ended = &data_counter[9:0];
 
`ifdef SIMULATE
assign test_error = error_1 | error_2 | error_3 | error_4;
`else
assign test_error = error_2 | error_4;
`endif
 
endmodule
 
 
//
// address & data generator
//
// compute pseudo-random 32-bit address
// and 64-bit data on request
//
 
module adgen(clk, rst,
next, addr, data);
input clk;
input rst;
input next;
output [21:0] addr;
output [63:0] data;
 
reg [31:0] a;
reg [63:0] d;
 
always @(posedge clk) begin
if (rst) begin
a[31: 0] <= 32'hC70337DB;
d[63:32] <= 32'h7F4D514F;
d[31: 0] <= 32'h75377599;
end else begin
if (next) begin
if (a[0] == 0) begin
a[31:0] <= a[31:0] >> 1;
end else begin
a[31:0] <= (a[31:0] >> 1) ^ 32'hD0000001;
end
if (d[32] == 0) begin
d[63:32] <= d[63:32] >> 1;
end else begin
d[63:32] <= (d[63:32] >> 1) ^ 32'hD0000001;
end
if (d[0] == 0) begin
d[31:0] <= d[31:0] >> 1;
end else begin
d[31:0] <= (d[31:0] >> 1) ^ 32'hD0000001;
end
end
end
end
 
assign addr[21:0] = a[21:0];
assign data[63:0] = d[63:0];
 
endmodule
/fpga/experiments/memctrl/sim/memctrl-1/memtest.v
0,0 → 1,101
//
// memtest.v -- test bench for memory controller
//
 
 
`include "ramtest/ramtest.v"
`include "ramctrl/ramctrl.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
module memtest;
 
reg clk; // system clock
reg clk_ok_in; // clock is stable, input
reg clk_ok; // system clock is stable
reg rst_in; // reset, input
reg rst; // system reset
 
wire inst_stb;
wire [25:0] inst_addr;
wire [63:0] inst_to_cache;
wire inst_ack;
wire inst_timeout;
 
wire data_stb;
wire data_we;
wire [25:0] data_addr;
wire [63:0] data_to_mctrl;
wire [63:0] data_to_cache;
wire data_ack;
wire data_timeout;
 
wire test_ended;
wire test_error;
 
// simulation control
initial begin
#0 $timeformat(-9, 1, " ns", 12);
$dumpfile("dump.vcd");
$dumpvars(0, memtest);
clk = 1;
clk_ok_in = 0;
rst_in = 1;
#43 clk_ok_in = 1;
#200360 rst_in = 0;
#284900 $finish;
end
 
// clock generator
always begin
#5 clk = ~clk; // 10 nsec cycle time
end
 
// clk_ok synchronizer
always @(posedge clk) begin
clk_ok <= clk_ok_in;
end
 
// reset synchronizer
always @(posedge clk) begin
rst <= rst_in;
end
 
ramctrl ramctrl_1(
.clk_ok(clk_ok),
.clk(clk),
.inst_stb(inst_stb),
.inst_addr(inst_addr[25:0]),
.inst_dout(inst_to_cache[63:0]),
.inst_ack(inst_ack),
.inst_timeout(inst_timeout),
.data_stb(data_stb),
.data_we(data_we),
.data_addr(data_addr[25:0]),
.data_din(data_to_mctrl[63:0]),
.data_dout(data_to_cache[63:0]),
.data_ack(data_ack),
.data_timeout(data_timeout)
);
 
ramtest ramtest_1(
.clk(clk),
.rst(rst),
.inst_stb(inst_stb),
.inst_addr(inst_addr[25:0]),
.inst_din(inst_to_cache[63:0]),
.inst_ack(inst_ack | inst_timeout),
.data_stb(data_stb),
.data_we(data_we),
.data_addr(data_addr[25:0]),
.data_dout(data_to_mctrl[63:0]),
.data_din(data_to_cache[63:0]),
.data_ack(data_ack | data_timeout),
.test_ended(test_ended),
.test_error(test_error)
);
 
endmodule
/fpga/experiments/memctrl/sim/memctrl-1/ramctrl/k4s561632e.v
0,0 → 1,3349
/*=============================================================================
* Copyright(c) Samsung Electronics Co., 1997,1998. All rights reseved.
*
* Verilog Behavioral Model of Synchronous 256 SDRAM
*
* Description : This is a synchrounous high data rate DRAM,
* fabricated with SAMSUNG's high performance
* CMOS technology.
*
* Revision No. : V4.5
* date : Jan. 21. 2002
*
*===============================================================================*/
 
`define M256
`define LVTTL
`define NBANK4
`define X16
`define S75
`define v
 
`ifdef LVTTL //M256+G6
`ifdef X16
`ifdef S75
`define tCCmin 7.5 // clock minimum cycle time
`define tCCmax 1000 // clock maximun cycle time
`define tCC3 7.5 // clock minimun cycle time at cas latency=3
`define tCC2 10 // clock minimun cycle time at cas latency=2
`define tCH 2.5 // clock high pulse width
`define tCL 2.5 // clock low pulse width
`define tSS 1.5 // input setup time
`define tSH 0.8 // input hold time
`define tRRD 15 // row to row delay(min)
`define tRCD 20 // ras to cas delay(min)
`define tRP 20 // row precharge time(min)
`define tRASmin 45 // row active minimum time
`define tRASmax 100000 // row active maximum time
`define tRC 65 // row cycle time(min)
`define tCCD 7.5 // col. address to col. address delay:
`define tSAC2 6
`define tSAC3 5.4
`define tSHZ2 6
`define tSHZ3 5.4
`endif //end of S75
`ifdef S60
`define tCCmin 6 // clock minimum cycle time
`define tCCmax 1000 // clock maximun cycle time
`define tCC3 6 // clock minimun cycle time at cas latency=3
`define tCH 2.5 // clock high pulse width
`define tCL 2.5 // clock low pulse width
`define tSS 1.5 // input setup time
`define tSH 1 // input hold time
`define tRRD 12 // row to row delay(min)
`define tRCD 18 // ras to cas delay(min)
`define tRP 18 // row precharge time(min)
`define tRASmin 42 // row active minimum time
`define tRASmax 100000 // row active maximum time
`define tRC 60 // row cycle time(min)
`define tCCD 6 // col. address to col. address delay:
`define tSAC3 5
`define tSHZ3 5
`endif //end of S60
`endif //end of X16
`ifdef X8
`ifdef S75
`define tCCmin 7.5 // clock minimum cycle time
`define tCCmax 1000 // clock maximun cycle time
`define tCC3 7.5 // clock minimun cycle time at cas latency=3
`define tCC2 10 // clock minimun cycle time at cas latency=2
`define tCH 2.5 // clock high pulse width
`define tCL 2.5 // clock low pulse width
`define tSS 1.5 // input setup time
`define tSH 0.8 // input hold time
`define tRRD 15 // row to row delay(min)
`define tRCD 20 // ras to cas delay(min)
`define tRP 20 // row precharge time(min)
`define tRASmin 45 // row active minimum time
`define tRASmax 100000 // row active maximum time
`define tRC 65 // row cycle time(min)
`define tCCD 7.5 // col. address to col. address delay:
`define tSAC2 6
`define tSAC3 5.4
`define tSHZ2 6
`define tSHZ3 5.4
`endif //end of S75
`endif //end of X8
`ifdef X4
`ifdef S75
`define tCCmin 7.5 // clock minimum cycle time
`define tCCmax 1000 // clock maximun cycle time
`define tCC3 7.5 // clock minimun cycle time at cas latency=3
`define tCC2 10 // clock minimun cycle time at cas latency=2
`define tCH 2.5 // clock high pulse width
`define tCL 2.5 // clock low pulse width
`define tSS 1.5 // input setup time
`define tSH 0.8 // input hold time
`define tRRD 15 // row to row delay(min)
`define tRCD 20 // ras to cas delay(min)
`define tRP 20 // row precharge time(min)
`define tRASmin 45 // row active minimum time
`define tRASmax 100000 // row active maximum time
`define tRC 65 // row cycle time(min)
`define tCCD 7.5 // col. address to col. address delay:
`define tSAC2 6
`define tSAC3 5.4
`define tSHZ2 6
`define tSHZ3 5.4
`endif //end of S75
`endif //end of X4
`endif //end of LVTTL
 
 
/*==================================================================
* Copyright(c) Samsung Electronics Co., 1997,1998. All rights reseved.
*
* Verilog Behavioral Model of Synchronous DRAM
*
* Device: - 16M SDRAM(2nd Gen., 3rd Gen., 4th Gen., 5th Gen.)
* - 64M SDRAM(2nd Gen., 3rd Gen., 4th Gen., 5th Gen.)
* - 128M SDRAM(1st Gen., 2nd Gen.,)
* - 256M SDRAM(2nd Gen.)
*
* Description : This is a synchrounous high data rate DRAM,
* fabricated with SAMSUNG's high performance
* CMOS technology.
*
* Developer : Jae-Ha Kim.
* CAE Team. Semiconductor R&D Centor.
* Semiconductor Division. Samsung Electronics Co.
*
* Revision : Yong-Cheol Bae. ( e-mail: jjbae@samsung.co.kr )
* 1.0~2.3 DRAM2 Design. Semiconductor R&D Centor.
* Semiconductor Division. Samsung Electronics Co.
* Revision : Kyung-Woo Nam. ( e-mail: aboverim@samsung.co.kr )
* 3.0~ DRAM2 Design. Semiconductor R&D Centor.
* Semiconductor Division. Samsung Electronics Co.
*==================================================================
* Revision No. : V2.3
* date : Aug. 20. 1997
* : Oct. 22. 1997
* : Jan. 15. 1998 - 16M 4Gen. & 64M 3Gen. spec update
* : Jun. 30. 1998 - 16M 4Gen. & 64M 3Gen. & 2Mx32 &
* 128M 1Gen. & 256M 2Gen. AC spec update
* : Oct. 08. 1998 - all-bank precharge revision
* bank note change: ba0=MSB,ba1=LSB @ 4banks
* : Nov. 18. 1998 - option set for verbose (e.g. +define+v )
* 128M 2Gen. AC spec added.
* conformed model through verilog-XL 2.6.27
* Revision No. : V3.0
* date : Apr. 07. 1999 - tRDL=2
* 1. parameterize auto-precharge address : ADDR_AP
* 2. divide auto-precharge process read/write
* 3. divide precharge_flag_kill process normal/read_autopre/write_autopre
* 4. generate wr_autoprecharge2 process excuting when tRDL=2
* 5. modify same-bank-autoprecharge-disable function
* (disable gapless, other bank interrupt case)
* Revision No. : V3.1
* date : May. 19. 1999
* 1. Add 16M 5th Gen. LVTTL(-10,-8,-8.7,-7,-6)
* 2. Modify 2Mx32 5th Gen. tSAC value
* Revision No. : V3.2
* date : Jun. 11. 1999
* 1. Modify -A AC parameter(64M 5th, 128M 2th, 256M 2th)
* Revision No. : V3.3
* date : Jun. 24. 1999
* 1. After 64MSD3, auto_flagx signal is not used,
* let auto_flagx be not enabled to device which is after 64MSD3
* 2. compile new versions
* verilog-xl : 2.7.17, NC-verilog : 2.1., VCS : 5.0.1a
* Revision No. : V3.4
* date : Jul. 12. 1999
* 1. To prevent roundoff error in AC parameter violation check procedure,
* define MARGIN paramter. (MARGIN=0.1ns now)
* Revision No. : V3.5
* date : Sep. 28. 1999
* 1. Warning message 'tCCmax violation' is appeared during self refresh operation.
* When self refresh or precharge-power down, clk can be don't care state. (can stay 'low' or 'high'-level)
* Therefore tCCmax violation should not be checked during self refresh or prech. power down.
* Revision No. : V3.6
* date : Dec. 14. 1999
* 1. Make MODELSIM version and add partial REF./VREFi change function for NOKIA
* Revision No. : V3.7
* date : Jul. 11. 2000
* 1. Add dynamic memory allocation function using VERILOG-XL PLI,
* then you must build verilog-XL excutable file containing PLI, and use +define+DYMEM option.
* Revision No. : V3.8
* date : Jul. 13. 2000
* 1. Add 128M SDRAM 3rd/4th Gen., 256M SDRAM 3rd Gen.
* Revision No. : V3.9
* date : Feb. 5. 2001
* 1. remove CL2 parameter at -A, -7,... when violated, error messages are printed.
* Revision No. : V4.0
* date : Jun. 11. 2001
* 1. 128M SDRAM X32 MCP (64M SDRAM X16 7th) parameter added
* Revision No. : V4.1
* date : Jun. 23. 2001
* 1. 256M SDRAM 4th parameters are added
* Revision No. : V4.2
* date : Jul. 31. 2001
* 1. because array of reg is not work at vcs 6.0, change array of reg to real variable (TRAS_PP, TPRE_P)
* Revision No. : V4.3
* date : Aug. 09. 2001
* 1. There is an error that use "<" instead of ">", in tRASmax violation check routine.
* Revision No. : V4.4
* date : Oct. 05. 2001
* 1. Add 128M Mobile SDRAM 5th Gen. (8Mx16, D-die)
* 2. Add 64M Mobile SDRAM 7th Gen. (2Mx32, F-die)
* Revision No. : V4.5
* date : Nov. 23. 2001
* 1. Add mobile function (EMRS:PASR/TCSR/DSC, DPD:pin/cmd control)
* Revision No. : V4.6
* date : Jan. 15. 2002
* 1. Add 512M SDRAM
* Revision No. : V4.6
* date : Aug. 27. 2002
* 1. Add 128M X32 SDRAM
* Revision No. : V4.7
* date : Nov. 25. 2003
* 1. Add 256M X32 SDRAM
* 2. Add 512M X32 SDRAM (DDP)
* 3. Add 512M X16 SDRAM (DDP: 2CS)
* 4. Add 1GM X4 SDRAM (DDP: 2CS)
* 5. Add 1GM X8 SDRAM (DDP: 2CS, 2CKE)
*==================================================================
*/
 
`timescale 1ns / 10ps
`default_nettype none
 
`define K1 1024
`define M1 1048576
`define BYTE 8
 
 
`ifdef CS2
`ifdef DPD_PIN
module sdram_cs2(clk, csb, cke, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
module sdram_cs2(clk, csb, cke, ba, ad, rasb, casb, web, dqm, dqi);
`endif
`else
`ifdef DPD_PIN
module sdram(clk, csb, cke, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
module sdram(clk, csb, cke, ba, ad, rasb, casb, web, dqm, dqi); //default port name
`endif
`endif
 
`ifdef M16
`define TBITS 16*`M1
`define nBank 2
`define ADDRTOP 10
`define ADDR_AP 10
`ifdef G2
`define M16G2_M641G
`else
`define M16G3_M64G2
`define M64G3_M128_M256
`endif
`endif
 
`ifdef M64
`define TBITS 64*`M1
`define ADDR_AP 10
`ifdef NBANK2
`define nBank 2
`ifdef X32
`define ADDRTOP 11
`else
`define ADDRTOP 12
`endif
`endif
`ifdef NBANK4
`define nBank 4
`ifdef X32
`define ADDRTOP 10
`else
`define ADDRTOP 11
`endif
`endif
`define M64_M128_M256 // for prech_reg
`ifdef G1
`define M16G2_M641G
`else
`ifdef G2
`define M16G3_M64G2
`else
`define M16G4_M64G3
`define M64G3_M128_M256
`endif
`endif
`endif
 
`ifdef M128
`define TBITS 128*`M1
`ifdef NBANK4
`define nBank 4
`define ADDRTOP 11
`endif
`define ADDR_AP 10
`define M64_M128_M256 // for prech_reg
`define M128_M256 // RFU, c_addr 10->11
`define M64G3_M128_M256 // from M64G3
`define M16G4_M64G3
`endif
`ifdef M256
`define TBITS 256*`M1
`define nBank 4
`ifdef X32
`define ADDRTOP 11
`else
`define ADDRTOP 12
`endif
`define ADDR_AP 10
`define M64_M128_M256 // for prech_reg
`define M128_M256 // RFU, c_addr 10->11
`define M64G3_M128_M256 // from M64G3
`define M16G4_M64G3
`endif
 
`ifdef M512
`define TBITS 512*`M1
`define nBank 4
`define ADDRTOP 12
`define ADDR_AP 10
`define M64_M128_M256 // for prech_reg
//`define M128_M256 // RFU, c_addr 10->11
`define M64G3_M128_M256 // from M64G3
`define M16G4_M64G3
`endif
 
`ifdef M1024
`define TBITS 1024*`M1
`define nBank 4
`define ADDRTOP 12
`define ADDR_AP 10
`define M64_M128_M256 // for prech_reg
//`define M128_M256 // RFU, c_addr 10->11
`define M64G3_M128_M256 // from M64G3
`define M16G4_M64G3
`endif
 
`ifdef M1024
`ifdef X4
`define M512_M1024_X4
`define B 4
`define nCOL 12
`define PAGEDEPTH 4096
`define nDQM 1
`endif
`ifdef X8
`define M512_M1024_X8
`define B 8
`define nCOL 11
`define PAGEDEPTH 2048
`define nDQM 1
`endif
`else
 
`ifdef M512
`ifdef X4
`define M512_M1024_X4
`define B 4
`define nCOL 12
`define PAGEDEPTH 4096
`define nDQM 1
`endif
`ifdef X8
`define M512_M1024_X8
`define B 8
`define nCOL 11
`define PAGEDEPTH 2048
`define nDQM 1
`endif
`ifdef X16
`define B 16
`ifdef CS2
`define nCOL 9
`define PAGEDEPTH 512
`else
`define nCOL 10
`define PAGEDEPTH 1024
`endif
`define nDQM 2
`endif
`ifdef X32
`define B 32
`define nCOL 9
`define PAGEDEPTH 512
`define nDQM 4
`endif
`else
`ifdef M256
`ifdef X4
`define M128_M256_X4 // 98.6.30 BYC
`define B 4 // number of bit(x4)
`define nCOL 11
`define PAGEDEPTH 2048
`define nDQM 1
`endif
`ifdef X8
`define B 8 // number of bit(x8)
`define nCOL 10
`define PAGEDEPTH 1024
`define nDQM 1
`endif
`ifdef X16
`define B 16 // number of bit(x16)
`define nCOL 9
`define PAGEDEPTH 512
`define nDQM 2
`endif
`ifdef X32
`define B 32 // number of bit(x32)
`define nCOL 9
`define PAGEDEPTH 512
`define nDQM 4
`endif
`else
`ifdef M128
`ifdef X4
`define M128_M256_X4 // 98.6.30 BYC
`define B 4 // number of bit(x4)
`define nCOL 11
`define PAGEDEPTH 2048
`define nDQM 1
`endif
`ifdef X8
`define B 8 // number of bit(x8)
`define nCOL 10
`define PAGEDEPTH 1024
`define nDQM 1
`endif
`ifdef X16
`define B 16 // number of bit(x16)
`define nCOL 9
`define PAGEDEPTH 512
`define nDQM 2
`endif
`ifdef X32
`define B 32 // number of bit(x32)
`define nCOL 8
`define PAGEDEPTH 256
`define nDQM 4
`endif
`else // 64M & 16M
`ifdef X4
`define B 4 // number of bit(x4)
`define nCOL 10
`define PAGEDEPTH 1024
`define nDQM 1
`endif
`ifdef X8
`define B 8 // number of bit(x8)
`define nCOL 9
`define PAGEDEPTH 512
`define nDQM 1
`endif
`ifdef X16
`define B 16 // number of bit(x16)
`define nCOL 8
`define PAGEDEPTH 256
`define nDQM 2
`endif
`ifdef X32
`define B 32 // number of bit(x32)
`define nCOL 8
`define PAGEDEPTH 256
`define nDQM 4
`endif
`endif
`endif
`endif
`endif
 
`ifdef tCC1
`else
`define NO_CL1
`endif
`ifdef tSAC1
`else
`define NO_CL1
`endif
`ifdef tSHZ1
`else
`define NO_CL1
`endif
`ifdef tCC2
`else
`define NO_CL2
`endif
`ifdef tSAC2
`else
`define NO_CL2
`endif
`ifdef tSHZ2
`else
`define NO_CL2
`endif
`ifdef tCC3
`else
`define NO_CL3
`endif
`ifdef tSAC3
`else
`define NO_CL3
`endif
`ifdef tSHZ3
`else
`define NO_CL3
`endif
 
`ifdef tRDL
`else
`define tRDL 1
`endif
 
`ifdef DPD_CMD
`define DPD
`endif
`ifdef DPD_PIN
`define DPD
`endif
 
`define HB `B/2
`define BIT `B-1:0
`define BIT_C `nCOL-1:0
`define BIT_T `nCOL+`ADDRTOP:0
`define nWORD `TBITS/`B/`nBank
`define WORD `nWORD-1:0
inout [`BIT] dqi;
input [`nBank/2-1:0] ba;
input [`ADDRTOP:0] ad;
input rasb,casb,web;
input clk,cke,csb;
input [`nDQM-1:0] dqm;
`ifdef DPD_PIN
input dpdb;
`endif
/*
`ifdef M64
`include "m64.ac"
`endif
`ifdef M16
`include "m16.ac"
`endif
`ifdef M128
`include "m128.ac"
`endif
`ifdef M256
`include "m256.ac"
`endif
*/
 
parameter pwrup_time = 200000, pwrup_check = 1;
 
wire [`nBank/2 + `ADDRTOP : 0] addr;
assign addr = {ba, ad};
 
wire [`BIT] dqi;
`ifdef DYMEM
initial begin
$damem_declare("mem_a", `B-1, 0, `nWORD-1, 0);
$damem_declare("mem_b", `B-1, 0, `nWORD-1, 0);
end
`else
reg [`BIT] mem_a[`WORD]; // memory cell array of a bank
reg [`BIT] mem_b[`WORD]; // memory cell array of b bank
`endif
`ifdef NBANK4
`ifdef DYMEM
initial begin
$damem_declare("mem_c", `B-1, 0, `nWORD-1, 0);
$damem_declare("mem_d", `B-1, 0, `nWORD-1, 0);
end
`else
reg [`BIT] mem_c[`WORD]; // memory cell array of c bank
reg [`BIT] mem_d[`WORD]; // memory cell array of d bank
`endif
`endif
 
reg [`BIT] dqo, t_dqo; // output temp. register declaration
reg [`ADDRTOP:0] r_addr_[`nBank-1:0];
reg [`ADDRTOP:0] r_addr;
reg [`BIT_C] c_addr; // column address
reg [`BIT_T] m_addr; // merge row and column address
reg [`BIT] dout_reg[`PAGEDEPTH:0];
reg [`BIT] din_rega[`PAGEDEPTH:0]; // din register for a bank
reg [`BIT] din_regb[`PAGEDEPTH:0]; // din register for b bank
`ifdef NBANK4
reg [`BIT] din_regc[`PAGEDEPTH:0]; // din register for c bank
reg [`BIT] din_regd[`PAGEDEPTH:0]; // din register for d bank
`endif
reg [`BIT] clk_dq;
reg ptr;
 
reg [`BIT] ZDATA;
reg [7:0] ZBYTE;
 
 
// define mode dependency flag
`define INITIAL 0 // no bank precharge
/*
`define IDLE_AB 1 // both bank precharge
`define ACT_A 2 // a bank active and b bank precharge
`define ACT_B 3 // b bank active and a bank precharge
`define ACT_AB 4 // a & b bank active
`define IDLE_A 5 // only a bank prechage
`define IDLE_B 6 // only b bank prechage
*/
 
`define TRUE 1
`define FALSE 0
`define HIGH 1
`define LOW 0
`define MARGIN 0.1
 
//parameter pwrup_time = 200000, pwrup_check = 1;
 
/*
*-----------------------------------------------------
* We know the phase of external signal
* by examining the state of its flag.
*-----------------------------------------------------
*/
 
reg r_bank_addr; // row bank check flag
reg [`nBank/2-1:0] c_bank_addr; // column bank check flag
reg [`nBank-1:0] auto_flag; // auto precharge flag
reg burst_type, // burst type flag
auto_flagx,
self_flag; // auto & self refresh flag
integer kill_bank, wr_kill_bank, rd_kill_bank;
integer k;
reg [`nBank-1:0] precharge_flag; // precharge each bank check flag
reg [`nBank/2:0] prech_reg; // precharge mode (addr[13:12] && addr[10])
reg [`nBank/2-1:0] rd_autoprech_reg;
reg [`nBank/2-1:0] wr_autoprech_reg;
reg [`nBank/2-1:0] wr_autoprech_reg2;
reg [`nBank/2-1:0] prev_ba; // bank address of previous command
reg pwrup_done;
reg [`nBank-1 : 0] first_pre;
//reg [8*8 : 1] str;
integer auto_cnt;
integer i;
 
`ifdef M16
wire [3:0] RFU = {addr[11:10], addr[8], addr[7]};
`endif
 
`ifdef M64
`ifdef NBANK2
wire [3:0] RFU = {addr[11:10], addr[8], addr[7]};
`endif
`ifdef NBANK4
`ifdef X32
wire [4:0] RFU = {addr[12:10], addr[8], addr[7]};
`else
wire [5:0] RFU = {addr[13:10], addr[8], addr[7]};
`endif
`endif
`endif
 
`ifdef M128
`ifdef NBANK4
wire [5:0] RFU = {addr[13:10], addr[8], addr[7]};
`endif
`endif
 
`ifdef M256
`ifdef X32
wire [5:0] RFU = {addr[13:10], addr[8], addr[7]};
`else
wire [6:0] RFU = {addr[14:10], addr[8], addr[7]};
`endif
`endif
 
`ifdef M512 // 98.6.30 BYC
wire [6:0] RFU = {addr[14:10], addr[8], addr[7]};
`endif
 
`ifdef M1024
wire [6:0] RFU = {addr[14:10], addr[8], addr[7]};
`endif
 
reg [`nBank-1:0] Mode; // check mode dependency
reg [`nBank-1:0] md;
reg rd_reautoprecharge, wr_reautoprecharge;
`ifdef NOKIA
reg REF16M_MODE, REF32M_MODE;
`endif
`ifdef DPD
`define tDPDEXIT 200000
reg D_POWERDOWN, D_PDOWN_EXIT;
integer PROC_DPDEXIT;
`endif
`ifdef MOBILE
reg REF4BANK, REF2BANK, REF1BANK;
`endif
integer BL, WBL, CL; // burst length & cas latency
real tSHZ; // clk to output in hi-Z
real tSAC; // clk to valid output
reg write_event;//KyW ... 0408 for VCS
 
event
active, // main operation of SDRAM
modeset,
read,
dqo_event,
write,
flush_write,
precharge,
rd_autoprecharge,
wr_autoprecharge,
wr_autoprecharge2,
precharge_start,
precharge_flag_kill,
wr_precharge_flag_kill,
rd_precharge_flag_kill,
autorefresh,
autostart,
selfrefresh,
`ifdef DPD
deeppowerdown,
d_pdown_exit,
`endif
selfexit;
 
`protect
 
// initialize each flag
initial
begin
for (i = 0; i < `nBank; i = i + 1)
auto_flag[i] = `FALSE;
auto_flagx = `FALSE;
rd_reautoprecharge =`FALSE;
wr_reautoprecharge =`FALSE;
self_flag = `FALSE;
pwrup_done = `FALSE;
Mode = `nBank'b0;
 
for(i = 0; i < `nBank; i = i + 1)
begin
first_pre[i] = `TRUE;
precharge_flag[i] = `FALSE;
end
 
ZBYTE = 8'bz;
for (i = 0; i < `B; i = i + 1) begin
ZDATA[i] = 1'bz;
end
end
 
//--------------------------------------------------------------
//--------- TIMING VIOLATION CHECK ROUTINE
//--------------------------------------------------------------
 
real CUR_TIME, TCKE, TADDR, TRASB, TCASB, TCSB, TWEB, TDQI, TCLK_H, TCLK_L,
TCC_P, pclk_high, last_read, last_rw;
 
reg [63:0] TDQM[`nDQM-1:0];
 
//real TRAS_P, TCAS_P, TRASA_P, TRASB_P, TPREA_P, TPREB_P, TSELF, TSEXIT;
// 4 bank
real TRAS_P, TCAS_P, TSELF, TSEXIT;
//reg [63:0] TRAS_PP [`nBank-1:0];
//reg [63:0] TPRE_P [`nBank-1:0];
real TRAS_PP0, TRAS_PP1, TRAS_PP2, TRAS_PP3;
real TPRE_P0, TPRE_P1, TPRE_P2, TPRE_P3;
 
reg CKE_FLAG, CSB_FLAG, RASB_FLAG, CASB_FLAG, WEB_FLAG;
 
//event MRS, ACTIVE;
reg MRS_SET, WRITE_MODE, READ_MODE, UNMODE, POWERDOWN_MODE, POWERDOWN_MODE1,//KyW ... 0928 for NOKIA claim
SUSPEND_MODE, AUTOREF_MODE, SELFREF_MODE;
reg PWR, INIT;
 
 
`define NOP (RASB_FLAG == `HIGH && CASB_FLAG == `HIGH && WEB_FLAG == `HIGH)
`define NOP1 (RASB_FLAG == `HIGH && CASB_FLAG == `HIGH)
/*
*-----------------------------------------------------
* wire declaration
*-----------------------------------------------------
*/
 
reg pcke;
reg [`nDQM-1:0] dqm_r;
reg [`nDQM-1:0] dqm_ri;
 
reg data_read;
reg tdata_read;
reg [`BIT] clkh_dq;
reg [2:0] prev_com;
reg rw_dqm;
reg gapless;
wire pclk = pcke & clk;
wire [2:0] com = {RASB_FLAG, CASB_FLAG, WEB_FLAG};
wire #(TCC_P+0.02) data_read_delay = data_read; // 98.6.29 BYC
`endprotect
 
`ifdef X32
assign #(tSAC, tSAC, tSHZ) dqi[`B-1:`B-8]= ( data_read & ~dqm_r[3] & ~rw_dqm)?dqo[`B-1:`B-8]:ZBYTE;
assign #(tSAC, tSAC, tSHZ) dqi[`B-9:`B-16] = ( data_read & ~dqm_r[2] & ~rw_dqm)?dqo[`B-9:`B-16]:ZBYTE;
assign #(tSAC, tSAC, tSHZ) dqi[`B-17:`B-24]= ( data_read & ~dqm_r[1] & ~rw_dqm)?dqo[`B-17:`B-24]:ZBYTE;
assign #(tSAC, tSAC, tSHZ) dqi[`B-25:0] = ( data_read & ~dqm_r[0] & ~rw_dqm)?dqo[`B-25:0]:ZBYTE;
`endif
`ifdef X16
assign #(tSAC, tSAC, tSHZ) dqi[`B-1:`B-8]= ( data_read & ~dqm_r[1] & ~rw_dqm)?dqo[`B-1:`B-8]:ZBYTE;
assign #(tSAC, tSAC, tSHZ) dqi[`HB-1:0] = ( data_read & ~dqm_r[0] & ~rw_dqm)?dqo[`B-9:0]:ZBYTE;
`endif
`ifdef X8
assign #(tSAC, tSAC, tSHZ) dqi[`B-1:0] = ( data_read & ~dqm_r & ~rw_dqm)?dqo[`B-1:0]:ZDATA;
`endif
`ifdef X4
assign #(tSAC, tSAC, tSHZ) dqi[`B-1:0] = ( data_read & ~dqm_r & ~rw_dqm)?dqo[`B-1:0]:ZDATA;
`endif
 
`protect
always @(posedge pclk) begin
pclk_high <= #0.01 $realtime;
clkh_dq <= #0.01 dqi;
end
 
 
always @(READ_MODE) begin
// data_read <= repeat(CL-1) @(posedge pclk) READ_MODE;
// VCS does not support above statement. However Verilog-XL is OK.
// So, I modified as following statement for VCS.
#0.1;
if (READ_MODE == 1'b1)
data_read <= repeat(CL-1) @(posedge pclk) 1'b1;
else
data_read <= repeat(CL-1) @(posedge pclk) 1'b0;
end
 
always @(negedge tdata_read) begin
data_read = tdata_read;
tdata_read = `TRUE;
end
 
always @(dqo_event)
dqo <= repeat(CL-1) @(posedge pclk) t_dqo;
 
/*
*-----------------------------------------------------
* setup hold check
*-----------------------------------------------------
*/
 
initial #0.01 pcke = cke;
 
initial // time variables initialization
begin
$timeformat(-9, 1, " ns", 10);
TCKE = 0;
TADDR = 0;
TRASB = 0;
TCASB = 0;
TCSB = 0;
TWEB = 0;
TDQI = 0;
TCLK_H = -20;
TCLK_L = -20;
TRAS_P = -200;
TCAS_P = -200;
TSELF = -200;
pclk_high = -20;
last_read = -200;
last_rw = -20;
for (i = 0; i < `nDQM; i = i + 1)
TDQM[i] = 64'b0;
// 4bank
//TRAS_PP[0] = -200;
//TRAS_PP[1] = -200;
//TPRE_P[0] = -200;
//TPRE_P[1] = -200;
TRAS_PP0 = -200;
TRAS_PP1 = -200;
TPRE_P0 = -200;
TPRE_P1 = -200;
`ifdef NBANK4
//TRAS_PP[2] = -200;
//TRAS_PP[3] = -200;
//TPRE_P[2] = -200;
//TPRE_P[3] = -200;
TRAS_PP2 = -200;
TRAS_PP3 = -200;
TPRE_P2 = -200;
TPRE_P3 = -200;
`endif
 
end
 
initial // mode register variables initialization
begin
RASB_FLAG = `HIGH;
CASB_FLAG = `HIGH;
CSB_FLAG = `HIGH;
WEB_FLAG = `HIGH;
end
 
initial // mode register variables initialization
begin
INIT = `TRUE;
MRS_SET = `FALSE;
WRITE_MODE = `FALSE;
READ_MODE = `FALSE;
POWERDOWN_MODE = `FALSE;
POWERDOWN_MODE1 = `FALSE;//KyW ... 0928 for NOKIA claim
SUSPEND_MODE = `FALSE;
AUTOREF_MODE = `FALSE;
SELFREF_MODE = `FALSE;
`ifdef NOKIA
REF16M_MODE = `FALSE;
REF32M_MODE = `FALSE;
`endif
`ifdef MOBILE
REF4BANK = `TRUE;
REF2BANK = `FALSE;
REF1BANK = `FALSE;
`endif
`ifdef DPD
D_POWERDOWN = `FALSE;
D_PDOWN_EXIT = `FALSE;
PROC_DPDEXIT = 0;
`endif
write_event = `FALSE; //KyW ... 0408 for VCS
end
 
always @(POWERDOWN_MODE) POWERDOWN_MODE1 = #0.1 POWERDOWN_MODE;//KyW ... 0928 for NOKIA claim
 
always @( posedge clk )
if( PWR == `TRUE )
begin : main
CUR_TIME = $realtime;
 
if( POWERDOWN_MODE == `TRUE && CKE_FLAG == `TRUE )
begin
if( SELFREF_MODE == `TRUE )
begin
if( CUR_TIME - TSELF < `tRASmin-`MARGIN )
begin
$display("Warning: tRAS violation in self refresh at %t", CUR_TIME);
end
->selfexit;
`ifdef v $display(">> self refresh exit at %t", CUR_TIME);
`endif
`ifdef v // $display(">> power down exit at %t", CUR_TIME);
`endif
POWERDOWN_MODE = `FALSE;
CKE_FLAG = `FALSE;
`endprotect
`ifdef M16G2_M641G
pcke <= repeat (1) @(negedge pclk) cke;
`else
#0 pcke = cke;
`endif
end
`ifdef DPD
else if (D_POWERDOWN == `TRUE)
begin
->d_pdown_exit;
`ifdef v $display(">> deep power down exit at %t", CUR_TIME);
`endif
POWERDOWN_MODE = `FALSE;
CKE_FLAG = `FALSE;
end
`endif
else
begin
`ifdef M16G2_M641G
if (CUR_TIME - TCKE >= `tPDE-`MARGIN)
`else
if( CUR_TIME - TCKE >= `tSS-`MARGIN )
`endif
begin
`ifdef v $display(">> power down exit at %t", CUR_TIME);
`endif
POWERDOWN_MODE = `FALSE;
CKE_FLAG = `FALSE;
pcke <= repeat (1) @(negedge pclk) cke;
end
else
begin
`ifdef M16G2_M641G
$display("Warning: tPDE violation at %t", CUR_TIME);
`else
$display("Warning: tSS Precharge Power Down Exit Setup Violation at %t",CUR_TIME);
`endif
disable main;
end
end
end
 
if( POWERDOWN_MODE == `FALSE)
begin
if( CUR_TIME - TCKE < `tSS-`MARGIN ) // check cke setup timing
$display("Warning: CKE setup violation at %t", CUR_TIME);
else if( cke && SUSPEND_MODE == `TRUE )
begin
`ifdef v $display(">> clock suspension exit at %t", CUR_TIME);
`endif
SUSPEND_MODE = `FALSE;
pcke <= @(negedge clk) cke;
end
else
pcke <= @(negedge clk) cke;
end
 
// clock timing check
 
TCC_P = CUR_TIME - TCLK_H; // saving current clock period
 
if( CUR_TIME - TCLK_H < `tCCmin-`MARGIN && POWERDOWN_MODE1 == `FALSE)//KyW ... 0928 for NOKIA claim
$display("Warning: tCCmin violation at %t", CUR_TIME);
 
if( CUR_TIME - TCLK_H > `tCCmax+`MARGIN && POWERDOWN_MODE1 == `FALSE)//KyW ... 0928 for NOKIA claim
$display("Warning: tCCmax violation at %t", CUR_TIME);
`protect
if( CUR_TIME - TCLK_L < `tCL-`MARGIN )
$display("Warning: tCL violation at %t", CUR_TIME);
 
// pcke is high
if( pcke ) begin
 
// csb timing check
if( CUR_TIME - TCSB < `tSS-`MARGIN )
$display("Warning: CSB setup violation at %t", CUR_TIME);
else // if( CUR_TIME - TCSB < `tCCmin + `tSS-`MARGIN )
CSB_FLAG = csb;
 
// if chip selected
if( CSB_FLAG == `LOW )
begin
if( CUR_TIME - TRASB < `tSS-`MARGIN )
$display("Warning: RASB setup violation at %t", CUR_TIME);
else
RASB_FLAG = rasb;
 
if( CUR_TIME - TCASB < `tSS-`MARGIN )
$display("Warning: CASB setup violation at %t", CUR_TIME);
else
CASB_FLAG = casb;
if( CUR_TIME - TWEB < `tSS-`MARGIN )
$display("Warning: WEB setup violation at %t", CUR_TIME);
else
WEB_FLAG = web;
 
end
for (i = 0; i < `nDQM; i = i + 1) begin
if( CUR_TIME - $bitstoreal(TDQM[i]) < `tSS-`MARGIN )
$display("Warning: DQM(%d) setup violation at %t", i, CUR_TIME);
else begin
// dqm_r[i] <= @(posedge pclk) dqm[i];
// VCS does not support above statement. However Verilog-XL is OK.
// So, I modified as following statement for VCS.
dqm_r[i] <= dqm_ri[i];
dqm_ri[i] <= dqm[i];
end
end
end
 
TCLK_H = CUR_TIME; // the time clock is high
 
end
 
/*------------------------------------------
* command recognition
*------------------------------------------
*/
 
always @( posedge pclk )
if( PWR == `TRUE )
begin : command
integer bank_id;
reg [8*8:1] str;
 
if( CSB_FLAG == `LOW )
begin : command_sel
if( auto_cnt == -1 )
begin
if( ~ `NOP ) // NOP1 -> NOP because of burst stop
$display("Warning: NOP required during power-up pause time.");
disable command_sel;
end
 
if( CUR_TIME - TADDR < `tSS-`MARGIN )
$display("Warning: Address setup violation at %t", CUR_TIME);
 
if( `NOP ) // deleted by burst stop -> NOP1 -> NOP
disable command_sel;
 
if( AUTOREF_MODE == `TRUE || SELFREF_MODE == `TRUE )
begin
$display("Warning: Illegal command in refresh operation at %t", CUR_TIME);
disable command_sel;
end
`ifdef DPD
if (D_POWERDOWN == `TRUE) begin
$display("Warning: Illegal command in deep power down exit at %t", CUR_TIME);
disable command_sel;
end
if (D_PDOWN_EXIT) begin
if (PROC_DPDEXIT == 0) begin
if ({RASB_FLAG,CASB_FLAG,WEB_FLAG} == 3'b010) begin
`ifdef M64_M128_M256
`ifdef NBANK2
prech_reg[1] = ba;
prech_reg[0] = addr[`ADDR_AP];
`endif
`ifdef NBANK4
prech_reg[2] = ba[1];
prech_reg[1] = ba[0];
prech_reg[0] = addr[`ADDR_AP];
`endif
`endif
PROC_DPDEXIT = 1;
->precharge;
end
else $display("Warning: all bank precharge required to complete deep power down mode exit.");
end
else if (PROC_DPDEXIT == 1 || PROC_DPDEXIT == 2) begin
if ({cke,RASB_FLAG,CASB_FLAG,WEB_FLAG} == 4'b1001) begin
PROC_DPDEXIT = PROC_DPDEXIT + 1;
->autorefresh;
end
else $display("Warning: 2 or more auto refresh required to complete deep power down mode exit.");
end
else if (PROC_DPDEXIT == 3) begin
if ({RASB_FLAG,CASB_FLAG,WEB_FLAG} == 3'b000) begin
D_PDOWN_EXIT = `FALSE;
PROC_DPDEXIT = 0;
->modeset;
end
else if ({cke,RASB_FLAG,CASB_FLAG,WEB_FLAG} == 4'b1001) begin
->autorefresh;
end
else $display("Warning: Mode register set required to complete deep power down mode exit.");
end
end
`endif
if( ~pwrup_done )
if( auto_cnt < 2 )
begin
case ( {RASB_FLAG,CASB_FLAG,WEB_FLAG} )
'b010 :
begin
`ifdef M64_M128_M256
`ifdef NBANK2
prech_reg[1] = ba;
prech_reg[0] = addr[`ADDR_AP];
`endif
`ifdef NBANK4
prech_reg[2] = ba[1];
prech_reg[1] = ba[0];
prech_reg[0] = addr[`ADDR_AP];
`endif
`endif
`ifdef M16
prech_reg = addr[11:10];
`endif
->precharge;
end
'b001 :
if( cke )
begin
auto_cnt = auto_cnt + 1;
->autorefresh;
end
'b000 :
begin
if( MRS_SET == `TRUE )
->modeset;
else if( INIT == `TRUE )
begin
->modeset;
INIT = `FALSE;
end
else
$display("Warning: MODE register set need 2 clock cycles at %t", CUR_TIME);
end
default: begin
$display("Warning: 2 or more auto-refresh required during power up sequence.");
end
endcase
disable command_sel;
end
else
pwrup_done = `TRUE;
 
case( {RASB_FLAG,CASB_FLAG,WEB_FLAG} )
'b000 :
begin
if( MRS_SET == `TRUE )
->modeset;
else if( INIT == `TRUE )
begin
->modeset;
INIT = `FALSE;
end
else
$display("Warning: MODE register set need 2 clock cycles at %t", CUR_TIME);
end
'b011 : // active
begin
if( MRS_SET == `TRUE )
begin
bank_id = BankSelect(ba);
str = PrintBank(ba);
if(Mode[bank_id] == `TRUE)
$display("Warning: Illegal active (%0s is not precharged) at %t",str,CUR_TIME);
 
else
->active;
end
 
else if( INIT == `FALSE )
$display("Warning: MODE register set need 2 clock cycles at %t",CUR_TIME);
else if( INIT == `TRUE )
$display("Warning: Initial MODE register set must be required before active at %t",CUR_TIME);
end
`endprotect
'b101 :
begin // read command
bank_id = BankSelect(ba);
str = PrintBank(ba);
gapless = (pclk_high == last_rw && auto_flag[bank_id]) ?
`TRUE : `FALSE;
`ifdef M16G4_M64G3
if (precharge_flag[bank_id])
begin
$display("Warning: Illegal command in precharge operation at %t",CUR_TIME);
disable command_sel;
end
`else
if( auto_flagx )
begin
$display("Warning: Illegal command in auto-precharge command at %t",CUR_TIME);
disable command_sel;
end
`endif
else if( Mode[bank_id] == `TRUE)
begin
if( READ_MODE == `TRUE)
begin
`ifdef M64G3_M128_M256
if (auto_flag[prev_ba] == `TRUE && prev_ba != bank_id) begin
rd_autoprech_reg = prev_ba;
->rd_autoprecharge;
end
`endif
READ_MODE = `FALSE;
#0 disable read_block;
end
if( WRITE_MODE == `TRUE)
begin
`ifdef M64G3_M128_M256
if (auto_flag[prev_ba] == `TRUE && prev_ba != bank_id) begin
//`ifdef RDL2
if (`tRDL == 2) begin
wr_autoprech_reg2 = prev_ba;
->wr_autoprecharge2;
end
//`else
else begin
wr_autoprech_reg = prev_ba;
->wr_autoprecharge;
end
//`endif
end
`endif
WRITE_MODE = `FALSE;
disable write_block;
end
last_read = CUR_TIME;
prev_com = {RASB_FLAG,CASB_FLAG,WEB_FLAG};
prev_ba = ba;
rw_dqm <= `FALSE;
#0 ->read;
end
 
else
$display("Warning: Illegal read (%0s is not active) at %t",str,CUR_TIME);
end
'b100 :
begin // write command
bank_id = BankSelect(ba);
str = PrintBank(ba);
if (prev_com == 3'b101) begin
if (clkh_dq !== `B'bz && data_read_delay == 1'b1) // 98.6.29 BYC
$display("Warning: HIZ should be issued 1 cycle before write op at %t", CUR_TIME);
end
`ifdef M16G2_M641G
`else
gapless = (pclk_high == last_rw && auto_flag[bank_id])
? `TRUE : `FALSE;
`endif
`ifdef M16G4_M64G3
if (precharge_flag[bank_id])
begin
$display("Warning: Illegal command in precharge operation at %t",CUR_TIME);
disable command_sel;
end
`else
if( auto_flagx )
begin
$display("Warning: Illegal command in auto-precharge command at %t",CUR_TIME);
disable command_sel;
end
`endif
`protect
else if( Mode[bank_id] == `TRUE)
begin
if( READ_MODE == `TRUE )
begin
`ifdef M64G3_M128_M256
if (auto_flag[prev_ba] == `TRUE && prev_ba != bank_id) begin
rd_autoprech_reg = prev_ba;
->rd_autoprecharge;
end
`endif
READ_MODE = `FALSE;
tdata_read <= @(posedge pclk) READ_MODE; // 3.2
#0 disable read_block;
end
if( WRITE_MODE == `TRUE )
begin
`ifdef M64G3_M128_M256
if (auto_flag[prev_ba] == `TRUE && prev_ba != bank_id) begin
//`ifdef RDL2
if (`tRDL == 2) begin
wr_autoprech_reg2 = prev_ba;
->wr_autoprecharge2;
end
//`else
else begin
wr_autoprech_reg = prev_ba;
->wr_autoprecharge;
end
//`endif
end
`endif
WRITE_MODE = `FALSE;
disable write_block;
end
if( |dqm === 1'b0 ) begin // 98.6.26 BYC
if( CUR_TIME - TDQI < `tSS-`MARGIN )
$display("Warning: DQi setup violation at %t", CUR_TIME);
end
prev_com = {RASB_FLAG,CASB_FLAG,WEB_FLAG};
prev_ba = ba;
if (pclk_high == last_read)
rw_dqm <= @(negedge pclk) `TRUE;
//#0 ->write;
write_event <= `TRUE; //KyW ... 0408 for VCS
write_event <= #0.1 `FALSE; //KyW ... 0408 for VCS
end
else
$display("Warning: Illegal write ( %0s is not active) at %t",str,CUR_TIME);
end
'b110 : // burst stop
`ifdef DPD
if( cke === 1'b0 )
->deeppowerdown;
else if (cke === 1'b1)
`endif
begin
`ifdef v $display ("Burst stop");
`endif
 
 
if( READ_MODE == `TRUE )
begin
READ_MODE = `FALSE;
`ifdef v $display("-- reading burst stop at %t", CUR_TIME);
`endif
disable read_block;
end
else if( WRITE_MODE == `TRUE)
begin
// at this clock, writing done
`ifdef v $display("-- writing burst stop at %t", CUR_TIME);
`endif
`ifdef M16G2_M641G
WRITE_MODE = @(negedge pclk) `FALSE;
`else
WRITE_MODE = `FALSE;
`endif
disable write_block;
end
prev_com = {RASB_FLAG,CASB_FLAG,WEB_FLAG};
end
'b010 :
begin
`endprotect
`ifdef M16G4_M64G3 //KyW ... 0624 : rev 3.3
`else
if(auto_flagx == `TRUE && (addr[`ADDR_AP] || ba == c_bank_addr))
begin
$display("Warning: Illegal command in auto-precharge command at %t",CUR_TIME);
disable command_sel;
end
`endif
`ifdef M64_M128_M256
`ifdef NBANK2
prech_reg[1] = ba;
prech_reg[0] = addr[`ADDR_AP];
`endif
`ifdef NBANK4
prech_reg[2] = ba[1];
prech_reg[1] = ba[0];
prech_reg[0] = addr[`ADDR_AP];
`endif
`endif
`ifdef M16
prech_reg = addr[11:10];
`endif
->precharge;
end
`protect
'b001 : begin
if( cke )
->autorefresh;
else if( ~cke )
->selfrefresh;
end
// default :
`ifdef v // $display("- NOP");
`endif
endcase
end // command_sel
 
// TCLK_H = CUR_TIME; // the time clock is high
end
 
`ifdef DPD_PIN
always @(negedge dpdb)
if (dpdb === 1'b0) ->deeppowerdown;
else begin
`ifdef v $display("Warning: Invalid dpdb pin state at %t", CUR_TIME);
`endif
end
always @(posedge dpdb)
if (dpdb === 1'b1) begin
if (D_POWERDOWN == `TRUE)
begin
->d_pdown_exit;
`ifdef v $display(">> deep power down exit at %t", CUR_TIME);
`endif
POWERDOWN_MODE = `FALSE;
CKE_FLAG = `FALSE;
end
end
else begin
`ifdef v $display("Warning: Invalid dpdb pin state at %t", CUR_TIME);
`endif
end
`endif
 
// power down or supend enter mode
always @( posedge pclk )
if( POWERDOWN_MODE == `FALSE && cke == `LOW && CUR_TIME - TCKE >= `tSS-`MARGIN )
begin
if( |Mode == 1'b0 ) //BYC
begin
`ifdef v $display(">> power down enter at %t",CUR_TIME);
`endif
POWERDOWN_MODE = `TRUE;
end
else
begin
`ifdef v $display(">> clock suspension enter at %t",CUR_TIME);
`endif
SUSPEND_MODE = `TRUE;
end
end
 
// clock width check
always @( negedge clk )
if( PWR == `TRUE )
begin
CUR_TIME = $realtime;
if( CUR_TIME - TCLK_H < `tCH-`MARGIN )
$display("Warning: tCH violation at %t", CUR_TIME);
TCLK_L = CUR_TIME;
end
 
// hold time check
always @(cke)
begin
CUR_TIME = $realtime;
if( PWR == `TRUE )
if( POWERDOWN_MODE == `FALSE && CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: CKE hold violation at %t", CUR_TIME);
else if( POWERDOWN_MODE == `TRUE && cke == `HIGH )
CKE_FLAG = `TRUE;
 
TCKE = CUR_TIME;
end
 
 
always @(addr) //posedge addr or negedge addr )
begin
CUR_TIME = $realtime;
if( PWR == `TRUE && CSB_FLAG == `LOW && pcke == `HIGH )
if( CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: Address hold violation at %t", CUR_TIME);
TADDR = CUR_TIME;
end
 
always @( negedge rasb or posedge rasb)
begin
CUR_TIME = $realtime;
if( PWR == `TRUE && CSB_FLAG == `LOW )
if( pcke == `HIGH && CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: RASB hold violation at %t", CUR_TIME);
if(rasb)
RASB_FLAG = `HIGH;
TRASB = CUR_TIME;
end
 
always @( negedge casb or posedge casb)
begin
CUR_TIME = $realtime;
if( PWR == `TRUE && CSB_FLAG == `LOW )
if( pcke == `HIGH && CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: CASB hold violation at %t", CUR_TIME);
if(casb)
CASB_FLAG = `HIGH;
TCASB = CUR_TIME;
end
 
always @( negedge csb or posedge csb)
begin
CUR_TIME = $realtime;
if( csb )
CSB_FLAG <= #(CUR_TIME - TCLK_H + `tSH) csb;
if( PWR == `TRUE && pcke == `HIGH && CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: CSB hold violation at %t", CUR_TIME);
TCSB = CUR_TIME;
end
 
always @( negedge web or posedge web)
begin
CUR_TIME = $realtime;
if( PWR == `TRUE && CSB_FLAG == `LOW )
if( pcke == `HIGH && CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: WEB hold violation at %t", CUR_TIME);
if(web)
WEB_FLAG = `HIGH;
else
WEB_FLAG = `LOW;
TWEB = CUR_TIME;
end
 
always @(dqi)
begin
if( WRITE_MODE )
begin
CUR_TIME = $realtime;
if( CUR_TIME - TCLK_H < `tSH-`MARGIN )
$display("Warning: DQi hold violation at %t", CUR_TIME);
end
TDQI = $realtime;
end
 
always @(dqm) begin
CUR_TIME = $realtime;
if (PWR == `TRUE)
for (i = 0; i < `nDQM; i = i + 1) begin
if (CUR_TIME - TCLK_H < `tSH-`MARGIN && pcke == `HIGH)
$display("Warning: DQM(%d) hold violation at %t", i, CUR_TIME);
TDQM[i] = $realtobits(CUR_TIME);
end
end
 
 
/*
*-----------------------------------------------------
* power up check routine
*-----------------------------------------------------
*/
 
initial
begin
auto_cnt = -1;
PWR = `FALSE;
if(pwrup_check)
fork
@(posedge clk or negedge clk) PWR <= #0 `TRUE;
begin
#pwrup_time auto_cnt = 0;
Mode = `INITIAL;
end
join
else
begin
@(posedge clk or negedge clk);
auto_cnt = 2;
pwrup_done = `TRUE;
PWR <= #0 `TRUE;
`ifdef v $display("-- power up check routine skipped");
`endif
end
end
 
/*
*-----------------------------------------------------
* MRS(mode register set)
*-----------------------------------------------------
*/
 
always @(modeset)
begin : mrs_op
if( &precharge_flag == 1'b1)
begin
$display("Warning: Illegal command in precharge operation at %t", CUR_TIME);
disable mrs_op;
end
 
if (|Mode == 1'b0)
$display(">> MODE register set at %t", CUR_TIME);
else
begin
$display("Warning: Illegal MRS command at %t",CUR_TIME);
disable mrs_op;
end
 
// mode initialization
MRS_SET = `FALSE;
 
begin
if(~|RFU)
begin // {
case(addr[2:0]) // burst length programming
3'b000:begin
BL = 1;
WBL = 1;
$display("-- burst length = 1");
end
3'b001:begin
BL = 2;
WBL = 2;
$display("-- burst length = 2");
end
3'b010:begin
BL = 4;
WBL = 4;
$display("-- burst length = 4");
end
3'b011:begin
BL = 8;
WBL = 8;
$display("-- burst length = 8");
end
3'b111:begin // added
BL = `PAGEDEPTH;
WBL = `PAGEDEPTH;
$display("-- burst length = %d", `PAGEDEPTH);
end
default $display("Warning: Invalid Burst length!");
endcase
`endprotect
if(addr[3] && BL != `PAGEDEPTH) // burst type programming
begin
burst_type = 1'b1;
$display("-- burst type = interleave.");
end
else
begin
`ifdef M16G4_M64G3 // jhkim(8.14)
if (addr[3] && BL == `PAGEDEPTH) begin
$display("Warning: interleave mode does not support Full page Mode");
$display(" interleave mode will be changed to sequential mode");
end
`endif
burst_type = 1'b0;
$display("-- burst type = sequential.");
end
case(addr[6:4]) // CAS latency programming
3'b001:begin
`ifdef NO_CL1
$display("Warning: cas latency 1 is not supported in 16M 4Gen. & 64M 3 Gen.");
`else
tSAC = `tSAC1; CL=1; tSHZ = `tSHZ1;
if( TCC_P < `tCC1-`MARGIN )
$display("Warning: clock minimun cycle violation at cas latency=1");
$display("-- cas latency = 1");
`endif
end
3'b010:begin
`ifdef NO_CL2 //KyW
$display("Warning: cas latency 2 is not supported in this device.");
`else
tSAC = `tSAC2; CL=2; tSHZ = `tSHZ2;
if( TCC_P < `tCC2-`MARGIN )
$display("Warning: clock minimun cycle violation at cas latency=2");
$display("-- cas latency = 2");
`endif
end
3'b011:begin
`ifdef NO_CL3 //KyW
$display("Warning: cas latency 3 is not supported in this device.");
`else
tSAC = `tSAC3; CL=3; tSHZ = `tSHZ3;
if( TCC_P < `tCC3-`MARGIN )
$display("Warning: clock minimun cycle violation at cas latency=3");
$display("-- cas latency = 3");
`endif
end
default $display("Warning: Invalid CAS latency!");
endcase
if(addr[9])
begin
$display("-- Burst read single bit write mode");
WBL = 1;
end
`ifdef NOKIA
REF16M_MODE = `FALSE;
REF32M_MODE = `FALSE;
`endif
`ifdef MOBILE
REF4BANK = `TRUE;
REF2BANK = `FALSE;
REF1BANK = `FALSE;
`endif
end
`ifdef NOKIA
else if (addr[8:7] === 2'b01) begin
if (addr[6:4] === 3'b000) begin
if (addr[3] === 1'b0) begin
$display("-- Partial Refresh mode (16M)");
REF16M_MODE = `TRUE;
REF32M_MODE = `FALSE;
end
else if (addr[3] === 1'b1) begin
$display("-- Partial Refresh mode (32M)");
REF32M_MODE = `TRUE;
REF16M_MODE = `FALSE;
end
end
else if (addr[4] === 1'b1) begin
if (addr[2] === 1'b0) $display("-- VREFi is set to 1.4V");
if (addr[2] === 1'b1) $display("-- VREFi is set to 0.9V");
end
end
`endif
`ifdef MOBILE
else if (ba[1] === 1'b1 && ba[0] === 1'b0) begin //Extended MRS for Mobile DRAM
case(addr[6:5]) // Drive Strength
2'b00:
$display("-- Full drive strength");
2'b01:
$display("-- Half drive strength");
default $display("Warning: Invalid drive strength address!");
endcase
case(addr[4:3]) // TCSR
2'b00:
$display("-- TCSR (46'C~70'C) mode");
2'b01:
$display("-- TCSR (16'C~45'C) mode");
2'b10:
$display("-- TCSR (-25'C~15'C) mode");
2'b11:
$display("-- TCSR (71'C~85'C) mode");
default $display("Warning: Invalid TCSR address!");
endcase
case(addr[2:0]) // PASR
3'b000: begin
$display("-- PASR (4 banks) mode");
REF4BANK = `TRUE;
REF2BANK = `FALSE;
REF1BANK = `FALSE;
end
3'b001: begin
$display("-- PASR (2 banks) mode");
REF4BANK = `FALSE;
REF2BANK = `TRUE;
REF1BANK = `FALSE;
end
3'b010: begin
$display("-- PASR (1 banks) mode");
REF4BANK = `FALSE;
REF2BANK = `FALSE;
REF1BANK = `TRUE;
end
default $display("Warning: Invalid PASR address!");
endcase
end
`endif
else
begin
$display("-- reserved for future use !!");
$display("-- check address: [11,10,8,7] = %b",RFU);
end
 
`ifdef M16G4_M64G3
MRS_SET <= repeat (2) @(negedge pclk) `TRUE; // From 3 -> 2
`else
MRS_SET <= repeat (2) @(negedge pclk) `TRUE; // From 3 -> 2
`endif
end
end
 
`protect
/*
*-----------------------------------------------------
* ACTIVE command
*-----------------------------------------------------
*/
 
// In active command, bank is selected in accordance with A11 address.
 
always @(active)
begin : active_op
integer bank_id;
reg [8*8:1] str;
 
if(CUR_TIME - TRAS_P < `tRRD-`MARGIN)
begin
$display("Warning: tRRD violation at %t", CUR_TIME);
disable active_op;
end
 
r_bank_addr = ba;
 
bank_id = BankSelect(ba);
str = PrintBank(ba);
 
//if(CUR_TIME - $bitstoreal(TPRE_P[bank_id]) < `tRP-`MARGIN)
if ((bank_id == 0) && (CUR_TIME - TPRE_P0 < `tRP-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TPRE_P1 < `tRP-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TPRE_P2 < `tRP-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TPRE_P3 < `tRP-`MARGIN))
begin
$display("Warning: tRP violation at %t", CUR_TIME);
disable active_op;
end
//if(CUR_TIME - $bitstoreal(TRAS_PP[bank_id]) < `tRC-`MARGIN) // 2.27
if ((bank_id == 0) && (CUR_TIME - TRAS_PP0 < `tRC-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TRAS_PP1 < `tRC-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TRAS_PP2 < `tRC-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TRAS_PP3 < `tRC-`MARGIN))
begin
$display("Warning: tRC violation at %t", CUR_TIME);
disable active_op;
end
 
if(Mode[bank_id] == `TRUE)
begin
$display("Warning: Illegal active (%0s is not precharged) at %t",str,CUR_TIME);
end
else
begin
/*
md = Mode;
md[bank_id] = 1;
Mode = md;
*/
Mode[bank_id] = 1'b1;
`ifdef v $display(">> active (%0s) at %t", str, CUR_TIME);
`endif
//TRAS_PP[bank_id] = $realtobits(CUR_TIME); // save current time for tRCD,tRC check.
case(bank_id)//TRAS_PP
'd0: TRAS_PP0 = CUR_TIME;
'd1: TRAS_PP1 = CUR_TIME;
'd2: TRAS_PP2 = CUR_TIME;
'd3: TRAS_PP3 = CUR_TIME;
endcase//TRAS_PP
 
r_addr_[bank_id] = addr[`ADDRTOP:0]; // check in 64M 2bank
end
//TRAS_PP[bank_id] = $realtobits(CUR_TIME); // save current time for tRCD,tRC check.
case(bank_id)//TRAS_PP
'd0: TRAS_PP0 = CUR_TIME;
'd1: TRAS_PP1 = CUR_TIME;
'd2: TRAS_PP2 = CUR_TIME;
'd3: TRAS_PP3 = CUR_TIME;
endcase//TRAS_PP
TRAS_P = CUR_TIME;
 
end // active operation
 
/*
*-----------------------------------------------------
* READ command
*-----------------------------------------------------
*/
 
always @(read)
begin :read_block
integer bank_id;
reg [8*8:1] str;
 
if(CUR_TIME - TCAS_P < `tCCD-`MARGIN)
begin
$display("Warning: tCCD violation at %t", CUR_TIME);
disable read_block;
end
 
`ifdef M512_M1024_X4
c_addr = {addr[12:11],addr[`nCOL-3:0]};
`else
`ifdef M512_M1024_X8
c_addr = {addr[11],addr[`nCOL-2:0]};
`else
`ifdef M128_M256_X4 // 98.6.30 BYC
c_addr = {addr[11],addr[`nCOL-2:0]};
`else
c_addr = addr[`BIT_C];
`endif
`endif
`endif
c_bank_addr = ba;
 
bank_id = BankSelect(ba);
str = PrintBank(ba);
//if(CUR_TIME - $bitstoreal(TRAS_PP[bank_id]) < `tRCD-`MARGIN)
if ((bank_id == 0) && (CUR_TIME - TRAS_PP0 < `tRCD-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TRAS_PP1 < `tRCD-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TRAS_PP2 < `tRCD-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TRAS_PP3 < `tRCD-`MARGIN))
begin
$display("Warning: tRCD violation at %t", CUR_TIME);
disable read_block;
end
r_addr = r_addr_[bank_id];
`endprotect
 
if(Mode[bank_id] == `TRUE)
begin
if( addr[`ADDR_AP] == `TRUE)
begin
`ifdef v $display(">> read with auto precharge(%0s) at %t",str,CUR_TIME);
`endif
auto_flag[bank_id] <= @(negedge pclk) `TRUE;
rd_autoprech_reg <= @(negedge pclk) ba;
end
else begin
`ifdef v $display(">> read (%0s) at %t ",str,CUR_TIME);
`endif
auto_flag[bank_id] <= @(negedge pclk) `FALSE;
end
end
 
else begin
`ifdef v $display("Illegal Read %0s is not activated",str);
`endif
disable read_block;
end
 
READ_MODE = `TRUE; // read operation start
TCAS_P = CUR_TIME;
 
m_addr = {r_addr, c_addr};
 
if(~burst_type)
increment_read;
else
interleave_read;
 
`ifdef M16G4_M64G3
`else
if( auto_flag[bank_id] )
begin
if( BL != 1)
auto_flagx <= @(negedge pclk) `TRUE;
->autostart;
end
`endif
 
read_task; // task call
 
READ_MODE = `FALSE; // read operation end.
// last_rw = CUR_TIME;
last_rw = TCLK_H;
 
if( auto_flag[bank_id] )
begin
// rd_autoprech_reg = c_bank_addr;
if ({CSB_FLAG,RASB_FLAG,CASB_FLAG} == 3'b010 && bank_id === ba)
$display($time, " Warning: For actual device, this gapless command would be illegal");
else
->rd_autoprecharge;
end
end
 
/*
*-----------------------------------------------------
* WRITE command
*-----------------------------------------------------
*/
 
//always @(write)
always @(posedge write_event)//KyW ... 0408 for VCS
begin:write_block
integer bank_id;
reg [8*8:1] str;
 
if(CUR_TIME - TCAS_P < `tCCD-`MARGIN)
begin
$display("Warning: tCCD violation at %t", CUR_TIME);
disable write_block;
end
 
`ifdef M512_X4
c_addr = {addr[12:11],addr[`nCOL-3:0]};
`else
`ifdef M512_X8
c_addr = {addr[11],addr[`nCOL-2:0]};
`else
`ifdef M128_M256_X4 // 98.6.30 BYC
c_addr = {addr[11],addr[`nCOL-2:0]};
`else
c_addr = addr[`BIT_C];
`endif
`endif
`endif
c_bank_addr = ba;
 
bank_id = BankSelect(ba);
str = PrintBank(ba);
r_addr = r_addr_[bank_id];
 
//if(CUR_TIME - $bitstoreal(TRAS_PP[bank_id]) < `tRCD-`MARGIN)
if ((bank_id == 0) && (CUR_TIME - TRAS_PP0 < `tRCD-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TRAS_PP1 < `tRCD-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TRAS_PP2 < `tRCD-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TRAS_PP3 < `tRCD-`MARGIN))
begin
$display("Warning: tRCD violation at %t", CUR_TIME);
disable write_block;
end
 
if(Mode[bank_id] == `TRUE)
begin
if(addr[`ADDR_AP])
begin
`ifdef v $display(">> write with auto precharge( %0s ) at %t",str,CUR_TIME);
`endif
auto_flag[bank_id] <= @(negedge pclk) `TRUE;
//`ifdef RDL2
if (`tRDL == 2)
wr_autoprech_reg2 <= @(negedge pclk) ba;
//`else
else
wr_autoprech_reg <= @(negedge pclk) ba;
//`endif
end
else begin
`ifdef v $display(">> write ( %0s ) at %t",str,CUR_TIME);
`endif
auto_flag[bank_id] <= @(negedge pclk) `FALSE;
/*
if (auto_flag == `TRUE && autoprech_reg == ba)
auto_flag = `FALSE;
*/
end
end
else
begin
$display("Warning: Illegal write command at %t",CUR_TIME);
disable write_block;
end
 
WRITE_MODE = `TRUE;
TCAS_P = CUR_TIME;
 
m_addr = {r_addr, c_addr};
 
`ifdef M16G4_M64G3
`else
if( auto_flag[bank_id] )
begin
if( WBL != 1)
auto_flagx <= @(negedge pclk) `TRUE;
->autostart;
end
`endif
 
write_task;
 
WRITE_MODE <= #(`tSH) `FALSE;
last_rw = CUR_TIME;
 
@(posedge pclk);
if(auto_flag[bank_id]) begin
if ({CSB_FLAG,RASB_FLAG,CASB_FLAG} == 3'b010 && bank_id === ba)
$display($time, " Warning: For actual device, this gapless command would be illegal");
else begin
//`ifdef RDL2
if (`tRDL == 2)
#0 ->wr_autoprecharge2;
//`else
else
->wr_autoprecharge;
//`endif
end
end
end
 
`protect
// In bank interleave write mode, din data should be stored
// in din register as the other bank selection occurred.
 
always @(flush_write)
begin
if(~burst_type)
increment_write;
else
interleave_write;
end
 
/*
*-----------------------------------------------------
* REFRESH command
*-----------------------------------------------------
*/
 
always @(autorefresh)
begin : auto_op
if (INIT == `FALSE && MRS_SET == `FALSE) // for refersh protection during MRS_ING
begin
$display("Warning: Illegal refresh command at %t",CUR_TIME);
disable auto_op;
end
 
if (|Mode !== 1'b0) begin
$display("Warning: Illegal refresh command at %t",CUR_TIME);
disable auto_op;
end
 
/* -- jhkim-TEST
`ifdef M16G4_M64G3
`else
for(i=0; i < `nBank; i=i+1)
begin
//if( CUR_TIME - $bitstoreal(TRAS_PP[i]) < `tRFC-`MARGIN )
if ((i == 0) && (CUR_TIME - TRAS_PP0 < `tRFC-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 < `tRFC-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 < `tRFC-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 < `tRFC-`MARGIN))
$display("Warning: tRFC violation at %t",CUR_TIME);
end
`endif
*/
 
AUTOREF_MODE = `TRUE;
`ifdef v
//`ifdef NOKIA
// if (REF16M_MODE == `TRUE)
// $display(">> partial auto refresh (16M) at %t",CUR_TIME);
// else if (REF32M_MODE == `TRUE)
// $display(">> partial auto refresh (32M) at %t",CUR_TIME);
// else
//`endif
$display(">> auto refresh at %t",CUR_TIME);
`endif
/* -- jhkim-TEST
`ifdef M16G4_M64G3
AUTOREF_MODE = #(`tRC) `FALSE;
`else
AUTOREF_MODE = #(`tRFC) `FALSE;
`endif
*/
`ifdef tARFC
AUTOREF_MODE = #(`tARFC) `FALSE;
`else
AUTOREF_MODE = #(`tRC) `FALSE;
`endif
 
end
 
/*
*-----------------------------------------------------
* SELF REFRESH command
*-----------------------------------------------------
*/
 
always @(selfrefresh)
begin : self_op
if (|Mode == 1'b0) begin
SELFREF_MODE = `TRUE;
`ifdef v
`ifdef NOKIA
if (REF16M_MODE == `TRUE)
$display(">> partial self refresh (16M) enter at %t",CUR_TIME);
else if (REF32M_MODE == `TRUE)
$display(">> partial self refresh (32M) enter at %t",CUR_TIME);
else
`endif
`ifdef MOBILE
if (REF4BANK == `TRUE)
$display(">> Partial Array Self Refresh (4banks) enter at %t",CUR_TIME);
else if (REF2BANK == `TRUE)
$display(">> Partial Array Self Refresh (2banks) enter at %t",CUR_TIME);
else if (REF1BANK == `TRUE)
$display(">> Partial Array Self Refresh (1banks) enter at %t",CUR_TIME);
else
`endif
$display(">> self refresh enter at %t",CUR_TIME);
`endif
TSELF = CUR_TIME;
end
else begin
$display("Warning: Illegal self refresh command at %t",CUR_TIME);
disable self_op;
end
 
for(i =0; i < `nBank; i = i+1)
begin
/* -- jhkim-TEST
`ifdef M16G4_M64G3
//if( CUR_TIME - $bitstoreal(TRAS_PP[i]) < `tRC-`MARGIN )
if ((i == 0) && (CUR_TIME - TRAS_PP0 < `tRC-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 < `tRC-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 < `tRC-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 < `tRC-`MARGIN))
$display("Warning: tRC violation at %t",CUR_TIME);
`else
//if( CUR_TIME - $bitstoreal(TRAS_PP[i]) < `tRFC-`MARGIN )
if ((i == 0) && (CUR_TIME - TRAS_PP0 < `tRFC-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 < `tRFC-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 < `tRFC-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 < `tRFC-`MARGIN))
$display("Warning: tRFC violation at %t",CUR_TIME);
`endif
*/
//if( CUR_TIME - $bitstoreal(TRAS_PP[i]) < `tRC-`MARGIN )
if ((i == 0) && (CUR_TIME - TRAS_PP0 < `tRC-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 < `tRC-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 < `tRC-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 < `tRC-`MARGIN))
$display("Warning: tRC violation at %t",CUR_TIME);
end
end
 
always @(selfexit) begin
TSEXIT = CUR_TIME;
/* -- jhkim-TEST
`ifdef M16G4_M64G3
SELFREF_MODE = #(`tRC) `FALSE;
`else
SELFREF_MODE = #(`tRFC) `FALSE;
`endif
*/
`ifdef tSRFX
SELFREF_MODE = #(`tSRFX) `FALSE;
`else
SELFREF_MODE = #(`tRC) `FALSE;
`endif
end
 
/*
always @(negedge cke) begin
if (SELFREF_MODE == `TRUE && POWERDOWN_MODE == `FALSE) begin
if (CUR_TIME - TSEXIT < `tSRX-`MARGIN)
$display("Warning: tSRX violation at %t", CUR_TIME);
end
end
*/
`endprotect
 
/*
*-----------------------------------------------------
* PRECHARGE command
*-----------------------------------------------------
*/
 
// precharge command performs to disable active operation.
 
always @(precharge)
begin : prech_op
integer bank_id;
integer i;
reg [8*8:1] str;
reg [8*8:1] str1;
 
`ifdef NBANK4
bank_id = BankSelect(prech_reg[2:1]);
str = PrintBank(prech_reg[2:1]);
`endif
`ifdef NBANK2
bank_id = BankSelect(prech_reg[1]);
str = PrintBank(prech_reg[1]);
`endif
`protect
 
if(prech_reg[0] == `FALSE)
begin
 
if(Mode[bank_id] !== 1'b0)
begin
 
//if(CUR_TIME - $bitstoreal(TRAS_PP[bank_id]) < `tRASmin-`MARGIN)
if ((bank_id == 0) && (CUR_TIME - TRAS_PP0 < `tRASmin-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TRAS_PP1 < `tRASmin-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TRAS_PP2 < `tRASmin-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TRAS_PP3 < `tRASmin-`MARGIN))
begin
$display("Warning: tRASmin violation( %0s ) at %t", str, CUR_TIME);
disable prech_op;
end
 
//if(first_pre[bank_id]==`FALSE && CUR_TIME - $bitstoreal(TRAS_PP[bank_id]) > `tRASmax+`MARGIN)
if (first_pre[bank_id]==`FALSE && ((bank_id == 0) && (CUR_TIME - TRAS_PP0 > `tRASmax-`MARGIN) ||
(bank_id == 1) && (CUR_TIME - TRAS_PP1 > `tRASmax-`MARGIN) ||
(bank_id == 2) && (CUR_TIME - TRAS_PP2 > `tRASmax-`MARGIN) ||
(bank_id == 3) && (CUR_TIME - TRAS_PP3 > `tRASmax-`MARGIN)))
$display("Warning: tRASmax violation( %0s ) at %t", str, CUR_TIME);
 
first_pre[bank_id] = `FALSE;
 
md = Mode;
md[bank_id] = 0;
Mode = md;
`ifdef v $display(">> precharge ( %0s ) at %t", str, CUR_TIME);
`endif
end
 
else
begin
`ifdef v $display("-- current precharge command is NOP at %t",CUR_TIME);
`endif
disable prech_op;
end
 
precharge_flag[bank_id] = `TRUE;
kill_bank = bank_id;
->precharge_flag_kill;
//TPRE_P[bank_id] = $realtobits(CUR_TIME);
case(bank_id)//TPRE_P
'd0: TPRE_P0 = CUR_TIME;
'd1: TPRE_P1 = CUR_TIME;
'd2: TPRE_P2 = CUR_TIME;
'd3: TPRE_P3 = CUR_TIME;
endcase//TPRE_P
end
else
begin
if(|Mode[`nBank-1:0] !== 1'b0) // BYC
begin
 
for(i = 0; i < `nBank; i = i+1)
begin
case(i)
'd0 :
str1 = " A Bank";
'd2 :
str1 = " B Bank";
'd1 :
str1 = " C Bank";
'd3 :
str1 = " D Bank";
default :
str1 = "Bad Bank";
endcase
 
//if(Mode[i] !== 1'b0 && CUR_TIME - $bitstoreal(TRAS_PP[i]) < `tRASmin-`MARGIN)
if (Mode[i] !== 1'b0 && ((i == 0) && (CUR_TIME - TRAS_PP0 < `tRASmin-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 < `tRASmin-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 < `tRASmin-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 < `tRASmin-`MARGIN)))
begin
$display("Warning: tRASmin violation ( %0s ) at %t", str1, CUR_TIME);
disable prech_op;
end
 
//if(Mode[i] !== 1'b0 && first_pre[i]==`FALSE && CUR_TIME - $bitstoreal(TRAS_PP[i]) > `tRASmax+`MARGIN)
if (Mode[i] !== 1'b0 && first_pre[i]==`FALSE && ((i == 0) && (CUR_TIME - TRAS_PP0 > `tRASmax-`MARGIN) ||
(i == 1) && (CUR_TIME - TRAS_PP1 > `tRASmax-`MARGIN) ||
(i == 2) && (CUR_TIME - TRAS_PP2 > `tRASmax-`MARGIN) ||
(i == 3) && (CUR_TIME - TRAS_PP3 > `tRASmax-`MARGIN)))
$display("Warning: tRASmax violation ( %0s ) at %t", str1, CUR_TIME);
 
first_pre[i] = `FALSE;
 
Mode[i] = 1'b0;
precharge_flag[i] = `TRUE;
//TPRE_P[i] = $realtobits(CUR_TIME);
case(i)//TPRE_P
'd0: TPRE_P0 = CUR_TIME;
'd1: TPRE_P1 = CUR_TIME;
'd2: TPRE_P2 = CUR_TIME;
'd3: TPRE_P3 = CUR_TIME;
endcase//TPRE_P
first_pre[i] = `FALSE;
end
`ifdef NBANK2
`ifdef v $display(">> precharge ( A and B bank ) at %t",CUR_TIME);
`endif
`endif
`ifdef NBANK4
`ifdef v $display(">> precharge ( A,B,C, and D bank ) at %t",CUR_TIME);
`endif
`endif
end
 
else
begin
`ifdef v $display("-- current precharge command is NOP at %t",CUR_TIME);
`endif
disable prech_op;
end
 
kill_bank = bank_id;
->precharge_flag_kill;
 
end
->precharge_start;
end
`endprotect
 
/*
*-----------------------------------------------------
* tRDL=2 AUTO PRECHARGE command
*-----------------------------------------------------
*/
 
always @(wr_autoprecharge2) begin
wr_autoprech_reg = wr_autoprech_reg2;
@(posedge pclk);
if ({CSB_FLAG,RASB_FLAG,CASB_FLAG} == 3'b010 && wr_autoprech_reg === ba)
$display($time, " Warning: For actual device, this 1-clk-gap command would be illegal");
else
->wr_autoprecharge;
end
 
/*
*-----------------------------------------------------
* READ AUTO PRECHARGE command
*-----------------------------------------------------
*/
 
always @(rd_autoprecharge or posedge rd_reautoprecharge)
begin : rd_autoprech_op
real difftime;
integer bank_id;
reg [8*8:1] str;
reg tmp_reauto;
integer prev_bank;
integer tmp_bank;
 
tmp_reauto = `FALSE;
bank_id = BankSelect(rd_autoprech_reg);
if (rd_reautoprecharge == `TRUE) begin
rd_reautoprecharge = `FALSE;
tmp_bank = prev_bank;
end
else
tmp_bank = bank_id;
str = PrintBank(tmp_bank);
//difftime = $realtime - $bitstoreal(TRAS_PP[tmp_bank]);
case(tmp_bank)//TRAS_PP
'd0: difftime = $realtime-TRAS_PP0;
'd1: difftime = $realtime-TRAS_PP1;
'd2: difftime = $realtime-TRAS_PP2;
'd3: difftime = $realtime-TRAS_PP3;
endcase//TRAS_PP
if(difftime < `tRASmin-`MARGIN)
begin
`ifdef M64G3_M128_M256
//auto_flagx <= `TRUE; // KyW ... 0624 : rev 3.3
//auto_flagx <= #(`tRASmin-difftime) `FALSE; // KyW ... 0624 : rev 3.3
prev_bank <= #(`tRASmin-difftime) tmp_bank;
rd_reautoprecharge <= #(`tRASmin-difftime) `TRUE;
tmp_reauto = `TRUE;
`ifdef v $display(" Info: Staring Auto precharge (%s) delayed by tRASmin violation at %t", str, $time);
`endif
// #0 disable rd_autoprech_op;
`else
rd_reautoprecharge = `FALSE;
$display("Warning: tRASmin violation at %t", $realtime);
disable rd_autoprech_op;
`endif
end
if(difftime > `tRASmax+`MARGIN)
begin
$display("Warning: tRASmax violation at %t", $realtime);
end
 
`ifdef M16G4_M64G3
if (tmp_reauto == `FALSE) begin
`endif
`ifdef v $display(">> auto precharge ( %0s) at %t", str, $realtime);
`endif
Mode[tmp_bank] = 0;
 
precharge_flag[tmp_bank] = `TRUE;
rd_kill_bank = tmp_bank;
->rd_precharge_flag_kill;
//TPRE_P[tmp_bank] = $realtobits($realtime);
case(tmp_bank)//TPRE_P
'd0: TPRE_P0 = $realtime;
'd1: TPRE_P1 = $realtime;
'd2: TPRE_P2 = $realtime;
'd3: TPRE_P3 = $realtime;
endcase//TPRE_P
`ifdef M16G4_M64G3
end
`endif
end
 
/*
*-----------------------------------------------------
* WRITE AUTO PRECHARGE command
*-----------------------------------------------------
*/
 
always @(wr_autoprecharge or posedge wr_reautoprecharge)
begin : wr_autoprech_op
real difftime;
integer bank_id;
reg [8*8:1] str;
reg tmp_reauto;
integer prev_bank;
integer tmp_bank;
 
tmp_reauto = `FALSE;
bank_id = BankSelect(wr_autoprech_reg);
if (wr_reautoprecharge == `TRUE) begin
wr_reautoprecharge = `FALSE;
tmp_bank = prev_bank;
end
else
tmp_bank = bank_id;
str = PrintBank(tmp_bank);
//difftime = $realtime - $bitstoreal(TRAS_PP[tmp_bank]);
case(tmp_bank)//TRAS_PP
'd0: difftime = $realtime-TRAS_PP0;
'd1: difftime = $realtime-TRAS_PP1;
'd2: difftime = $realtime-TRAS_PP2;
'd3: difftime = $realtime-TRAS_PP3;
endcase//TRAS_PP
if(difftime < `tRASmin-`MARGIN)
begin
`ifdef M64G3_M128_M256
//auto_flagx <= `TRUE; // KyW ... 0624 : rev 3.3
//auto_flagx <= #(`tRASmin-difftime) `FALSE; // KyW ... 0624 : rev 3.3
prev_bank <= #(`tRASmin-difftime) tmp_bank;
wr_reautoprecharge <= #(`tRASmin-difftime) `TRUE;
tmp_reauto = `TRUE;
`ifdef v $display(" Info: Staring Auto precharge (%s) delayed by tRASmin violation at %t", str, $time);
`endif
// #0 disable wr_autoprech_op;
`else
wr_reautoprecharge = `FALSE;
$display("Warning: tRASmin violation at %t", $realtime);
disable wr_autoprech_op;
`endif
end
if(difftime > `tRASmax+`MARGIN)
begin
$display("Warning: tRASmax violation at %t", $realtime);
end
 
`ifdef M16G4_M64G3
if (tmp_reauto == `FALSE) begin
`endif
`ifdef v $display(">> auto precharge ( %0s) at %t", str, $realtime);
`endif
Mode[tmp_bank] = 0;
 
precharge_flag[tmp_bank] = `TRUE;
wr_kill_bank = tmp_bank;
->wr_precharge_flag_kill;
//TPRE_P[tmp_bank] = $realtobits($realtime);
case(tmp_bank)//TPRE_P
'd0: TPRE_P0 = $realtime;
'd1: TPRE_P1 = $realtime;
'd2: TPRE_P2 = $realtime;
'd3: TPRE_P3 = $realtime;
endcase//TPRE_P
`ifdef M16G4_M64G3
end
`endif
end
 
/*
*-----------------------------------------------------
*/
 
always @(autostart)
begin
if( READ_MODE )
begin
auto_flagx = repeat (BL) @(negedge pclk) `FALSE;
end
else if( WRITE_MODE )
begin
auto_flagx = repeat (WBL) @(negedge pclk) `FALSE;
end
end
/*
*-----------------------------------------------------
* DEEP POWER DOWN
*-----------------------------------------------------
*/
`ifdef DPD
always @(deeppowerdown)
begin : d_powerdown
if (|Mode == 1'b0) begin
D_POWERDOWN = `TRUE;
`ifdef v
$display(">> Deep power down enter at %t",CUR_TIME);
`endif
end
else begin
$display("Warning: Illegal deep power down command at %t",CUR_TIME);
disable d_powerdown;
end
end
 
always @(d_pdown_exit) begin
D_POWERDOWN <= #(`tDPDEXIT-`MARGIN) `FALSE;
D_PDOWN_EXIT <= #(`tDPDEXIT-`MARGIN) `TRUE;
end
`endif
 
/*
*-----------------------------------------------------
* move memory data to dout register
* by sequential counter
*-----------------------------------------------------
*/
 
// This task models behavior of increment counter
// Simply, address is increased by one and one.
 
task increment_read;
begin:ir
integer j,s,t;
integer bank;
reg [`BIT_T] maddr;
reg [`BIT_C] check_111;
 
bank = BankSelect(c_bank_addr);
 
maddr = m_addr;
for(j=0; j<= BL-1; j=j+1) begin
 
case(bank)
'd0: begin
`ifdef DYMEM
$damem_read("mem_a", maddr, dout_reg[j]);
$damem_read("mem_a", maddr, din_rega[j]);
`else
dout_reg[j] = mem_a[maddr];
din_rega[j] = mem_a[maddr];
`endif
end
'd1: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF1BANK == `TRUE) dout_reg[j] = `B'bx;
else
$damem_read("mem_b", maddr, dout_reg[j]);
`else
$damem_read("mem_b", maddr, dout_reg[j]);
`endif
$damem_read("mem_b", maddr, din_regb[j]);
`else
`ifdef MOBILE
if (REF1BANK == `TRUE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_b[maddr];
`else
dout_reg[j] = mem_b[maddr];
`endif
din_regb[j] = mem_b[maddr];
`endif
end
`ifdef NBANK4
'd2: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
$damem_read("mem_c", maddr, dout_reg[j]);
`else
$damem_read("mem_c", maddr, dout_reg[j]);
`endif
$damem_read("mem_c", maddr, din_regc[j]);
`else
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_c[maddr];
`else
dout_reg[j] = mem_c[maddr];
`endif
din_regc[j] = mem_c[maddr];
`endif
end
'd3: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
$damem_read("mem_d", maddr, dout_reg[j]);
`else
$damem_read("mem_d", maddr, dout_reg[j]);
`endif
$damem_read("mem_d", maddr, din_regd[j]);
`else
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_d[maddr];
`else
dout_reg[j] = mem_d[maddr];
`endif
din_regd[j] = mem_d[maddr];
`endif
end
`endif
endcase
 
case(BL)
'd1: begin
end
'd2: maddr[0] = ~maddr[0];
'd4: begin
check_111 = m_addr + j+1;
maddr[1:0] = check_111[1:0];
end
'd8: begin
check_111 = m_addr + j+1;
maddr[2:0] = check_111[2:0];
end
`PAGEDEPTH: begin // case 256
check_111 = m_addr + j+1;
maddr[`BIT_C] = check_111[`BIT_C];
end
default: begin
$display("Warning: burst length is out of spec");
disable increment_read;
end
endcase
end // end of for loop
 
end
endtask
 
/*
*-----------------------------------------------------
* move memory data to dout register
* by interleave counter
*-----------------------------------------------------
*/
 
// Interleave counting mechanism is different from
// sequential method. Counting step could be varied with
// initial address.(refer to data sheet)
 
task interleave_read;
begin:ir1
integer j;
integer bank;
reg [`BIT_T] maddr;
 
bank = BankSelect(c_bank_addr);
maddr = m_addr;
for(j=0; j<=BL-1; j=j+1) begin
case(bank)
'd0: begin
`ifdef DYMEM
$damem_read("mem_a", maddr, dout_reg[j]);
$damem_read("mem_a", maddr, din_rega[j]);
`else
dout_reg[j] = mem_a[maddr];
din_rega[j] = mem_a[maddr];
`endif
end
'd1: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF1BANK == `TRUE) dout_reg[j] = `B'bx;
else
$damem_read("mem_b", maddr, dout_reg[j]);
`else
$damem_read("mem_b", maddr, dout_reg[j]);
`endif
$damem_read("mem_b", maddr, din_regb[j]);
`else
`ifdef MOBILE
if (REF1BANK == `TRUE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_b[maddr];
`else
dout_reg[j] = mem_b[maddr];
`endif
din_regb[j] = mem_b[maddr];
`endif
end
`ifdef NBANK4
'd2: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
$damem_read("mem_c", maddr, dout_reg[j]);
`else
$damem_read("mem_c", maddr, dout_reg[j]);
`endif
$damem_read("mem_c", maddr, din_regc[j]);
`else
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_c[maddr];
`else
dout_reg[j] = mem_c[maddr];
`endif
din_regc[j] = mem_c[maddr];
`endif
end
'd3: begin
`ifdef DYMEM
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
$damem_read("mem_d", maddr, dout_reg[j]);
`else
$damem_read("mem_d", maddr, dout_reg[j]);
`endif
$damem_read("mem_d", maddr, din_regd[j]);
`else
`ifdef MOBILE
if (REF4BANK == `FALSE) dout_reg[j] = `B'bx;
else
dout_reg[j] = mem_d[maddr];
`else
dout_reg[j] = mem_d[maddr];
`endif
din_regd[j] = mem_d[maddr];
`endif
end
`endif
endcase
 
case(BL)
'd1:begin
end
'd2:
maddr[0] = ~maddr[0];
'd4: begin
if( j == 0 || j == 2)
maddr[0] = ~maddr[0];
else
maddr[1:0] = ~maddr[1:0];
end
'd8: begin
if(j == 0 || j == 2 || j == 4 || j==6)
maddr[0] = ~maddr[0];
else if(j == 1 || j == 5)
maddr[1:0] = ~maddr[1:0];
else
maddr[2:0] = ~maddr[2:0];
end
default: $display("Warning: burst length is out of spec.");
endcase
end
end
endtask
 
/*
*-----------------------------------------------------
* move memory data to din register array
* by sequential counter
*-----------------------------------------------------
*/
 
task increment_write;
begin:iw
integer j,s,t;
reg [`BIT_T] maddr;
reg [`BIT_C] check_111;
integer bank;
 
bank = BankSelect(c_bank_addr);
maddr = m_addr;
for(j=0; j<=WBL-1; j=j+1) begin
case(bank)
'd0:
`ifdef DYMEM
$damem_write("mem_a", maddr, din_rega[j]);
`else
mem_a[maddr] = din_rega[j];
`endif
'd1:
`ifdef DYMEM
$damem_write("mem_b", maddr, din_regb[j]);
`else
mem_b[maddr] = din_regb[j];
`endif
`ifdef NBANK4
'd2:
`ifdef DYMEM
$damem_write("mem_c", maddr, din_regc[j]);
`else
mem_c[maddr] = din_regc[j];
`endif
'd3:
`ifdef DYMEM
$damem_write("mem_d", maddr, din_regd[j]);
`else
mem_d[maddr] = din_regd[j];
`endif
`endif
endcase
case(WBL)
'd1: begin
end
'd2:
maddr[0] = ~maddr[0];
'd4: begin
check_111 = m_addr +j+1;
maddr[1:0] = check_111[1:0];
end
'd8: begin
check_111 = m_addr +j+1;
maddr[2:0] = check_111[2:0];
end
`PAGEDEPTH: begin
check_111 = m_addr +j+1;
maddr[`BIT_C] = check_111[`BIT_C];
end
default: begin
$display("Warning: burst length is out of spec");
disable increment_write;
end
endcase
end
end
endtask
 
/*
*-----------------------------------------------------
* move memory data to din register array
* by interleave counter
*-----------------------------------------------------
*/
 
task interleave_write;
begin:iw1
integer j;
integer bank;
reg [`BIT_T] maddr;
 
bank = BankSelect(c_bank_addr);
maddr = m_addr;
for(j=0; j <= WBL-1; j=j+1) begin
case(bank)
'd0:
`ifdef DYMEM
$damem_write("mem_a", maddr, din_rega[j]);
`else
mem_a[maddr] = din_rega[j];
`endif
'd1:
`ifdef DYMEM
$damem_write("mem_b", maddr, din_regb[j]);
`else
mem_b[maddr] = din_regb[j];
`endif
`ifdef NBANK4
'd2:
`ifdef DYMEM
$damem_write("mem_c", maddr, din_regc[j]);
`else
mem_c[maddr] = din_regc[j];
`endif
'd3:
`ifdef DYMEM
$damem_write("mem_d", maddr, din_regd[j]);
`else
mem_d[maddr] = din_regd[j];
`endif
`endif
endcase
case(WBL)
'd1:begin
end
'd2:
maddr[0] = ~maddr[0];
'd4: begin
if((j % 2) == 0)
maddr[0] = ~maddr[0];
else
maddr[1:0] = ~maddr[1:0];
end
'd8: begin
if((j % 2) == 0)
maddr[0] = ~maddr[0];
else if(j == 1 || j == 5)
maddr[1:0] = ~maddr[1:0];
else
maddr[2:0] = ~maddr[2:0];
end
default:
begin
$display("Warning: burst length is out of spec.");
end
endcase
end
end
endtask
 
`protect
 
/*
*-----------------------------------------------------
* precharge interrupt
*-----------------------------------------------------
*/
always @(precharge_start)
begin: pc_start
integer bank_id;
reg [8*8:1] str;
 
if( READ_MODE == `TRUE )
begin
bank_id = BankSelect(c_bank_addr);
str = PrintBank(c_bank_addr);
if(precharge_flag[bank_id])
begin
`ifdef v $display("-- read operation interrupted by precharge");
`endif
READ_MODE = `FALSE;
disable read_block;
end
end
if( WRITE_MODE == `TRUE )
begin
bank_id = BankSelect(c_bank_addr);
str = PrintBank(c_bank_addr);
if(precharge_flag[bank_id])
begin
`ifdef v $display("-- write operation interrupted by precharge");
`endif
for (i = 0; i < `nDQM; i = i + 1) begin : dqm_high_check
if(dqm[i] == `FALSE) begin
`ifdef v $display(" DQM must be high at %t", CUR_TIME);
`endif
i = `nDQM;
end
end
WRITE_MODE = `FALSE;
disable write_block;
end
end
end
 
always @(precharge_flag_kill) begin
if (prech_reg[0] == `TRUE) begin
for (i = 0; i < `nBank; i = i+1)
precharge_flag[i] <= #(`tRP-1) `FALSE;
end
else begin
if( precharge_flag[kill_bank] )
precharge_flag[kill_bank] <= #(`tRP-1) `FALSE;
end
end
always @(rd_precharge_flag_kill) begin
if (prech_reg[0] == `TRUE) begin
for (i = 0; i < `nBank; i = i+1)
precharge_flag[i] <= #(`tRP-1) `FALSE;
end
else begin
if( precharge_flag[rd_kill_bank] )
precharge_flag[rd_kill_bank] <= #(`tRP-1) `FALSE;
end
end
always @(wr_precharge_flag_kill) begin
if (prech_reg[0] == `TRUE) begin
for (i = 0; i < `nBank; i = i+1)
precharge_flag[i] <= #(`tRP-1) `FALSE;
end
else begin
if( precharge_flag[wr_kill_bank] )
precharge_flag[wr_kill_bank] <= #(`tRP-1) `FALSE;
end
end
`endprotect
 
/*
*-----------------------------------------------------
* read task
*-----------------------------------------------------
*/
 
task read_task;
 
begin
 
begin: read_op
integer i;
for( i=0; i < BL; i=i+1 )
begin
t_dqo = dout_reg[i];
->dqo_event;
@(posedge pclk);
`ifdef M16G4_M64G3 // jhkim(8.14)
if( i == `PAGEDEPTH - 1 )
i = -1; // full page wrap around
`endif
end
end
 
end
endtask
 
/*
*-----------------------------------------------------
* write task
*-----------------------------------------------------
*/
 
task write_task;
begin
begin: write_op
integer i, j, k;
reg [`BIT] tmp_reg;
integer bank_id;
reg [8*8:1] str;
 
if(~burst_type)
increment_read;
else
interleave_read;
 
begin: write_seq
for(i = 0; i < WBL; i = i+1)
begin // { for loop
begin
bank_id = BankSelect(c_bank_addr);
str = PrintBank(c_bank_addr);
if(precharge_flag[bank_id] == `TRUE)
disable write_seq;
case (bank_id)
'd0: tmp_reg = din_rega[i];
'd1: tmp_reg = din_regb[i];
`ifdef NBANK4
'd2: tmp_reg = din_regc[i];
'd3: tmp_reg = din_regd[i];
`endif
endcase
 
for (k = 0; k < `nDQM; k = k + 1) begin
if (dqm[k] == 1'b0) begin
for (j = k*`BYTE; j < (k+1)*`BYTE; j = j + 1) begin
tmp_reg[j] = (dqi[j] == 1'b1 || dqi[j] == 1'b0)?
dqi[j]:1'bx;
end
end
end
 
case (bank_id)
'd0: din_rega[i] = tmp_reg;
'd1: din_regb[i] = tmp_reg;
`ifdef NBANK4
'd2: din_regc[i] = tmp_reg;
'd3: din_regd[i] = tmp_reg;
`endif
endcase
end
 
m_addr = {r_addr, c_addr};
#0 ->flush_write;
 
`ifdef M16G4_M64G3 // jhkim(8.14)
if( i == WBL-1 && WBL !== `PAGEDEPTH )
disable write_seq;
`else
if( i == WBL-1 && i != `PAGEDEPTH )
disable write_seq;
`endif
@(posedge pclk);
#0.1; //KyW ... 0408 for VCS
if( |dqm === 1'b0 ) begin // 98.6.26 BYC
if( CUR_TIME - TDQI < `tSS-`MARGIN )
$display("Warning: DQi setup violation at %t", CUR_TIME);
end
`ifdef M16G4_M64G3 // jhkim(8.14)
if ( i == `PAGEDEPTH -1)
i = -1; // full page wrap around
`endif
 
end // } for loop end
end // write_seq
 
// m_addr = {r_addr, c_addr};
// ->flush_write;
 
end
 
end
 
endtask
 
`ifdef NBANK2
function integer BankSelect;
input c_addr;
integer bank;
begin
case(c_addr)
1'b0 :
bank = 0;
1'b1 :
bank = 1;
default :
bank = -1;
endcase
BankSelect = bank;
end
endfunction
function [8*8 : 1] PrintBank;
input bs;
reg [8*8 : 1] s_bank;
begin
case(bs)
1'b0 :
s_bank = " A Bank";
1'b1 :
s_bank = " B Bank";
default :
s_bank = "Bad Bank";
endcase
PrintBank = s_bank;
end
endfunction
`endif
 
`ifdef NBANK4
function integer BankSelect;
input [1:0] c_addr;
integer bank;
begin
case(c_addr)
2'b00 :
bank = 0;
2'b01 :
bank = 1;
2'b10 :
bank = 2;
2'b11 :
bank = 3;
default :
bank = -1;
endcase
BankSelect = bank;
end
endfunction
function [8*8 : 1] PrintBank;
input [1:0] bs;
reg [8*8 : 1] s_bank;
begin
case(bs)
2'b00 :
s_bank = " A Bank";
2'b01 :
s_bank = " B Bank";
2'b10 :
s_bank = " C Bank";
2'b11 :
s_bank = " D Bank";
default :
s_bank = "Bad Bank";
endcase
PrintBank = s_bank;
end
endfunction
`endif
 
endmodule
 
`ifdef CS2
`ifdef DPD_PIN
module sdram(clk, cs0b, cs1b, cke, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
module sdram(clk, cs0b, cs1b, cke, ba, ad, rasb, casb, web, dqm, dqi);
`endif
 
inout [`BIT] dqi;
input [`nBank/2-1:0] ba;
input [`ADDRTOP:0] ad;
input rasb,casb,web;
input clk,cke,cs0b,cs1b;
input [`nDQM-1:0] dqm;
 
`ifdef DPD_PIN
input dpdb;
`endif
 
`ifdef DPD_PIN
sdram_cs2 i0(clk, cs0b, cke, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
sdram_cs2 i1(clk, cs1b, cke, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
sdram_cs2 i0(clk, cs0b, cke, ba, ad, rasb, casb, web, dqm, dqi);
sdram_cs2 i1(clk, cs1b, cke, ba, ad, rasb, casb, web, dqm, dqi);
`endif
endmodule
`endif
 
`ifdef CS2_CKE2
`ifdef DPD_PIN
module sdram(clk, cs0b, cs1b, cke0, cke1, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
module sdram(clk, cs0b, cs1b, cke0, cke1, ba, ad, rasb, casb, web, dqm, dqi);
`endif
 
inout [`BIT] dqi;
input [`nBank/2-1:0] ba;
input [`ADDRTOP:0] ad;
input rasb,casb,web;
input clk,cke0,cke1,cs0b,cs1b;
input [`nDQM-1:0] dqm;
 
`ifdef DPD_PIN
input dpdb;
`endif
 
`ifdef DPD_PIN
sdram_cs2 i0(clk, cs0b, cke0, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
sdram_cs2 i1(clk, cs1b, cke1, ba, ad, rasb, casb, web, dqm, dqi, dpdb);
`else
sdram_cs2 i0(clk, cs0b, cke0, ba, ad, rasb, casb, web, dqm, dqi);
sdram_cs2 i1(clk, cs1b, cke1, ba, ad, rasb, casb, web, dqm, dqi);
`endif
endmodule
`endif
 
/fpga/experiments/memctrl/sim/memctrl-1/ramctrl/ramctrl.v
0,0 → 1,558
//
// ramctrl.v -- RAM controller
//
 
 
`include "ramctrl/k4s561632e.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
`define MODE 13'h0032 // CL = 3, sequ. burst length = 4
 
`define CMD_MRSET 3'b000 // mode register set
`define CMD_ARFRS 3'b001 // auto refresh
`define CMD_PRCHG 3'b010 // precharge (deactivate row/rows)
`define CMD_ACTV 3'b011 // select bank, activate row
`define CMD_WRITE 3'b100 // select bank & column, start write
`define CMD_READ 3'b101 // select bank & column, start read
`define CMD_BSTOP 3'b110 // burst stop
`define CMD_NOP 3'b111 // no operation
 
//
// Note: The FSM is a registered Mealy machine. Its actions, which
// are noted here for a specific state, take place in the next
// clock cycle. This is only a notational problem: the actions
// should in fact be associated with state transitions.
//
// ST_RESET // NOP, CKE=0, CS_N=1, wait 100 us
`define ST_INIT0 5'd0 // NOP, CKE=1, CS_N=0, wait 100 us
`define ST_INIT1 5'd1 // PRECHARGE ALL
`define ST_INIT2 5'd2 // NOP, wait tRP - 1 cycle
`define ST_INIT3 5'd3 // AUTO REFRESH
`define ST_INIT4 5'd4 // NOP, wait tRFC - 1 cycle
`define ST_INIT5 5'd5 // AUTO REFRESH
`define ST_INIT6 5'd6 // NOP, wait tRFC - 1 cycle
`define ST_INIT7 5'd7 // MODE REGISTER SET
`define ST_INIT8 5'd8 // NOP, wait tMRD - 1 cycle
`define ST_IDLE 5'd9 // AUTO REFRESH, ACTIVE, or NOP
`define ST_RFRSH 5'd10 // NOP, wait tRFC - 1 cycle
`define ST_WRDATA0 5'd11 // NOP, wait tRCD - 1 cycle
`define ST_WRDATA1 5'd12 // WRITE, de=1
`define ST_WRDATA2 5'd13 // NOP, wait 3 cycles
`define ST_WRDATA3 5'd14 // NOP, ack=1, de=0
`define ST_WRDATA4 5'd15 // NOP, ack=0, wait 3 cycles
`define ST_RDDATA0 5'd16 // NOP, wait tRCD - 1 cycle
`define ST_RDDATA1 5'd17 // READ
`define ST_RDDATA2 5'd18 // NOP, wait 2 cycles
`define ST_RDDATA3 5'd19 // NOP, ld=1, wait 4 cycles
`define ST_RDDATA4 5'd20 // NOP, ack=1, ld=0
`define ST_RDDATA5 5'd21 // NOP, ack=0, wait 4 cycles
`define ST_RDINST0 5'd22 // NOP, wait tRCD - 1 cycle
`define ST_RDINST1 5'd23 // READ
`define ST_RDINST2 5'd24 // NOP, wait 2 cycles
`define ST_RDINST3 5'd25 // NOP, ld=1, wait 4 cycles
`define ST_RDINST4 5'd26 // NOP, ack=1, ld=0
`define ST_RDINST5 5'd27 // NOP, ack=0, wait 4 cycles
`define ST_ILLDA0 5'd28 // NOP, data_timeout=1
`define ST_ILLDA1 5'd29 // NOP, data_timeout=0
`define ST_ILLIA0 5'd30 // NOP, inst_timeout=1
`define ST_ILLIA1 5'd31 // NOP, inst_timeout=0
 
`define T_INIT0 14'd10000 // min 100 usec with CKE = 0
`define T_INIT1 14'd10000 // min 100 usec with CKE = 1
`define T_RP 14'd3 // min 20 ns row precharge time
`define T_RFC 14'd9 // min 66 ns auto refresh period
`define T_MRD 14'd3 // min load mode register delay
`define T_RCD 14'd3 // min 20 ns active-to-rw delay
 
`define REFCNT 10'd780 // 8192 refresh cycles per 64 ms
 
 
module ramctrl(clk_ok, clk,
inst_stb, inst_addr,
inst_dout, inst_ack,
inst_timeout,
data_stb, data_we,
data_addr, data_din,
data_dout, data_ack,
data_timeout);
input clk_ok;
input clk;
input inst_stb;
input [25:0] inst_addr;
output [63:0] inst_dout;
output reg inst_ack;
output reg inst_timeout;
input data_stb;
input data_we;
input [25:0] data_addr;
input [63:0] data_din;
output [63:0] data_dout;
output reg data_ack;
output reg data_timeout;
 
wire sdram_clk;
wire sdram_clk_aux;
reg sdram_cke;
reg sdram_cs_n;
wire sdram_ras_n;
wire sdram_cas_n;
wire sdram_we_n;
reg [1:0] sdram_ba;
reg [12:0] sdram_a;
wire [1:0] sdram_dqm;
wire [15:0] sdram_dq;
 
reg [1:0] ram_cnt;
wire [15:0] ram_dout;
reg ram_de;
reg [63:0] data;
reg data_ld;
 
wire inst_addr_out_of_range;
wire data_addr_out_of_range;
 
reg [2:0] ram_cmd;
reg [1:0] ram_dqm;
reg [13:0] count;
reg [4:0] state;
 
reg [9:0] refcnt;
reg refflg;
reg refrst;
 
//
// create ram instance
//
 
sdram sdram_1(
.clk(sdram_clk),
.cke(sdram_cke),
.csb(sdram_cs_n),
.rasb(sdram_ras_n),
.casb(sdram_cas_n),
.web(sdram_we_n),
.ba(sdram_ba[1:0]),
.ad(sdram_a[12:0]),
.dqm(sdram_dqm[1:0]),
.dqi(sdram_dq[15:0])
);
 
//
// clock output to ram
// the necessary phase shift will be accomplished by
// a DLL if the controller is implemented on an FPGA
//
 
not #4 not_1(sdram_clk_aux, clk);
not #5 not_2(sdram_clk, sdram_clk_aux);
 
//
// data output to ram
//
 
assign ram_dout[15:0] =
~ram_cnt[1] ? (~ram_cnt[0] ? data_din[63:48] : data_din[47:32]) :
(~ram_cnt[0] ? data_din[31:16] : data_din[15: 0]);
assign sdram_dq[15:0] = ram_de ? ram_dout[15:0] : 16'hzzzz;
 
//
// data output to cache
//
 
always @(posedge clk) begin
if (data_ld & (ram_cnt[1:0] == 2'b00)) begin
data[63:48] <= sdram_dq[15:0];
end
if (data_ld & (ram_cnt[1:0] == 2'b01)) begin
data[47:32] <= sdram_dq[15:0];
end
if (data_ld & (ram_cnt[1:0] == 2'b10)) begin
data[31:16] <= sdram_dq[15:0];
end
if (data_ld & (ram_cnt[1:0] == 2'b11)) begin
data[15: 0] <= sdram_dq[15:0];
end
end
 
assign inst_dout[63:0] = data[63:0];
assign data_dout[63:0] = data[63:0];
 
//
// address range check
//
 
assign inst_addr_out_of_range = | inst_addr[25:22];
assign data_addr_out_of_range = | data_addr[25:22];
 
//
// ramctrl state machine
//
 
assign sdram_ras_n = ram_cmd[2];
assign sdram_cas_n = ram_cmd[1];
assign sdram_we_n = ram_cmd[0];
 
assign sdram_dqm[1] = ram_dqm[1];
assign sdram_dqm[0] = ram_dqm[0];
 
always @(posedge clk or negedge clk_ok) begin
// asynchronous reset
if (~clk_ok) begin
inst_ack <= 0;
inst_timeout <= 0;
data_ack <= 0;
data_timeout <= 0;
sdram_cke <= 0;
sdram_cs_n <= 1;
ram_cnt <= 0;
ram_de <= 0;
data_ld <= 0;
ram_cmd <= `CMD_NOP;
ram_dqm <= 2'b11;
count <= `T_INIT0 - 1;
state <= `ST_INIT0;
refrst <= 0;
end else begin
if (|count[13:0]) begin
// wait until count = 0
// if count is loaded with N on a state transition, the
// new state will last for (N+1)/fclk cycles before (!)
// any action specified in the new state will take place
count <= count - 1;
// ram_cnt cycles through the 16-bit half-words in SDRAM
// during burst read/writes while the main state machine
// waits, thus it must be incremented here
ram_cnt <= ram_cnt + 1;
end else begin
case (state)
//----------------------------
// init
//----------------------------
`ST_INIT0:
begin
sdram_cke <= 1;
sdram_cs_n <= 0;
ram_cmd <= `CMD_NOP;
count <= `T_INIT1 - 1;
state <= `ST_INIT1;
end
`ST_INIT1:
begin
ram_cmd <= `CMD_PRCHG;
sdram_ba <= 2'b00; // don't care
sdram_a <= 13'h0400; // precharge all
state <= `ST_INIT2;
end
`ST_INIT2:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RP - 2;
state <= `ST_INIT3;
end
`ST_INIT3:
begin
ram_cmd <= `CMD_ARFRS;
state <= `ST_INIT4;
end
`ST_INIT4:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RFC - 2;
state <= `ST_INIT5;
end
`ST_INIT5:
begin
ram_cmd <= `CMD_ARFRS;
state <= `ST_INIT6;
end
`ST_INIT6:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RFC - 2;
state <= `ST_INIT7;
end
`ST_INIT7:
begin
ram_cmd <= `CMD_MRSET;
sdram_ba <= 2'b00;
sdram_a <= `MODE;
state <= `ST_INIT8;
end
`ST_INIT8:
begin
ram_cmd <= `CMD_NOP;
ram_dqm <= 2'b00;
count <= `T_MRD - 2;
state <= `ST_IDLE;
end
//----------------------------
// idle
//----------------------------
`ST_IDLE:
begin
if (refflg) begin
// refresh request
ram_cmd <= `CMD_ARFRS;
state <= `ST_RFRSH;
refrst <= 1;
end else begin
if (data_stb) begin
if (data_addr_out_of_range) begin
// illegal data address
ram_cmd <= `CMD_NOP;
state <= `ST_ILLDA0;
end else begin
// data address is ok
if (data_we) begin
// data write request
ram_cmd <= `CMD_ACTV;
sdram_ba <= data_addr[21:20];
sdram_a <= data_addr[19:7];
state <= `ST_WRDATA0;
end else begin
// data read request
ram_cmd <= `CMD_ACTV;
sdram_ba <= data_addr[21:20];
sdram_a <= data_addr[19:7];
state <= `ST_RDDATA0;
end
end
end else begin
if (inst_stb) begin
if (inst_addr_out_of_range) begin
// illegal inst address
ram_cmd <= `CMD_NOP;
state <= `ST_ILLIA0;
end else begin
// inst address is ok
// inst read request
ram_cmd <= `CMD_ACTV;
sdram_ba <= inst_addr[21:20];
sdram_a <= inst_addr[19:7];
state <= `ST_RDINST0;
end
end else begin
// no request
ram_cmd <= `CMD_NOP;
state <= `ST_IDLE;
end
end
end
end
//----------------------------
// refresh
//----------------------------
`ST_RFRSH:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RFC - 2;
state <= `ST_IDLE;
refrst <= 0;
end
//----------------------------
// write data
//----------------------------
`ST_WRDATA0:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RCD - 2;
state <= `ST_WRDATA1;
end
`ST_WRDATA1:
begin
ram_cnt <= 0;
ram_de <= 1;
ram_cmd <= `CMD_WRITE;
sdram_ba <= data_addr[21:20];
sdram_a <= { 6'b0010, data_addr[6:0], 2'b00 };
state <= `ST_WRDATA2;
end
`ST_WRDATA2:
begin
ram_cnt <= ram_cnt + 1;
ram_cmd <= `CMD_NOP;
count <= 2;
state <= `ST_WRDATA3;
end
`ST_WRDATA3:
begin
data_ack <= 1;
ram_de <= 0;
ram_cmd <= `CMD_NOP;
state <= `ST_WRDATA4;
end
`ST_WRDATA4:
begin
data_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 2;
state <= `ST_IDLE;
end
//----------------------------
// read data
//----------------------------
`ST_RDDATA0:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RCD - 2;
state <= `ST_RDDATA1;
end
`ST_RDDATA1:
begin
ram_cmd <= `CMD_READ;
sdram_ba <= data_addr[21:20];
sdram_a <= { 6'b0010, data_addr[6:0], 2'b00 };
state <= `ST_RDDATA2;
end
`ST_RDDATA2:
begin
ram_cmd <= `CMD_NOP;
count <= 1;
state <= `ST_RDDATA3;
end
`ST_RDDATA3:
begin
ram_cnt <= 0;
data_ld <= 1;
ram_cmd <= `CMD_NOP;
count <= 3;
state <= `ST_RDDATA4;
end
`ST_RDDATA4:
begin
data_ack <= 1;
data_ld <= 0;
ram_cmd <= `CMD_NOP;
state <= `ST_RDDATA5;
end
`ST_RDDATA5:
begin
data_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 3;
state <= `ST_IDLE;
end
//----------------------------
// read inst
//----------------------------
`ST_RDINST0:
begin
ram_cmd <= `CMD_NOP;
count <= `T_RCD - 2;
state <= `ST_RDINST1;
end
`ST_RDINST1:
begin
ram_cmd <= `CMD_READ;
sdram_ba <= inst_addr[21:20];
sdram_a <= { 6'b0010, inst_addr[6:0], 2'b00 };
state <= `ST_RDINST2;
end
`ST_RDINST2:
begin
ram_cmd <= `CMD_NOP;
count <= 1;
state <= `ST_RDINST3;
end
`ST_RDINST3:
begin
ram_cnt <= 0;
data_ld <= 1;
ram_cmd <= `CMD_NOP;
count <= 3;
state <= `ST_RDINST4;
end
`ST_RDINST4:
begin
inst_ack <= 1;
data_ld <= 0;
ram_cmd <= `CMD_NOP;
state <= `ST_RDINST5;
end
`ST_RDINST5:
begin
inst_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 3;
state <= `ST_IDLE;
end
//----------------------------
// illegal data address
//----------------------------
`ST_ILLDA0:
begin
data_timeout <= 1;
ram_cmd <= `CMD_NOP;
state <= `ST_ILLDA1;
end
`ST_ILLDA1:
begin
data_timeout <= 0;
ram_cmd <= `CMD_NOP;
state <= `ST_IDLE;
end
//----------------------------
// illegal inst address
//----------------------------
`ST_ILLIA0:
begin
inst_timeout <= 1;
ram_cmd <= `CMD_NOP;
state <= `ST_ILLIA1;
end
`ST_ILLIA1:
begin
inst_timeout <= 0;
ram_cmd <= `CMD_NOP;
state <= `ST_IDLE;
end
//----------------------------
// not used
//----------------------------
default:
begin
inst_ack <= 0;
inst_timeout <= 0;
data_ack <= 0;
data_timeout <= 0;
sdram_cke <= 0;
sdram_cs_n <= 1;
ram_cnt <= 0;
ram_de <= 0;
data_ld <= 0;
ram_cmd <= `CMD_NOP;
ram_dqm <= 2'b11;
count <= `T_INIT0 - 1;
state <= `ST_INIT0;
refrst <= 0;
end
endcase
end
end
end
 
//
// refresh counter
//
 
always @(posedge clk or negedge clk_ok) begin
if (~clk_ok) begin
refcnt <= 10'd0;
end else begin
if (refcnt == 10'd0) begin
refcnt <= `REFCNT;
refflg <= 1;
end else begin
refcnt <= refcnt - 1;
if (refrst) begin
refflg <= 0;
end
end
end
end
 
endmodule
/fpga/experiments/memctrl/sim/memctrl-1/memtest.cfg
0,0 → 1,73
[timestart] 0
[size] 1280 725
[pos] -1 -1
*-16.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
[treeopen] memtest.
[treeopen] memtest.ramctrl_1.
@28
memtest.clk
memtest.clk_ok
memtest.rst
@200
--- INST RD --
@28
memtest.inst_stb
@22
memtest.inst_addr[25:0]
memtest.inst_to_cache[63:0]
@28
memtest.inst_ack
memtest.inst_timeout
@200
--- DATA RD/WR --
@28
memtest.data_stb
memtest.data_we
@22
memtest.data_addr[25:0]
memtest.data_to_mctrl[63:0]
memtest.data_to_cache[63:0]
@28
memtest.data_ack
memtest.data_timeout
@200
--- TEST RESULT --
@28
memtest.test_ended
memtest.test_error
@200
--- SDRAM CHIP --
@28
memtest.ramctrl_1.sdram_clk
memtest.ramctrl_1.sdram_cke
memtest.ramctrl_1.sdram_cs_n
memtest.ramctrl_1.sdram_ras_n
memtest.ramctrl_1.sdram_cas_n
memtest.ramctrl_1.sdram_we_n
memtest.ramctrl_1.sdram_ba[1:0]
@22
memtest.ramctrl_1.sdram_a[12:0]
@28
memtest.ramctrl_1.sdram_dqm[1:0]
@22
memtest.ramctrl_1.sdram_dq[15:0]
@200
--- SDRAM CTRL --
@28
memtest.ramctrl_1.ram_cnt[1:0]
@22
memtest.ramctrl_1.ram_dout[15:0]
@28
memtest.ramctrl_1.ram_de
@22
memtest.ramctrl_1.data[63:0]
@28
memtest.ramctrl_1.data_ld
memtest.ramctrl_1.ram_cmd[2:0]
@22
memtest.ramctrl_1.count[13:0]
memtest.ramctrl_1.state[4:0]
memtest.ramctrl_1.refcnt[9:0]
@28
memtest.ramctrl_1.refflg
memtest.ramctrl_1.refrst
/fpga/experiments/memctrl/sim/memctrl-1/Makefile
0,0 → 1,18
#
# Makefile for testing the memory controller
#
 
all: show
 
install:
 
memtest: memtest.v
iverilog -Wall -o memtest memtest.v
 
show: memtest
./memtest
gtkwave dump.vcd memtest.cfg
 
clean:
rm -f *~ memtest dump.vcd
rm -f ramtest/*~ ramctrl/*~
/fpga/experiments/memctrl/sim/memctrl-1/README
0,0 → 1,37
Structure
---------
 
A top-level module (memtest.v) creates instances of a memory
test circuit (ramtest/ramtest.v) and a memory controller
(ramctrl/ramctrl.v), which in turn builds an internal model
of the external SDRAM (ramctrl/k4s561632e.v).
 
 
Intended Use
------------
 
The memory controller offers a complete simulation of the memory
subsystem, including a simulation model of a 256 Mbit SDRAM chip
(provided by Samsung Electronics). The controller can also be
synthesized for use on a real FPGA (but the DLL for clock phase
shifting required in this case is not included here).
 
 
Front-End (interface to caches)
-------------------------------
 
instruction read:
2^26 * 64 bit = 512 MB
strobe/acknowledge/timeout handshake
 
data read/write:
2^26 * 64 bit = 512 MB
strobe/acknowledge/timeout handshake
 
 
Back-End (interface to SDRAM)
-----------------------------
 
This is the standard SDRAM interface for 256 Mbit devices,
organized as 16 M x 16 bit (in 4 banks, 8192 rows each).
4 banks * 8192 rows * 512 columns * 16 bit = 256 Mbit = 32 MB

powered by: WebSVN 2.1.0

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