1977 lines
69 KiB
Verilog

//////////////////////////////////////////////////////////////////////////////
// File name : mt48lc4m32b2.v
//////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2006 Free Model Foundry; http://www.freemodelfoundry.com
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// MODIFICATION HISTORY:
//
// version: | author: | mod date: | changes made:
// V1.0 I.Milutinovic 06 Apr 18 Initial release
//
//////////////////////////////////////////////////////////////////////////////
// PART DESCRIPTION:
//
// Library: RAM
// Technology: LVTTL
// Part: MT48LC4M32B2
//
// Description: 1M x 32 x 4Banks SDRAM
//
//////////////////////////////////////////////////////////////////////////////
// Known Bugs:
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// MODULE DECLARATION //
//////////////////////////////////////////////////////////////////////////////
`timescale 1 ns/100 ps
module mt48lc4m32b2
(
A11 ,
A10 ,
A9 ,
A8 ,
A7 ,
A6 ,
A5 ,
A4 ,
A3 ,
A2 ,
A1 ,
A0 ,
DQ31 ,
DQ30 ,
DQ29 ,
DQ28 ,
DQ27 ,
DQ26 ,
DQ25 ,
DQ24 ,
DQ23 ,
DQ22 ,
DQ21 ,
DQ20 ,
DQ19 ,
DQ18 ,
DQ17 ,
DQ16 ,
DQ15 ,
DQ14 ,
DQ13 ,
DQ12 ,
DQ11 ,
DQ10 ,
DQ9 ,
DQ8 ,
DQ7 ,
DQ6 ,
DQ5 ,
DQ4 ,
DQ3 ,
DQ2 ,
DQ1 ,
DQ0 ,
BA0 ,
BA1 ,
DQM3 ,
DQM2 ,
DQM1 ,
DQM0 ,
CLK ,
CKE ,
WENeg ,
RASNeg ,
CSNeg ,
CASNeg );
////////////////////////////////////////////////////////////////////////
// Port / Part Pin Declarations
////////////////////////////////////////////////////////////////////////
input A11 ;
input A10 ;
input A9 ;
input A8 ;
input A7 ;
input A6 ;
input A5 ;
input A4 ;
input A3 ;
input A2 ;
input A1 ;
input A0 ;
inout DQ31 ;
inout DQ30 ;
inout DQ29 ;
inout DQ28 ;
inout DQ27 ;
inout DQ26 ;
inout DQ25 ;
inout DQ24 ;
inout DQ23 ;
inout DQ22 ;
inout DQ21 ;
inout DQ20 ;
inout DQ19 ;
inout DQ18 ;
inout DQ17 ;
inout DQ16 ;
inout DQ15 ;
inout DQ14 ;
inout DQ13 ;
inout DQ12 ;
inout DQ11 ;
inout DQ10 ;
inout DQ9 ;
inout DQ8 ;
inout DQ7 ;
inout DQ6 ;
inout DQ5 ;
inout DQ4 ;
inout DQ3 ;
inout DQ2 ;
inout DQ1 ;
inout DQ0 ;
input BA0 ;
input BA1 ;
input DQM3 ;
input DQM2 ;
input DQM1 ;
input DQM0 ;
input CLK ;
input CKE ;
input WENeg ;
input RASNeg ;
input CSNeg ;
input CASNeg ;
// interconnect path delay signals
wire A11_ipd ;
wire A10_ipd ;
wire A9_ipd ;
wire A8_ipd ;
wire A7_ipd ;
wire A6_ipd ;
wire A5_ipd ;
wire A4_ipd ;
wire A3_ipd ;
wire A2_ipd ;
wire A1_ipd ;
wire A0_ipd ;
wire [11 : 0] A;
assign A = {A11_ipd,
A10_ipd,
A9_ipd,
A8_ipd,
A7_ipd,
A6_ipd,
A5_ipd,
A4_ipd,
A3_ipd,
A2_ipd,
A1_ipd,
A0_ipd };
wire DQ31_ipd ;
wire DQ30_ipd ;
wire DQ29_ipd ;
wire DQ28_ipd ;
wire DQ27_ipd ;
wire DQ26_ipd ;
wire DQ25_ipd ;
wire DQ24_ipd ;
wire DQ23_ipd ;
wire DQ22_ipd ;
wire DQ21_ipd ;
wire DQ20_ipd ;
wire DQ19_ipd ;
wire DQ18_ipd ;
wire DQ17_ipd ;
wire DQ16_ipd ;
wire DQ15_ipd ;
wire DQ14_ipd ;
wire DQ13_ipd ;
wire DQ12_ipd ;
wire DQ11_ipd ;
wire DQ10_ipd ;
wire DQ9_ipd ;
wire DQ8_ipd ;
wire DQ7_ipd ;
wire DQ6_ipd ;
wire DQ5_ipd ;
wire DQ4_ipd ;
wire DQ3_ipd ;
wire DQ2_ipd ;
wire DQ1_ipd ;
wire DQ0_ipd ;
wire [31 : 0 ] DQIn;
assign DQIn = { DQ31_ipd,
DQ30_ipd,
DQ29_ipd,
DQ28_ipd,
DQ27_ipd,
DQ26_ipd,
DQ25_ipd,
DQ24_ipd,
DQ23_ipd,
DQ22_ipd,
DQ21_ipd,
DQ20_ipd,
DQ19_ipd,
DQ18_ipd,
DQ17_ipd,
DQ16_ipd,
DQ15_ipd,
DQ14_ipd,
DQ13_ipd,
DQ12_ipd,
DQ11_ipd,
DQ10_ipd,
DQ9_ipd,
DQ8_ipd,
DQ7_ipd,
DQ6_ipd,
DQ5_ipd,
DQ4_ipd,
DQ3_ipd,
DQ2_ipd,
DQ1_ipd,
DQ0_ipd };
wire [31 : 0] DQOut;
assign DQOut = { DQ31,
DQ30,
DQ29,
DQ28,
DQ27,
DQ26,
DQ25,
DQ24,
DQ23,
DQ22,
DQ21,
DQ20,
DQ19,
DQ18,
DQ17,
DQ16,
DQ15,
DQ14,
DQ13,
DQ12,
DQ11,
DQ10,
DQ9,
DQ8,
DQ7,
DQ6,
DQ5,
DQ4,
DQ3,
DQ2,
DQ1,
DQ0 };
wire BA0_ipd ;
wire BA1_ipd ;
wire DQM3_ipd ;
wire DQM2_ipd ;
wire DQM1_ipd ;
wire DQM0_ipd ;
wire CLK_ipd ;
wire CKE_ipd ;
wire WENeg_ipd ;
wire RASNeg_ipd ;
wire CSNeg_ipd ;
wire CASNeg_ipd ;
integer bank;
integer bank_tmp;
// internal delays
reg rct_in ;
reg rct_out;
reg [3:0] rcdt_in ;
reg [3:0] rcdt_out;
reg pre_in ;
reg pre_out ;
reg refreshed_in ;
reg refreshed_out ;
reg rcar_out ;
reg rcar_in ;
reg wrt_in ;
reg wrt_out ;
reg [3:0] ras_in = 1'b0;
reg [3:0] ras_out = 1'b0;
reg [31 : 0] DQ_zd = 32'bz;
assign {DQ31_zd,
DQ30_zd,
DQ29_zd,
DQ28_zd,
DQ27_zd,
DQ26_zd,
DQ25_zd,
DQ24_zd,
DQ23_zd,
DQ22_zd,
DQ21_zd,
DQ20_zd,
DQ19_zd,
DQ18_zd,
DQ17_zd,
DQ16_zd,
DQ15_zd,
DQ14_zd,
DQ13_zd,
DQ12_zd,
DQ11_zd,
DQ10_zd,
DQ9_zd,
DQ8_zd,
DQ7_zd,
DQ6_zd,
DQ5_zd,
DQ4_zd,
DQ3_zd,
DQ2_zd,
DQ1_zd,
DQ0_zd } = DQ_zd;
parameter UserPreload = 1'b1;
parameter mem_file_name = "none"; //"mt48lc4m32b2.mem";
parameter TimingModel = "DefaultTimingModel";
parameter PartID = "mt48lc4m32b2";
parameter hi_bank = 3;
parameter depth = 25'h100000;
reg PoweredUp = 1'b0;
reg CKEreg = 1'b0;
reg CAS_Lat ;
reg CAS_Lat2;
reg [31:0] DataDrive = 32'bz ;
// Memory array declaration
integer Mem [0:(hi_bank+1)*depth*4-1];
// Type definition for state machine
parameter pwron = 5'd0;
parameter precharge = 5'd1;
parameter idle = 5'd2;
parameter mode_set = 5'd3;
parameter self_refresh = 5'd4;
parameter auto_refresh = 5'd5;
parameter pwrdwn = 5'd6;
parameter bank_act = 5'd7;
parameter bank_act_pwrdwn = 5'd8;
parameter write = 5'd9;
parameter write_suspend = 5'd10;
parameter read = 5'd11;
parameter read_suspend = 5'd12;
parameter write_auto_pre = 5'd13;
parameter read_auto_pre = 5'd14;
reg [4:0] statebank [hi_bank:0];
// Type definition for commands
parameter desl = 4'd0;
parameter nop = 4'd1;
parameter bst = 4'd2;
parameter rd = 4'd3;
parameter writ = 4'd4;
parameter act = 4'd5;
parameter pre = 4'd6;
parameter mrs = 4'd7;
parameter ref = 4'd8;
reg [3:0] command = desl;
// burst type
parameter sequential = 1'b0;
parameter interleave = 1'b1;
reg Burst ;
// write burst mode
parameter programmed = 1'b0;
parameter single = 1'b1;
reg WB ;
//burst sequences
integer intab [0:63];
reg [19:0] MemAddr [hi_bank:0];
integer BurstCnt [hi_bank:0];
integer StartAddr [hi_bank:0];
integer BurstInc [hi_bank:0];
integer BaseLoc [hi_bank:0];
integer Loc;
integer BurstLen;
integer Burst_Bits;
reg written = 1'b0;
reg chip_en = 1'b0;
integer cur_bank;
reg [11:0] ModeReg ;
integer Ref_Cnt = 0;
time Next_Ref = 0;
reg [8*8:1] BankString ;
reg Viol = 1'b0;
reg [31:0] DataDriveOut = 32'bz;
reg [31:0] DataDrive1 = 32'bz;
reg [31:0] DataDrive2 = 32'bz;
reg [31:0] DataDrive3 = 32'bz;
reg DQM0_reg0 ;
reg DQM0_reg1 ;
reg DQM0_reg2 ;
reg DQM1_reg0 ;
reg DQM1_reg1 ;
reg DQM1_reg2 ;
reg DQM2_reg0 ;
reg DQM2_reg1 ;
reg DQM2_reg2 ;
reg DQM3_reg0 ;
reg DQM3_reg1 ;
reg DQM3_reg2 ;
// tdevice values: values for internal delays
time tdevice_TRC = 0;
time tdevice_TRCAR = 0;
time tdevice_TRCD = 0;
time tdevice_TRP = 0;
time tdevice_TWR = 0;
///////////////////////////////////////////////////////////////////////////
//Interconnect Path Delay Section
///////////////////////////////////////////////////////////////////////////
buf (A11_ipd, A11);
buf (A10_ipd, A10);
buf (A9_ipd , A9 );
buf (A8_ipd , A8 );
buf (A7_ipd , A7 );
buf (A6_ipd , A6 );
buf (A5_ipd , A5 );
buf (A4_ipd , A4 );
buf (A3_ipd , A3 );
buf (A2_ipd , A2 );
buf (A1_ipd , A1 );
buf (A0_ipd , A0 );
buf (DQ31_ipd , DQ31 );
buf (DQ30_ipd , DQ30 );
buf (DQ29_ipd , DQ29 );
buf (DQ28_ipd , DQ28 );
buf (DQ27_ipd , DQ27 );
buf (DQ26_ipd , DQ26 );
buf (DQ25_ipd , DQ25 );
buf (DQ24_ipd , DQ24 );
buf (DQ23_ipd , DQ23 );
buf (DQ22_ipd , DQ22 );
buf (DQ21_ipd , DQ21 );
buf (DQ20_ipd , DQ20 );
buf (DQ19_ipd , DQ19 );
buf (DQ18_ipd , DQ18 );
buf (DQ17_ipd , DQ17 );
buf (DQ16_ipd , DQ16 );
buf (DQ15_ipd , DQ15 );
buf (DQ14_ipd , DQ14 );
buf (DQ13_ipd , DQ13 );
buf (DQ12_ipd , DQ12 );
buf (DQ11_ipd , DQ11 );
buf (DQ10_ipd , DQ10 );
buf (DQ9_ipd , DQ9 );
buf (DQ8_ipd , DQ8 );
buf (DQ7_ipd , DQ7 );
buf (DQ6_ipd , DQ6 );
buf (DQ5_ipd , DQ5 );
buf (DQ4_ipd , DQ4 );
buf (DQ3_ipd , DQ3 );
buf (DQ2_ipd , DQ2 );
buf (DQ1_ipd , DQ1 );
buf (DQ0_ipd , DQ0 );
buf (CASNeg_ipd, CASNeg);
buf (RASNeg_ipd, RASNeg);
buf (BA0_ipd , BA0 );
buf (BA1_ipd , BA1 );
buf (DQM0_ipd , DQM0 );
buf (DQM1_ipd , DQM1 );
buf (DQM2_ipd , DQM2 );
buf (DQM3_ipd , DQM3 );
buf (CLK_ipd , CLK );
buf (CKE_ipd , CKE );
buf (WENeg_ipd , WENeg );
buf (CSNeg_ipd , CSNeg );
///////////////////////////////////////////////////////////////////////////
// Propagation delay Section
///////////////////////////////////////////////////////////////////////////
nmos (DQ31 , DQ31_zd , 1);
nmos (DQ30 , DQ30_zd , 1);
nmos (DQ29 , DQ29_zd , 1);
nmos (DQ28 , DQ28_zd , 1);
nmos (DQ27 , DQ27_zd , 1);
nmos (DQ26 , DQ26_zd , 1);
nmos (DQ25 , DQ25_zd , 1);
nmos (DQ24 , DQ24_zd , 1);
nmos (DQ23 , DQ23_zd , 1);
nmos (DQ22 , DQ22_zd , 1);
nmos (DQ21 , DQ21_zd , 1);
nmos (DQ20 , DQ20_zd , 1);
nmos (DQ19 , DQ19_zd , 1);
nmos (DQ18 , DQ18_zd , 1);
nmos (DQ17 , DQ17_zd , 1);
nmos (DQ16 , DQ16_zd , 1);
nmos (DQ15 , DQ15_zd , 1);
nmos (DQ14 , DQ14_zd , 1);
nmos (DQ13 , DQ13_zd , 1);
nmos (DQ12 , DQ12_zd , 1);
nmos (DQ11 , DQ11_zd , 1);
nmos (DQ10 , DQ10_zd , 1);
nmos (DQ9 , DQ9_zd , 1);
nmos (DQ8 , DQ8_zd , 1);
nmos (DQ7 , DQ7_zd , 1);
nmos (DQ6 , DQ6_zd , 1);
nmos (DQ5 , DQ5_zd , 1);
nmos (DQ4 , DQ4_zd , 1);
nmos (DQ3 , DQ3_zd , 1);
nmos (DQ2 , DQ2_zd , 1);
nmos (DQ1 , DQ1_zd , 1);
nmos (DQ0 , DQ0_zd , 1);
wire deg;
wire chip_act;
assign chip_act = chip_en;
wire chip_act_deg;
assign chip_act_deg = chip_act && deg;
wire cas_latency1;
wire cas_latency2;
wire cas_latency3;
assign cas_latency1 = CAS_Lat && ~CAS_Lat2;
assign cas_latency2 = ~CAS_Lat && CAS_Lat2;
assign cas_latency3 = CAS_Lat && CAS_Lat2;
specify
// tipd delays: interconnect path delays, mapped to input port delays.
// In Verilog it is not necessary to declare any tipd delay variables,
// they can be taken from SDF file
// With all the other delays real delays would be taken from SDF file
// tpd delays
specparam tpd_CLK_DQ1 = 1;
specparam tpd_CLK_DQ2 = 1;
specparam tpd_CLK_DQ3 = 1;
// tpw values: pulse widths
specparam tpw_CLK_posedge = 1;
specparam tpw_CLK_negedge = 1;
// tsetup values: setup times
specparam tsetup_DQ0_CLK = 1; // tDS
// thold values: hold times
specparam thold_DQ0_CLK = 1; // tDH
// tperiod_min: minimum clock period = 1/max freq
specparam tperiod_CLK_cl0_eq_1_posedge = 1; //tCK
specparam tperiod_CLK_cl1_eq_1_posedge = 1;
specparam tperiod_CLK_cl2_eq_1_posedge = 1;
// tdevice values: values for internal delays
specparam tdevice_REF = 15625 ;
specparam tdevice_TRASmin = 42;
specparam tdevice_TRASmax = 120000;
///////////////////////////////////////////////////////////////////////
// Input Port Delays don't require Verilog description
///////////////////////////////////////////////////////////////////////
// Path delays //
///////////////////////////////////////////////////////////////////////
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ1;
if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ1;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ2;
if (~CAS_Lat && CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ2;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ3;
if (CAS_Lat && CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ3;
////////////////////////////////////////////////////////////////////////
// Timing Check Section
////////////////////////////////////////////////////////////////////////
$setup (BA0 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (BA1 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (DQM0, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (DQM1, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (DQM2, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (DQM3, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (CKE , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (WENeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (CSNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (CASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (RASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (DQ0 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ1 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ2 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ3 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ4 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ5 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ6 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ7 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ8 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ9 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ10 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ11 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ12 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ13 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ14 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ15 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ16 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ17 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ18 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ19 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ20 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ21 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ22 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ23 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ24 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ25 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ26 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ27 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ28 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ29 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ30 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (DQ31 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol);
$setup (A0, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A1, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A2, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A3, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A4, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A5, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A6, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A7, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A8, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A9, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A10, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$setup (A11, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, BA0, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, BA1, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, DQM0, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, DQM1, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, DQM2, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, DQM3, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, CKE , thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, CASNeg, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, RASNeg, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, WENeg, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, CSNeg, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A0, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A1, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A2, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A3, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A4, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A5, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A6, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A7, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A8, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A9, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A10, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act, A11, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ0, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ1, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ2, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ3, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ4, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ5, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ6, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ7, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ8, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ9, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ10, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ11, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ12, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ13, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ14, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ15, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ16, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ17, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ18, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ19, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ20, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ21, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ22, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ23, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ24, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ25, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ26, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ27, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ28, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ29, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ30, thold_DQ0_CLK, Viol);
$hold (posedge CLK &&& chip_act_deg, DQ31, thold_DQ0_CLK, Viol);
$width (posedge CLK &&& chip_act, tpw_CLK_posedge);
$width (negedge CLK &&& chip_act, tpw_CLK_negedge);
$period (posedge CLK &&& cas_latency1, tperiod_CLK_cl0_eq_1_posedge);
$period (posedge CLK &&& cas_latency2, tperiod_CLK_cl1_eq_1_posedge);
$period (posedge CLK &&& cas_latency3, tperiod_CLK_cl2_eq_1_posedge);
endspecify
task generate_out ;
output [31:0] DataDrive;
input Bank;
integer Bank;
integer location;
begin
location = Bank * depth * 4 + Loc;
DataDrive[7:0] = 8'bx;
if (Mem[location] > -1)
DataDrive[7:0] = Mem[location];
DataDrive[15:8] = 8'bx;
if (Mem[location+1] > -1)
DataDrive[15:8] = Mem[location+1];
DataDrive[23:16] = 8'bx;
if (Mem[location+2] > -1)
DataDrive[23:16] = Mem[location+2];
DataDrive[31:24] = 8'bx;
if (Mem[location+3] > -1)
DataDrive[31:24] = Mem[location+3];
end
endtask
task MemWrite;
input Bank;
integer Bank;
integer location;
begin
location = Bank * depth * 4 + Loc;
if (~DQM0_ipd)
begin
Mem[location] = -1;
if (~Viol)
Mem[location] = DQIn[7:0];
end
if (~DQM1_ipd)
begin
Mem[location+1] = -1;
if (~Viol)
Mem[location+1] = DQIn[15:8];
end
if (~DQM2_ipd)
begin
Mem[location+2] = -1;
if (~Viol)
Mem[location+2] = DQIn[23:16];
end
if (~DQM3_ipd)
begin
Mem[location+3] = -1;
if (~Viol)
Mem[location+3] = DQIn[31:24];
end
end
endtask
task BurstIncProc;
input Bank;
integer Bank;
begin
BurstInc[Bank] = 0;
if (Burst_Bits == 1)
BurstInc[Bank] = A[0:0];
if (Burst_Bits == 2)
BurstInc[Bank] = A[1:0];
if (Burst_Bits == 3)
BurstInc[Bank] = A[2:0];
if (Burst_Bits == 7)
BurstInc[Bank] = A[6:0];
end
endtask
task NextStateAuto;
input Bank;
input state;
integer Bank;
reg [4:0] state;
begin
if (~A[10])
statebank[Bank] = state;
else if (A[10])
if (state == write)
statebank[Bank] = write_auto_pre;
else
statebank[Bank] = read_auto_pre;
end
endtask
//////////////////////////////////////////////////////////////////////////
// Main Behavior Block //
//////////////////////////////////////////////////////////////////////////
// chech when data is generated from model to avoid setup/hold check in
// those occasion
reg deq;
always @(DQIn, DQOut)
begin
if (DQIn==DQOut)
deq=1'b1;
else
deq=1'b0;
end
assign deg=deq;
// initialize burst sequences
initial
begin
intab[0] = 0;
intab[1] = 1;
intab[2] = 2;
intab[3] = 3;
intab[4] = 4;
intab[5] = 5;
intab[6] = 6;
intab[7] = 7;
intab[8] = 1;
intab[9] = 0;
intab[10] = 3;
intab[11] = 2;
intab[12] = 5;
intab[13] = 4;
intab[14] = 7;
intab[15] = 6;
intab[16] = 2;
intab[17] = 3;
intab[18] = 0;
intab[19] = 1;
intab[20] = 6;
intab[21] = 7;
intab[22] = 4;
intab[23] = 5;
intab[24] = 3;
intab[25] = 2;
intab[26] = 1;
intab[27] = 0;
intab[28] = 7;
intab[29] = 6;
intab[30] = 5;
intab[31] = 4;
intab[32] = 4;
intab[33] = 5;
intab[34] = 6;
intab[35] = 7;
intab[36] = 0;
intab[37] = 1;
intab[38] = 2;
intab[39] = 3;
intab[40] = 5;
intab[41] = 4;
intab[42] = 7;
intab[43] = 6;
intab[44] = 1;
intab[45] = 0;
intab[46] = 3;
intab[47] = 2;
intab[48] = 6;
intab[49] = 7;
intab[50] = 4;
intab[51] = 5;
intab[52] = 2;
intab[53] = 3;
intab[54] = 0;
intab[55] = 1;
intab[56] = 7;
intab[57] = 6;
intab[58] = 5;
intab[59] = 4;
intab[60] = 3;
intab[61] = 2;
intab[62] = 1;
intab[63] = 0;
end
// initialize memory and load preload files if any
initial
begin: InitMemory
integer i;
for (i=0; i<=((hi_bank+1)*depth*4 - 1); i=i+1)
begin
Mem[i] = -1;
end
// Memory preload file
// mt48lc4m32b2.mem file
// @bbbbbb - <bbbbbb> stands for address within memory,
// dd - <dd> is word to be written at Mem(bbbbbb++)
// (bbbbbb is incremented at every load)
if (UserPreload && !(mem_file_name == "none"))
$readmemh(mem_file_name,Mem);
end
//Power Up time 100 us;
initial
begin
PoweredUp = 1'b0;
statebank[0] = pwron;
statebank[1] = pwron;
statebank[2] = pwron;
statebank[3] = pwron;
#100000 PoweredUp = 1'b1;
end
always @(posedge wrt_in)
begin:TWRrise
#tdevice_TWR wrt_out = wrt_in;
end
always @(negedge wrt_in)
begin:TWRfall
#1 wrt_out = wrt_in;
end
always @(posedge ras_in[0])
begin:TRASrise0
ras_out[0] <= #tdevice_TRASmin ras_in[0];
end
always @(negedge ras_in[0])
begin:TRASfall0
ras_out[0] <= #tdevice_TRASmax ras_in[0];
end
always @(posedge ras_in[1])
begin:TRASrise1
ras_out[1] <= #tdevice_TRASmin ras_in[1];
end
always @(negedge ras_in[1])
begin:TRASfall1
ras_out[1] <= #tdevice_TRASmax ras_in[1];
end
always @(posedge ras_in[2])
begin:TRASrise2
ras_out[2] <= #tdevice_TRASmin ras_in[2];
end
always @(negedge ras_in[2])
begin:TRASfall2
ras_out[2] <= #tdevice_TRASmax ras_in[2];
end
always @(posedge ras_in[3])
begin:TRASrise3
ras_out[3] <= #tdevice_TRASmin ras_in[3];
end
always @(negedge ras_in[3])
begin:TRASfall3
ras_out[3] <= #tdevice_TRASmax ras_in[3];
end
always @(posedge rcdt_in[0])
begin:TRCDrise0
rcdt_out[0] <= #5 1'b1;
end
always @(negedge rcdt_in[0])
begin:TRCDfall0
rcdt_out[0] <= #tdevice_TRCD 1'b0;
end
always @(posedge rcdt_in[1])
begin:TRCDrise1
rcdt_out[1] <= #5 1'b1;
end
always @(negedge rcdt_in[1])
begin:TRCDfall1
rcdt_out[1] <= #tdevice_TRCD 1'b0;
end
always @(posedge rcdt_in[2])
begin:TRCDrise2
rcdt_out[2] <= #5 1'b1;
end
always @(negedge rcdt_in[2])
begin:TRCDfall2
rcdt_out[2] <= #tdevice_TRCD 1'b0;
end
always @(posedge rcdt_in[3])
begin:TRCDrise3
rcdt_out[3] <= #5 1'b1;
end
always @(negedge rcdt_in[3])
begin:TRCDfall3
rcdt_out[3] <= #tdevice_TRCD 1'b0;
end
/////////////////////////////////////////////////////////////////////////
// Functional Section
/////////////////////////////////////////////////////////////////////////
always @(posedge CLK)
begin
if ($time > Next_Ref && PoweredUp && Ref_Cnt > 0)
begin
Ref_Cnt = Ref_Cnt - 1;
Next_Ref = $time + tdevice_REF;
end
if (CKEreg)
begin
if (~CSNeg_ipd)
chip_en = 1;
else
chip_en = 0;
end
if (CKEreg && ~CSNeg_ipd)
begin
if (DQM0_ipd == 1'bx)
$display(" Unusable value for DQM0 ");
if (DQM1_ipd == 1'bx)
$display(" Unusable value for DQM1 ");
if (DQM2_ipd == 1'bx)
$display(" Unusable value for DQM2 ");
if (DQM3_ipd == 1'bx)
$display(" Unusable value for DQM3 ");
if (WENeg_ipd == 1'bx)
$display(" Unusable value for WENeg ");
if (RASNeg_ipd == 1'bx)
$display(" Unusable value for RASNeg ");
if (CASNeg_ipd == 1'bx)
$display(" Unusable value for CASNeg ");
// Command Decode
if (RASNeg_ipd && CASNeg_ipd && WENeg_ipd)
command = nop;
else if (~RASNeg_ipd && CASNeg_ipd && WENeg_ipd)
command = act;
else if (RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd)
command = rd;
else if (RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd)
command = writ;
else if (RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd)
command = bst;
else if (~RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd)
command = pre;
else if (~RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd)
command = ref;
else if (~RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd)
command = mrs;
// PowerUp Check
if (~(PoweredUp) && command != nop)
begin
$display (" Incorrect power up. Command issued before ");
$display (" power up complete. ");
end
// Bank Decode
if (~BA0_ipd && ~BA1_ipd)
cur_bank = 0;
else if (BA0_ipd && ~BA1_ipd)
cur_bank = 1;
else if (~BA0_ipd && BA1_ipd)
cur_bank = 2;
else if (BA0_ipd && BA1_ipd)
cur_bank = 3;
else
begin
$display ("Could not decode bank selection - results");
$display ("may be incorrect.");
end
end
// The Big State Machine
if (CKEreg)
begin
if (CSNeg_ipd == 1'bx)
$display ("Unusable value for CSNeg");
if (CSNeg_ipd)
command = nop;
// DQM pipeline
DQM0_reg2 = DQM0_reg1;
DQM0_reg1 = DQM0_reg0;
DQM0_reg0 = DQM0_ipd;
DQM1_reg2 = DQM1_reg1;
DQM1_reg1 = DQM1_reg0;
DQM1_reg0 = DQM1_ipd;
DQM2_reg2 = DQM2_reg1;
DQM2_reg1 = DQM2_reg0;
DQM2_reg0 = DQM2_ipd;
DQM3_reg2 = DQM3_reg1;
DQM3_reg1 = DQM3_reg0;
DQM3_reg0 = DQM3_ipd;
// by default data drive is Z, might get over written in one
// of the passes below
DataDrive = 32'bz;
for (bank = 0; bank <= hi_bank; bank = bank + 1)
begin
case (statebank[bank])
pwron :
begin
if (~DQM0_ipd)
begin
$display ("DQM0 must be held high during");
$display ("initialization.");
end
if (~DQM1_ipd)
begin
$display ("DQM1 must be held high during");
$display ("initialization.");
end
if (~DQM2_ipd)
begin
$display ("DQM2 must be held high during");
$display ("initialization.");
end
if (~DQM3_ipd)
begin
$display ("DQM3 must be held high during");
$display ("initialization.");
end
if (~PoweredUp)
begin
if (command != nop)
$display ("Only NOPs allowed during power up.");
DataDrive = 32'bz;
end
else if (command == pre && (cur_bank == bank || A[10]))
begin
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
end
end
precharge :
begin
if (cur_bank == bank)
// It is only an error if this bank is selected
if (command != nop && command != pre)
begin
$display ("Illegal command received ");
$display ("during precharge.",$time);
end
end
idle :
begin
if (command == nop || command == bst || command == pre
|| cur_bank != bank)
begin
end
else if (command == mrs)
begin
if (statebank[0] == idle && statebank[1] == idle &&
statebank[2] == idle && statebank[3] == idle)
begin
ModeReg = A;
statebank[bank] = mode_set;
end
end
else if (command == ref)
begin
if (statebank[0] == idle && statebank[1] == idle &&
statebank[2] == idle && statebank[3] == idle)
if (CKE)
begin
statebank[bank] = auto_refresh;
statebank[bank] <= #tdevice_TRCAR idle;
end
else
begin
statebank[0] = self_refresh;
statebank[1] = self_refresh;
statebank[2] = self_refresh;
statebank[3] = self_refresh;
end
end
else if (command == act)
begin
statebank[bank] = bank_act;
ras_in[bank] = 1'b1;
ras_in [bank] <= #70 1'b0;
rct_in = 1'b1;
rct_in <= #1 1'b0;
rcdt_in[bank] = 1'b1;
rcdt_in[bank] <= #1 1'b0;
MemAddr[bank][19:8] = A; // latch row addr
end
else
$display ("Illegal command received in idle state.",$time);
end
mode_set :
begin
if (ModeReg[7] != 0 || ModeReg[8] != 0)
$display ("Illegal operating mode set.");
if (command != nop)
begin
$display ("Illegal command received during mode");
$display ("set.",$time);
end
// read burst length
if (ModeReg[2:0] == 3'b000)
begin
BurstLen = 1;
Burst_Bits = 0;
end
else if (ModeReg[2:0] == 3'b001)
begin
BurstLen = 2;
Burst_Bits = 1;
end
else if (ModeReg[2:0] == 3'b010)
begin
BurstLen = 4;
Burst_Bits = 2;
end
else if (ModeReg[2:0] == 3'b011)
begin
BurstLen = 8;
Burst_Bits = 3;
end
else if (ModeReg[2:0] == 3'b111)
begin
BurstLen = 256;
Burst_Bits = 7;
end
else
$display ("Invalid burst length specified.");
// read burst type
if (~ModeReg[3])
Burst = sequential;
else if (ModeReg[3])
Burst = interleave;
else
$display ("Invalid burst type specified.");
// read CAS latency
if (ModeReg[6:4] == 3'b001)
begin
CAS_Lat = 1'b1;
CAS_Lat2 = 1'b0;
end
else if (ModeReg[6:4] == 3'b010)
begin
CAS_Lat = 1'b0;
CAS_Lat2 = 1'b1;
end
else if (ModeReg[6:4] == 3'b011)
begin
CAS_Lat = 1'b1;
CAS_Lat2 = 1'b1;
end
else
$display ("CAS Latency set incorrecty");
// write burst mode
if (~ModeReg[9])
WB = programmed;
else if (ModeReg[9])
WB = single;
else
$display ("Invalid burst type specified.");
statebank[bank] = idle;
end
auto_refresh :
begin
if (Ref_Cnt < 4096)
Ref_Cnt = Ref_Cnt + 1;
if (command != nop)
begin
$display ("Illegal command received during");
$display ("auto_refresh.",$time);
end
end
bank_act :
begin
if (command == pre && (cur_bank == bank || A[10]))
begin
if (~ras_out[bank])
begin
$display ("precharge command does not meet tRAS");
$display ("time", $time);
end
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
end
else if (command == nop || command == bst
|| cur_bank != bank)
begin
end
else if (command == rd)
begin
if (rcdt_out[bank])
begin
$display ("read command received too soon");
$display ("after active",$time);
end
if (A[10] == 1'bx)
begin
$display ("A(10) = X during read command.");
$display ("Next state unknown.");
end
MemAddr[bank][7:0] = 8'b0;// clr old addr
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
BurstIncProc(bank);
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
generate_out(DataDrive,bank);
BurstCnt[bank] = 1;
NextStateAuto(bank, read);
bank_tmp = bank;
end
else if (command == writ)
begin
if (rcdt_out[bank])
begin
$display ("write command received too soon");
$display ("after active",$time);
end
if (A[10] == 1'bx)
begin
$display ("A(10) = X during write command.");
$display ("Next state unknown.");
end
MemAddr[bank][7:0] = 8'b0; // clr old addr
BurstIncProc(bank);
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
MemWrite(bank);
BurstCnt[bank] = 1'b1;
wrt_in = 1'b1;
NextStateAuto(bank, write);
written = 1'b1;
end
else if (cur_bank == bank || command == mrs)
begin
$display ("Illegal command received in");
$display ("active state",$time);
end
end
write :
begin
if (command == bst)
begin
statebank[bank] = bank_act;
BurstCnt[bank] = 1'b0;
end
else if (command == rd)
if (cur_bank == bank)
begin
MemAddr[bank][7:0] = 8'b0;// clr old addr
BurstIncProc(bank);
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
generate_out(DataDrive, bank);
BurstCnt[bank] = 1'b1;
NextStateAuto(bank, read);
end
else
statebank[bank] = bank_act;
else if (command == writ)
if (cur_bank == bank)
begin
MemAddr[bank][7:0] = 8'b0;// clr old addr
BurstIncProc(bank);
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
MemWrite(bank);
BurstCnt[bank] = 1'b1;
wrt_in = 1'b1;
if (A[10])
statebank[bank] = write_auto_pre;
end
else
statebank[bank] = bank_act;
else if (command == pre && (cur_bank == bank || A[10]))
begin
if (~ras_out[bank])
begin
$display ("precharge command does not meet tRAS time",$time);
end
if (~DQM0_ipd)
begin
$display ("DQM0 should be held high, data is");
$display ("lost.",$time);
end
if (~DQM1_ipd)
begin
$display ("DQM1 should be held high, data is");
$display ("lost.",$time);
end
if (~DQM2_ipd)
begin
$display ("DQM2 should be held high, data is");
$display ("lost.",$time);
end
if (~DQM2_ipd)
begin
$display ("DQM2 should be held high, data is");
$display ("lost.",$time);
end
wrt_in = 1'b0;
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
end
else if (command == nop || cur_bank != bank)
if (BurstCnt[bank] == BurstLen || WB == single)
begin
statebank[bank] = bank_act;
BurstCnt[bank] = 1'b0;
ras_in[bank] = 1'b1;
end
else
begin
if (Burst == sequential)
BurstInc[bank] = (BurstInc[bank]+1) % BurstLen;
else
BurstInc[bank] =
intab[StartAddr[bank]*8 + BurstCnt[bank]];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
MemWrite(bank);
BurstCnt[bank] = BurstCnt[bank] + 1;
wrt_in = 1'b1;
end
else if (cur_bank == bank)
$display ("Illegal command received in write state",$time);
end
read :
begin
if (command == bst)
begin
statebank[bank] = bank_act;
BurstCnt[bank] = 1'b0;
end
else if (command == rd)
if (cur_bank == bank)
begin
MemAddr[bank][7:0] = 8'b0;// clr old addr
BurstIncProc(bank);
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
generate_out(DataDrive, bank);
BurstCnt[bank] = 1'b1;
NextStateAuto(bank, read);
end
else
statebank[bank] = bank_act;
else if (command == writ)
if (cur_bank == bank)
begin
if (rcdt_out[bank])
begin
$display ("write command received too soon after active",$time);
end
if (A[10] == 1'bx)
begin
$display ("A(10) = X during write command.");
$display ("Next state unknown.");
end
MemAddr[bank][7:0] = 8'b0;// clr old addr
BurstIncProc(bank);
// latch col addr
if (Burst_Bits == 0)
MemAddr[bank][7:0] = A[7:0];
if (Burst_Bits == 1)
MemAddr[bank][7:1] = A[7:1];
if (Burst_Bits == 2)
MemAddr[bank][7:2] = A[7:2];
if (Burst_Bits == 3)
MemAddr[bank][7:3] = A[7:3];
if (Burst_Bits == 7)
MemAddr[bank][7:7] = A[7:7];
StartAddr[bank] = BurstInc[bank] % 8;
BaseLoc[bank] = MemAddr[bank];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
MemWrite(bank);
BurstCnt[bank] = 1'b1;
wrt_in = 1'b1;
NextStateAuto(bank,write);
end
else
statebank[bank] = bank_act;
else if (command == pre && (cur_bank == bank || A[10]))
begin
if (~ras_out[bank])
begin
$display ("Precharge command does not meet tRAS time",$time);
end
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
end
else if (command == nop || cur_bank != bank)
begin
if (BurstCnt[bank] == BurstLen)
begin
statebank[bank] = bank_act;
BurstCnt[bank] = 1'b0;
ras_in[bank] = 1'b1;
end
else
begin
if (Burst == sequential)
BurstInc[bank] = (BurstInc[bank]+1) % BurstLen;
else
BurstInc[bank] =
intab[StartAddr[bank]*8 + BurstCnt[bank]];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
generate_out(DataDrive, bank);
BurstCnt[bank] = BurstCnt[bank] + 1;
end
end
else if (cur_bank == bank)
$display ("Illegal command received in read state",$time);
end
write_auto_pre :
begin
if (command == nop || cur_bank != bank)
if (BurstCnt[bank] == BurstLen || WB == single)
begin
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
BurstCnt[bank] = 1'b0;
ras_in[bank] = 1'b1;
end
else
begin
if (Burst == sequential)
BurstInc[bank] = (BurstInc[bank]+1) % BurstLen;
else
BurstInc[bank] =
intab[StartAddr[bank]*8 + BurstCnt[bank]];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
MemWrite(bank);
BurstCnt[bank] = BurstCnt[bank] + 1;
wrt_in = 1'b1;
end
else
$display ("Illegal command received in write state.",$time);
end
read_auto_pre :
begin
if (command == nop || (cur_bank != bank && command != rd
&& command != writ))
if (BurstCnt[bank] == BurstLen)
begin
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
BurstCnt[bank] = 1'b0;
ras_in[bank] = 1'b1;
end
else
begin
if (Burst == sequential)
BurstInc[bank] = (BurstInc[bank]+1) % BurstLen;
else
BurstInc[bank] =
intab[StartAddr[bank]*8 + BurstCnt[bank]];
Loc = 4*(BaseLoc[bank] + BurstInc[bank]);
generate_out(DataDrive, bank);
BurstCnt[bank] = BurstCnt[bank] + 1;
end
else if ((command == rd || command == writ) && cur_bank
!= bank)
begin
statebank[bank] = precharge;
statebank[bank] <= #tdevice_TRP idle;
end
else
$display ("Illegal command received in read state",$time);
end
endcase
end
// Check Refresh Status
if (written && (Ref_Cnt == 0))
$display ("memory not refreshed (by ref_cnt)", $time);
DataDrive3 = DataDrive2;
DataDrive2 = DataDrive1;
DataDrive1 = DataDrive;
end
// Latency adjustments and DQM read masking
if (~DQM0_reg1)
if (CAS_Lat && CAS_Lat2)
DataDriveOut[7:0] = DataDrive3[7:0];
else if (~CAS_Lat && CAS_Lat2)
DataDriveOut[7:0] = DataDrive2[7:0];
else
DataDriveOut[7:0] = DataDrive1[7:0];
else
DataDriveOut[7:0] = 8'bz;
if (~DQM1_reg1)
if (CAS_Lat && CAS_Lat2)
DataDriveOut[15:8] = DataDrive3[15:8];
else if (~CAS_Lat && CAS_Lat2)
DataDriveOut[15:8] = DataDrive2[15:8];
else
DataDriveOut[15:8] = DataDrive1[15:8];
else
DataDriveOut[15:8] = 8'bz;
if (~DQM2_reg1)
if (CAS_Lat && CAS_Lat2)
DataDriveOut[23:16] = DataDrive3[23:16];
else if (~CAS_Lat && CAS_Lat2)
DataDriveOut[23:16] = DataDrive2[23:16];
else
DataDriveOut[23:16] = DataDrive1[23:16];
else
DataDriveOut[23:16] = 8'bz;
if (~DQM3_reg1)
if (CAS_Lat && CAS_Lat2)
DataDriveOut[31:24] = DataDrive3[31:24];
else if (~CAS_Lat && CAS_Lat2)
DataDriveOut[31:24] = DataDrive2[31:24];
else
DataDriveOut[31:24] = DataDrive1[31:24];
else
DataDriveOut[31:24] = 8'bz;
// The Powering-up State Machine
if (~CKEreg && CKE_ipd)
begin
if (CSNeg_ipd == 1'bx)
$display ("Unusable value for CSNeg");
if (CSNeg_ipd)
command = nop;
case (statebank[cur_bank])
write_suspend :
begin
statebank[cur_bank] = write;
end
read_suspend :
begin
statebank[cur_bank] = read;
end
self_refresh :
begin
statebank[0] <= #tdevice_TRP idle;
statebank[1] <= #tdevice_TRP idle;
statebank[2] <= #tdevice_TRP idle;
statebank[3] <= #tdevice_TRP idle;
Ref_Cnt = 4096;
if (command != nop)
begin
$display ("Illegal command received during self");
$display ("refresh",$time);
end
end
pwrdwn :
begin
statebank[0] = idle;
statebank[1] = idle;
statebank[2] = idle;
statebank[3] = idle;
end
bank_act_pwrdwn :
begin
statebank[cur_bank] = bank_act;
end
endcase
end
// The Powering-down State Machine
if (CKEreg && ~CKE_ipd)
begin
if (CSNeg_ipd == 1'bx)
$display ("Unusable value for CSNeg");
if (CSNeg_ipd)
command = nop;
case (statebank[cur_bank])
idle :
begin
if (command == nop)
begin
statebank[0] = pwrdwn;
statebank[1] = pwrdwn;
statebank[2] = pwrdwn;
statebank[3] = pwrdwn;
end
end
write :
begin
statebank[cur_bank] = write_suspend;
end
read :
begin
statebank[cur_bank] = read_suspend;
end
bank_act :
begin
statebank[cur_bank] = bank_act_pwrdwn;
end
endcase
end
CKEreg = CKE_ipd;
end
always @(DataDriveOut)
begin
DQ_zd = DataDriveOut;
end
reg TRC_In , TRCAR_In;
reg TRCD_In , TRP_In , TWR_In;
wire TRC_Out, TRCAR_Out, TRCD_Out, TRP_Out, TWR_Out;
BUFFER BUF_TRC (TRC_Out , TRC_In);
BUFFER BUF_TRCAR (TRCAR_Out, TRCAR_In);
BUFFER BUF_TRCD (TRCD_Out , TRCD_In);
BUFFER BUF_TRP (TRP_Out , TRP_In);
BUFFER BUF_TWR (TWR_Out , TWR_In);
initial
begin
TRC_In = 1;
TRCAR_In = 1;
TRCD_In = 1'b1;
TRP_In = 1;
TWR_In = 1;
end
always @(posedge TRC_Out)
begin
tdevice_TRC = $time;
end
always @(posedge TRCAR_Out)
begin
tdevice_TRCAR = $time;
end
always @(posedge TRCD_Out)
begin
tdevice_TRCD = $time;
end
always @(posedge TRP_Out)
begin
tdevice_TRP = $time;
end
always @(posedge TWR_Out)
begin
tdevice_TWR = $time;
end
endmodule
module BUFFER (OUT,IN);
input IN;
output OUT;
buf (OUT, IN);
endmodule