URL
https://opencores.org/ocsvn/eco32/eco32/trunk
Subversion Repositories eco32
[/] [eco32/] [trunk/] [fpga/] [experiments/] [memctrl/] [sim/] [memctrl-1/] [ramctrl/] [k4s561632e.v] - Rev 313
Compare with Previous | Blame | View Log
/*============================================================================= * 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