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/fpga/experiments
    from Rev 313 to Rev 314
    Reverse comparison

Rev 313 → Rev 314

/memctrl/sim/memctrl-2/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
/memctrl/sim/memctrl-2/memtest.v
0,0 → 1,108
//
// memtest.v -- test bench for memory controller
//
 
 
`include "ramtest/ramtest.v"
`include "ramctrl/ramctrl.v"
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
module memtest;
 
reg clk2; // system clock, 100 MHz
reg clk; // system clock, 50 MHz
reg clk_ok_in; // clocks are stable, input
reg clk_ok; // system clocks are 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);
clk2 = 1;
clk = 0;
clk_ok_in = 0;
rst_in = 1;
#43 clk_ok_in = 1;
#200360 rst_in = 0;
#488900 $finish;
end
 
// clock generator, 100 MHz
always begin
#5 clk2 = ~clk2; // 10 nsec cycle time
end
 
// clock generator, 50 MHz
always begin
#10 clk = ~clk; // 20 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(clk2),
.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
/memctrl/sim/memctrl-2/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
 
/memctrl/sim/memctrl-2/ramctrl/ramctrl.v
0,0 → 1,563
//
// 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, wait 2 cycles
`define ST_WRDATA4 5'd15 // NOP, ack=0, wait 2 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, wait 2 cycles
`define ST_RDDATA5 5'd21 // NOP, ack=0, wait 3 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, wait 2 cycles
`define ST_RDINST5 5'd27 // NOP, ack=0, wait 3 cycles
`define ST_ILLDA0 5'd28 // NOP, data_timeout=1, wait 2 cycles
`define ST_ILLDA1 5'd29 // NOP, data_timeout=0
`define ST_ILLIA0 5'd30 // NOP, inst_timeout=1, wait 2 cycles
`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;
count <= 1;
state <= `ST_WRDATA4;
end
`ST_WRDATA4:
begin
data_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 1;
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;
count <= 1;
state <= `ST_RDDATA5;
end
`ST_RDDATA5:
begin
data_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 2;
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;
count <= 1;
state <= `ST_RDINST5;
end
`ST_RDINST5:
begin
inst_ack <= 0;
ram_cmd <= `CMD_NOP;
count <= 2;
state <= `ST_IDLE;
end
//----------------------------
// illegal data address
//----------------------------
`ST_ILLDA0:
begin
data_timeout <= 1;
ram_cmd <= `CMD_NOP;
count <= 1;
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;
count <= 1;
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
/memctrl/sim/memctrl-2/memtest.cfg
0,0 → 1,74
[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.clk2
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
/memctrl/sim/memctrl-2/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/*~
/memctrl/sim/memctrl-2/README
0,0 → 1,49
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
 
 
Clocks
------
 
The SDRAM controller (and the SDRAM itself) is clocked with
100 MHz, the rest of the circuit is clocked with 50 MHz. The
clocks are synchronized, so that every other positive clock
edge at 100 MHz coincides with a positive clock edge at 50 MHz.
Therefore we don't need complicated circuits (FIFO, etc.) to
safely cross the clock domain border; simply stretching both
acknowledge signals to two 100 MHz clock cycles will do.

powered by: WebSVN 2.1.0

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