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

Subversion Repositories mem_ctrl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mem_ctrl/trunk/bench/verilog
    from Rev 23 to Rev 28
    Reverse comparison

Rev 23 → Rev 28

/test_bench_top.v
0,0 → 1,1108
/////////////////////////////////////////////////////////////////////
//// ////
//// Top Level Test Bench ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: test_bench_top.v,v 1.7 2002-01-21 13:10:37 rudi Exp $
//
// $Date: 2002-01-21 13:10:37 $
// $Revision: 1.7 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.6 2001/11/29 02:17:36 rudi
//
//
// - More Synthesis cleanup, mostly for speed
// - Several bug fixes
// - Changed code to avoid auto-precharge and
// burst-terminate combinations (apparently illegal ?)
// Now we will do a manual precharge ...
//
// Revision 1.5 2001/11/13 00:45:15 rudi
//
// Just minor test bench update, syncing all the files.
//
// Revision 1.4 2001/11/11 01:52:02 rudi
//
// Minor fixes to testbench ...
//
// Revision 1.3 2001/09/02 02:29:43 rudi
//
// Fixed the TMS register setup to be tight and correct.
//
// Revision 1.2 2001/08/10 08:16:21 rudi
//
// - Changed IO names to be more clear.
// - Uniquifyed define names to be core specific.
// - Removed "Refresh Early" configuration
//
// Revision 1.1 2001/07/29 07:34:40 rudi
//
//
// 1) Changed Directory Structure
// 2) Fixed several minor bugs
//
// Revision 1.2 2001/06/03 11:34:18 rudi
// *** empty log message ***
//
// Revision 1.1.1.1 2001/05/13 09:36:32 rudi
// Created Directory Structure
//
//
//
//
 
`include "mc_defines.v"
 
module test;
 
reg clk;
reg rst;
 
// IO Prototypes
 
wire [31:0] wb_data_i;
wire [31:0] wb_data_o;
wire [31:0] wb_addr_i;
wire [3:0] wb_sel_i;
wire wb_we_i;
wire wb_cyc_i;
wire wb_stb_i;
wire wb_ack_o;
wire wb_err_o;
wire wb_rty_o;
 
reg susp_req, resume_req;
wire suspended;
wire [31:0] poc;
 
reg mc_clk;
reg mc_br;
wire mc_bg;
wire mc_ack;
wire [23:0] mc_addr;
wire [31:0] mc_data_i;
wire [31:0] mc_data_o;
wire [3:0] mc_dp_i;
wire [3:0] mc_dp_o;
wire mc_data_oe;
wire [3:0] mc_dqm;
wire mc_oe_;
wire mc_we_;
wire mc_cas_;
wire mc_ras_;
wire mc_cke_;
wire [7:0] mc_cs_;
wire mc_sts;
wire mc_rp_;
wire mc_vpen;
wire mc_adsc_;
wire mc_adv_;
wire mc_zz;
wire mc_c_oe;
 
 
// Test Bench Variables
reg [31:0] wd_cnt;
integer error_cnt;
integer verbose;
integer poc_mode;
reg wb_err_check_dis;
integer LVL;
 
integer cyc_cnt;
integer ack_cnt;
 
// Misc Variables
 
integer n,m;
 
reg [31:0] data;
 
reg [31:0] buffer32;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer read, write;
integer done;
integer adr;
integer do_quick;
 
/////////////////////////////////////////////////////////////////////
//
// Defines
//
 
`define MEM_BASE 32'h0000_0000
`define MEM_BASE1 32'h0400_0000
`define MEM_BASE2 32'h0800_0000
`define MEM_BASE3 32'h0c00_0000
`define MEM_BASE4 32'h1000_0000
`define MEM_BASE5 32'h1400_0000
`define MEM_BASE6 32'h1800_0000
`define REG_BASE 32'h6000_0000
 
`define CSR 8'h00
`define POC 8'h04
`define BA_MASK 8'h08
 
`define CSC0 8'h10
`define TMS0 8'h14
`define CSC1 8'h18
`define TMS1 8'h1c
`define CSC2 8'h20
`define TMS2 8'h24
`define CSC3 8'h28
`define TMS3 8'h2c
`define CSC4 8'h30
`define TMS4 8'h34
`define CSC5 8'h38
`define TMS5 8'h3c
`define CSC6 8'h40
`define TMS6 8'h44
`define CSC7 8'h48
`define TMS7 8'h4c
 
/////////////////////////////////////////////////////////////////////
//
// Simulation Initialization and Start up Section
//
 
`define SDRAM0 1
`define SRAM 1
`define MULTI_SDRAM 1
`define FLASH 1
`define MICRON 1
 
initial
begin
$display("\n\n");
$display("*****************************************************");
$display("* WISHBONE Memory Controller Simulation started ... *");
$display("*****************************************************");
$display("\n");
`ifdef WAVES
$shm_open("waves");
$shm_probe("AS",test,"AS");
$display("INFO: Signal dump enabled ...\n\n");
`endif
do_quick = 0;
poc_mode = 1;
#1;
poc_mode = 0;
wb_err_check_dis=0;
cyc_cnt = 0;
ack_cnt = 0;
wd_cnt = 0;
error_cnt = 0;
clk = 1;
mc_clk = 0;
rst = 1;
susp_req = 0;
resume_req = 0;
verbose = 1;
mc_br = 0;
 
repeat(11) @(posedge clk);
#1;
rst = 0;
repeat(10) @(posedge clk);
 
// HERE IS WHERE THE TEST CASES GO ...
 
LVL = 2;
if(0) // Full Regression Run
begin
$display(" ......................................................");
$display(" : :");
$display(" : Long Regression Run ... :");
$display(" :....................................................:");
verbose = 0;
`ifdef FLASH
boot(0);
`endif
 
m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0000_0000);
sdram_wr1(0);
sdram_rd1(0);
sdram_rd2(0);
sdram_wr2(0);
sdram_rd3(0);
sdram_wr3(0);
sdram_rd4(0);
sdram_wr4(0);
sdram_wp(0);
sdram_bo;
sdram_rmw1(0);
sdram_rmw2(0);
rmw_cross1(0);
 
`ifdef MULTI_SDRAM
sdram_rd5(0);
sdram_wr5(0);
`endif
 
`ifdef FLASH
asc_rdwr1(0);
`endif
 
`ifdef SRAM
sram_rd1;
sram_wr1;
sram_wp;
sram_rmw1;
sram_rmw2;
`endif
 
scs_rdwr1(0);
end
else
if(1) // Quick Regression Run
begin
$display(" ......................................................");
$display(" : :");
$display(" : Short Regression Run ... :");
$display(" :....................................................:");
do_quick = 1;
verbose = 0;
LVL = 1;
 
`ifdef FLASH
boot(LVL);
`endif
m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0000_0000);
 
sdram_rd1(LVL);
sdram_wr1(LVL);
 
sdram_rd2(LVL);
sdram_wr2(LVL);
 
sdram_rd3(LVL);
sdram_wr3(LVL);
 
sdram_rd4(LVL);
sdram_wr4(LVL);
 
sdram_wp(LVL);
sdram_bo;
sdram_rmw1(LVL);
sdram_rmw2(LVL);
rmw_cross1(LVL);
 
`ifdef MULTI_SDRAM
sdram_rd5(LVL);
sdram_wr5(LVL);
`endif
 
 
`ifdef FLASH
asc_rdwr1(LVL);
`endif
 
`ifdef SRAM
sram_rd1;
sram_wr1;
sram_wp;
sram_rmw1;
sram_rmw2;
`endif
scs_rdwr1(LVL);
 
mc_reset;
end
if(do_quick) // Suspend resume testing
begin
$display(" ......................................................");
$display(" : :");
$display(" : Suspend Resume Testing ... :");
$display(" :....................................................:");
//verbose = 0;
//LVL = 1;
done = 0;
fork
begin
 
`ifdef FLASH
boot(LVL);
`endif
m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0000_0000);
 
while(susp_req | suspended) @(posedge clk);
sdram_rd1(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_wr1(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_rd2(LVL);
 
while(susp_req | suspended) @(posedge clk);
sdram_wr2(LVL);
 
while(susp_req | suspended) @(posedge clk);
sdram_rd3(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_wr3(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_rd4(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_wr4(LVL);
 
while(susp_req | suspended) @(posedge clk);
sdram_wp(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_bo;
while(susp_req | suspended) @(posedge clk);
sdram_rmw1(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_rmw2(LVL);
 
while(susp_req | suspended) @(posedge clk);
rmw_cross1(LVL);
 
 
`ifdef MULTI_SDRAM
while(susp_req | suspended) @(posedge clk);
sdram_rd5(LVL);
while(susp_req | suspended) @(posedge clk);
sdram_wr5(LVL);
`endif
 
`ifdef FLASH
while(susp_req | suspended) @(posedge clk);
asc_rdwr1(LVL);
`endif
 
`ifdef SRAM
while(susp_req | suspended) @(posedge clk);
sram_rd1;
while(susp_req | suspended) @(posedge clk);
sram_wr1;
while(susp_req | suspended) @(posedge clk);
sram_wp;
while(susp_req | suspended) @(posedge clk);
sram_wp;
while(susp_req | suspended) @(posedge clk);
sram_rmw1;
 
while(susp_req | suspended) @(posedge clk);
sram_rmw1;
while(susp_req | suspended) @(posedge clk);
sram_rmw2;
`endif
while(susp_req | suspended) @(posedge clk);
scs_rdwr1(LVL);
 
done = 1;
end
 
begin
repeat(50) @(posedge clk);
while(!done)
begin
repeat(40) @(posedge clk);
susp_res;
end
end
join
 
mc_reset;
end
if(do_quick) // Bus Request testing
begin
$display(" ......................................................");
$display(" : :");
$display(" : Bus Request/Grant Testing ... :");
$display(" :....................................................:");
verbose = 0;
done = 0;
fork
begin
`ifdef FLASH
boot(LVL);
`endif
 
m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0000_0000);
 
sdram_rd1(LVL);
sdram_wr1(LVL);
sdram_rd1(LVL);
sdram_wr1(LVL);
sdram_rd3(LVL);
sdram_wr3(LVL);
sdram_rd4(LVL);
sdram_wr4(LVL);
sdram_wp(LVL);
sdram_bo;
sdram_rmw1(LVL);
sdram_rmw2(LVL);
 
`ifdef MULTI_SDRAM
sdram_rd5(LVL);
sdram_wr5(LVL);
`endif
 
 
`ifdef FLASH
asc_rdwr1(LVL);
`endif
 
`ifdef SRAM
sram_rd1;
sram_wr1;
sram_wp;
sram_rmw1;
sram_rmw2;
`endif
scs_rdwr1(LVL);
done = 1;
end
 
begin
repeat(50) @(posedge clk);
while(!done)
begin
repeat(40) @(posedge clk);
bus_req;
end
end
 
join
end
else
if(0) // Debug Tests
begin
$display(" ......................................................");
$display(" : :");
$display(" : Test Debug Testing ... :");
$display(" :....................................................:");
verbose = 0;
//boot(2);
 
m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0000_0000);
//sdram_rd1(2);
//sdram_wr1(2);
//asc_rdwr1(2);
// sram_rd1;
// sram_wr1;
//sram_rmw1;
//sram_rmw2;
//sram_wp;
//scs_rdwr1(2);
 
//scs_rdwr1(2);
 
//asc_rdwr1(2);
//asc_rdwr1_x(2);
 
//sdram_wp(2);
//sdram_rmw1(2);
//sdram_rmw2(2);
 
//sdram_rd2(2);
//sdram_wr2(2);
 
//sdram_bo;
//sdram_rd1b(2);
 
 
 
 
//sdram_rd4(2);
//sdram_wr4(2);
//sdram_rd5(2);
//sdram_wr5(2);
 
//sdram_wp(2);
//sdram_rmw1(2);
//sdram_rmw2(2);
 
//rmw_cross1(2);
 
/*
sram_rd1;
sram_wr1;
sram_rmw1;
sram_rmw2;
sram_wp;
*/
 
 
sdram_rd1(2);
sdram_wr1(2);
sdram_rd2(2);
sdram_wr2(2);
sdram_rd3(2);
sdram_wr3(2);
sdram_rd4(2);
sdram_wr4(2);
 
 
sdram_rd5(2);
sdram_wr5(2);
 
sdram_wp(2);
 
sdram_rmw1(2);
sdram_rmw2(2);
rmw_cross1(2);
 
 
 
 
repeat(100) @(posedge clk);
$finish;
end
else
begin
 
//
// TEST DEVELOPMENT AREA
//
$display("\n\n");
$display("*****************************************************");
$display("*** Test Development ... ***");
$display("*****************************************************\n");
 
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
 
repeat(100) @(posedge clk);
$finish;
 
end // End of Initial
 
 
/////////////////////////////////////////////////////////////////////
//
// Clock Generation
//
 
always #2.5 clk = ~clk;
 
always @(posedge clk)
mc_clk <= ~mc_clk;
 
/////////////////////////////////////////////////////////////////////
//
// IO Monitors
//
 
`define STD 10
always @(posedge clk)
if((wb_ack_o === 1'bx) & ($time > `STD) )
begin
$display("ERROR: Wishbone ACK unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(posedge clk)
if( (wb_err_o === 1'bx) & ($time > `STD) )
 
begin
$display("ERROR: Wishbone ERR unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(posedge clk)
if( (mc_ras_ === 1'bx) & ($time > `STD) )
 
begin
$display("ERROR: MC RAS unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(posedge clk)
if( (mc_cas_ === 1'bx) & ($time > `STD) )
 
begin
$display("ERROR: MC CAS unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(posedge clk)
if( (mc_we_ === 1'bx) & ($time > `STD) )
 
begin
$display("ERROR: MC WE unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(posedge clk)
if( ((|mc_cs_) === 1'bx) & ($time > `STD) )
 
begin
$display("ERROR: MC CS unknown (%t)", $time);
error_cnt = error_cnt + 1;
end
 
always @(error_cnt)
if(error_cnt > 25) #500 $finish;
 
/*
time mc_time;
 
always @(posedge mc_clk)
mc_time = $time;
 
always @(mc_cke_)
if($time != (mc_time+1) )
$display("WARNING: Unsexpected change of CKE (%t)", $time);
*/
/////////////////////////////////////////////////////////////////////
//
// IO Buffers
//
 
reg rst_r1, rst_r2, rst_r3, rst_r4;
 
always @(posedge clk or posedge rst)
if(rst) rst_r1 <= #1 1'b1;
else rst_r1 <= #1 1'b0;
 
always @(posedge clk or posedge rst)
if(rst) rst_r2 <= #1 1'b1;
else rst_r2 <= #1 rst_r1;
 
always @(posedge clk or posedge rst)
if(rst) rst_r3 <= #1 1'b1;
else rst_r3 <= #1 rst_r2;
 
always @(posedge clk or posedge rst)
if(rst) rst_r4 <= #1 1'b1;
else rst_r4 <= #1 rst_r3;
 
 
wire [31:0] mc_dq;
wire [3:0] mc_dqp;
wire [23:0] _mc_addr;
wire [3:0] _mc_dqm;
wire _mc_oe_;
wire _mc_we_;
wire _mc_cas_;
wire _mc_ras_;
wire _mc_cke_;
wire [7:0] _mc_cs_;
wire _mc_rp_;
wire _mc_vpen;
wire _mc_adsc_;
wire _mc_adv_;
wire _mc_zz;
reg [31:0] rst_dq_val;
 
always @(poc_mode)
case(poc_mode)
0: rst_dq_val = {28'hzzz_zzzz, 2'b10, 2'b00};
1: rst_dq_val = {28'hzzz_zzzz, 2'b10, 2'b01};
2: rst_dq_val = {28'hzzz_zzzz, 2'b10, 2'b10};
// 3: rst_dq_val = {28'hzzzz_zzzz, 2'b10, 2'b11};
default: rst_dq_val = 32'hzzzz_zzzz;
endcase
 
assign mc_dq = mc_data_oe ? mc_data_o : (rst_r4 ? rst_dq_val : 32'hzzzz_zzzz);
assign mc_data_i = mc_dq;
 
assign mc_dqp = mc_data_oe ? mc_dp_o : 4'hz;
assign mc_dp_i = mc_dqp;
 
assign mc_addr = mc_c_oe ? _mc_addr : 24'bz;
assign mc_dqm = mc_c_oe ? _mc_dqm : 4'bz;
assign mc_oe_ = mc_c_oe ? _mc_oe_ : 1'bz;
assign mc_we_ = mc_c_oe ? _mc_we_ : 1'bz;
assign mc_cas_ = mc_c_oe ? _mc_cas_ : 1'bz;
assign mc_ras_ = mc_c_oe ? _mc_ras_ : 1'bz;
assign mc_cke_ = mc_c_oe ? _mc_cke_ : 1'bz;
assign mc_cs_ = mc_c_oe ? _mc_cs_ : 8'bz;
assign mc_rp_ = mc_c_oe ? _mc_rp_ : 1'bz;
assign mc_vpen = mc_c_oe ? _mc_vpen : 1'bz;
assign mc_adsc_ = mc_c_oe ? _mc_adsc_ : 1'bz;
assign mc_adv_ = mc_c_oe ? _mc_adv_ : 1'bz;
assign mc_zz = mc_c_oe ? _mc_zz : 1'bz;
 
pullup p0(mc_cas_);
pullup p1(mc_ras_);
pullup p2(mc_oe_);
pullup p3(mc_we_);
pullup p4(mc_cke_);
pullup p5(mc_adsc_);
pullup p6(mc_adv_);
pullup p70(mc_cs_[0]);
pullup p71(mc_cs_[1]);
pullup p72(mc_cs_[2]);
pullup p73(mc_cs_[3]);
pullup p74(mc_cs_[4]);
pullup p75(mc_cs_[5]);
pullup p76(mc_cs_[6]);
pullup p77(mc_cs_[7]);
pullup p8(mc_rp_);
 
 
/////////////////////////////////////////////////////////////////////
//
// WISHBONE Memory Controller IP Core
//
mc_top u0(
.clk_i( clk ),
.rst_i( rst ),
.wb_data_i( wb_data_i ),
.wb_data_o( wb_data_o ),
.wb_addr_i( wb_addr_i ),
.wb_sel_i( wb_sel_i ),
.wb_we_i( wb_we_i ),
.wb_cyc_i( wb_cyc_i ),
.wb_stb_i( wb_stb_i ),
.wb_ack_o( wb_ack_o ),
.wb_err_o( wb_err_o ),
.susp_req_i( susp_req ),
.resume_req_i( resume_req ),
.suspended_o( suspended ),
.poc_o( poc ),
.mc_clk_i( mc_clk ),
.mc_br_pad_i( mc_br ),
.mc_bg_pad_o( mc_bg ),
.mc_ack_pad_i( mc_ack ),
.mc_addr_pad_o( _mc_addr ),
.mc_data_pad_i( mc_data_i ),
.mc_data_pad_o( mc_data_o ),
.mc_dp_pad_i( mc_dp_i ),
.mc_dp_pad_o( mc_dp_o ),
.mc_doe_pad_doe_o(mc_data_oe ),
.mc_dqm_pad_o( _mc_dqm ),
.mc_oe_pad_o_( _mc_oe_ ),
.mc_we_pad_o_( _mc_we_ ),
.mc_cas_pad_o_( _mc_cas_ ),
.mc_ras_pad_o_( _mc_ras_ ),
.mc_cke_pad_o_( _mc_cke_ ),
.mc_cs_pad_o_( _mc_cs_ ),
.mc_sts_pad_i( mc_sts ),
.mc_rp_pad_o_( _mc_rp_ ),
.mc_vpen_pad_o( _mc_vpen ),
.mc_adsc_pad_o_(_mc_adsc_ ),
.mc_adv_pad_o_( _mc_adv_ ),
.mc_zz_pad_o( _mc_zz ),
.mc_coe_pad_coe_o(mc_c_oe )
);
 
/////////////////////////////////////////////////////////////////////
//
// WISHBONE Master Model
//
 
wb_mast m0( .clk( clk ),
.rst( ~rst ),
.adr( wb_addr_i ),
.din( wb_data_o ),
.dout( wb_data_i ),
.cyc( wb_cyc_i ),
.stb( wb_stb_i ),
.sel( wb_sel_i ),
.we( wb_we_i ),
.ack( wb_ack_o ),
.err( wb_err_o ),
.rty( wb_rty_o )
);
 
/////////////////////////////////////////////////////////////////////
//
// Sync. CS Device Model
//
 
sync_cs_dev s0(
.clk( mc_clk ),
.addr( mc_addr[15:0] ),
.dq( mc_dq ),
.cs_( mc_cs_[5] ),
.we_( mc_we_ ),
.oe_( mc_oe_ ),
.ack_( mc_ack )
);
 
 
/////////////////////////////////////////////////////////////////////
//
// Memory Models
//
 
wire [27:0] dq_tmp;
 
`ifdef SDRAM0
// Model: MT48LC2M32B2 (2Meg x 32 x 4 Banks)
mt48lc2m32b2 sdram0(
.Dq( mc_dq ),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[0] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
mt48lc2m32b2 sdram0p(
.Dq( {dq_tmp, mc_dqp}),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[0] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
`endif
 
`ifdef MULTI_SDRAM
// Model: MT48LC2M32B2 (2Meg x 32 x 4 Banks)
 
mt48lc2m32b2 sdram1(
.Dq( mc_dq ),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[1] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
mt48lc2m32b2 sdram1p(
.Dq( {dq_tmp, mc_dqp} ),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[1] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
 
// Model: MT48LC2M32B2 (2Meg x 32 x 4 Banks)
mt48lc2m32b2 sdram2(
.Dq( mc_dq ),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[2] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
mt48lc2m32b2 sdram2p(
.Dq( {dq_tmp, mc_dqp}),
.Addr( mc_addr[10:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[2] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm )
);
 
mt48lc16m16a2 sdram1a(
.Dq( mc_dq[15:0] ),
.Addr( mc_addr[12:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[5] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm[1:0] )
);
 
mt48lc16m16a2 sdram1b(
.Dq( mc_dq[31:16] ),
.Addr( mc_addr[12:0] ),
.Ba( mc_addr[14:13] ),
.Clk( mc_clk ),
.Cke( mc_cke_ ),
.Cs_n( mc_cs_[5] ),
.Ras_n( mc_ras_ ),
.Cas_n( mc_cas_ ),
.We_n( mc_we_ ),
.Dqm( mc_dqm[3:2] )
);
 
`endif
 
`ifdef FLASH
IntelAdvBoot f1(
.dq( mc_dq[15:0] ),
.addr( mc_addr[19:0] ),
.ceb( mc_cs_[3] ),
.oeb( mc_oe_ ),
.web( mc_we_ ),
.rpb( mc_rp_ ),
.wpb( 1'b0 ),
.vpp( 3300 ),
.vcc( 3300 )
);
`endif
 
 
`ifdef SRAM
 
`ifdef MICRON
mt58l1my18d sram0a(
.Dq( {mc_dqp[1],
mc_dq[15:8],
mc_dqp[0],
mc_dq[7:0]} ),
 
.Addr( mc_addr[19:0] ),
.Mode( 1'b0 ),
.Adv_n( mc_adv_ ),
.Clk( mc_clk ),
.Adsc_n( mc_adsc_ ),
.Adsp_n( 1'b1 ),
 
.Bwa_n( mc_dqm[0] ),
.Bwb_n( mc_dqm[1] ),
.Bwe_n( mc_we_ ),
.Gw_n( 1'b1 ),
 
.Ce_n( mc_cs_[4] ),
.Ce2( 1'b1 ),
.Ce2_n( 1'b0 ),
.Oe_n( mc_oe_ ),
.Zz( mc_zz )
);
 
 
mt58l1my18d sram0b(
.Dq( {mc_dqp[3],
mc_dq[31:24],
mc_dqp[2],
mc_dq[23:16]} ),
 
.Addr( mc_addr[19:0] ),
.Mode( 1'b0 ),
.Adv_n( mc_adv_ ),
.Clk( mc_clk ),
.Adsc_n( mc_adsc_ ),
.Adsp_n( 1'b1 ),
 
.Bwa_n( mc_dqm[2] ),
.Bwb_n( mc_dqm[3] ),
.Bwe_n( mc_we_ ),
.Gw_n( 1'b1 ),
 
.Ce_n( mc_cs_[4] ),
.Ce2( 1'b1 ),
.Ce2_n( 1'b0 ),
.Oe_n( mc_oe_ ),
.Zz( mc_zz )
);
 
`else
 
idt71t67802s133 sram0a(
.A( mc_addr[18:0] ),
.D( mc_dq[15:0] ),
.DP( mc_dqp[1:0] ),
.oe_( mc_oe_ ),
.ce_( mc_cs_[4] ),
.cs0( 1'b1 ),
.cs1_( 1'b0 ),
.lbo_( 1'b0 ),
 
.gw_( 1'b1 ),
.bwe_( mc_we_ ),
.bw2_( mc_dqm[1] ),
.bw1_( mc_dqm[0] ),
 
.adsp_( 1'b1 ),
.adsc_( mc_adsc_ ),
.adv_( mc_adv_ ),
.clk( mc_clk )
);
 
idt71t67802s133 sram0b(
.A( mc_addr[18:0] ),
.D( mc_dq[31:16] ),
.DP( mc_dqp[3:2] ),
.oe_( mc_oe_ ),
.ce_( mc_cs_[4] ),
.cs0( 1'b1 ),
.cs1_( 1'b0 ),
.lbo_( 1'b0 ),
 
.gw_( 1'b1 ),
.bwe_( mc_we_ ),
.bw2_( mc_dqm[3] ),
.bw1_( mc_dqm[2] ),
 
.adsp_( 1'b1 ),
.adsc_( mc_adsc_ ),
.adv_( mc_adv_ ),
.clk( mc_clk )
);
`endif
 
`endif
 
`include "tests.v"
`include "test_lib.v"
 
endmodule
 
/sram_models/MicronSRAM/mt58l1my18d.v
0,0 → 1,220
/****************************************************************************************
*
* File Name: MT58L1MY18D.V
* Version: 1.3
* Date: March 8th, 1999
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Part #: MT58L1MY18D (1Mb x 18)
*
* Description: This is Micron's Syncburst SRAM (Pipelined DCD)
*
* Limitation:
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
* Copyright (c) 1997 Micron Semiconductor Products, Inc.
* All rights researved
*
* Rev Author Date Changes
* --- ---------------------------- ---------- ---------------------------------------
* 1.3 Son P. Huynh 208-368-3825 03/08/1999 Improve model functionality
* Micron Technology, Inc.
*
****************************************************************************************/
 
// DO NOT CHANGE THE TIMESCALE
// MAKE SURE YOUR SIMULATOR USE "PS" RESOLUTION
`timescale 1ns / 100ps
 
module mt58l1my18d (Dq, Addr, Mode, Adv_n, Clk, Adsc_n, Adsp_n, Bwa_n, Bwb_n, Bwe_n, Gw_n, Ce_n, Ce2, Ce2_n, Oe_n, Zz);
 
parameter addr_bits = 20; // 20 bits
parameter data_bits = 18; // 18 bits
parameter mem_sizes = 1048575; // 1 Mb
parameter reg_delay = 0.1; // 100 ps
parameter out_delay = 0.1; // 100 ps
parameter tKQHZ = 3.5; // -6 device
 
inout [(data_bits - 1) : 0] Dq; // Data IO
input [(addr_bits - 1) : 0] Addr; // Address
input Mode; // Burst Mode
input Adv_n; // Synchronous Address Advance
input Clk; // Clock
input Adsc_n; // Synchronous Address Status Controller
input Adsp_n; // Synchronous Address Status Processor
input Bwa_n; // Synchronous Byte Write Enables
input Bwb_n; // Synchronous Byte Write Enables
input Bwe_n; // Byte Write Enable
input Gw_n; // Global Write
input Ce_n; // Synchronous Chip Enable
input Ce2; // Synchronous Chip Enable
input Ce2_n; // Synchronous Chip Enable
input Oe_n; // Output Enable
input Zz; // Snooze Mode
 
reg [((data_bits / 2) - 1) : 0] bank0 [0 : mem_sizes]; // Memory Bank 0
reg [((data_bits / 2) - 1) : 0] bank1 [0 : mem_sizes]; // Memory Bank 1
 
reg [(data_bits - 1) : 0] din; // Input Registers
reg [(data_bits - 1) : 0] dout; // Output Registers
reg [(addr_bits - 1) : 0] addr_reg_in; // Address Register In
reg [(addr_bits - 1) : 0] addr_reg_read; // Address Register for Read Operation
reg [1 : 0] bcount; // 2-bit Burst Counter
 
reg ce_reg;
reg pipe_reg;
reg bwa_reg;
reg bwb_reg;
reg sys_clk;
 
wire ce = (~Ce_n & ~Ce2_n & Ce2);
wire bwa_n = (((Bwa_n | Bwe_n) & Gw_n) | (~Ce_n & ~Adsp_n));
wire bwb_n = (((Bwb_n | Bwe_n) & Gw_n) | (~Ce_n & ~Adsp_n));
wire clr = (~Adsc_n | (~Adsp_n & ~Ce_n));
 
wire [(addr_bits - 1) : 0] addr_reg_write; // Address Register for Write Operation
wire baddr1; // Burst Address 1
wire baddr0; // Burst Address 0
 
// Initialize
initial begin
ce_reg = 1'b0;
sys_clk = 1'b0;
pipe_reg = 1'b0;
$timeformat (-9, 1, " ns", 10); // Format time unit
end
 
 
task mem_fill;
input x;
 
integer a, n, x;
reg [15:0] data;
begin
 
a=0;
for(n=0;n<x;n=n+1)
begin
data = a;
bank0[n] = { ^data[15:8], data[15:8], ^data[7:0], data[7:0]};
data = a+1;
bank1[n] = { ^data[15:8], data[15:8], ^data[7:0], data[7:0]};
a=a+2;
end
 
end
endtask
 
// System Clock
always begin
@ (posedge Clk) begin
sys_clk = ~Zz;
end
@ (negedge Clk) begin
sys_clk = 1'b0;
end
end
 
always @ (posedge sys_clk) begin
// Address Register
if (clr) addr_reg_in <= Addr;
addr_reg_read <= {addr_reg_in [(addr_bits - 1) : 2], baddr1, baddr0};
 
// Binary Counter and Logic
if ( Mode & clr) bcount <= 0; // Interleaved Burst
else if (~Mode & clr) bcount <= Addr [1 : 0]; // Linear Burst
else if (~Adv_n & ~clr) bcount <= (bcount + 1); // Advance Counter
 
// Byte Write Register
bwa_reg <= ~bwa_n;
bwb_reg <= ~bwb_n;
 
// Enable Register
if (clr) ce_reg <= ce;
 
// Pipelined Enable
pipe_reg <= ce_reg;
end
 
// Burst Address Decode
assign addr_reg_write = {addr_reg_in [(addr_bits - 1) : 2], baddr1, baddr0};
assign baddr1 = Mode ? (bcount [1] ^ addr_reg_in [1]) : bcount [1];
assign baddr0 = Mode ? (bcount [0] ^ addr_reg_in [0]) : bcount [0];
 
// Write Driver
always @ (posedge Clk) begin
#reg_delay;
if (ce_reg & bwa_reg) begin
din [data_bits / 2 - 1 : 0] <= Dq [data_bits / 2 - 1 : 0];
bank0 [addr_reg_write] <= Dq [data_bits / 2 - 1 : 0];
end
if (ce_reg & bwb_reg) begin
din [data_bits - 1 : data_bits / 2] <= Dq [data_bits - 1 : data_bits / 2];
bank1 [addr_reg_write] <= Dq [data_bits - 1 : data_bits / 2];
end
end
 
// Output Registers
always @ (posedge Clk) begin
#out_delay;
if (~(bwa_reg | bwb_reg)) begin
dout [data_bits / 2 - 1 : 0] <= bank0 [addr_reg_read];
dout [data_bits - 1 : data_bits / 2] <= bank1 [addr_reg_read];
end else begin
dout [data_bits - 1 : 0] <= {data_bits{1'bz}};
end
end
 
// Output Buffers
assign #(tKQHZ) Dq = (~Oe_n & ~Zz & pipe_reg & ~(bwa_reg | bwb_reg)) ? dout : {data_bits{1'bz}};
 
// Timing Check (6 ns clock cycle / 166 MHz)
// Please download latest datasheet from our Web site:
// http://www.micron.com/mti
specify
specparam tKC = 6.0, // Clock - Clock cycle time
tKH = 2.3, // Clock HIGH time
tKL = 2.3, // Clock LOW time
tAS = 1.5, // Setup Times - Address
tADSS = 1.5, // Address Status
tAAS = 1.5, // Address Advance
tWS = 1.5, // Byte Write Enables
tDS = 1.5, // Data-in
tCES = 1.5, // Chip Enable
tAH = 0.5, // Hold Times - Address
tADSH = 0.5, // Address Status
tAAH = 0.5, // Address Advance
tWH = 0.5, // Byte Write Enables
tDH = 0.5, // Data-in
tCEH = 0.5; // Chip Enable
 
$width (negedge Clk, tKL);
$width (posedge Clk, tKH);
$period (negedge Clk, tKC);
$period (posedge Clk, tKC);
$setuphold (posedge Clk, Adsp_n, tADSS, tADSH);
$setuphold (posedge Clk, Adsc_n, tADSS, tADSH);
$setuphold (posedge Clk, Addr, tAS, tAH);
$setuphold (posedge Clk, Bwa_n, tWS, tWH);
$setuphold (posedge Clk, Bwb_n, tWS, tWH);
$setuphold (posedge Clk, Bwe_n, tWS, tWH);
$setuphold (posedge Clk, Gw_n, tWS, tWH);
$setuphold (posedge Clk, Ce_n, tCES, tCEH);
$setuphold (posedge Clk, Ce2, tCES, tCEH);
$setuphold (posedge Clk, Ce2_n, tCES, tCEH);
$setuphold (posedge Clk, Adv_n, tAAS, tAAH);
endspecify
 
endmodule
 
/sram_models/IDT71T67802/readme_71T67802
0,0 → 1,11
IDT71V2578 - s133/150/166/183/200 verilog models/testbench
----------------------------------------------------------
07/09/99
rev01 - devoloped from IDT71V2576_rev01
 
----------------------------------------------------------
03/23/00
built from 71V2578 verilog file
----------------------------------------------------------
 
 
/sram_models/IDT71T67802/idt71t67802s150.v
0,0 → 1,303
/*******************************************************************************
* Copyright 1999 Integrated Device Technology, Inc.
* All right reserved.
*
* This program is proprietary and confidential information of
* IDT Corp. and may be used and disclosed only as authorized
* in a license agreement controlling such use and disclosure.
*
* IDT reserves the right to make any changes to
* the product herein to improve function or design.
* IDT does not assume any liability arising out of
* the application or use of the product herein.
*
* WARNING: The unlicensed shipping, mailing, or carring of this
* technical data outside the United States, or the unlicensed
* disclosure, by whatever means, through visits abroad, or the
* unlicensed disclosure to foreign national in the United States,
* may violate the United States criminal law.
*
* File Name : idt71t67802s150.v
* Product : IDT71T67802
* Function : 512Kx18 pipeline burst Static RAM
* Simulation Tool/Version : Verilog-XL 2.5
* Revision : rev00
* Date : 23/03/00
*
******************************************************************************/
/*******************************************************************************
* Module Name: idt71t67802s150
*
* Notes : This model is believed to be functionally
* accurate. Please direct any inquiries to
* IDT SRAM Applications at: sramhelp@idt.com
*
*******************************************************************************/
`timescale 1ns/10ps
 
module idt71t67802s150(A, D, DP, oe_, ce_, cs0, cs1_, lbo_,
gw_, bwe_, bw2_, bw1_, adsp_, adsc_, adv_, clk);
initial
begin
$write("\n********************************************************\n");
$write(" idt71t67802s150 \n");
$write(" Rev: 01 July '99 \n");
$write(" copyright 1997,1998,1999 by IDT, Inc. \n");
$write("**********************************************************\n");
end
 
parameter addr_msb = 18;
parameter mem_top = 524287;
 
parameter regdelay = 1;
 
inout [15:0] D;
inout [1:0] DP;
input [addr_msb:0] A;
input oe_, ce_, cs0, cs1_, lbo_, gw_, bwe_, bw2_, bw1_,
adsp_, adsc_, adv_, clk;
 
//internal registers for data, address, burst counter
 
reg [15:0] din, dout;
reg [1:0] dpin, dpout;
reg [addr_msb:0] reg_addr;
reg [1:0] brst_cnt;
 
wire[addr_msb:0] m_ad;
wire[15:0] data_out;
wire[1:0] dp_out;
 
reg wr_b1_, wr_b2_, deselr, deselrr;
 
wire check_data = (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)))
| (~deselr & adsc_ & (adsp_ | ce_)
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)));
 
wire check_addr = (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_);
 
 
specify
specparam
 
//Clock Parameters
tCYC = 6.7, //clock cycle time
tCH = 2.6, //clock high time
tCL = 2.6, //clock low time
//Output Parameters
tCD = 3.8, //clk to data
tCDC = 1.5, //output hold from clock
tCLZ = 0, //CLK to output Low-Z
tCHZ = 3.8, //CLK to output Hi-Z
tOE = 3.8, //OE to output valid
tOLZ = 0, //OE to output Hi-Z
tOHZ = 3.8, //OE to output Hi-Z
//Set up times
tSA = 1.5, //address set-up
tSS = 1.5, //address status set-up
tSD = 1.5, //data set-up
tSW = 1.5, //write set-up
tSAV = 1.5, //address advance set-up
tSC = 1.5, //chip enable and chip select set-up
//Hold times
tHA = 0.5, //Address hold
tHS = 0.5, //address status hold
tHD = 0.5, //data hold
tHW = 0.5, //write hold
tHAV = 0.5, //address advance hold
tHC = 0.5; //chip enable and chip select hold
 
(oe_ *> D) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> D) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
(oe_ *> DP) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> DP) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
//timing checks
 
$period(posedge clk, tCYC );
$width (posedge clk, tCH );
$width (negedge clk, tCL );
 
$setuphold(posedge clk, adsp_, tSS, tHS);
$setuphold(posedge clk, adsc_, tSS, tHS);
$setuphold(posedge clk, adv_, tSAV, tHAV);
$setuphold(posedge clk, gw_, tSW, tHW);
$setuphold(posedge clk, bwe_, tSW, tHW);
$setuphold(posedge clk, bw1_, tSW, tHW);
$setuphold(posedge clk, bw2_, tSW, tHW);
$setuphold(posedge clk, ce_, tSC, tHC);
$setuphold(posedge clk, cs0, tSC, tHC);
$setuphold(posedge clk, cs1_, tSC, tHC);
$setuphold(posedge clk &&& check_addr, A, tSA, tHA);
$setuphold(posedge clk &&& check_data, D, tSD, tHD);
$setuphold(posedge clk &&& check_data, DP, tSD, tHD);
 
endspecify
 
//////////////memory array//////////////////////////////////////////////
 
reg [7:0] memb1[0:mem_top], memb2[0:mem_top];
 
reg memb1p[0:mem_top], memb2p[0:mem_top];
 
 
wire doe, baddr1, baddr0, dsel;
 
/////////////////////////////////////////////////////////////////////////
//
//Output buffers: using a bufif1 has the same effect as...
//
// assign D = doe ? data_out : 32'hz;
//
//It was coded this way to support SPECIFY delays in the specparam section.
//
/////////////////////////////////////////////////////////////////////////
 
bufif1 (D[0],data_out[0],doe);
bufif1 (D[1],data_out[1],doe);
bufif1 (D[2],data_out[2],doe);
bufif1 (D[3],data_out[3],doe);
bufif1 (D[4],data_out[4],doe);
bufif1 (D[5],data_out[5],doe);
bufif1 (D[6],data_out[6],doe);
bufif1 (D[7],data_out[7],doe);
bufif1 (DP[0], dp_out[0],doe);
 
bufif1 (D[8],data_out[8],doe);
bufif1 (D[9],data_out[9],doe);
bufif1 (D[10],data_out[10],doe);
bufif1 (D[11],data_out[11],doe);
bufif1 (D[12],data_out[12],doe);
bufif1 (D[13],data_out[13],doe);
bufif1 (D[14],data_out[14],doe);
bufif1 (D[15],data_out[15],doe);
bufif1 (DP[1], dp_out[1],doe);
 
assign doe = ~deselr & ~deselrr & ~oe_ & wr_b1_ & wr_b2_ ;
 
assign dsel = (ce_ | ~cs0 | cs1_);
 
always @(posedge clk)
begin
if ( ~adsc_ || ( ~adsp_ && ~ce_ ))
deselr <= dsel;
end
 
always @(posedge clk)
begin
deselrr <= deselr;
end
 
/////////////////////////////////////////////////////////////////////////
//
//write enable generation
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw1_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw1_)))
wr_b1_ <= 0;
else wr_b1_ <= 1;
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw2_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw2_)))
wr_b2_ <= 0;
else wr_b2_ <= 1;
end
 
/////////////////////////////////////////////////////////////////////////
//
//input address register
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_)) reg_addr[addr_msb:0] <= A[addr_msb:0];
end
 
/////////////////////////////////////////////////////////////////////////
//
// burst counter
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if (lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= 0;
else if (~lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= A[1:0];
else if ((adsp_ | ce_) & adsc_ & ~adv_) brst_cnt <= brst_cnt + 1;
end
 
//////////////////////////////////////////////////////////////////////////
//
//determine the memory address
//
//////////////////////////////////////////////////////////////////////////
 
assign baddr1 = lbo_ ? (brst_cnt[1] ^ reg_addr[1]) : brst_cnt[1];
assign baddr0 = lbo_ ? (brst_cnt[0] ^ reg_addr[0]) : brst_cnt[0];
 
assign #regdelay m_ad[addr_msb:0] = {reg_addr[addr_msb:2], baddr1, baddr0};
 
//////////////////////////////////////////////////////////////////////////
//
//data output register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
dout[15:8] <= memb2[m_ad];
dpout[1] <= memb2p[m_ad];
 
dout[7:0] <= memb1[m_ad];
dpout[0] <= memb1p[m_ad];
end
 
assign data_out = dout;
assign dp_out = dpout;
 
//////////////////////////////////////////////////////////////////////////
//
//data input register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
din <= #regdelay D;
dpin <= #regdelay DP;
end
 
//////////////////////////////////////////////////////////////////////////
//
// write to ram
//
//////////////////////////////////////////////////////////////////////////
 
wire #1 wrb1 = ~wr_b1_ & ~clk;
wire #1 wrb2 = ~wr_b2_ & ~clk;
 
always @(clk)
begin
if (wrb1) begin
memb1[m_ad] = din[7:0];
memb1p[m_ad] = dpin[0];
end
if (wrb2) begin
memb2[m_ad] = din[15:8];
memb2p[m_ad] = dpin[1];
end
end
 
endmodule
/sram_models/IDT71T67802/idt71t67802s133.v
0,0 → 1,321
/*******************************************************************************
* Copyright 1999 Integrated Device Technology, Inc.
* All right reserved.
*
* This program is proprietary and confidential information of
* IDT Corp. and may be used and disclosed only as authorized
* in a license agreement controlling such use and disclosure.
*
* IDT reserves the right to make any changes to
* the product herein to improve function or design.
* IDT does not assume any liability arising out of
* the application or use of the product herein.
*
* WARNING: The unlicensed shipping, mailing, or carring of this
* technical data outside the United States, or the unlicensed
* disclosure, by whatever means, through visits abroad, or the
* unlicensed disclosure to foreign national in the United States,
* may violate the United States criminal law.
*
* File Name : idt71t67802s133.v
* Product : IDT71T67802
* Function : 512Kx18 pipeline burst Static RAM
* Simulation Tool/Version : Verilog-XL 2.5
* Revision : rev00
* Date : 23/03/00
*
******************************************************************************/
/*******************************************************************************
* Module Name: idt71t67802s133
*
* Notes : This model is believed to be functionally
* accurate. Please direct any inquiries to
* IDT SRAM Applications at: sramhelp@idt.com
*
*******************************************************************************/
`timescale 1ns/10ps
 
module idt71t67802s133(A, D, DP, oe_, ce_, cs0, cs1_, lbo_,
gw_, bwe_, bw2_, bw1_, adsp_, adsc_, adv_, clk);
initial
begin
$write("\n********************************************************\n");
$write(" idt71t67802s133 \n");
$write(" Rev: 01 July '99 \n");
$write(" copyright 1997,1998,1999 by IDT, Inc. \n");
$write("**********************************************************\n");
end
 
parameter addr_msb = 18;
parameter mem_top = 524287;
 
parameter regdelay = 1;
 
inout [15:0] D;
inout [1:0] DP;
input [addr_msb:0] A;
input oe_, ce_, cs0, cs1_, lbo_, gw_, bwe_, bw2_, bw1_,
adsp_, adsc_, adv_, clk;
 
//internal registers for data, address, burst counter
 
reg [15:0] din, dout;
reg [1:0] dpin, dpout;
reg [addr_msb:0] reg_addr;
reg [1:0] brst_cnt;
 
wire[addr_msb:0] m_ad;
wire[15:0] data_out;
wire[1:0] dp_out;
 
reg wr_b1_, wr_b2_, deselr, deselrr;
 
wire check_data = (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)))
| (~deselr & adsc_ & (adsp_ | ce_)
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)));
 
wire check_addr = (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_);
 
specify
specparam
 
//Clock Parameters
tCYC = 7.5, //clock cycle time
tCH = 3, //clock high time
tCL = 3, //clock low time
//Output Parameters
tCD = 4.2, //clk to data
tCDC = 1.5, //output hold from clock
tCLZ = 0, //CLK to output Low-Z
tCHZ = 4.2, //CLK to output Hi-Z
tOE = 4.2, //OE to output valid
tOLZ = 0, //OE to output Hi-Z
tOHZ = 4.2, //OE to output Hi-Z
//Set up times
tSA = 1.5, //address set-up
tSS = 1.5, //address status set-up
tSD = 1.5, //data set-up
tSW = 1.5, //write set-up
tSAV = 1.5, //address advance set-up
tSC = 1.5, //chip enable and chip select set-up
//Hold times
tHA = 0.5, //Address hold
tHS = 0.5, //address status hold
tHD = 0.5, //data hold
tHW = 0.5, //write hold
tHAV = 0.5, //address advance hold
tHC = 0.5; //chip enable and chip select hold
 
(oe_ *> D) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> D) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
(oe_ *> DP) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> DP) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
//timing checks
 
$period(posedge clk, tCYC );
$width (posedge clk, tCH );
$width (negedge clk, tCL );
 
$setuphold(posedge clk, adsp_, tSS, tHS);
$setuphold(posedge clk, adsc_, tSS, tHS);
$setuphold(posedge clk, adv_, tSAV, tHAV);
$setuphold(posedge clk, gw_, tSW, tHW);
$setuphold(posedge clk, bwe_, tSW, tHW);
$setuphold(posedge clk, bw1_, tSW, tHW);
$setuphold(posedge clk, bw2_, tSW, tHW);
$setuphold(posedge clk, ce_, tSC, tHC);
$setuphold(posedge clk, cs0, tSC, tHC);
$setuphold(posedge clk, cs1_, tSC, tHC);
$setuphold(posedge clk &&& check_addr, A, tSA, tHA);
$setuphold(posedge clk &&& check_data, D, tSD, tHD);
$setuphold(posedge clk &&& check_data, DP, tSD, tHD);
 
endspecify
 
//////////////memory array//////////////////////////////////////////////
 
reg [7:0] memb1[0:mem_top];
reg [7:0] memb2[0:mem_top];
 
reg memb1p[0:mem_top], memb2p[0:mem_top];
 
wire doe, baddr1, baddr0, dsel;
 
task mem_fill;
input x;
 
integer a, n, x;
 
begin
 
a=0;
for(n=0;n<x;n=n+1)
begin
memb1[n] = a[7:0];
a=a+1;
memb2[n] = a[7:0];
a=a+1;
end
 
end
endtask
 
/////////////////////////////////////////////////////////////////////////
//
//Output buffers: using a bufif1 has the same effect as...
//
// assign D = doe ? data_out : 32'hz;
//
//It was coded this way to support SPECIFY delays in the specparam section.
//
/////////////////////////////////////////////////////////////////////////
 
bufif1 (D[0],data_out[0],doe);
bufif1 (D[1],data_out[1],doe);
bufif1 (D[2],data_out[2],doe);
bufif1 (D[3],data_out[3],doe);
bufif1 (D[4],data_out[4],doe);
bufif1 (D[5],data_out[5],doe);
bufif1 (D[6],data_out[6],doe);
bufif1 (D[7],data_out[7],doe);
bufif1 (DP[0], dp_out[0],doe);
 
bufif1 (D[8],data_out[8],doe);
bufif1 (D[9],data_out[9],doe);
bufif1 (D[10],data_out[10],doe);
bufif1 (D[11],data_out[11],doe);
bufif1 (D[12],data_out[12],doe);
bufif1 (D[13],data_out[13],doe);
bufif1 (D[14],data_out[14],doe);
bufif1 (D[15],data_out[15],doe);
bufif1 (DP[1], dp_out[1],doe);
 
assign doe = ~deselr & ~deselrr & ~oe_ & wr_b1_ & wr_b2_ ;
 
assign dsel = (ce_ | ~cs0 | cs1_);
 
always @(posedge clk)
begin
if ( ~adsc_ || ( ~adsp_ && ~ce_ ))
deselr <= dsel;
end
 
always @(posedge clk)
begin
deselrr <= deselr;
end
 
/////////////////////////////////////////////////////////////////////////
//
//write enable generation
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw1_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw1_)))
wr_b1_ <= 0;
else wr_b1_ <= 1;
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw2_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw2_)))
wr_b2_ <= 0;
else wr_b2_ <= 1;
end
 
/////////////////////////////////////////////////////////////////////////
//
//input address register
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_)) reg_addr[addr_msb:0] <= A[addr_msb:0];
end
 
/////////////////////////////////////////////////////////////////////////
//
// burst counter
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if (lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= 0;
else if (~lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= A[1:0];
else if ((adsp_ | ce_) & adsc_ & ~adv_) brst_cnt <= brst_cnt + 1;
end
 
//////////////////////////////////////////////////////////////////////////
//
//determine the memory address
//
//////////////////////////////////////////////////////////////////////////
 
assign baddr1 = lbo_ ? (brst_cnt[1] ^ reg_addr[1]) : brst_cnt[1];
assign baddr0 = lbo_ ? (brst_cnt[0] ^ reg_addr[0]) : brst_cnt[0];
 
assign #regdelay m_ad[addr_msb:0] = {reg_addr[addr_msb:2], baddr1, baddr0};
 
//////////////////////////////////////////////////////////////////////////
//
//data output register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
dout[15:8] <= memb2[m_ad];
dpout[1] <= memb2p[m_ad];
 
dout[7:0] <= memb1[m_ad];
dpout[0] <= memb1p[m_ad];
end
 
assign data_out = dout;
assign dp_out = dpout;
 
//////////////////////////////////////////////////////////////////////////
//
//data input register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
din <= #regdelay D;
dpin <= #regdelay DP;
end
 
//////////////////////////////////////////////////////////////////////////
//
// write to ram
//
//////////////////////////////////////////////////////////////////////////
 
wire #1 wrb1 = ~wr_b1_ & ~clk;
wire #1 wrb2 = ~wr_b2_ & ~clk;
 
always @(clk)
begin
if (wrb1) begin
memb1[m_ad] = din[7:0];
memb1p[m_ad] = dpin[0];
end
if (wrb2) begin
memb2[m_ad] = din[15:8];
memb2p[m_ad] = dpin[1];
end
end
 
endmodule
/sram_models/IDT71T67802/idt71t67802s166.v
0,0 → 1,303
/*******************************************************************************
* Copyright 1999 Integrated Device Technology, Inc.
* All right reserved.
*
* This program is proprietary and confidential information of
* IDT Corp. and may be used and disclosed only as authorized
* in a license agreement controlling such use and disclosure.
*
* IDT reserves the right to make any changes to
* the product herein to improve function or design.
* IDT does not assume any liability arising out of
* the application or use of the product herein.
*
* WARNING: The unlicensed shipping, mailing, or carring of this
* technical data outside the United States, or the unlicensed
* disclosure, by whatever means, through visits abroad, or the
* unlicensed disclosure to foreign national in the United States,
* may violate the United States criminal law.
*
* File Name : idt71t67802s166.v
* Product : IDT71T67802
* Function : 512Kx18 pipeline burst Static RAM
* Simulation Tool/Version : Verilog-XL 2.5
* Revision : rev00
* Date : 23/03/00
*
******************************************************************************/
/*******************************************************************************
* Module Name: idt71t67802s166
*
* Notes : This model is believed to be functionally
* accurate. Please direct any inquiries to
* IDT SRAM Applications at: sramhelp@idt.com
*
*******************************************************************************/
`timescale 1ns/10ps
 
module idt71t67802s166(A, D, DP, oe_, ce_, cs0, cs1_, lbo_,
gw_, bwe_, bw2_, bw1_, adsp_, adsc_, adv_, clk);
initial
begin
$write("\n********************************************************\n");
$write(" idt71t67802s166 \n");
$write(" Rev: 01 July '99 \n");
$write(" copyright 1997,1998,1999 by IDT, Inc. \n");
$write("**********************************************************\n");
end
 
parameter addr_msb = 18;
parameter mem_top = 524287;
 
parameter regdelay = 1;
 
inout [15:0] D;
inout [1:0] DP;
input [addr_msb:0] A;
input oe_, ce_, cs0, cs1_, lbo_, gw_, bwe_, bw2_, bw1_,
adsp_, adsc_, adv_, clk;
 
//internal registers for data, address, burst counter
 
reg [15:0] din, dout;
reg [1:0] dpin, dpout;
reg [addr_msb:0] reg_addr;
reg [1:0] brst_cnt;
 
wire[addr_msb:0] m_ad;
wire[15:0] data_out;
wire[1:0] dp_out;
 
reg wr_b1_, wr_b2_, deselr, deselrr;
 
wire check_data = (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)))
| (~deselr & adsc_ & (adsp_ | ce_)
& (~gw_ | ~bwe_ & (~bw1_ | ~bw2_)));
 
wire check_addr = (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_);
 
 
specify
specparam
 
//Clock Parameters
tCYC = 6.0, //clock cycle time
tCH = 2.4, //clock high time
tCL = 2.4, //clock low time
//Output Parameters
tCD = 3.5, //clk to data
tCDC = 1.5, //output hold from clock
tCLZ = 0, //CLK to output Low-Z
tCHZ = 3.5, //CLK to output Hi-Z
tOE = 3.5, //OE to output valid
tOLZ = 0, //OE to output Hi-Z
tOHZ = 3.5, //OE to output Hi-Z
//Set up times
tSA = 1.5, //address set-up
tSS = 1.5, //address status set-up
tSD = 1.5, //data set-up
tSW = 1.5, //write set-up
tSAV = 1.5, //address advance set-up
tSC = 1.5, //chip enable and chip select set-up
//Hold times
tHA = 0.5, //Address hold
tHS = 0.5, //address status hold
tHD = 0.5, //data hold
tHW = 0.5, //write hold
tHAV = 0.5, //address advance hold
tHC = 0.5; //chip enable and chip select hold
 
(oe_ *> D) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> D) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
(oe_ *> DP) = (tOE,tOE,tOHZ,tOLZ,tOHZ,tOLZ); //(01,10,0z,z1,1z,z0)
(clk *> DP) = (tCD,tCD,tCHZ,tCLZ,tCHZ,tCLZ); //(01,10,0z,z1,1z,z0)
 
//timing checks
 
$period(posedge clk, tCYC );
$width (posedge clk, tCH );
$width (negedge clk, tCL );
 
$setuphold(posedge clk, adsp_, tSS, tHS);
$setuphold(posedge clk, adsc_, tSS, tHS);
$setuphold(posedge clk, adv_, tSAV, tHAV);
$setuphold(posedge clk, gw_, tSW, tHW);
$setuphold(posedge clk, bwe_, tSW, tHW);
$setuphold(posedge clk, bw1_, tSW, tHW);
$setuphold(posedge clk, bw2_, tSW, tHW);
$setuphold(posedge clk, ce_, tSC, tHC);
$setuphold(posedge clk, cs0, tSC, tHC);
$setuphold(posedge clk, cs1_, tSC, tHC);
$setuphold(posedge clk &&& check_addr, A, tSA, tHA);
$setuphold(posedge clk &&& check_data, D, tSD, tHD);
$setuphold(posedge clk &&& check_data, DP, tSD, tHD);
 
endspecify
 
//////////////memory array//////////////////////////////////////////////
 
reg [7:0] memb1[0:mem_top], memb2[0:mem_top];
 
reg memb1p[0:mem_top], memb2p[0:mem_top];
 
 
wire doe, baddr1, baddr0, dsel;
 
/////////////////////////////////////////////////////////////////////////
//
//Output buffers: using a bufif1 has the same effect as...
//
// assign D = doe ? data_out : 32'hz;
//
//It was coded this way to support SPECIFY delays in the specparam section.
//
/////////////////////////////////////////////////////////////////////////
 
bufif1 (D[0],data_out[0],doe);
bufif1 (D[1],data_out[1],doe);
bufif1 (D[2],data_out[2],doe);
bufif1 (D[3],data_out[3],doe);
bufif1 (D[4],data_out[4],doe);
bufif1 (D[5],data_out[5],doe);
bufif1 (D[6],data_out[6],doe);
bufif1 (D[7],data_out[7],doe);
bufif1 (DP[0], dp_out[0],doe);
 
bufif1 (D[8],data_out[8],doe);
bufif1 (D[9],data_out[9],doe);
bufif1 (D[10],data_out[10],doe);
bufif1 (D[11],data_out[11],doe);
bufif1 (D[12],data_out[12],doe);
bufif1 (D[13],data_out[13],doe);
bufif1 (D[14],data_out[14],doe);
bufif1 (D[15],data_out[15],doe);
bufif1 (DP[1], dp_out[1],doe);
 
assign doe = ~deselr & ~deselrr & ~oe_ & wr_b1_ & wr_b2_ ;
 
assign dsel = (ce_ | ~cs0 | cs1_);
 
always @(posedge clk)
begin
if ( ~adsc_ || ( ~adsp_ && ~ce_ ))
deselr <= dsel;
end
 
always @(posedge clk)
begin
deselrr <= deselr;
end
 
/////////////////////////////////////////////////////////////////////////
//
//write enable generation
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw1_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw1_)))
wr_b1_ <= 0;
else wr_b1_ <= 1;
if ( (~adsc_ & adsp_ & ~ce_ & cs0 & ~cs1_ & (~gw_ | ~bwe_ & ~bw2_))
| (~deselr & adsc_ & (adsp_ | ce_) & (~gw_ | ~bwe_ & ~bw2_)))
wr_b2_ <= 0;
else wr_b2_ <= 1;
end
 
/////////////////////////////////////////////////////////////////////////
//
//input address register
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_)) reg_addr[addr_msb:0] <= A[addr_msb:0];
end
 
/////////////////////////////////////////////////////////////////////////
//
// burst counter
//
/////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
if (lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= 0;
else if (~lbo_ & ( (~adsp_ & ~ce_ & cs0 & ~cs1_)
| ( adsp_ & ~adsc_ & ~ce_ & cs0 & ~cs1_))) brst_cnt <= A[1:0];
else if ((adsp_ | ce_) & adsc_ & ~adv_) brst_cnt <= brst_cnt + 1;
end
 
//////////////////////////////////////////////////////////////////////////
//
//determine the memory address
//
//////////////////////////////////////////////////////////////////////////
 
assign baddr1 = lbo_ ? (brst_cnt[1] ^ reg_addr[1]) : brst_cnt[1];
assign baddr0 = lbo_ ? (brst_cnt[0] ^ reg_addr[0]) : brst_cnt[0];
 
assign #regdelay m_ad[addr_msb:0] = {reg_addr[addr_msb:2], baddr1, baddr0};
 
//////////////////////////////////////////////////////////////////////////
//
//data output register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
dout[15:8] <= memb2[m_ad];
dpout[1] <= memb2p[m_ad];
 
dout[7:0] <= memb1[m_ad];
dpout[0] <= memb1p[m_ad];
end
 
assign data_out = dout;
assign dp_out = dpout;
 
//////////////////////////////////////////////////////////////////////////
//
//data input register
//
//////////////////////////////////////////////////////////////////////////
 
always @(posedge clk)
begin
din <= #regdelay D;
dpin <= #regdelay DP;
end
 
//////////////////////////////////////////////////////////////////////////
//
// write to ram
//
//////////////////////////////////////////////////////////////////////////
 
wire #1 wrb1 = ~wr_b1_ & ~clk;
wire #1 wrb2 = ~wr_b2_ & ~clk;
 
always @(clk)
begin
if (wrb1) begin
memb1[m_ad] = din[7:0];
memb1p[m_ad] = dpin[0];
end
if (wrb2) begin
memb2[m_ad] = din[15:8];
memb2p[m_ad] = dpin[1];
end
end
 
endmodule
/sram_models/IDT71T67802/idt_512Kx18_PBSRAM_test.v
0,0 → 1,1106
///////////////////////////////////////////////////////////
//
// Test fixture for IDT 9Meg Synchronous Burst SRAMs
// (for 512K x 18 configurations)
//
//////////////////////////////////////////////////////////
 
`timescale 1ns / 10ps
 
`define Max 16
`define Max1 8
`define Max2 16
 
module main;
 
parameter addr_msb = 18;
 
 
/////// Remove comments for specific device under test ////
 
 
//////////////////////////////////////////////
//
//Pipelined sync burst SRAMs
//
/////////////////////////////////////////////
 
/////// 2.5v I/O ////////////
parameter pipe = 1, Tcyc = 7.5, Tsu = 1.5, Tdh = 0.5, Tcd = 4.2, Toe = 4.2;
`define device idt71t67802s133
//parameter pipe = 1, Tcyc = 6.7, Tsu = 1.5, Tdh = 0.5, Tcd = 3.8, Toe = 3.8;
// `define device idt71t67802s150
//parameter pipe = 1, Tcyc = 6.0, Tsu = 1.5, Tdh = 0.5, Tcd = 3.5, Toe = 3.5;
// `define device idt71t67802s166
 
//////////////////////////////////////////////
//
//Flow-through sync burst SRAMs
//
//////////////////////////////////////////////
 
/////// 2.5v I/O ////////////
//parameter pipe = 0, Tcyc = 11.5, Tsu = 2.0, Tdh = 0.5, Tcd = 8.5, Toe = 3.5;
// `define device idt71t67902s85
//parameter pipe = 0, Tcyc = 10.0, Tsu = 2.0, Tdh = 0.5, Tcd = 8.0, Toe = 3.5;
// `define device idt71t67902s80
//parameter pipe = 0, Tcyc = 8.5, Tsu = 1.5, Tdh = 0.5, Tcd = 7.5, Toe = 3.5;
// `define device idt71t67902s75
 
reg [addr_msb:0] A;
reg CLK;
reg ADSP_;
reg ADV_;
reg LBO_;
reg ADSC_;
reg [2:1] BW_;
reg BWE_;
reg GW_;
reg CE_;
reg CS0;
reg CS1_;
reg OE_;
 
reg [17:0] DataOut;
reg [17:0] TempReg;
 
reg [17:0] DQ;
wire [15:0] DQbus = {DQ[16:9], DQ[7:0]};
wire [2:1] DQPbus = {DQ[17], DQ[8]};
reg [17:0] Dstore[0:`Max-1]; //temp data store
reg [17:0] data;
reg [addr_msb:0] lastaddr;
reg tempcs1_;
reg tempcs0;
reg tempce_;
 
reg [17:0] RandomData[0:`Max-1];
reg [17:0] BurstData[0:`Max-1];
 
reg [8*4:1] status; //data read pass/fail
 
//internal
 
reg check_data_m1, qual_ads;
reg check_data;
 
integer i,j,addrb,counter,
result;
 
// Output files
initial begin
$recordfile ("idt_sram_67802.trn");
$recordvars;
 
// $dumpfile ("idt_sram_67802.vcd");
// $dumpvars;
 
result = $fopen("idt_sram.res"); if (result == 0) $finish;
end
 
always begin
@(posedge CLK)
$fdisplay(result,
"%b", ADSC_,
"%b", ADSP_,
"%b", BWE_,
"%b", CE_,
"%b", CS0,
"%b", CS1_,
"%b", LBO_,
"%b", OE_,
"%b", BW_, // 2 bits
"%b", ADV_,
"%b ", GW_,
"%h ", {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]},
"%h ", A,
"%d", $stime
);
end
 
initial begin
ADSC_ = 1;
ADSP_ = 1;
BWE_ = 1;
CE_ = 0;
CS0 = 1;
CS1_ = 0;
LBO_ = 0;
OE_ = 1;
CLK = 0;
BW_ = 2'hf;
ADV_ = 1;
GW_ = 1;
counter = 0;
 
for (i=0;i<`Max;i=i+1) begin // Generate random data for testing
RandomData[i] = $random;
end
 
//****************
//disable_ce;
//disable_cs0;
 
//####
init;
$display($time,"(1) write adsp_ = 0");
for(i=0; i<`Max1; i=i+1) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
$display($time," read adsp_ = 0");
for(i=0; i<`Max1; i=i+1) begin
read(i,0,1,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
dummy_cyc(1);
$display($time," status = %s",status);
//####
init;
$display($time,"(2) write adsc_ = 0");
for(i=0; i<`Max1; i=i+1) begin
write(i,i,1,0,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
$display($time," read adsc_ = 0");
for(i=0; i<`Max1; i=i+1) begin
read(i,1,0,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(3) write adsp_ = 0");
for(i=0; i<`Max1; i=i+1) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
$display($time," read adsp_ = 0 cs1_ = 1 - every other cyc");
for(i=0; i<`Max1; i=i+2) begin
read(i,0,1,0,1,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
read(i+1,0,1,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(4) write/read adsp_ = 0");
for(i=0; i<`Max1; i=i+1) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
read(i,0,1,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(5) write/read adsc_ = 0");
for(i=0; i<`Max1; i=i+1) begin
write(i,i,1,0,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
read(i,1,0,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
dummy_cyc(1);
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(6) burst_write adsp_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_write(i,i,0,1,0,0,0,1,4); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,nburst
end
$display($time," burst_read adsp_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_read(i,0,1,0,0,1,4); //addr,adsp_,adsc_,ce_,cs1_,cs0,nburst
end
dummy_cyc(1);
$display($time," status = %s",status);
 
//####
init;
$display($time,"(7) burst_write adsc_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_write(i,i,1,0,0,0,0,1,4); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,nburst
end
$display($time," burst_read adsc_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_read(i,1,0,0,0,1,4); //addr,adsp_,adsc_,ce_,cs1_,cs0,nburst
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(8) write adsp_ = 0 cs1_ = 1 - every other cyc");
for(i=0; i<`Max1; i=i+2) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
write(i+1,9,0,1,0,0,1,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
$display($time," read adsp_ = 0");
for(i=0; i<`Max1; i=i+2) begin
read(i,0,1,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(9) write adsp_ = 0 cs0 = 0 - every other cyc");
for(i=0; i<`Max1; i=i+2) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
write(i+1,9,0,1,0,0,0,0); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
$display($time," read adsc_ = 0");
for(i=0; i<`Max1; i=i+2) begin
read(i,1,0,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(10) write adsp_ = 0 ce_ = 1 - every other cyc");
for(i=0; i<`Max1; i=i+2) begin
write(i,i,0,1,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
write(i+1,i,0,1,0,1,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
write(i,i,0,1,0,0,0,1); //this will write last address to Dstore
$display($time," read adsp_ = 0");
for(i=0; i<`Max1; i=i+2) begin
read(i,0,1,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(11) write adsc_ = 0 ce_ = 1 - every other cyc");
for(i=0; i<`Max1; i=i+2) begin
write(i,i,1,0,0,0,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
write(i+1,i+1,1,0,0,1,0,1); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
end
write(i,i,1,0,0,0,0,1); //this will write last address to Dstore
$display($time," read adsc_ = 0");
for(i=0; i<`Max1; i=i+2) begin
read(i,1,0,0,0,1); //addr,adsp_,adsc_,ce_,cs1_,cs0
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(12) burst_write_adv adsc_ = 0 adv_ = 1 - 2nd cyc");
for(i=0; i<`Max2; i=i+4) begin
burst_write_adv(i,i,1,0,0,0,0,1,1,0); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,adv_,tempcounter
burst_write_adv(i,i,1,0,0,0,0,1,1,1);
burst_write_adv(i+1,i+1,1,0,0,0,0,1,0,2);
burst_write_adv(i+2,i+2,1,0,0,0,0,1,0,3);
burst_write_adv(i+3,i+3,1,0,0,0,0,1,0,4);
end
$display($time," burst_read adsc_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_read(i,1,0,0,0,1,4); //addr,adsp_,adsc_,ce_,cs1_,cs0,nburst
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(13) burst_write_adv adsp_ = 0 adv_ = 1 - 2nd cyc");
for(i=0; i<`Max2; i=i+4) begin
burst_write_adv(i,i,0,1,0,0,0,1,1,0); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,adv_,tempcounter
burst_write_adv(i,i,0,0,0,1,0,1,1,1);
burst_write_adv(i+1,i+1,0,1,0,0,0,1,0,2);
burst_write_adv(i+2,i+2,0,1,0,0,0,1,0,3);
burst_write_adv(i+3,i+3,0,1,0,0,0,1,0,4);
end
$display($time," burst_read adsc_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_read(i,1,0,0,0,1,4); //addr,adsp_,adsc_,ce_,cs1_,cs0,nburst
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(14) burst_write adsp_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_write(i,i,0,1,0,0,0,1,4); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,nburst
end
$display($time," burst_read_adv adsp_ = 0 adv_ = 1 - 3rd cyc");
for(i=0; i<`Max2; i=i+4) begin
burst_read_adv(i, 0,1,0,0,1,1,0); //addr,adsp_,adsc_,ce_,cs1_,cs0,adv_,tempcounter
burst_read_adv(i+1,1,1,0,0,1,0,1);
burst_read_adv(i+2,1,1,0,0,1,1,2);
burst_read_adv(i+3,1,1,0,0,1,0,3);
end
$display($time," status = %s",status);
 
//####
init;
$display($time,"(15) burst_write adsp_ = 0");
for(i=0; i<`Max2; i=i+4) begin
burst_write(i,i,0,1,0,0,0,1,4); //addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0,nburst
end
$display($time," burst_read_adv adsp_=1/ce_=0 - 2/3 cyc, adsp = 0/ce_=1 - 4/5 cyc");
for(i=0; i<`Max2; i=i+4) begin
burst_read_adv(i, 0,1,0,0,1,1,0); //addr,adsp_,adsc_,ce_,cs1_,cs0,adv_,tempcounter
burst_read_adv(i+1,1,1,0,0,1,0,1);
burst_read_adv(i+2,1,1,0,0,1,0,2);
burst_read_adv(i+3,0,1,1,0,1,0,3);
burst_read_adv(i, 0,1,1,0,1,0,4);
end
$display($time," status = %s",status);
//####
 
 
@( negedge CLK );
@( negedge CLK );
@( negedge CLK );
 
//*****************
CE_ = 0;
CS0 = 1;
CS1_ = 0;
 
$display($time,,"Simple read/write test");
for (i=0;i<`Max;i=i+1) begin // Test straight write/read
write_random(i, RandomData[i]);
$display($time,,"Simple read test");
read_random(i, DataOut, RandomData[i]);
end
 
$display($time,,"CE_ disable - random data");
read_random(3, DataOut, RandomData[3]);
disable_ce;
read_random(7, DataOut, RandomData[7]);
disable_cs0;
read_random(2, DataOut, RandomData[2]);
for (i=0;i<`Max;i=i+1) begin // Fill RAM with zero's
write_random(i, 0);
end
 
$display($time,,"Byte mode read/write test - random data");
// GW_ = 1; // Disable global write
// BWE_ = 0; // Enable byte write
for (i=0;i<`Max;i=i+1) begin // Test byte write/read
BW_ = $random;
TempReg = RandomData[i];
byte_write_random(i, TempReg);
if ( BW_[1] == 1 ) TempReg[8:0] = 0;
if ( BW_[2] == 1 ) TempReg[17:9] = 0;
read_random(i, DataOut, TempReg);
end
BWE_ = 1; // Disable byte write
 
 
// Test burst mode write/read
$display($time,,"Burst mode read/write test - random data");
for (i=0;i<`Max;i=i+1) begin // Test byte write/read
BurstData[i] = RandomData[i];
end
 
GW_ = 0; // Enable global write
for (i=0;i<`Max;i=i+4) begin // Write data from BurstData buffer
burst_write_random(i,4);
end
GW_ = 1; // Disable global write
 
for (i=0;j<`Max;i=i+1) begin // Clear data buffer
BurstData[i] = 0;
end
for (i=0;i<`Max;i=i+4) begin
burst_read_random(i,4);
// for (j=i;j<i+4;j=j+1) begin // verify read data
// if ( BurstData[j] != RandomData[j] )
// $display("%d Burst error: Addr %h Exp %h Act %h", $stime, j, RandomData[j], BurstData[j]);
// end
end
burst_wrap_random(0);
disable_ce;
burst_rd_pipe_random(0,4);
 
$finish;
end
/////////////////////////////////////////////////////////////////
 
always @(posedge CLK) begin
if ((~ADSC_ | ~ADSP_) & ~CE_ & CS0 & ~CS1_) qual_ads <= #1 1;
else qual_ads <= #1 0;
check_data_m1 <= #1 ~ADV_;
 
if (pipe == 0) check_data = #1 (qual_ads | ~ADV_);
else check_data = #1 (qual_ads | check_data_m1);
end
 
always #(Tcyc/2) CLK = ~CLK;
 
`device dut (
.A (A),
.D (DQbus),
.DP (DQPbus),
.oe_ (OE_),
.ce_ (CE_),
.cs0 (CS0),
.cs1_ (CS1_),
.lbo_ (LBO_),
.gw_ (GW_),
.bwe_ (BWE_),
.bw2_ (BW_[2]),
.bw1_ (BW_[1]),
.adsp_ (ADSP_),
.adsc_ (ADSC_),
.adv_ (ADV_),
.clk (CLK)
);
 
//================ test bench tasks
 
task disable_ce;
begin
OE_ = 0;
if (CLK)
@( negedge CLK );
ADSC_ = 0;
CE_ = 1;
@( posedge CLK );
@( negedge CLK );
ADSC_ = 1;
CE_ = 0;
end
endtask
 
task disable_cs0;
begin
OE_ = 0;
if (CLK)
@( negedge CLK );
ADSP_ = 0;
CS0 = 0;
@( posedge CLK );
@( negedge CLK );
ADSP_ = 1;
CS0 = 1;
end
endtask
 
task dummy_cyc;
input oe;
begin
@(posedge CLK);
@(negedge CLK);
#Tcd;
OE_ = oe;
end
endtask
 
task init;
begin
for(i=0; i<`Max2; i=i+1) begin // fill memory with 0 data
write(i,0,0,1,0,0,0,1); // addr,data,adsp_,adsc_,gw_,ce_,cs1_,cs0
Dstore[i] = 18'hx; // fill temp memory with xx data
end
end
endtask
 
task read; // ADSP|ADSC controlled PL - adsp_/adsc_ 2cycle read
input [addr_msb:0] addr; // ADSP|ADSC controlled FT - adsp_/adsc_ 1cycle read
input adsp_;
input adsc_;
input ce_;
input cs1_;
input cs0;
begin
@( negedge CLK );
#(Tcyc/2 - Tsu);
A = addr;
ADV_ = 1;
GW_ = 1;
BWE_ = 1;
ADSP_ = adsp_;
ADSC_ = adsc_;
CE_ = ce_;
CS1_ = cs1_;
CS0 = cs0;
assign data = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
@( posedge CLK ); // SRAM latches Address and begins internal read
tempcs0 <= cs0; tempcs1_ <= cs1_; tempce_ <= ce_;
lastaddr <= addr;
A <= #Tdh 19'hz;
ADSP_ <= #Tdh 1;
ADSC_ <= #Tdh 1;
CE_ <= #Tdh 1;
CS1_<= #Tdh 1;
CS0 <= #Tdh 0;
if(pipe == 1)
OE_ <= #(Tcyc+Tcd-Toe) 0;
else if(pipe == 0)
OE_ <= #(Tcd-Toe) 0;
if(counter != 0)
if ( data !== Dstore[lastaddr] ) begin
if (tempcs0 & ~tempce_ & ~tempcs1_) begin
status = "FAIL";
$display("%d Read error: Addr %h Exp %h Act %h", $stime, lastaddr,
Dstore[lastaddr], data);
end
end
else if (tempcs0 & ~tempce_ & ~tempcs1_)
status = "PASS";
DQ = 18'hz;
if(pipe == 1)
#(Tcyc/2);
counter = counter+1;
end
endtask
 
task burst_read; // ADSP|ADSC controlled - adsp/adsc 3-1-1-1 PL read
input [addr_msb:0] addr; // adsp/adsc 2-1-1-1 FT read
input adsp_;
input adsc_;
input ce_;
input cs1_;
input cs0;
input [3:0] nburst;
integer tempaddr,tempcounter;
begin
tempcounter = 0;
for (tempaddr=addr; tempaddr<addr+nburst; tempaddr=tempaddr+1) begin
@( negedge CLK );
if (tempaddr == addr) begin // 1st address
#(Tcyc/2 - Tsu);
A = addr;
GW_ = 1;
BWE_ = 1;
ADSP_ = adsp_;
ADSC_ = adsc_;
ADV_ = 1;
CE_ = ce_;
CS1_ = cs1_;
CS0 = cs0;
end
else begin
#(Tcyc/2 - Tsu); // after 2nd address
A = 19'hz;
ADV_ = 0;
end
assign data = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
@( posedge CLK ); // SRAM latches Address and begins internal read
lastaddr <= #(Tcyc) tempaddr;
if (tempaddr == addr) begin // 1st address
A <= #Tdh 19'hz;
ADSP_ <= #Tdh 1;
ADSC_ <= #Tdh 1;
CE_ <= #Tdh ~ce_;
CS1_ <= #Tdh ~cs1_;
CS0 <= #Tdh ~cs0;
if(pipe == 1)
OE_ <= #(Tcyc+Tcd-Toe) 0;
if(pipe == 0)
OE_ <= #(Tcd-Toe) 0;
end
else begin // after 2nd address
ADV_ <= #Tdh 1;
end
if(pipe == 1)
if(tempcounter > 1 )
if ( data !== Dstore[lastaddr] ) begin
status = "FAIL";
$display("%d Read error: Addr %h Exp %h Act %h", $stime, lastaddr,
Dstore[lastaddr], data);
end
else status = "PASS";
else if(pipe == 0)
if(tempcounter > 0 )
if ( data !== Dstore[lastaddr] ) begin
status = "FAIL";
$display("%d Read error: Addr %h Exp %h Act %h", $stime, lastaddr,
Dstore[lastaddr], data);
end
else status = "PASS";
DQ = 18'hz;
#Tdh;
tempcounter = tempcounter+1;
end
end
endtask
 
task burst_read_adv; // ADSP|ADSC controlled - adsp/adsc 3-1-1-1 PL read
input [addr_msb:0] addr; // adsp/adsc 2-1-1-1 FT read
input adsp_;
input adsc_;
input ce_;
input cs1_;
input cs0;
input adv_;
input [3:0] tempcounter;
begin
@( negedge CLK );
if (tempcounter == 0) begin // 1st address
#(Tcyc/2 - Tsu);
A = addr;
GW_ = 1;
BWE_ = 1;
ADSP_ = adsp_;
ADSC_ = adsc_;
ADV_ = adv_;
CE_ = ce_;
CS1_ = cs1_;
CS0 = cs0;
end
else begin
#(Tcyc/2 - Tsu); // after 2nd address
A = 19'hz;
ADSP_ = adsp_;
ADSC_ = adsc_;
CE_ = ce_;
ADV_ = adv_;
end
assign data = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
@( posedge CLK ); // SRAM latches Address and begins internal read
lastaddr <= #(Tcyc) addr;
if (tempcounter == 0) begin // 1st address
A <= #Tdh 19'hz;
ADSP_ <= #Tdh ~adsp_;
ADSC_ <= #Tdh ~adsc_;
CE_ <= #Tdh ~ce_;
CS1_ <= #Tdh ~cs1_;
CS0 <= #Tdh ~cs0;
if(pipe == 1)
OE_ <= #(Tcyc+Tcd-Toe) 0;
if(pipe == 0)
OE_ <= #(Tcd-Toe) 0;
end
else begin // after 2nd address
ADSP_ <= #Tdh ~adsp_;
ADSC_ <= #Tdh ~adsc_;
CE_ <= #Tdh ~ce_;
ADV_ <= #Tdh ~adv_;
end
if(pipe == 1)
if(tempcounter > 1 )
if ( data !== Dstore[lastaddr] ) begin
status = "FAIL";
$display("%d Read error: Addr %h Exp %h Act %h", $stime, lastaddr,
Dstore[lastaddr], data);
end
else status = "PASS";
else if(pipe == 0)
if(tempcounter > 0 )
if ( data !== Dstore[lastaddr] ) begin
status = "FAIL";
$display("%d Read error: Addr %h Exp %h Act %h", $stime, lastaddr,
Dstore[lastaddr], data);
end
else status = "PASS";
DQ = 18'hz;
end
endtask
 
task read_random;
input [addr_msb:0] addr;
output [17:0] data;
input [17:0] exp;
begin
if (CLK )
@( negedge CLK );
// DQ = 18'hz;
ADV_ = 1;
A = addr;
ADSP_ = 0;
@( posedge CLK ); // SRAM latches Address and begins internal read
@( negedge CLK );
ADSP_ = 1;
OE_ = 0;
if (pipe == 1) @( posedge CLK ); // SRAM begins placing data onto bus
@( posedge CLK ); // Data sampled by reading device
// Hopefully the SRAM has an output hold time
data = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
if ( data !== exp )
$display("%d Read_random error: Addr %h Exp %h Act %h", $stime, addr, exp, data);
@( negedge CLK );
OE_ = 1;
 
end
endtask
 
task burst_read_random;
input [addr_msb:0] addr;
input [17:0] n;
integer i;
begin
DQ = 18'hz;
if ( CLK )
@( negedge CLK );
#1 A = addr;
ADSP_ = 0;
@( posedge CLK ); // Address latched by SRAM, begins internal read
#(Tcyc/2) ADSP_ = 1; // SRAM starts driving bus (flow-through)
#1 OE_ = 0;
ADV_ = 0;
if (pipe == 1) @(posedge CLK); //SRAM starts driving bus (pipelined)
for (i=addr;i<addr+n;i=i) begin
@( posedge CLK ) begin
if (check_data == 1)
BurstData[i] = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
if ( BurstData[i] !== RandomData[i] && check_data == 1 )
$display("%d task burst_read_random read error: Addr %h Exp %h Act %h", $stime, i, RandomData[i], BurstData[i]);
end
@( negedge CLK );
if (check_data) i=i+1;
if ( ($random & 3) === 2'b11 ) // suspend burst 25% of the time
ADV_ = 1;
else begin
ADV_ = 0;
end
end
 
OE_ = 1;
ADV_ = 1;
end
endtask
 
task burst_wrap_random; //checks burst counter wrap-around
input [addr_msb:0] addr;
integer i,j;
begin
DQ = 18'hz;
if ( CLK )
@( negedge CLK );
#1 A = addr;
ADSP_ = 0;
@(posedge CLK); // Address latched by SRAM, begins internal read
#(Tcyc/2) ADSP_ = 1;
#1 OE_ = 0;
ADV_ = 0;
if (pipe == 1) @(posedge CLK);
for (i=0;i<2;i=i+1) begin
for (j=0;j<4;j=j+1) begin
@( posedge CLK ) begin
if (check_data == 1)
BurstData[j] = {DQPbus[2], DQbus[15:8], DQPbus[1], DQbus[7:0]};
if ( BurstData[j] !== RandomData[j] && check_data == 1 )
$display("%d task burst_wrap_random read error: Addr %h Exp %h Act %h", $stime, i, RandomData[i], BurstData[i]);
end
end
end
#1 OE_ = 1;
ADV_ = 1;
end
endtask
 
task burst_rd_pipe_random;
input [addr_msb:0] addr1;
input [addr_msb:0] addr2;
 
integer i;
 
begin
DQ = 18'hz;
for (i=0;i<12;i=i+1) begin
@(posedge CLK);
 
if (i == 0 | i == 4) begin
#(Tcyc/2) ADSP_ <= 0;
if (i == 0) A = addr1;
if (i == 4) A = addr2;
end
else #(Tcyc/2) ADSP_ <= 1;
 
if (i >= 1 && i <=10) OE_ = 0;
else OE_ = 1;
 
if (i >= 1 && i <= 3 || i >= 5 && i<= 7) ADV_ <= 0;
else ADV_ <= 1;
end
end
endtask
 
task write; //ADSP|ADSC controlled PL|FT - adsp 2cycle/adsc 1cycle write
input [addr_msb:0] addr;
input [17:0] data;
input adsp_;
input adsc_;
input gw_;
input ce_;
input cs1_;
input cs0;
begin
@( negedge CLK );
A <= #(Tcyc/2-Tsu) addr;
ADSP_ <= #(Tcyc/2-Tsu) adsp_;
ADSC_ <= #(Tcyc/2-Tsu) adsc_;
DQ = 18'hz;
ADV_ = 1;
CE_ <= #(Tcyc/2-Tsu) ce_;
CS1_ <= #(Tcyc/2-Tsu) cs1_;
CS0 <= #(Tcyc/2-Tsu) cs0;
OE_ <= #(Tcyc/2-Tsu) 1;
if (adsp_ == 0) // if adsp_ controlled
GW_ = ~gw_;
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
#(Tcyc/2-Tsu)
GW_ = gw_;
DQ = data;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[addr] = data;
end
else
DQ = 18'hz;
@( posedge CLK );
counter = 0;
A <= #Tdh 19'hz;
ADSP_ <= #Tdh 1;
ADSC_ <= #Tdh 1;
// OE_ <= #Tdh 1;
CE_ <= #Tdh 1;
CS1_ <= #Tdh 1;
CS0 <= #Tdh 0;
if (adsp_ == 0) begin // if adsp controlled
#(Tcyc - Tsu);
GW_ = gw_;
DQ = data;
//$display($time, "DQ %h data %d addr %d", DQ, data, addr);
GW_ <= #(Tsu + Tdh) ~gw_;
DQ <= #(Tsu + Tdh) 18'hz;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[addr] = data;
end
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
GW_ <= #Tdh ~gw_;
DQ <= #Tdh 18'hz;
end
else
DQ = 18'hz;
end
endtask
 
task burst_write; //ADSP&ADSC controlled PL|FT - adsp_ 2-1-1-1/adsc_ 1-1-1-1 write
input [addr_msb:0] addr;
input [17:0] data;
input adsp_;
input adsc_;
input gw_;
input ce_;
input cs1_;
input cs0;
input [3:0] nburst;
integer tempaddr,tempcounter;
begin
tempcounter = 0;
for (tempaddr=addr; tempaddr<addr+nburst; tempaddr=tempaddr+1) begin
@( negedge CLK );
DQ = 18'hz;
if (tempaddr == addr) begin
A <= #(Tcyc/2-Tsu) addr;
ADSP_ <= #(Tcyc/2-Tsu) adsp_;
ADSC_ <= #(Tcyc/2-Tsu) adsc_;
ADV_ = 1;
CE_ <= #(Tcyc/2-Tsu) ce_;
CS1_ <= #(Tcyc/2-Tsu) cs1_;
CS0 <= #(Tcyc/2-Tsu) cs0;
if (adsp_ == 0) begin // if adsp_ controlled
ADV_ = 1;
GW_ = ~gw_;
end
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
#(Tcyc/2-Tsu);
GW_ = gw_;
DQ = data;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[tempaddr] = data;
end
else
DQ = 18'hz;
end
else begin // burst after 2nd cycle
ADSP_ = 1;
ADSC_ = 1;
#(Tcyc/2-Tsu);
GW_ = gw_;
data = data+1;
DQ = data;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[tempaddr] = data;
if (tempcounter == 0) ADV_ = 1;
else ADV_ = 0;
end
@( posedge CLK );
counter = 0;
if (tempaddr == addr) begin
A <= #Tdh 19'hz;
ADSP_ <= #Tdh 1;
ADSC_ <= #Tdh 1;
OE_ <= #Tdh 1;
CE_ <= #Tdh ~ce_;
CS1_ <= #Tdh ~cs1_;
CS0 <= #Tdh ~cs0;
if (adsp_ == 0) begin // if adsp_ controlled
#(Tcyc - Tsu);
GW_ = gw_;
DQ = data;
ADV_ <= #(Tsu + Tdh) 1;
GW_ <= #(Tsu + Tdh) ~gw_;
DQ <= #(Tsu + Tdh) 18'hz;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[tempaddr] = data;
if (tempcounter == 0) ADV_ = 1;
else ADV_ = 0;
end
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
ADV_ <= #Tdh 1;
GW_ <= #Tdh ~gw_;
DQ <= #Tdh 18'hz;
end
else
DQ = 18'hz;
end
else begin // burst after 2nd cycle
ADV_ <= #Tdh 1;
GW_ <= #Tdh ~gw_;
DQ <= #Tdh 18'hz;
end
tempcounter = tempcounter+1;
end
end
endtask
 
task burst_write_adv; //ADSP|ADSC controlled PL|FT - adsp_ 2-1-1-1/adsc_ 1-1-1-1 write
input [addr_msb:0] addr;
input [17:0] data;
input adsp_;
input adsc_;
input gw_;
input ce_;
input cs1_;
input cs0;
input adv_;
input [3:0] tempcounter;
begin
@( negedge CLK );
DQ = 18'hz;
if (tempcounter == 0) begin
A <= #(Tcyc/2-Tsu) addr;
ADSP_ <= #(Tcyc/2-Tsu) adsp_;
ADSC_ <= #(Tcyc/2-Tsu) adsc_;
ADV_ = adv_;
CE_ <= #(Tcyc/2-Tsu) ce_;
CS1_ <= #(Tcyc/2-Tsu) cs1_;
CS0 <= #(Tcyc/2-Tsu) cs0;
if (adsp_ == 0) begin // if adsp_ controlled
ADV_ = adv_;
GW_ = ~gw_;
end
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
#(Tcyc/2-Tsu);
GW_ = gw_;
DQ = data;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[addr] = data;
end
else
DQ = 18'hz;
end
else begin // burst after 2nd cycle
ADSP_ = 1;
ADSC_ = 1;
#(Tcyc/2-Tsu);
GW_ = gw_;
ADV_ = adv_;
DQ = data;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[addr] = data;
end
@( posedge CLK );
counter = 0;
if (tempcounter == 0) begin
A <= #Tdh 19'hz;
ADSP_ <= #Tdh 1;
ADSC_ <= #Tdh 1;
OE_ <= #Tdh 1;
CE_ <= #Tdh ~ce_;
CS1_ <= #Tdh ~cs1_;
CS0 <= #Tdh ~cs0;
if (adsp_ == 0) begin // if adsp_ controlled
#(Tcyc - Tsu);
GW_ = gw_;
DQ = data;
ADV_ <= #(Tsu + Tdh) ~adv_;
GW_ <= #(Tsu + Tdh) ~gw_;
DQ <= #(Tsu + Tdh) 18'hz;
if (cs1_ == 0 & cs0 == 1 & ce_ == 0)
Dstore[addr] = data;
ADV_ = adv_;
end
else if (adsp_ == 1 & adsc_ == 0) begin // if adsc_ controlled
ADV_ <= #Tdh 1;
GW_ <= #Tdh ~gw_;
DQ <= #Tdh 18'hz;
end
else
DQ = 18'hz;
end
else begin // burst after 2nd cycle
ADV_ <= #Tdh 1;
GW_ <= #Tdh ~gw_;
DQ <= #Tdh 18'hz;
end
end
endtask
 
task write_random;
input [addr_msb:0] addr;
input [17:0] data;
begin
if ( CLK )
@( negedge CLK );
OE_ = 1;
ADV_ = 1;
A = addr;
ADSP_ = 0;
@( negedge CLK );
ADSP_ = 1;
GW_ = 0;
#(Tcyc/2-Tsu) DQ = data;
@( posedge CLK );
#Tdh
DQ = 18'hz;
@( negedge CLK );
GW_ = 1;
end
endtask
 
task burst_write_random;
input [addr_msb:0] addr;
input [17:0] n;
integer i;
begin
if ( CLK )
@( negedge CLK );
#1 A = addr;
ADSP_ = 0;
for (i=addr;i<addr+n;i=i+1) begin
@( negedge CLK );
ADSP_ = 1;
if (addr!=i) ADV_ = 0;
#(Tcyc/2-Tsu) DQ = BurstData[i];
@( posedge CLK );
end
@( negedge CLK );
ADV_ = 1;
end
endtask
 
task byte_write_random;
input [addr_msb:0] addr;
input [17:0] data;
begin
if ( CLK )
@( negedge CLK );
ADV_ = 1;
A = addr;
ADSP_ = 0;
@( negedge CLK );
ADSP_ = 1;
BWE_ = 0;
#(Tcyc/2-Tsu) DQ = data;
@( posedge CLK );
#Tdh
DQ = 18'hz;
@( negedge CLK );
BWE_ = 1;
end
endtask
 
endmodule
 
/tests.v
0,0 → 1,3640
/////////////////////////////////////////////////////////////////////
//// ////
//// Top Level Test Bench ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: tests.v,v 1.7 2002-01-21 13:10:37 rudi Exp $
//
// $Date: 2002-01-21 13:10:37 $
// $Revision: 1.7 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.6 2001/11/29 02:17:36 rudi
//
//
// - More Synthesis cleanup, mostly for speed
// - Several bug fixes
// - Changed code to avoid auto-precharge and
// burst-terminate combinations (apparently illegal ?)
// Now we will do a manual precharge ...
//
// Revision 1.5 2001/11/13 00:45:19 rudi
//
// Just minor test bench update, syncing all the files.
//
// Revision 1.4 2001/11/11 01:52:03 rudi
//
// Minor fixes to testbench ...
//
// Revision 1.3 2001/09/02 02:29:43 rudi
//
// Fixed the TMS register setup to be tight and correct.
//
// Revision 1.2 2001/08/10 08:16:21 rudi
//
// - Changed IO names to be more clear.
// - Uniquifyed define names to be core specific.
// - Removed "Refresh Early" configuration
//
// Revision 1.1 2001/07/29 07:34:40 rudi
//
//
// 1) Changed Directory Structure
// 2) Fixed several minor bugs
//
// Revision 1.1.1.1 2001/05/13 09:36:38 rudi
// Created Directory Structure
//
//
//
//
 
 
 
task sdram_bo;
 
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer write;
reg [31:0] mem_data;
reg [1:0] bas, kro;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Bank Overflow test 1 ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
//force sdram0.Debug = 1;
del = 1;
bas = 0;
kro = 1;
for(kro=0;kro<2;kro=kro+1)
for(bas=0;bas<2;bas=bas+1)
begin
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821 | (bas<<9) | (kro<<10));
 
fill_mem(1024);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd8, // Trfc [27:24]
4'd3, // Trp [23:20]
3'd3, // Trcd [19:17]
2'd2, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0 // Burst Length
});
 
$display("kro: %0d, bas: %0d", kro, bas);
 
m0.mem_fill;
for(n=250;n<260;n=n+1)
begin
 
m0.wb_rd_mult(`MEM_BASE + (n*4), 4'hf, del, 1);
 
if(!bas)
case(n[9:8])
0: mem_data = sdram0.Bank0[n];
1: mem_data = sdram0.Bank1[n-256];
2: mem_data = sdram0.Bank2[n];
3: mem_data = sdram0.Bank3[n];
endcase
else mem_data = sdram0.Bank0[n];
 
if((mem_data !== m0.rd_mem[n-250]) |
(|mem_data === 1'bx) |
(|m0.rd_mem[n-250] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, mem_data, m0.rd_mem[n-250], $time);
error_cnt = error_cnt + 1;
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
task sdram_rd1;
input quick;
 
integer quick;
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer write;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Read test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821);
 
case(quick)
0: sz_max = 64;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 6;
endcase
 
size = 4;
del = 0;
mode = 2;
write = 1; // enable writes for parity !
 
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd8, // Trfc [27:24]
4'd3, // Trp [23:20]
3'd3, // Trcd [19:17]
2'd2, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("Mode: %b", mode);
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE + 0, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + 0, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
for(n=0;n<(size*4);n=n+1)
begin
if((sdram0.Bank0[n] !== m0.rd_mem[n]) |
(|sdram0.Bank0[n] === 1'bx) |
(|m0.rd_mem[n] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, sdram0.Bank0[n], m0.rd_mem[n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
task sdram_wr1;
input quick;
 
integer quick;
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Write test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821);
 
case(quick)
0: sz_max = 64;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 6;
endcase
 
size = 1;
del = 2;
mode = 16;
read = 1;
//force sdram0.Debug = 1;
 
for(mode=0;mode<20;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
if(mode[1])
sz_inc = 1;
else
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d (%t)", mode, size, del, $time);
 
m0.wb_wr_mult(`MEM_BASE + 0, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + 0, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
for(n=0;n< (size*4);n=n+1)
begin
if((sdram0.Bank0[n] !== m0.wr_mem[n]) |
(|sdram0.Bank0[n] === 1'bx) |
(|m0.wr_mem[n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, sdram0.Bank0[n], m0.wr_mem[n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
task sdram_rd2;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Read test 2 ... ***");
$display("*** Different Row and Bank ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821 | (bas[0]<<9));
 
size = 33;
del = 0;
mode = 0;
 
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
 
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2);n=n+1)
begin
adr = (m * page_size) + (m*size*2) + n;
 
if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.rd_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.rd_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.rd_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
end
 
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
task sdram_wr2;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Write test 2 ... ***");
$display("*** Different Row and Bank ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821 | (bas[0]<<9));
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 3;
del = 0;
mode = 10;
//force sdram0.Debug = 1;
 
for(mode=0;mode<20;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[4:2])
0: bs = 0; // 1 Transfer
1: bs = 1; // 2 Transfers
2: bs = 2; // 4 Transfers
3: bs = 3; // 8 Transfers
4: bs = 7; // Page Size Transfer
endcase
 
if(mode[1])
begin
sz_inc = 1;
end
else
begin
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
end
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, { // 22'h3fff_ff,
 
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
for(m=0;m<4;m=m+1)
for(n=0;n<size*2;n=n+1)
begin
adr = (m * page_size) + (m*size*2) + n;
 
if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.wr_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.wr_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.wr_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
task sdram_rd3;
input quick;
 
integer quick;
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer sbs, write;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Read test 3 ... ***");
$display("*** Keep Row Open Active ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21);
 
case(quick)
0: sz_max = 65;
1: sz_max = 33;
2: sz_max = 17;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 4;
del = 0;
mode = 8;
write = 1;
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sbs = 1;
1: sbs = 2;
2: sbs = 4;
3: sbs = 8;
4: sbs = 1024;
endcase
 
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
 
4'd0, // RESERVED [31:28]
4'd5, // Trfc [27:24]
4'd1, // Trp [23:20]
3'd1, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
 
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE + 0, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + 0, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
for(n=0;n<(size*4);n=n+1)
begin
if((sdram0.Bank0[n] !== m0.rd_mem[n]) |
(|sdram0.Bank0[n] === 1'bx) |
(|m0.rd_mem[n] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, sdram0.Bank0[n], m0.rd_mem[n], $time);
error_cnt = error_cnt + 1;
end
 
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
task sdram_wr3;
input quick;
 
integer quick;
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer sbs, read;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Write test 3 ... ***");
$display("*** Keep Row Open Active ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21);
 
case(quick)
0: sz_max = 64;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 8;
del = 0;
mode = 16;
read = 1;
//force sdram0.Debug = 1;
 
for(mode=0;mode<20;mode=mode+1)
begin
 
sdram0.mem_fill(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
case(mode[4:2])
0: sbs = 1;
1: sbs = 2;
2: sbs = 4;
3: sbs = 8;
4: sbs = 1024;
endcase
 
if(mode[1])
sz_inc = 1;
else
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
 
4'd0, // RESERVED [31:28]
4'd5, // Trfc [27:24]
4'd1, // Trp [23:20]
3'd1, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
//bw_clear;
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + 0, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + 0, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
//bw_report;
repeat(10) @(posedge clk);
 
for(n=0;n< (size*4);n=n+1)
begin
if((sdram0.Bank0[n] !== m0.wr_mem[n]) |
(|sdram0.Bank0[n] === 1'bx) |
(|m0.wr_mem[n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, sdram0.Bank0[n], m0.wr_mem[n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
task sdram_rd4;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
integer write;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Read test 4 ... ***");
$display("*** KRO & Different Row and Bank ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
fill_mem(1024);
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21 | (bas[0]<<9));
 
size = 2;
del = 3;
mode = 0;
write = 1;
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
sdram0.mem_fill(1024);
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
//$display("Accessing Bank 0");
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
//$display("Accessing Bank 1");
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
//$display("Accessing Bank 2");
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
//$display("Accessing Bank 3");
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
 
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2);n=n+1)
begin
adr = (m * page_size) + (m*(size*2)) + n;
 
if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.rd_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.rd_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.rd_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
 
task sdram_wr4;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Write test 4 ... ***");
$display("*** KRO & Different Row and Bank ***");
$display("*****************************************************\n");
 
//force sdram0.Debug = 1;
 
page_size = 256; // 64 mbit x 32 SDRAM
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21 | (bas[0]<<9));
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 8;
endcase
 
size = 1;
del = 3;
mode = 4;
read = 1;
 
for(mode=0;mode<20;mode=mode+1)
begin
 
//sdram0.mem_fill(1024);
fill_mem(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
if(mode[1])
sz_inc = 1;
else
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
 
repeat(20) @(posedge clk);
 
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2);n=n+1)
begin
adr = (m * page_size) + (m*size*2) + n;
 
if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.wr_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.wr_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.wr_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
 
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
`ifdef MULTI_SDRAM
 
task sdram_rd5;
input quick;
 
integer quick;
integer s,n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
integer write;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Read test 5 ... ***");
$display("*** KRO & Different Row and Bank and CS ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 8;
endcase
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS1, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS2, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21 | (bas[0]<<9));
m0.wb_wr1(`REG_BASE + `CSC1, 4'hf, 32'h0020_0c21 | (bas[0]<<9));
m0.wb_wr1(`REG_BASE + `CSC2, 4'hf, 32'h0040_0c21 | (bas[0]<<9));
 
size = 2;
del = 3;
mode = 0;
write = 1;
if(0)
begin
force sdram0.Debug = 1;
force sdram1.Debug = 1;
force sdram2.Debug = 1;
end
 
for(mode=0;mode<10;mode=mode+1)
for(mode=0;mode<10;mode=mode+1)
begin
//sdram0.mem_fill(1024);
//sdram1.mem_fill(1024);
//sdram2.mem_fill(1024);
 
fill_mem(1024);
fill_mem1(1024);
fill_mem2(1024);
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS1, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS2, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd3-mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE1 + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE1 + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(write)
m0.wb_wr_mult(`MEM_BASE2 + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_rd_mult(`MEM_BASE2 + (page_size*3*4) + size*7*4, 4'hf, del, size);
 
for(m=0;m<4;m=m+1)
for(s=0;s<3;s=s+1)
for(n=0;n<(size*2);n=n+1)
begin
adr = (m * page_size) + (m*(size*2)) + n;
 
case(s)
0: if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
1: if(bas[0]) data = sdram1.Bank0[adr];
else
case(m)
0: data = sdram1.Bank0[n];
1: data = sdram1.Bank1[n+1*size*2];
2: data = sdram1.Bank2[n+2*size*2];
3: data = sdram1.Bank3[n+3*size*2];
endcase
2: if(bas[0]) data = sdram2.Bank0[adr];
else
case(m)
0: data = sdram2.Bank0[n];
1: data = sdram2.Bank1[n+1*size*2];
2: data = sdram2.Bank2[n+2*size*2];
3: data = sdram2.Bank3[n+3*size*2];
endcase
endcase
 
if((data !== m0.rd_mem[(m*size*6)+(s*size*2)+n]) | (|data === 1'bx) |
(|m0.rd_mem[(m*size*6)+(s*size*2)+n] === 1'bx) )
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*6)+(s*size*2)+n, data, m0.rd_mem[(m*size*6)+(s*size*2)+n], $time);
error_cnt = error_cnt + 1;
if(error_cnt > 25) $finish;
end
 
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
 
task sdram_wr5;
input quick;
 
integer quick;
integer s,n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data;
integer page_size;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode Write test 5 ... ***");
$display("*** KRO & Different Row and Bank and CS ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0000);
m0.wb_wr1(`REG_BASE + `CSC1, 4'hf, 32'h0000_0000);
m0.wb_wr1(`REG_BASE + `CSC2, 4'hf, 32'h0000_0000);
repeat(10) @(posedge clk);
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS1, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
m0.wb_wr1(`REG_BASE + `TMS2, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
bas = 0;
for(bas=0;bas<2;bas=bas+1)
begin
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0c21 | (bas[0]<<9));
m0.wb_wr1(`REG_BASE + `CSC1, 4'hf, 32'h0020_0c21 | (bas[0]<<9));
m0.wb_wr1(`REG_BASE + `CSC2, 4'hf, 32'h0040_0c21 | (bas[0]<<9));
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 8;
endcase
 
size = 5;
del = 0;
mode = 0;
read = 1;
 
if(0)
begin
force sdram0.Debug = 1;
force sdram1.Debug = 1;
force sdram2.Debug = 1;
end
 
for(mode=0;mode<20;mode=mode+1)
begin
 
//sdram0.mem_fill(1024);
//sdram1.mem_fill(1024);
//sdram2.mem_fill(1024);
 
fill_mem(1024);
fill_mem1(1024);
fill_mem2(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
if(mode[1])
sz_inc = 1;
else
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
 
m0.wb_wr1(`REG_BASE + `TMS1, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd3-mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
 
m0.wb_wr1(`REG_BASE + `TMS2, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("BAS: %0d, Mode: %b", bas, mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
if(verbose) $display("BAS: %0d, Mode: %b, Size: %0d, Delay: %0d",
bas, mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*0*4) + size*1*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*0*4) + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*0*4) + size*0*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*0*4) + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*0*4) + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*1*4) + size*3*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*1*4) + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*1*4) + size*2*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*1*4) + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*1*4) + size*3*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*2*4) + size*5*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*2*4) + size*4*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*2*4) + size*4*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*2*4) + size*5*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*2*4) + size*5*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE1 + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE1 + (page_size*3*4) + size*7*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*3*4) + size*6*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*3*4) + size*6*4, 4'hf, del, size);
m0.wb_wr_mult(`MEM_BASE2 + (page_size*3*4) + size*7*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE2 + (page_size*3*4) + size*7*4, 4'hf, del, size);
 
 
 
repeat(20) @(posedge clk);
 
for(m=0;m<4;m=m+1)
for(s=0;s<3;s=s+1)
for(n=0;n<(size*2);n=n+1)
begin
adr = (m * page_size) + (m*size*2) + n;
 
case(s)
0: if(bas[0]) data = sdram0.Bank0[adr];
else
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
1: if(bas[0]) data = sdram1.Bank0[adr];
else
case(m)
0: data = sdram1.Bank0[n];
1: data = sdram1.Bank1[n+1*size*2];
2: data = sdram1.Bank2[n+2*size*2];
3: data = sdram1.Bank3[n+3*size*2];
endcase
2: if(bas[0]) data = sdram2.Bank0[adr];
else
case(m)
0: data = sdram2.Bank0[n];
1: data = sdram2.Bank1[n+1*size*2];
2: data = sdram2.Bank2[n+2*size*2];
3: data = sdram2.Bank3[n+3*size*2];
endcase
endcase
 
if((data !== m0.wr_mem[(m*size*6)+(s*size*2)+n]) | (|data === 1'bx) |
(|m0.wr_mem[(m*size*6)+(s*size*2)+n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d-%0d] Mismatch: Expected: %x, Got: %x (%0t)",
s, (m*size*2)+n, data, m0.wr_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
 
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
`endif
 
 
task rmw_cross1;
input quick;
 
integer quick;
integer x,s,n,m,adr;
integer del, size;
reg [7:0] mode, a_mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data, exp;
integer page_size;
integer cycle;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** RMW CS Cross Test 1 ... ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS3, 4'hf, 32'hffff_f40c);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821);
 
case(quick)
0: sz_max = 32;
1: sz_max = 16;
2: sz_max = 8;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 16;
del = 0;
mode = 4;
a_mode = 0;
read = 1;
write = 1;
cycle = 1;
 
for(cycle=0;cycle<7;cycle = cycle + 1)
for(mode=0;mode<19;mode=mode+1)
for(a_mode=0;a_mode<3;a_mode=a_mode+1)
begin
 
repeat(1) @(posedge clk);
 
sdram0.mem_fill(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
case(a_mode)
0: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0025); // 32 bit bus
1: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0005); // 8 bit bus
2: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0015); // 16 bit bus
endcase
 
repeat(10) @(posedge clk);
if(!verbose) $display("Mode: %b, Bus Width: %0d, Cycle Delay: %0d", mode, a_mode, cycle);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
for(n=0;n<1024;n=n+1)
m0.wr_mem[n] = {n[15:0],n[15:0]};
 
if(verbose) $display("Mode: %0d, A_mode: %0d, Size: %0d, Delay: %0d, Cyc. Delay: %0d", mode, a_mode, size, del, cycle);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*0*4,
`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*1*4,
`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*2*4,
`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*3*4,
`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*4*4,
`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*5*4,
`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*6*4,
`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw2(`MEM_BASE3 + size*7*4,
`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size, size);
 
repeat(10) @(posedge clk);
 
x = 0;
for(n=0;n<(size*8);n=n+1)
begin
 
case(a_mode)
0: data = {16'hxxxx, n[15:0]};
1:
begin
data[31:24] = x[7:0]+3;
data[23:16] = x[7:0]+2;
data[15:08] = x[7:0]+1;
data[07:00] = x[7:0]+0;
end
2: begin
data[31:16] = x[15:0]+1;
data[15:00] = x[15:0]+0;
end
endcase
 
case(a_mode)
0: x = x + 1;
1: x = x + 4;
2: x = x + 2;
endcase
 
exp = m0.rd_mem[n];
if(a_mode==0) exp[31:16] = data[31:16];
 
if(data !== exp)
begin
$display("ERROR: RD[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, data, exp, $time);
error_cnt = error_cnt + 1;
end
 
end
 
for(m=0;m<4;m=m+1)
for(n=0;n<size*2;n=n+1)
begin
 
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.wr_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.wr_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.wr_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
 
task asc_rdwr1;
input quick;
 
integer quick;
integer x,s,n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data, exp;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** ASC Read/Write Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS3, 4'hf, 32'hffff_f40b);
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 16;
del = 0;
mode = 0;
read = 1;
write = 1;
 
sz_max = 6;
for(mode=0;mode<3;mode=mode+1)
begin
 
repeat(1) @(posedge clk);
 
case(mode)
0: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0025); // 32 bit bus
1: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0005); // 8 bit bus
2: m0.wb_wr1(`REG_BASE + `CSC3, 4'hf, 32'h0060_0015); // 16 bit bus
endcase
 
repeat(10) @(posedge clk);
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=1;size<sz_max;size=size+1)
begin
m0.mem_fill;
for(n=0;n<1024;n=n+1)
m0.wr_mem[n] = 32'hffff_ffff;
if(verbose) $display("Mode: %0d, Size: %0d, Delay: %0d", mode, size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE3 + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE3 + size*0*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE3 + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE3 + size*1*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE3 + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE3 + size*2*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE3 + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE3 + size*3*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
x = 0;
for(n=0;n<(size*4);n=n+1)
begin
 
case(mode)
0: data = {16'hxxxx, n[15:0]};
1:
begin
data[31:24] = x[7:0]+3;
data[23:16] = x[7:0]+2;
data[15:08] = x[7:0]+1;
data[07:00] = x[7:0]+0;
end
2: begin
data[31:16] = x[15:0]+1;
data[15:00] = x[15:0]+0;
end
endcase
 
case(mode)
0: x = x + 1;
1: x = x + 4;
2: x = x + 2;
endcase
 
exp = m0.rd_mem[n];
if(mode==0) exp[31:16] = data[31:16];
 
if(data !== exp)
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, data, exp, $time);
error_cnt = error_cnt + 1;
end
end
 
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
task boot;
input quick;
 
integer quick;
integer x,s,n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data, exp;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** ASC Boot Test 1 ... ***");
$display("*****************************************************\n");
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 1;
del = 0;
mode = 0;
read = 1;
write = 1;
 
for(mode=0;mode<3;mode=mode+1)
begin
 
repeat(1) @(posedge clk);
 
case(mode)
0: begin
poc_mode = 2;
mc_reset;
end
1: begin
poc_mode = 0;
mc_reset;
end
2: begin
poc_mode = 1;
mc_reset;
end
endcase
 
repeat(5) @(posedge clk);
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=1;size<sz_max;size=size+1)
begin
m0.mem_fill;
for(n=0;n<1024;n=n+1)
m0.wr_mem[n] = 32'hffff_ffff;
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*0*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
x = 0;
for(n=0;n<(size*4);n=n+1)
begin
 
case(mode)
0: data = {16'hxxxx, n[15:0]};
1:
begin
data[31:24] = x[7:0]+3;
data[23:16] = x[7:0]+2;
data[15:08] = x[7:0]+1;
data[07:00] = x[7:0]+0;
end
 
2: begin
data[31:16] = x[15:0]+1;
data[15:00] = x[15:0]+0;
end
endcase
 
case(mode)
0: x = x + 1;
1: x = x + 4;
2: x = x + 2;
endcase
 
exp = m0.rd_mem[n];
if(mode==0) exp[31:16] = data[31:16];
 
if(data !== exp)
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, data, exp, $time);
error_cnt = error_cnt + 1;
end
end
end
end
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
 
`ifdef SRAM
task sram_rd1;
 
integer n,m,read,write;
integer d2, del, size;
reg [31:0] data;
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SRAM Size & Delay Read Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS4, 4'hf, 32'hffff_ffff);
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC4, 4'hf, 32'h0080_0803);
 
size = 5;
del = 0;
read = 1;
write = 1;
 
sram0a.mem_fill( 1024 );
sram0b.mem_fill( 1024 );
 
repeat(1) @(posedge clk);
 
for(del=0;del<16;del=del+1)
for(size=1;size<18;size=size+1)
begin
m0.mem_fill;
 
$display("Size: %0d, Delay: %0d", size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE4 + size * 0 * 16, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + size * 0 * 16, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + size * 1 * 16, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + size * 1 * 16, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + size * 2 * 16, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + size * 2 * 16, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + size * 3 * 16, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + size * 3 * 16, 4'hf, del, size);
 
for(m=0;m< 4;m=m+1)
for(n=0;n< size;n=n+1)
begin
 
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*size*4)+n];
data[15:08] = sram0a.bank1[(m*size*4)+n];
data[23:16] = sram0b.bank0[(m*size*4)+n];
data[31:24] = sram0b.bank1[(m*size*4)+n];
 
`else
data[07:00] = sram0a.memb1[(m*4)+n];
data[15:08] = sram0a.memb2[(m*4)+n];
data[23:16] = sram0b.memb1[(m*4)+n];
data[31:24] = sram0b.memb2[(m*4)+n];
`endif
 
 
if(data !== m0.rd_mem[(m*size)+n])
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*4)+n, data, m0.rd_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
task sram_wr1;
 
integer n,m,read,write;
integer del, size;
reg [31:0] data;
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SRAM Size & Delay Write Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS4, 4'hf, 32'hffff_ffff);
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC4, 4'hf, 32'h0080_0803);
 
size = 4;
del = 4;
mode = 0;
read = 1;
write = 1;
 
sram0a.mem_fill( 256 );
sram0b.mem_fill( 256 );
 
repeat(1) @(posedge clk);
 
for(del=0;del<16;del=del+1)
for(size=1;size<18;size=size+1)
begin
m0.mem_fill;
 
$display("Size: %0d, Delay: %0d", size, del);
//bw_clear;
 
if(write) m0.wb_wr_mult(`MEM_BASE4 + 0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 0*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 32*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 32*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 64*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 64*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 96*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 96*4, 4'hf, del, size);
 
//bw_report;
 
repeat(10) @(posedge clk);
 
for(m=0;m< 4;m=m+1)
for(n=0;n< size;n=n+1)
begin
 
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*32)+n];
data[15:08] = sram0a.bank1[(m*32)+n];
data[23:16] = sram0b.bank0[(m*32)+n];
data[31:24] = sram0b.bank1[(m*32)+n];
`else
data[07:00] = sram0a.memb1[(m*32)+n];
data[15:08] = sram0a.memb2[(m*32)+n];
data[23:16] = sram0b.memb1[(m*32)+n];
data[31:24] = sram0b.memb2[(m*32)+n];
`endif
 
if(data !== m0.wr_mem[(m*size)+n])
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*32)+n, data, m0.wr_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
`endif
 
 
task scs_rdwr1;
input quick;
 
integer quick;
integer x,s,n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
reg [2:0] bas;
reg [31:0] data;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SCS Read/Write Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS5, 4'hf, 32'hf03f_4105);
m0.wb_wr1(`REG_BASE + `CSC5, 4'hf, 32'h00a0_0027);
 
 
case(quick)
0: sz_max = 32;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 1;
del = 0;
mode = 1;
read = 1;
write = 0;
 
s0.mem_fill;
 
repeat(5) @(posedge clk);
 
for(del=0;del<del_max;del=del+1)
for(size=1;size<sz_max;size=size+1)
begin
m0.mem_fill;
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
if(write) m0.wb_wr_mult(`MEM_BASE5 + size*0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE5 + size*0*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE5 + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE5 + size*1*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE5 + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE5 + size*2*4, 4'hf, del, size);
 
if(write) m0.wb_wr_mult(`MEM_BASE5 + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE5 + size*3*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
x = 0;
for(n=0;n<(size*4);n=n+1)
begin
 
data = s0.mem[n];
 
if(data !== m0.rd_mem[n])
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, data, m0.rd_mem[n], $time);
error_cnt = error_cnt + 1;
end
end
 
end
 
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
 
task sdram_wp;
input quick;
 
integer quick;
integer n;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
integer read;
 
begin
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Write Protect Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6020_0200);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0921);
 
wb_err_check_dis=1;
case(quick)
0: sz_max = 64;
1: sz_max = 32;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 4;
endcase
 
size = 4;
del = 1;
mode = 0;
read = 1;
//force sdram0.Debug = 1;
 
for(mode=0;mode<20;mode=mode+1)
begin
fill_mem(1024);
 
case(mode[4:2])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
 
if(mode[1])
sz_inc = 1;
else
case(mode[4:2])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[1], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2+mode[0], // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
if(!verbose) $display("Mode: %b", mode);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
 
if(verbose) $display("Mode: %b, Size: %0d, Delay: %0d", mode, size, del);
 
m0.wb_wr_mult(`MEM_BASE + 0, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + 0, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*1*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*2*4, 4'hf, del, size);
 
m0.wb_wr_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE + size*3*4, 4'hf, del, size);
 
repeat(10) @(posedge clk);
 
for(n=0;n< (size*4);n=n+1)
begin
if((sdram0.Bank0[n] == m0.wr_mem[n]) |
(|sdram0.Bank0[n] === 1'bx) |
(|m0.wr_mem[n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
n, sdram0.Bank0[n], m0.wr_mem[n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
 
wb_err_check_dis=0;
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
`ifdef SRAM
task sram_wp;
 
integer n,m,read,write;
integer del, size;
reg [31:0] data;
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SRAM Write Protect Test 1 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS4, 4'hf, 32'hffff_ffff);
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC4, 4'hf, 32'h0080_0903);
 
size = 17;
del = 15;
mode = 0;
read = 1;
write = 1;
 
sram0a.mem_fill( 256 );
sram0b.mem_fill( 256 );
 
wb_err_check_dis=1;
repeat(1) @(posedge clk);
 
for(del=0;del<16;del=del+1)
for(size=1;size<18;size=size+1)
begin
m0.mem_fill;
 
$display("Size: %0d, Delay: %0d", size, del);
//bw_clear;
 
if(write) m0.wb_wr_mult(`MEM_BASE4 + 0*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 0*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 32*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 32*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 64*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 64*4, 4'hf, del, size);
if(write) m0.wb_wr_mult(`MEM_BASE4 + 96*4, 4'hf, del, size);
if(read) m0.wb_rd_mult(`MEM_BASE4 + 96*4, 4'hf, del, size);
 
//bw_report;
 
repeat(10) @(posedge clk);
 
for(m=0;m< 4;m=m+1)
for(n=0;n< size;n=n+1)
begin
 
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*32)+n];
data[15:08] = sram0a.bank1[(m*32)+n];
data[23:16] = sram0b.bank0[(m*32)+n];
data[31:24] = sram0b.bank1[(m*32)+n];
`else
data[07:00] = sram0a.memb1[(m*32)+n];
data[15:08] = sram0a.memb2[(m*32)+n];
data[23:16] = sram0b.memb1[(m*32)+n];
data[31:24] = sram0b.memb2[(m*32)+n];
`endif
 
if(data == m0.wr_mem[(m*size)+n])
begin
$display("ERROR: Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*32)+n, data, m0.wr_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
 
end
 
wb_err_check_dis=0;
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
`endif
 
 
task sdram_rmw1;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
reg [2:0] kro;
reg [31:0] data;
integer page_size;
reg [31:0] mem0[0:1024];
reg [31:0] mem1[0:1024];
reg [31:0] mem2[0:1024];
reg [31:0] mem3[0:1024];
integer cycle;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode RMW test 1 ... ***");
$display("*** Different Row and Bank ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
case(quick)
0: sz_max = 32;
1: sz_max = 16;
2: sz_max = 16;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 8;
endcase
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
kro = 1;
cycle=3;
for(cycle=0;cycle<8;cycle=cycle+1)
for(kro=0;kro<2;kro=kro+1) // Don't Need this for this test
begin
 
// Parity nabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821 | (kro[0]<<10));
 
size = 2;
del = 5;
mode = 2;
 
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0+mode[0], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
repeat(50) @(posedge clk);
 
if(!verbose) $display("KRO: %0d, Mode: %b, Cyc. Delay: %0d", kro, mode, cycle);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
fill_mem(1024);
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2)+1;n=n+1)
case(m)
0: mem0[n] = sdram0.Bank0[n];
1: mem1[n] = sdram0.Bank1[n+1*size*2];
2: mem2[n] = sdram0.Bank2[n+2*size*2];
3: mem3[n] = sdram0.Bank3[n+3*size*2];
endcase
 
if(verbose) $display("KRO: %0d, Mode: %b, Size: %0d, Delay: %0d, Cyc. Delay: %0d (%t)",
kro, mode, size, del, cycle, $time);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_rmw(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
 
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2);n=n+1)
begin
case(m)
0: data = mem0[n];
1: data = mem1[n];
2: data = mem2[n];
3: data = mem3[n];
endcase
 
if((data !== m0.rd_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.rd_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: RD Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.rd_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
end
 
repeat(10) @(posedge clk);
 
for(m=0;m<4;m=m+1)
for(n=0;n<size*2;n=n+1)
begin
 
case(m)
0: data = sdram0.Bank0[n];
1: data = sdram0.Bank1[n+1*size*2];
2: data = sdram0.Bank2[n+2*size*2];
3: data = sdram0.Bank3[n+3*size*2];
endcase
 
if((data !== m0.wr_mem[(m*size*2)+n]) | (|data === 1'bx) |
(|m0.wr_mem[(m*size*2)+n] === 1'bx) )
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.wr_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
end
end
 
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
 
 
task sdram_rmw2;
input quick;
 
integer quick;
integer n,m,adr;
integer del, size;
reg [7:0] mode;
reg [2:0] bs;
integer sz_inc;
integer sz_max, del_max;
reg [2:0] kro;
reg [31:0] data, data1;
integer page_size;
integer cycle;
 
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SDRAM Size, Delay & Mode RMW test 2 ... ***");
$display("*** Different Row and Bank ***");
$display("*****************************************************\n");
 
page_size = 256; // 64 mbit x 32 SDRAM
 
case(quick)
0: sz_max = 32;
1: sz_max = 16;
2: sz_max = 10;
endcase
 
case(quick)
0: del_max = 16;
1: del_max = 8;
2: del_max = 8;
endcase
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
1'd0, // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd3 // Burst Length
});
 
kro = 1;
for(cycle=0;cycle<8;cycle=cycle+1)
for(kro=0;kro<2;kro=kro+1) // Don't Need this for this test
begin
 
// Parity nabled !
m0.wb_wr1(`REG_BASE + `CSC0, 4'hf, 32'h0000_0821 | (kro[0]<<10));
 
size = 1;
del = 0;
mode = 0;
 
//force sdram0.Debug = 1;
 
for(mode=0;mode<10;mode=mode+1)
begin
 
case(mode[3:1])
0: bs = 0;
1: bs = 1;
2: bs = 2;
3: bs = 3;
4: bs = 7;
endcase
case(mode[3:1])
0: sz_inc = 1;
1: sz_inc = 2;
2: sz_inc = 4;
3: sz_inc = 8;
4: sz_inc = 1;
endcase
 
m0.wb_wr1(`REG_BASE + `TMS0, 4'hf, {
 
4'd0, // RESERVED [31:28]
4'd7, // Trfc [27:24]
4'd2, // Trp [23:20]
3'd2, // Trcd [19:17]
2'd1, // Twr [16:15]
5'd0, // RESERVED [14:10]
 
1'd0+mode[0], // Wr. Burst Len (1=Single)
2'd0, // Op Mode
3'd2, // CL
1'b0, // Burst Type (0=Seq;1=Inter)
3'd0+bs // Burst Length
});
 
repeat(50) @(posedge clk);
 
if(!verbose) $display("KRO: %0d, Mode: %b, Cyc.Del: %0d", kro, mode, cycle);
 
for(del=0;del<del_max;del=del+1)
for(size=sz_inc;size<sz_max;size=size+sz_inc)
begin
m0.mem_fill;
fill_mem(1024);
 
if(verbose) $display("KRO: %0d, Mode: %b, Size: %0d, Delay: %0d, Cyc.Del: %0d (%t)",
kro, mode, size, del, cycle, $time);
 
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*0*4) + size*0*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*0*4) + size*1*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*1*4) + size*2*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*1*4) + size*3*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*2*4) + size*4*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*2*4) + size*5*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*3*4) + size*6*4, 4'hf, del, size, size);
repeat(cycle) @(posedge clk);
m0.wb_wmr(`MEM_BASE + (page_size*3*4) + size*7*4, 4'hf, del, size, size);
 
repeat(cycle) @(posedge clk);
for(n=0;n<(size*2);n=n+1)
begin
 
data = m0.wr_mem[n];
data1 = m0.rd_mem[n];
 
if((data !== data1) | (|data === 1'bx) |
(|data1 === 1'bx) )
begin
$display("ERROR: WMR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*size*2)+n, data, m0.rd_mem[(m*size*2)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
 
end
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
end
endtask
 
 
`ifdef SRAM
task sram_rmw1;
 
integer n,m,read,write;
integer del, size;
reg [31:0] data;
reg [31:0] mem[0:1024];
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SRAM Size & Delay RMW Test 1 ... ***");
$display("*** Time: %t", $time);
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS4, 4'hf, 32'hffff_ffff);
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC4, 4'hf, 32'h0080_0003);
 
size = 1;
del = 0;
 
repeat(1) @(posedge clk);
 
for(del=0;del<16;del=del+1)
for(size=1;size<18;size=size+1)
begin
m0.mem_fill;
sram0a.mem_fill( 256 );
sram0b.mem_fill( 256 );
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2)+1;n=n+1)
begin
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*32)+n];
data[15:08] = sram0a.bank1[(m*32)+n];
data[23:16] = sram0b.bank0[(m*32)+n];
data[31:24] = sram0b.bank1[(m*32)+n];
`else
data[07:00] = sram0a.memb1[(m*32)+n];
data[15:08] = sram0a.memb2[(m*32)+n];
data[23:16] = sram0b.memb1[(m*32)+n];
data[31:24] = sram0b.memb2[(m*32)+n];
`endif
mem[(m*32)+n] = data;
end
 
 
$display("Size: %0d, Delay: %0d", size, del);
//bw_clear;
 
m0.wb_rmw(`MEM_BASE4 + 00*4, 4'hf, del, size, size);
m0.wb_rmw(`MEM_BASE4 + 32*4, 4'hf, del, size, size);
m0.wb_rmw(`MEM_BASE4 + 64*4, 4'hf, del, size, size);
m0.wb_rmw(`MEM_BASE4 + 96*4, 4'hf, del, size, size);
 
//bw_report;
 
repeat(10) @(posedge clk);
 
for(m=0;m< 4;m=m+1)
for(n=0;n< size;n=n+1)
begin
 
data = mem[(m*32)+n];
 
if(data !== m0.rd_mem[(m*size)+n])
begin
$display("ERROR: RD Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*32)+n, data, m0.rd_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
if(error_cnt > 10) $finish;
end
 
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*32)+n];
data[15:08] = sram0a.bank1[(m*32)+n];
data[23:16] = sram0b.bank0[(m*32)+n];
data[31:24] = sram0b.bank1[(m*32)+n];
`else
data[07:00] = sram0a.memb1[(m*32)+n];
data[15:08] = sram0a.memb2[(m*32)+n];
data[23:16] = sram0b.memb1[(m*32)+n];
data[31:24] = sram0b.memb2[(m*32)+n];
`endif
 
if(data !== m0.wr_mem[(m*size)+n])
begin
$display("ERROR: WR Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*32)+n, data, m0.wr_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
if(error_cnt > 10) $finish;
end
 
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
 
 
task sram_rmw2;
 
integer n,m,read,write;
integer del, size;
reg [31:0] data;
reg [31:0] mem[0:1024];
begin
 
$display("\n\n");
$display("*****************************************************");
$display("*** SRAM Size & Delay RMW Test 2 ... ***");
$display("*****************************************************\n");
 
m0.wb_wr1(`REG_BASE + `CSR, 4'hf, 32'h6030_0300);
m0.wb_wr1(`REG_BASE + `BA_MASK, 4'hf, 32'h0000_00f0);
 
m0.wb_wr1(`REG_BASE + `TMS4, 4'hf, 32'hffff_ffff);
// Parity Enabled !
m0.wb_wr1(`REG_BASE + `CSC4, 4'hf, 32'h0080_0803);
 
size = 4;
del = 4;
 
repeat(1) @(posedge clk);
 
for(del=0;del<16;del=del+1)
for(size=1;size<18;size=size+1)
begin
m0.mem_fill;
sram0a.mem_fill( 256 );
sram0b.mem_fill( 256 );
for(m=0;m<4;m=m+1)
for(n=0;n<(size*2)+1;n=n+1)
begin
`ifdef MICRON
data[07:00] = sram0a.bank0[(m*32)+n];
data[15:08] = sram0a.bank1[(m*32)+n];
data[23:16] = sram0b.bank0[(m*32)+n];
data[31:24] = sram0b.bank1[(m*32)+n];
`else
data[07:00] = sram0a.memb1[(m*32)+n];
data[15:08] = sram0a.memb2[(m*32)+n];
data[23:16] = sram0b.memb1[(m*32)+n];
data[31:24] = sram0b.memb2[(m*32)+n];
`endif
mem[(m*32)+n] = data;
end
 
 
$display("Size: %0d, Delay: %0d", size, del);
//bw_clear;
 
m0.wb_wmr(`MEM_BASE4 + 00*4, 4'hf, del, size, size);
m0.wb_wmr(`MEM_BASE4 + 32*4, 4'hf, del, size, size);
m0.wb_wmr(`MEM_BASE4 + 64*4, 4'hf, del, size, size);
m0.wb_wmr(`MEM_BASE4 + 96*4, 4'hf, del, size, size);
 
//bw_report;
 
repeat(10) @(posedge clk);
 
 
for(m=0;m< 4;m=m+1)
for(n=0;n< size;n=n+1)
begin
 
data = m0.wr_mem[(m*size)+n];
 
if(data !== m0.rd_mem[(m*size)+n])
begin
$display("ERROR: RD Data[%0d] Mismatch: Expected: %x, Got: %x (%0t)",
(m*32)+n, data, m0.rd_mem[(m*size)+n], $time);
error_cnt = error_cnt + 1;
end
 
end
 
end
 
show_errors;
$display("*****************************************************");
$display("*** Test DONE ... ***");
$display("*****************************************************\n\n");
 
end
endtask
 
`endif
 
/test_lib.v
0,0 → 1,294
/////////////////////////////////////////////////////////////////////
//// ////
//// Top Level Test Bench ////
//// Task Library ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
//// www.asics.ws ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: test_lib.v,v 1.4 2002-01-21 13:10:37 rudi Exp $
//
// $Date: 2002-01-21 13:10:37 $
// $Revision: 1.4 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.3 2001/11/11 01:52:03 rudi
//
// Minor fixes to testbench ...
//
// Revision 1.2 2001/09/02 02:29:43 rudi
//
// Fixed the TMS register setup to be tight and correct.
//
// Revision 1.1 2001/07/29 07:34:40 rudi
//
//
// 1) Changed Directory Structure
// 2) Fixed several minor bugs
//
// Revision 1.1.1.1 2001/05/13 09:36:38 rudi
// Created Directory Structure
//
//
//
//
 
 
/////////////////////////////////////////////////////////////////////
//
// Bandwidth Monitor
//
 
always @(posedge clk)
if(wb_cyc_i) cyc_cnt = cyc_cnt + 1;
 
always @(posedge clk)
if(wb_ack_o) ack_cnt = ack_cnt + 1;
 
task bw_report;
 
integer bytes;
 
begin
 
bytes = ack_cnt * 4;
$display("Last WB Bandwidth: %0d Mbytes/sec", bytes * 1000/(cyc_cnt * 10));
end
endtask
 
task bw_clear;
 
begin
cyc_cnt = 0;
ack_cnt = 0;
end
endtask
 
/////////////////////////////////////////////////////////////////////
//
// Suspend Resume Task
//
 
task susp_res;
begin
 
#1;
susp_req = 1;
while(!suspended) @(posedge clk);
#1;
susp_req = 0;
repeat(20) @(posedge clk);
#1;
resume_req = 1;
while(suspended) @(posedge clk);
#1;
resume_req = 0;
repeat(1) @(posedge clk);
 
end
endtask
 
/////////////////////////////////////////////////////////////////////
//
// Bus Request/Grant Task
//
task bus_req;
begin
mc_br = 1;
while(!mc_bg) @(posedge clk);
repeat(40) @(posedge clk);
mc_br = 0;
repeat(2) @(posedge clk);
end
endtask
 
/////////////////////////////////////////////////////////////////////
//
// Monitor CKE
//
time cke_low;
 
always @(negedge mc_cke_)
cke_low = $time;
 
always @(posedge mc_cke_)
if(($time-cke_low) < 10)
$display("WARNING: Cke low period was %t. (%t, %t)",($time-cke_low), cke_low, $time);
 
/////////////////////////////////////////////////////////////////////
//
// Monitor wb_err_o
//
always @(posedge clk)
if(wb_err_o & !wb_err_check_dis)
$display("WARNING: WB_ERR_O was asserted at time %0t",$time);
 
/////////////////////////////////////////////////////////////////////
//
// Watchdog Counter
//
 
always @(wb_ack_o or wb_stb_i)
wd_cnt = 0;
 
always @(posedge clk)
wd_cnt = wd_cnt + 1;
 
always @(wd_cnt)
if(wd_cnt>6000)
begin
$display("\n\n*************************************\n");
$display("ERROR: Watch Dog Counter Expired\n");
$display("*************************************\n\n\n");
$finish;
end
 
/////////////////////////////////////////////////////////////////////
//
// Show Errors
//
 
task show_errors;
 
begin
 
$display("\n");
$display(" +--------------------+");
$display(" | Total ERRORS: %0d |", error_cnt);
$display(" +--------------------+");
 
end
endtask
 
/////////////////////////////////////////////////////////////////////
//
// Reset Memory Controller
//
 
task mc_reset;
 
begin
repeat(10) @(posedge clk);
rst = 1;
repeat(10) @(posedge clk);
rst = 0;
repeat(20) @(posedge clk);
end
endtask
 
/////////////////////////////////////////////////////////////////////
//
// Fill SDRAMs
//
 
task fill_mem;
input size;
 
integer size, n;
reg [31:0] data;
 
begin
sdram0.mem_fill(size);
 
for(n=0;n<size;n=n+1)
begin
data = sdram0.Bank0[n];
sdram0p.Bank0[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram0.Bank1[n];
sdram0p.Bank1[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram0.Bank2[n];
sdram0p.Bank2[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram0.Bank3[n];
sdram0p.Bank3[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
end
 
end
endtask
 
 
task fill_mem1;
input size;
 
integer size, n;
reg [31:0] data;
 
begin
sdram1.mem_fill(size);
 
for(n=0;n<size;n=n+1)
begin
data = sdram1.Bank0[n];
sdram1p.Bank0[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram1.Bank1[n];
sdram1p.Bank1[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram1.Bank2[n];
sdram1p.Bank2[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram1.Bank3[n];
sdram1p.Bank3[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
end
 
end
endtask
 
task fill_mem2;
input size;
 
integer size, n;
reg [31:0] data;
 
begin
sdram2.mem_fill(size);
 
for(n=0;n<size;n=n+1)
begin
data = sdram2.Bank0[n];
sdram2p.Bank0[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram2.Bank1[n];
sdram2p.Bank1[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram2.Bank2[n];
sdram2p.Bank2[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
data = sdram2.Bank3[n];
sdram2p.Bank3[n] = {28'h0, ^data[31:24], ^data[23:16], ^data[15:8], ^data[7:0] };
end
 
end
endtask
 
 
/wb_mast_model.v
0,0 → 1,706
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE Master Model ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
/// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: wb_mast_model.v,v 1.3 2001-11-29 02:17:36 rudi Exp $
//
// $Date: 2001-11-29 02:17:36 $
// $Revision: 1.3 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/11/11 01:52:03 rudi
//
// Minor fixes to testbench ...
//
// Revision 1.1 2001/07/29 07:34:40 rudi
//
//
// 1) Changed Directory Structure
// 2) Fixed several minor bugs
//
// Revision 1.1.1.1 2001/05/13 09:36:33 rudi
// Created Directory Structure
//
//
//
//
//
 
`include "wb_model_defines.v"
 
module wb_mast(clk, rst, adr, din, dout, cyc, stb, sel, we, ack, err, rty);
 
input clk, rst;
output [31:0] adr;
input [31:0] din;
output [31:0] dout;
output cyc, stb;
output [3:0] sel;
output we;
input ack, err, rty;
 
////////////////////////////////////////////////////////////////////
//
// Local Wires
//
 
parameter mem_size = 4096;
 
reg [31:0] adr;
reg [31:0] dout;
reg cyc, stb;
reg [3:0] sel;
reg we;
 
reg [31:0] rd_mem[mem_size:0];
reg [31:0] wr_mem[mem_size:0];
integer rd_cnt;
integer wr_cnt;
 
////////////////////////////////////////////////////////////////////
//
// Memory Logic
//
 
initial
begin
//adr = 32'hxxxx_xxxx;
//adr = 0;
adr = 32'hffff_ffff;
dout = 32'hxxxx_xxxx;
cyc = 0;
stb = 0;
sel = 4'hx;
we = 1'hx;
rd_cnt = 0;
wr_cnt = 0;
#1;
$display("\nINFO: WISHBONE MASTER MODEL INSTANTIATED (%m)\n");
end
 
 
 
task mem_fill;
 
integer n;
begin
rd_cnt = 0;
wr_cnt = 0;
for(n=0;n<mem_size;n=n+1)
begin
rd_mem[n] = $random;
wr_mem[n] = $random;
end
end
endtask
 
////////////////////////////////////////////////////////////////////
//
// Write 1 Word Task
//
 
task wb_wr1;
input [31:0] a;
input [3:0] s;
input [31:0] d;
 
begin
 
//@(posedge clk);
#1;
adr = a;
dout = d;
cyc = 1;
stb = 1;
we=1;
sel = s;
 
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#1;
cyc=0;
stb=0;
adr = 32'hxxxx_xxxx;
//adr = 32'hffff_ffff;
//adr = 0;
dout = 32'hxxxx_xxxx;
we = 1'hx;
sel = 4'hx;
 
end
endtask
 
////////////////////////////////////////////////////////////////////
//
// Write 4 Words Task
//
 
task wb_wr4;
input [31:0] a;
input [3:0] s;
input delay;
input [31:0] d1;
input [31:0] d2;
input [31:0] d3;
input [31:0] d4;
 
integer delay;
 
begin
 
@(posedge clk);
#1;
cyc = 1;
sel = s;
 
repeat(delay)
begin
@(posedge clk);
#1;
end
adr = a;
dout = d1;
stb = 1;
we=1;
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
dout = 32'hxxxx_xxxx;
 
 
repeat(delay)
begin
@(posedge clk);
#1;
end
stb=1;
adr = a+4;
dout = d2;
we=1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
dout = 32'hxxxx_xxxx;
 
repeat(delay)
begin
@(posedge clk);
#1;
end
stb=1;
adr = a+8;
dout = d3;
we=1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
dout = 32'hxxxx_xxxx;
 
repeat(delay)
begin
@(posedge clk);
#1;
end
stb=1;
adr = a+12;
dout = d4;
we=1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#1;
stb=0;
cyc=0;
 
adr = 32'hxxxx_xxxx;
//adr = 0;
//adr = 32'hffff_ffff;
dout = 32'hxxxx_xxxx;
we = 1'hx;
sel = 4'hx;
 
end
endtask
 
 
task wb_wr_mult;
input [31:0] a;
input [3:0] s;
input delay;
input count;
 
integer delay;
integer count;
integer n;
 
begin
 
@(posedge clk);
#1;
cyc = 1;
 
for(n=0;n<count;n=n+1)
begin
repeat(delay)
begin
@(posedge clk);
#1;
end
adr = a + (n*4);
dout = wr_mem[n + wr_cnt];
stb = 1;
we=1;
sel = s;
if(n!=0) @(posedge clk);
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
sel = 4'hx;
dout = 32'hxxxx_xxxx;
adr = 32'hxxxx_xxxx;
end
 
cyc=0;
 
adr = 32'hxxxx_xxxx;
//adr = 32'hffff_ffff;
 
wr_cnt = wr_cnt + count;
end
endtask
 
 
task wb_rmw;
input [31:0] a;
input [3:0] s;
input delay;
input rcount;
input wcount;
 
integer delay;
integer rcount;
integer wcount;
 
begin
wb_rmw2(a,a,s,delay,rcount,wcount);
end
endtask
 
 
task wb_rmw2;
input [31:0] ra;
input [31:0] wa;
input [3:0] s;
input delay;
input rcount;
input wcount;
 
integer delay;
integer rcount;
integer wcount;
integer n;
 
begin
 
//@(posedge clk);
#1;
cyc = 1;
we = 0;
sel = s;
repeat(delay) @(posedge clk);
 
for(n=0;n<rcount-1;n=n+1)
begin
adr = ra + (n*4);
stb = 1;
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hxxxx_xxxx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
end
 
adr = ra+(n*4);
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );
#1;
stb=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hxxxx_xxxx;
 
rd_cnt = rd_cnt + rcount;
 
//@(posedge clk);
 
 
for(n=0;n<wcount;n=n+1)
begin
repeat(delay)
begin
@(posedge clk);
#1;
end
adr = wa + (n*4);
dout = wr_mem[n + wr_cnt];
stb = 1;
we=1;
sel = s;
// if(n!=0)
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
sel = 4'hx;
dout = 32'hxxxx_xxxx;
adr = 32'hxxxx_xxxx;
end
 
cyc=0;
 
adr = 32'hxxxx_xxxx;
//adr = 32'hffff_ffff;
 
wr_cnt = wr_cnt + wcount;
end
endtask
 
 
 
 
task wb_wmr;
input [31:0] a;
input [3:0] s;
input delay;
input rcount;
input wcount;
 
integer delay;
integer rcount;
integer wcount;
integer n;
 
begin
 
//@(posedge clk);
#1;
cyc = 1;
we = 1'bx;
sel = 4'hx;
sel = s;
 
for(n=0;n<wcount;n=n+1)
begin
repeat(delay)
begin
@(posedge clk);
#1;
end
adr = a + (n*4);
dout = wr_mem[n + wr_cnt];
stb = 1;
we=1;
sel = s;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
#2;
stb=0;
we=1'bx;
sel = 4'hx;
dout = 32'hxxxx_xxxx;
adr = 32'hxxxx_xxxx;
end
 
wr_cnt = wr_cnt + wcount;
stb=0;
repeat(delay) @(posedge clk);
#1;
 
sel = s;
we = 0;
for(n=0;n<rcount-1;n=n+1)
begin
adr = a + (n*4);
stb = 1;
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hxxxx_xxxx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
end
 
adr = a+(n*4);
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
rd_cnt = rd_cnt + rcount;
//$display("Rd Mem[%0d]: %h", (n + rd_cnt), rd_mem[n + rd_cnt] );
#1;
 
cyc = 0;
stb = 0;
we = 1'hx;
sel = 4'hx;
adr = 32'hxxxx_xxxx;
 
end
endtask
 
 
 
 
////////////////////////////////////////////////////////////////////
//
// Read 1 Word Task
//
 
task wb_rd1;
input [31:0] a;
input [3:0] s;
output [31:0] d;
 
begin
 
//@(posedge clk);
#1;
adr = a;
cyc = 1;
stb = 1;
we = 0;
sel = s;
 
//@(posedge clk);
while(~ack & ~err) @(posedge clk);
d = din;
#1;
cyc=0;
stb=0;
//adr = 32'hxxxx_xxxx;
//adr = 0;
adr = 32'hffff_ffff;
dout = 32'hxxxx_xxxx;
we = 1'hx;
sel = 4'hx;
 
end
endtask
 
 
////////////////////////////////////////////////////////////////////
//
// Read 4 Words Task
//
 
 
task wb_rd4;
input [31:0] a;
input [3:0] s;
input delay;
output [31:0] d1;
output [31:0] d2;
output [31:0] d3;
output [31:0] d4;
 
integer delay;
begin
 
@(posedge clk);
#1;
cyc = 1;
we = 0;
sel = s;
repeat(delay) @(posedge clk);
 
adr = a;
stb = 1;
while(~ack & ~err) @(posedge clk);
d1 = din;
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
 
adr = a+4;
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
d2 = din;
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
 
 
adr = a+8;
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
d3 = din;
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
 
adr = a+12;
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
d4 = din;
#1;
stb=0;
cyc=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hffff_ffff;
end
endtask
 
 
 
task wb_rd_mult;
input [31:0] a;
input [3:0] s;
input delay;
input count;
 
integer delay;
integer count;
integer n;
 
begin
 
@(posedge clk);
#1;
cyc = 1;
we = 0;
sel = s;
repeat(delay) @(posedge clk);
 
for(n=0;n<count-1;n=n+1)
begin
adr = a + (n*4);
stb = 1;
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
#2;
stb=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hxxxx_xxxx;
repeat(delay)
begin
@(posedge clk);
#1;
end
we = 0;
sel = s;
end
 
adr = a+(n*4);
stb = 1;
@(posedge clk);
while(~ack & ~err) @(posedge clk);
rd_mem[n + rd_cnt] = din;
#1;
stb=0;
cyc=0;
we = 1'hx;
sel = 4'hx;
adr = 32'hffff_ffff;
adr = 32'hxxxx_xxxx;
 
rd_cnt = rd_cnt + count;
end
endtask
 
endmodule
/160b3ver/adv_bb.v
0,0 → 1,1193
 
 
 
 
//`timescale 1ns/1ns
 
 
//****************************************************************************
// This file contains the paramenters which define the part for the
// Smart 3 Advanced Boot Block memory model (adv_bb.v). The '2.7V Vcc Timing'
// parameters are representative of the 28F160B3-120 operating at 2.7-3.6V Vcc.
// These parameters need to be changed if the 28F160B3-150 operating at
// 2.7-3.6V Vcc is to be modeled. The parameters were taken from the Smart 3
// Advanced Boot Block Flash Memory Family datasheet (Order Number 290580).
 
// This file must be loaded before the main model, as it contains
// definitions required by the model.
 
//28F160B3-B
 
`define BlockFileBegin "f160b3b.bkb" //starting addresses of each block
`define BlockFileEnd "f160b3b.bke" //ending addresses of each block
`define BlockFileType "f160b3b.bkt" //block types
 
//Available Vcc supported by the device.
`define VccLevels 4 //Bit 0 - 5V, Bit 1 = 3.3V, Bit 2 = 2.7V
 
`define AddrSize 20 //number of address pins
`define MaxAddr `AddrSize'hFFFFF // device ending address
`define MainArraySize 0:`MaxAddr //array definition in bytes
//include A-1 for 8 bit mode
`define MaxOutputs 16 //number of output pins
`define NumberOfBlocks 39 //number of blocks in the array
 
`define ID_DeviceCodeB 'h8891 //160B3 Bottom
`define ID_ManufacturerB 'h0089
 
// Timing parameters. See the data sheet for definition of the parameter.
// Only the WE# controlled write timing parameters are used since their
// respective CE# controlled write timing parameters have the same value.
// The model does not differentiate between the two types of writes.
 
//2.7V Vcc Timing
 
// Changed the timings below to represent a "c3" device. --- RU 9/9/99
 
`define TAVAV_27 110
`define TAVQV_27 110
`define TELQV_27 110
`define TPHQV_27 150
`define TGLQV_27 0.1
`define TELQX_27 0
`define TEHQZ_27 20
`define TGLQX_27 0
`define TGHQZ_27 20
`define TOH_27 0
`define TPHWL_27 150
`define TWLWH_27 70
`define TDVWH_27 60
`define TAVWH_27 70
`define TWHDX_27 0
`define TWHAX_27 0
`define TWHWL_27 30
`define TVPWH_27 200
 
 
// The following constants control how long it take an algorithm to run
// to scale all times together (for making simulation run faster
// change the constant later listed as TimerPeriod. The actual delays
// are TimerPeriod*xxx_Time, except for the suspend latency times.
 
`define TimerPeriod_ 1000 //1 usec = 1000ns requires for
//following times to be accurate
 
// The typical values given in the datasheet are used.
 
// reducing the following will reduce simulation time
 
//2.7V Vcc, 12V Vpp
`define AC_ProgramTime_Word_27_12 8 //usecs
`define AC_EraseTime_Param_27_12 800000 //0.8secs
`define AC_EraseTime_Main_27_12 1100000 //1.1secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_12 5000 //5 usecs
`define AC_Erase_Suspend_27_12 10000 //10 usecs
 
//2.7V Vcc 2.7V Vpp
`define AC_ProgramTime_Word_27_27 22 //usecs
`define AC_EraseTime_Param_27_27 1000000 //1sec
`define AC_EraseTime_Main_27_27 1800000 //1.8secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_27 6000 //6 usecs
`define AC_Erase_Suspend_27_27 13000 //13 usecs
 
 
 
//generic defines for readability
`define FALSE 1'b0
`define TRUE 1'b1
 
`define Word 15:0
`define Byte 7:0
 
`define VIL 1'b0
`define VIH 1'b1
 
`define Ready 1'b1
`define Busy 1'b0
 
// These constants are the actual command codes
`define ClearCSRCmd 8'h50
`define ProgramCmd 8'h10
`define Program2Cmd 8'h40
`define EraseBlockCmd 8'h20
`define ReadArrayCmd 8'hFF
`define ReadCSRCmd 8'h70
`define ReadIDCmd 8'h90
`define SuspendCmd 8'hB0 //Valid for both erase
`define ResumeCmd 8'hD0 //and program suspend
`define ConfirmCmd 8'hD0
 
`define ReadMode_T 2:0
`define rdARRAY 3'b000
`define rdCSR 3'b011
`define rdID 3'b100
 
`define Program 2'b00
`define Erase 2'b01
 
// Cmd_T record
`define Cmd_T 172:0
`define CmdAdd_1 172:153
`define CmdAdd_2 152:133
`define Add 132:113
`define CmdData_1 112:97
`define CmdData_2 96:81
`define Cmd 80:73
`define Count 72:41
`define Time 40:9
`define Confirm 8
`define OpBlock 7:2
`define OpType 1:0
`define CmdData1Fx8 104:97
 
`define WritePtr_T 1:0
`define NewCmd 2'b01
`define CmdField 2'b10
 
`define BlockType_T 1:0
`define MainBlock 2'b00
`define LockBlock 2'b01
`define ParamBlock 2'b10
 
`define Vcc2700 3'b100
`define Vcc3300 3'b010
`define Vcc5000 3'b001
 
 
// device specific
 
//module definition for Intel Advanced Boot Block Flash Memory Family
//
//vpp and vcc are are 32 bit vectors which are treated as unsigned int
//scale for vpp and vcc is millivolts. ie. 0 = 0V, 5000 = 5V
//
 
module IntelAdvBoot(dq, addr, ceb, oeb, web, rpb, wpb, vpp, vcc);
 
inout [`MaxOutputs-1:0] dq; //16 outputs
 
input [`AddrSize-1:0] addr; //address pins.
 
input ceb, //CE# - chip enable bar
oeb, //OE# - output enable bar
web, //WE# - write enable bar
rpb, //RP# - reset bar, powerdown
wpb; //WP# = write protect bar
input [31:0] vpp, //vpp in millivolts
vcc; //vcc in millivolts
 
reg [`Word] MainArray[`MainArraySize]; //flash array
 
// Flag to show that a Cmd has been written
// and needs predecoding
reg CmdValid ;
 
// This points to where data written to the part will
// go. By default it is to NewCmd. CmdField means the
// chip is waiting on more data for the cmd (ie confirm)
 
reg [`WritePtr_T] WriteToPtr ;
 
// Contains the current executing command and all its
// support information.
reg [`Cmd_T] Cmd;
reg [`Cmd_T] Algorithm;
reg [`Cmd_T] SuspendedAlg;
 
// Output of Data
reg [`Word] ArrayOut ;
 
// Current output of the Compatible status register
reg [`Word] CSROut ;
 
// Current output of the ID register
reg [`Word] IDOut ;
 
// Startup Flag phase
reg StartUpFlag ;
 
// Global Reset Flag
reg Reset ;
 
//Vpp Monitoring
reg VppFlag ;
reg VppError ;
reg VppErrFlag ;
reg ClearVppFlag ;
 
// Internal representation of the CSR SR.1 bit
reg BlockLockStatus;
// Internal representation of the CSR SR.4 bit
reg ProgramError;
// Internal representation of the CSR SR.5 bit
reg EraseError;
 
// Internal representation of CUI modes
reg [`ReadMode_T] ReadMode ;
 
// Current value of the CSR
wire [`Byte] CSR ;
 
// Flag that determines if the chip is driving
// the outputs
reg DriveOutputs ;
 
// Internal value of the out data. If DriveOutputs
// is active this value will be placed on the
// outputs. -1 == Unknown or XXXX
reg [`MaxOutputs-1:0] InternalOutput ;
 
// Number of addition writes necessary to
// supply the current command information.
// When it hits zero it goes to Decode
integer DataPtr ;
 
// Master internal write enable
wire Internal_WE ;
// Master internal output enable
wire Internal_OE ;
wire Internal_OE2 ;
wire Internal_OE3 ;
 
// Master internal read enable
wire Internal_RE ;
 
// Master internal boot block write enable
reg InternalBoot_WE ;
wire InternalBoot;
 
// Internal flag to tell if an algorithm is running
reg ReadyBusy ;
//reg RunningAlgorithm ; *******************************
 
// Flag to represent if the chip is write suspended
reg WriteSuspended ;
// Flag to represent if the chip is erase suspended
reg EraseSuspended ;
// Flag for if the chip should be suspended
reg Suspend ;
// Variable to hold which algorithm (program or erase)
// is to be suspended
reg [1:0] ToBeSuspended;
 
// Algorithm Timer
reg TimerClk ;
 
// Flag to show the running algorithm is done.
reg AlgDone ;
 
// Number of timer cycles remaining for the
// current algorithm
integer AlgTime;
 
// Number of timer cycles remaining for erase operation
// when erase suspended and program operation in progress
integer TimeLeft;
 
// Generic temporary varible
integer LoopCntr ;
reg Other ;
 
//Block begin and end address
reg [`AddrSize-1:0] BlocksBegin[0:`NumberOfBlocks-1];
reg [`AddrSize-1:0] BlocksEnd[0:`NumberOfBlocks-1];
reg [`BlockType_T] BlocksType[0:`NumberOfBlocks-1];
reg [31:0] BlocksEraseCount[0:`NumberOfBlocks-1];
 
//************************************************************************
//TIMING VALUES
 
//************************************************************************
time ToOut ;
time last_addr_time ,curr_addr_time;
time last_oe_time, curr_oe_time;
time last_ce_time, curr_ce_time;
time last_rp_time, curr_rp_time;
time last_ReadMode_time, curr_ReadMode_time ;
time last_Internal_RE_time, curr_Internal_RE_time ;
time last_Internal_WE_time, curr_Internal_WE_time ;
time last_dq_time ,curr_dq_time;
time last_rpb_time, curr_rpb_time ;
time WriteRecovery ;
time TempTime;
 
time Program_Time_Word;
time Param_Erase_Time;
time Main_Erase_Time;
time Program_Suspend_Time; // latency time
time Erase_Suspend_Time; // latency time
 
//************************************************************************
//input configuration
 
parameter
LoadOnPowerup = `FALSE, //load array from file
LoadFileName = "f160b3.dat", //File to load array with
SaveOnPowerdown = `FALSE, //save array to file
SaveFileName = "f160b3.dat"; //save file name
 
//TIMING PARAMETERS
parameter
TAVAV = `TAVAV_27,
TAVQV = `TAVQV_27,
TELQV = `TELQV_27,
TPHQV = `TPHQV_27,
TGLQV = `TGLQV_27,
TELQX = `TELQX_27,
TEHQZ = `TEHQZ_27,
TGLQX = `TGLQX_27,
TGHQZ = `TGHQZ_27,
TOH = `TOH_27 ,
TPHWL = `TPHWL_27,
TWLWH = `TWLWH_27,
TDVWH = `TDVWH_27,
TAVWH = `TAVWH_27,
TWHDX = `TWHDX_27,
TWHAX = `TWHAX_27,
TWHWL = `TWHWL_27,
TVPWH = `TVPWH_27,
TimerPeriod = `TimerPeriod_;
 
//************************************************************************
 
 
initial begin
Other = `FALSE ;
AlgDone = `FALSE ;
Reset = 1'hx ;
Reset <= `TRUE ;
StartUpFlag = `TRUE ;
StartUpFlag <= #2 `FALSE ;
DriveOutputs = `FALSE ;
ToOut = 0 ;
VppError = `FALSE ;
VppErrFlag = `FALSE ;
ClearVppFlag = `FALSE ;
VppFlag = `FALSE ;
WriteSuspended = `FALSE ;
EraseSuspended = `FALSE ;
Suspend = `FALSE ;
ToBeSuspended = `Program;
EraseError = `FALSE ;
TimerClk = 1'b0 ;
ArrayOut = `MaxOutputs'hxxxx ;
CSROut = 0 ;
IDOut = 0 ;
CmdValid = `FALSE ;
WriteToPtr = `NewCmd ;
last_addr_time = 0 ;
curr_addr_time = 0 ;
last_ce_time = 0 ;
curr_ce_time = 0 ;
last_oe_time = 0 ;
curr_oe_time = 0 ;
last_rp_time = 0 ;
curr_rp_time = 0 ;
last_ReadMode_time = 0 ;
curr_ReadMode_time = 0 ;
last_dq_time = 0 ;
curr_dq_time = 0 ;
last_rpb_time = 0 ;
curr_rpb_time = 0 ;
WriteRecovery = 0 ;
last_Internal_RE_time = 0 ;
curr_Internal_RE_time = 0 ;
InternalOutput = `MaxOutputs'hx ;
last_Internal_WE_time = 0 ;
curr_Internal_WE_time = 0 ;
Program_Time_Word = `AC_ProgramTime_Word_27_12;
Param_Erase_Time = `AC_EraseTime_Param_27_12;
Main_Erase_Time = `AC_EraseTime_Main_27_12;
Program_Suspend_Time = `AC_Program_Suspend_27_12;
Erase_Suspend_Time = `AC_Erase_Suspend_27_12;
 
$readmemh(`BlockFileBegin,BlocksBegin);
$readmemh(`BlockFileEnd,BlocksEnd);
$readmemh(`BlockFileType,BlocksType,0,`NumberOfBlocks-1);
for (LoopCntr = 0; LoopCntr <= `NumberOfBlocks; LoopCntr = LoopCntr + 1) begin
BlocksEraseCount [LoopCntr] = 0 ;
end
 
//------------------------------------------------------------------------
// Array Init
//------------------------------------------------------------------------
 
//Constant condition expression: LoadOnPowerup == 1'b1
if (LoadOnPowerup)
LoadFromFile;
else begin
//$display("Initializing Memory to 'hFFFF");
//for (LoopCntr = 0; LoopCntr <= `MaxAddr; LoopCntr = LoopCntr + 1) begin
// MainArray [LoopCntr] = 16'hFFFF ;
$display("FLASH: Initializing Memory data to address value (0, 1, 2 ...)");
for (LoopCntr = 0; LoopCntr <= 1024; LoopCntr = LoopCntr + 1) begin
MainArray [LoopCntr] = LoopCntr ;
 
end
end
end
 
 
//------------------------------------------------------------------------
// LoadFromFile
// This is used when the LoadOnPowerup parameter is set so that the Main
// array contains code at startup. Basically it loads the array from
// data in a file (LoadFileName).
//------------------------------------------------------------------------
 
task LoadFromFile ;
begin
$display("FLASH: Loading from file %s",LoadFileName);
$readmemh(LoadFileName,MainArray);
end
endtask
 
//------------------------------------------------------------------------
// StoreToFile
// This is used when the SaveOnPowerDown flag is set so that the Main
// Array stores code at powerdown. Basically it stores the array into
// a file (SaveFileName).
//-----------------------------------------------------------------
 
task StoreToFile;
reg [31:0] ArrayAddr ;
reg [31:0] outfile ;
begin
outfile = $fopen(SaveFileName) ;
if (outfile == 0)
$display("FLASH: Error, cannot open output file %s",SaveFileName) ;
else
$display("FLASH: Saving data to file %s",SaveFileName);
for (ArrayAddr = 0 ; ArrayAddr <= `MaxAddr; ArrayAddr = ArrayAddr + 1) begin
$fdisplay(outfile,"%h",MainArray[ArrayAddr]);
end
end
endtask
 
//------------------------------------------------------------------------
// Program
// -- Description: Programs new values in to the array --
//------------------------------------------------------------------------
 
task Program ;
inout [`Word] TheArrayValue ;
input [`Word] DataIn;
 
reg [`Word] OldData;
begin
OldData = TheArrayValue;
TheArrayValue = DataIn & OldData;
end
endtask
 
 
assign Internal_OE = !(ceb | oeb | !rpb) ;
assign Internal_OE2 = Internal_OE ;
assign Internal_OE3 = Internal_OE2 ;
assign Internal_RE = (((ReadyBusy == `Ready) || (ReadMode != `rdARRAY)) && !ceb && !Reset) ;
assign Internal_WE = !(ceb | web | !rpb) ;
assign InternalBoot = wpb ;
 
//******************************************************************
// Determine if the algorithm engine is operating
//assign ReadyBusy = (RunningAlgorithm & !Suspended) ? `Busy : `Ready;
//******************************************************************
 
// register definitions //
 
// Compatible Status Register
assign CSR [7] = ReadyBusy;
assign CSR [6] = EraseSuspended ;
assign CSR [5] = EraseError ;
assign CSR [4] = ProgramError ;
assign CSR [3] = VppError ;
assign CSR [2] = WriteSuspended;
assign CSR [1] = BlockLockStatus;
assign CSR [0] = 1'b0;
 
 
// Output Drivers //
assign dq = (DriveOutputs == `TRUE) ? InternalOutput : 16'hz;
 
always @(Reset) begin : Reset_process
if (Reset) begin
ClearVppFlag <= #1 `TRUE ;
ClearVppFlag <= #9 `FALSE ;
AlgDone = `FALSE ;
VppError = `FALSE ;
ReadMode = `rdARRAY;
ReadyBusy = `Ready ;
WriteSuspended = `FALSE ;
EraseSuspended = `FALSE ;
Suspend = `FALSE ;
EraseError = `FALSE ;
ProgramError = `FALSE ;
BlockLockStatus = `FALSE ;
AlgTime = 0 ;
CmdValid = `FALSE ;
WriteToPtr = `NewCmd ;
CSROut = 0 ;
IDOut = 0 ;
end
end
 
 
always @(Internal_RE or ReadMode or addr) begin : array_read
if (Internal_RE && ReadMode == `rdARRAY) begin
ArrayOut = MainArray[addr] ; // x16 outputs
end
end
 
 
always @(Internal_RE or ReadMode or addr or Internal_OE2 or ArrayOut) begin
// output mux
// Determine and generate the access time .
ToOut = 0;
 
if ($time > TAVQV) begin
last_addr_time = $time - curr_addr_time;
 
if ((last_addr_time < TAVQV) && ((TAVQV - last_addr_time) > ToOut))
ToOut = TAVQV - last_addr_time ;
last_oe_time = $time - curr_oe_time;
if ((last_oe_time < TGLQV) && ((TGLQV - last_oe_time) > ToOut))
ToOut = TGLQV - last_oe_time ;
last_ce_time = $time - curr_ce_time;
 
if ((last_ce_time < TELQV) && ((TELQV - last_ce_time) > ToOut))
ToOut = TELQV - last_ce_time ;
last_rp_time = $time - curr_rp_time;
if ((last_rp_time < TPHQV) && ((TPHQV - last_rp_time) > ToOut))
ToOut = TPHQV - last_rp_time ;
last_ReadMode_time = $time - curr_ReadMode_time;
if ((last_ReadMode_time < TAVQV) && ((TAVQV - last_ReadMode_time) > ToOut))
ToOut = TAVQV - last_ReadMode_time ;
last_Internal_RE_time = $time - curr_Internal_RE_time ;
if ((last_Internal_RE_time < TAVQV) && ((TAVQV - last_Internal_RE_time) > ToOut)) begin
ToOut = TAVQV - last_Internal_RE_time ;
end
 
end
 
// Output Mux with timing
if (!StartUpFlag) begin
case (ReadMode)
`rdARRAY : begin
if ( (EraseSuspended == `TRUE) && (WriteSuspended == `FALSE)
&& (addr >= BlocksBegin[Algorithm[`OpBlock]])
&& (addr <= BlocksEnd[Algorithm[`OpBlock]]) && (oeb == `VIL) ) begin
$display("FLASH: Error: Attempting to read from erase suspended block");
InternalOutput <= `MaxOutputs'hxxxx;
end
else if ( (WriteSuspended == `TRUE) && (EraseSuspended == `TRUE)
&& (addr >= BlocksBegin[SuspendedAlg[`OpBlock]])
&& (addr <= BlocksEnd[SuspendedAlg[`OpBlock]]) && (oeb == `VIL)) begin
$display("FLASH: Error: Attempting to read from erase suspended block");
InternalOutput <= `MaxOutputs'hxxxx;
end
else if ( (WriteSuspended == `TRUE) && (addr == Algorithm[`CmdAdd_1])
&& (oeb == `VIL) ) begin
$display("FLASH: Error: Attempting to read from write suspended address");
InternalOutput = `MaxOutputs'hxxxx;
end
else
InternalOutput <= #ToOut ArrayOut ;
end
`rdCSR : begin
InternalOutput <= #ToOut CSROut ;
end
`rdID : begin
InternalOutput <= #ToOut IDOut ;
end
default : begin
$display("FLASH: Error: illegal readmode");
end
endcase
end
end
 
 
 
//
// other reads
//
always @(Internal_OE or addr) begin : other_read
if (!Reset) begin
if (ReadMode != `rdARRAY) begin
CSROut = {8'h00,CSR} ;
if (addr[0] == 1'b0)
IDOut = `ID_ManufacturerB ;
else
IDOut = `ID_DeviceCodeB ;
end
end
end
 
// Handle Write to Part
 
always @(negedge Internal_WE) begin : handle_write
reg [`Word] temp ; // temporary variable needed for double
// indexing CmdData.
if (!Reset) begin
case (WriteToPtr) // Where are we writting to ?
`NewCmd : begin // This is a new command.
Cmd[`Cmd] = dq[7:0];
Cmd[`Add] = addr[`AddrSize-1:0]; //by 16 word index
CmdValid <= `TRUE ; // CmdValid sends it to the Predecode section
DataPtr <= -1;
end
`CmdField : begin // This is data used by another command
if (DataPtr == 1) begin
Cmd[`CmdData_1] = dq[`Word];
Cmd[`CmdAdd_1] = addr[`AddrSize-1:0];
end
else if (DataPtr == 2) begin
Cmd[`CmdData_2] = dq[`Word];
Cmd[`CmdAdd_2] = addr[`AddrSize-1:0];
end
else
$display("FLASH: DataPtr out of range");
DataPtr <= #1 DataPtr - 1 ; // When DataPtr = 0 the command goes to Decode section
end
default : begin
$display("FLASH: Error: Write To ? Cmd");
end
endcase
end
end
 
//
// Predecode Command
//
always @(posedge CmdValid) begin : predecode
reg [`Byte] temp; // temporary variable needed for double
// indexing BSR.
if (!Reset) begin
// Set Defaults
Cmd [`OpType] = `Program ;
WriteToPtr = `NewCmd ;
DataPtr <= 0 ;
case (Cmd [`Cmd]) // Handle the basic read mode commands
// READ ARRAY COMMAND --
`ReadArrayCmd : begin // Read Flash Array
CmdValid <= `FALSE ;
if (ReadyBusy == `Busy) // Can not read array when running an algorithm
ReadMode <= `rdCSR ;
else
ReadMode <= `rdARRAY ;
end
// READ INTELLIGENT IDENTIFIER COMMAND --
`ReadIDCmd : begin // Read Intelligent ID
if ((WriteSuspended == `TRUE) || (EraseSuspended == `TRUE))
$display("FLASH: Invalid read ID command during suspend");
else
ReadMode <= `rdID ;
CmdValid <= `FALSE ;
end
// READ COMPATIBLE STATUS REGISTER COMMAND --
`ReadCSRCmd : begin // Read CSR
ReadMode <= `rdCSR ;
CmdValid <= `FALSE ;
end
default : begin
Other = `TRUE ; // Other flag marks commands that are algorithms
Cmd [`Confirm] = `FALSE ; // Defaults
case (Cmd [`Cmd])
// PROGRAM WORD COMMAND --
`ProgramCmd : begin // Program Word
if (WriteSuspended == `TRUE) begin
$display("FLASH: Error: Program Command during Write Suspend");
CmdValid <= `FALSE;
end
else begin
WriteToPtr = `CmdField;
DataPtr <= 1;
if (EraseSuspended == `TRUE) begin
TimeLeft = AlgTime;
SuspendedAlg = Algorithm;
end
ToBeSuspended = `Program;
Cmd [`Time] = Program_Time_Word;
end
end
// PROGRAM WORD COMMAND --
`Program2Cmd : begin // Program Word
if (WriteSuspended == `TRUE) begin
$display("FLASH: Error: Program Command during Write Suspend");
CmdValid <= `FALSE;
end
else begin
Cmd [`Cmd] = `ProgramCmd;
WriteToPtr = `CmdField;
DataPtr <= 1;
if (EraseSuspended == `TRUE) begin
TimeLeft = AlgTime;
SuspendedAlg = Algorithm;
end
ToBeSuspended = `Program;
Cmd [`Time] = Program_Time_Word ;
end
end
// ERASE BLOCK COMMAND --
`EraseBlockCmd : begin // Single Block Erase
if ((WriteSuspended == `TRUE) || (EraseSuspended == `TRUE)) begin
$display("FLASH: Attempted to erase block while suspended");
CmdValid <= `FALSE;
end
else begin
WriteToPtr = `CmdField;
DataPtr <= 1;
// Cmd [`Time] = `AC_EraseTime ;
Cmd [`OpType] = `Erase;
Cmd [`Confirm] = `TRUE;
ToBeSuspended = `Erase;
end
end
default : begin // The remaining commands are complex non-algorithm commands
Other = `FALSE ;
CmdValid = `FALSE ;
// CLEAR STATUS REGISTER COMMAND
if (Cmd [`Cmd] == `ClearCSRCmd) begin
if (WriteSuspended | EraseSuspended)
ReadMode <= `rdARRAY;
else if (ReadyBusy == `Busy)
ReadMode <= `rdCSR;
else begin
EraseError <= `FALSE;
ProgramError <= `FALSE;
VppError <= `FALSE;
BlockLockStatus <= `FALSE;
ReadMode <= `rdCSR;
end
end
// RESUME COMMAND --
else if (Cmd [`Cmd] == `ResumeCmd) begin
if (WriteSuspended | EraseSuspended)
ReadMode <= `rdCSR;
Suspend = `FALSE;
if (ToBeSuspended == `Program)
WriteSuspended <= `FALSE;
else
EraseSuspended <= `FALSE;
ReadyBusy = `Busy;
end
// SUSPEND COMMAND --
else if (Cmd [`Cmd] == `SuspendCmd) begin
if (ReadyBusy == `Ready) begin
ReadMode <= `rdARRAY;
$display("FLASH: Algorithm finished; nothing to suspend");
end
else begin
ReadMode <= `rdCSR;
Suspend = `TRUE;
end
CmdValid <= `FALSE;
end
else begin
CmdValid <= `FALSE;
$display("FLASH: Warning:Illegal Command (%h)", Cmd [`Cmd]); // Added displaying command code,--- RU 9/10/99
end
end //default
endcase
end //default
endcase
end //if
end //always (predecode)
 
 
//
// Command Decode
//
always @(DataPtr) begin : command
integer BlockUsed;
// When DataPtr hits zero it means that all the
// additional data has been given to the current command
if (!Reset && (DataPtr == 0) && (WriteToPtr != `NewCmd)) begin
if (CmdValid && (WriteToPtr == `CmdField)) begin
WriteToPtr = `NewCmd;
// Just finish a multi-cycle command. Determine which block the command uses
BlockUsed = -1;
for (LoopCntr = `NumberOfBlocks-1; LoopCntr >= 0; LoopCntr = LoopCntr - 1) begin
if (Cmd[`CmdAdd_1] <= BlocksEnd[LoopCntr])
BlockUsed = LoopCntr;
end
if (BlockUsed == -1)
$display("FLASH: Error: Invalid Command Address");
else
Cmd [`OpBlock] = BlockUsed;
if (Cmd [`OpType] == `Erase ) begin
if (BlocksType[BlockUsed] == `MainBlock)
Cmd[`Time] = Main_Erase_Time;
else
Cmd[`Time] = Param_Erase_Time;
end
else if (Cmd [`OpType] == `Program)
Cmd[`Time] = Program_Time_Word;
else
Cmd[`Time] = 0;
// If this command needs a confirm
// (flaged at predecode) then check if confirm was received
if (Cmd [`Confirm]) begin
if (Cmd[`CmdData1Fx8] == `ConfirmCmd) begin
// If the command is still valid put it in the queue and deactivate the array
Algorithm = Cmd;
AlgTime = Cmd [`Time] ;
CmdValid <= `FALSE;
if (!VppError)
ReadyBusy <= #1 `Busy;
ReadMode <= `rdCSR;
end
else begin
ReadMode <= `rdCSR ;
ProgramError <= `TRUE;
EraseError <= `TRUE;
CmdValid <= `FALSE;
end
end
else begin
Algorithm = Cmd;
AlgTime = Cmd [`Time] ;
CmdValid <= `FALSE;
if (!VppError)
ReadyBusy <= #1 `Busy ;
ReadMode <= `rdCSR;
end
end
end
end //always (command)
 
//////////////
// Execution //
//////////////
always @(posedge AlgDone) begin : execution
if (!Reset) begin
if (AlgDone) begin // When the algorithm finishes
// if chips is executing during an erase interrupt
// then execute out of queue slot 2
if (Algorithm [`OpType] == `Erase) begin
// ERASE COMMAND //
if (VppFlag) begin
VppError <= `TRUE ;
EraseError <= `TRUE;
end
else begin
// Do ERASE to OpBlock
if ((BlocksType[Algorithm[`OpBlock]] == `LockBlock) && !InternalBoot_WE) begin
$display("FLASH: Error: Attempted to erase locked block.");
EraseError <= `TRUE;
BlockLockStatus <= `TRUE;
end
else begin
for (LoopCntr = BlocksBegin[Algorithm[`OpBlock]];
LoopCntr <= BlocksEnd[Algorithm[`OpBlock]]; LoopCntr = LoopCntr + 1)
MainArray [LoopCntr] = 'hFFFF;
BlocksEraseCount[Algorithm[`OpBlock]] = BlocksEraseCount[Algorithm[`OpBlock]] + 1;
$display("FLASH: Block %d Erase Count: %d",Algorithm[`OpBlock],BlocksEraseCount[Algorithm[`OpBlock]]);
end
end
end
else begin
// PROGRAM COMMAND //
if (VppFlag) begin
ProgramError <= `TRUE;
VppError <= `TRUE ;
end
else begin
if ((BlocksType[Algorithm[`OpBlock]] == `LockBlock) && !InternalBoot_WE) begin
$display("FLASH: Error: Attempted to program locked boot block.");
ProgramError <= `TRUE;
BlockLockStatus <= `TRUE;
end
else begin
Program (MainArray[Algorithm [`CmdAdd_1]], Algorithm [`CmdData_1]);
if (EraseSuspended == `TRUE) begin
AlgTime = TimeLeft;
ToBeSuspended = `Erase;
Algorithm = SuspendedAlg;
end
end
end
end
end //if (AlgDone)
ReadyBusy <= `Ready;
end //if (!Reset)
end //always (execution)
 
always @(ReadyBusy) begin
if ((!Reset) && (ReadyBusy == `Busy)) begin // If the algorithm engine
// just started, start the clock
ClearVppFlag <= #1 `TRUE ;
ClearVppFlag <= #3 `FALSE ;
TimerClk <= #1 1'b1 ;
TimerClk <= #TimerPeriod 1'b0 ;
end
end
 
// record the time for addr changes .
always @(addr) begin
if ($time != 0 & !ceb) begin
if (((curr_addr_time + TAVAV) > $time) & !ceb) //Read/Write Cycle Time --- Added "& !ceb" RU 9/9/99 9pm
$display("FLASH: [",$time,"] Timing Violation: Read/Write Cycle Time (TAVAV), Last addr change: %d",curr_addr_time) ;
curr_addr_time = $time ;
end
end
 
// record the time for oe changes .
always @(oeb) begin
if ($time != 0) begin
curr_oe_time = $time ;
end
end
 
// record the time for ce changes .
always @(ceb) begin
if ($time != 0) begin
curr_ce_time = $time ;
end
end
 
reg rpb_r;
initial rpb_r = rpb;
 
// record the time for rp changes .
always @(rpb) begin
if ((rpb_r != rpb) & ($time != 0) ) begin
curr_rp_time = $time ;
rpb_r = rpb;
end
end
 
// record the time for ReadMode changes .
always @(ReadMode) begin
if ($time != 0) begin
curr_ReadMode_time = $time ;
end
end
 
// record the time for Internal_RE changes .
always @(Internal_RE) begin
if ($time != 0) begin
curr_Internal_RE_time = $time ;
end
end
 
always @(InternalBoot) begin
InternalBoot_WE <= #TVPWH InternalBoot;
end
 
always @(TimerClk) begin
if ((!Reset) && (ReadyBusy == `Busy) && (TimerClk == 1'b0)) begin // Reschedule clock and
// decrement algorithm count
TimerClk <= #1 1'b1 ;
TimerClk <= #TimerPeriod 1'b0 ;
if (Suspend) begin // Is the chip pending suspend? If so do it
Suspend = `FALSE;
if (ToBeSuspended == `Program) begin
WriteSuspended <= #Program_Suspend_Time `TRUE;
ReadyBusy <= #Program_Suspend_Time `Ready;
end
else begin
EraseSuspended <= #Erase_Suspend_Time `TRUE;
ReadyBusy <= #Erase_Suspend_Time `Ready;
end
end
if (ReadyBusy == `Busy) begin
AlgTime = AlgTime - 1;
if (AlgTime <= 0) begin // Check if the algorithm is done
AlgDone <= #1 `TRUE ;
AlgDone <= #10 `FALSE ;
end
end
end
end
 
//------------------------------------------------------------------------
// Reset Controller
//------------------------------------------------------------------------
 
always @(rpb or vcc) begin : ResetPowerdownMonitor
// Go into reset if reset powerdown pin is active or
// the vcc is too low
if ((rpb != `VIH) || (vcc < 2500)) begin // Low Vcc protection
Reset <= `TRUE ;
if (!((vcc >= 2500) || StartUpFlag))
$display ("FLASH: Low Vcc: Chip Resetting") ;
end
else
// Coming out of reset takes time
Reset <= #TPHWL `FALSE ;
end
 
 
//------------------------------------------------------------------------
// VccMonitor
//------------------------------------------------------------------------
 
always @(Reset or vcc) begin : VccMonitor
// Save the array when chip is powered off
if ($time > 0) begin
if (vcc == 0 && SaveOnPowerdown)
StoreToFile;
if (vcc < 2700)
$display("FLASH: Vcc is below minimum operating specs");
else if ((vcc >= 2700) && (vcc <= 3600) && (`VccLevels & `Vcc2700)) begin
//$display ("Vcc is in operating range for 2.7 volt mode") ; // Commented out RU 9/11/99
/*
TAVAV = `TAVAV_27;
TAVQV = `TAVQV_27;
TELQV = `TELQV_27;
TPHQV = `TPHQV_27;
TGLQV = `TGLQV_27;
TELQX = `TELQX_27;
TEHQZ = `TEHQZ_27;
TGLQX = `TGLQX_27;
TGHQZ = `TGHQZ_27;
TOH = `TOH_27 ;
TPHWL = `TPHWL_27;
TWLWH = `TWLWH_27;
TDVWH = `TDVWH_27;
TAVWH = `TAVWH_27;
TWHDX = `TWHDX_27;
TWHAX = `TWHAX_27;
TWHWL = `TWHWL_27;
TVPWH = `TVPWH_27;
*/
if ((vpp <= 3600) && (vpp >= 2700)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_27;
Main_Erase_Time = `AC_EraseTime_Main_27_27;
Program_Time_Word = `AC_ProgramTime_Word_27_27;
end
else begin
Param_Erase_Time = `AC_EraseTime_Param_27_12;
Main_Erase_Time = `AC_EraseTime_Main_27_12;
Program_Time_Word = `AC_ProgramTime_Word_27_12;
end
end
else
$display ("FLASH: Vcc is out of operating range") ;
end //$time
end
 
//------------------------------------------------------------------------
// VppMonitor
//------------------------------------------------------------------------
always @(VppFlag or ClearVppFlag or vpp) begin : VppMonitor
if (ClearVppFlag) begin
VppErrFlag = `FALSE ;
end
else
if (!(((vpp <= 12600) && (vpp >= 11400)) || ((vpp <= 3600) && (vpp >= 2700)))) begin
VppErrFlag = `TRUE ;
end
if ((vpp <= 3600) && (vpp >= 2700)) begin
if ((vcc >= 2700) && (vcc <= 3600)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_27;
Main_Erase_Time = `AC_EraseTime_Main_27_27;
Program_Time_Word = `AC_ProgramTime_Word_27_27;
end
else begin
$display("FLASH: Invalid Vcc level at Vpp change");
VppErrFlag = `TRUE;
end
end
else begin
if ((vcc >= 2700) && (vcc <= 3600)) begin
Param_Erase_Time = `AC_EraseTime_Param_27_12;
Main_Erase_Time = `AC_EraseTime_Main_27_12;
Program_Time_Word = `AC_ProgramTime_Word_27_12;
end
else begin
$display("FLASH: Invalid Vcc level at Vpp change");
VppErrFlag = `TRUE;
end
end
VppFlag <= VppErrFlag;
end
 
 
always @(StartUpFlag or Internal_OE3) begin : OEMonitor
// This section generated DriveOutputs which is the main signal that
// controls the state of the output drivers
 
if (!StartUpFlag) begin
WriteRecovery = 0 ;
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (Internal_OE) begin
TempTime = WriteRecovery + TGLQX ;
DriveOutputs = `FALSE ;
WriteRecovery = WriteRecovery + TGLQV - TempTime;
DriveOutputs <= #WriteRecovery `TRUE ;
end
else begin
InternalOutput <= #TOH `MaxOutputs'hx;
if (oeb == `VIH)
WriteRecovery = WriteRecovery + TGHQZ;
else
WriteRecovery = WriteRecovery + TEHQZ;
DriveOutputs <= #WriteRecovery `FALSE ;
end
end
else
DriveOutputs <= `FALSE ;
end
 
/////// Timing Checks /////////////
 
always @(Internal_WE) begin : Timing_chk
if ($time > 0) begin
// pulse chk
if (Internal_WE) begin
if ((($time - curr_Internal_WE_time) < TWHWL) && (TWHWL > 0 )) begin
$display("FLASH: [",$time,"] Timing Violation: Internal Write Enable Insufficient High Time") ;
end
end
else if ((($time - curr_Internal_WE_time) < TWLWH) && (TWLWH > 0 ))
$display("FLASH: [",$time,"] Timing Violation: Internal Write Enable Insufficient Low Time") ;
curr_Internal_WE_time = $time ;
// timing_chk - addr
last_dq_time = $time - curr_dq_time;
last_rpb_time = $time - curr_rpb_time;
last_addr_time = $time - curr_addr_time;
if (Internal_WE == 0) begin
if ((last_addr_time < TAVWH) && (last_addr_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Address setup time during write, Last Event %d",last_addr_time) ;
if ((last_rpb_time < TPHWL) && (last_rpb_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Writing while coming out of powerdown, Last Event %d",last_rpb_time) ;
if ((last_dq_time < TDVWH) && (last_dq_time > 0))
$display("FLASH: [",$time,"] Timing Violation: Data setup time during write, Last Event %d",last_dq_time) ;
end
end
end
 
always @(addr) begin
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (($time > 0) && !Internal_WE) begin //timing chk
if ((last_Internal_WE_time < TWHAX) && (last_Internal_WE_time > 0))
$display("FLASH: [",$time,"] Timing Violation:Address hold time after write, Last Event %d",last_Internal_WE_time) ;
end
end
 
always @(rpb) begin
if ((rpb_r != rpb) & ($time > 0)) begin
curr_rpb_time = $time ;
end
end
 
always @(dq) begin
curr_dq_time = $time ;
last_Internal_WE_time = $time - curr_Internal_WE_time;
if (($time > 0) && !Internal_WE) begin
if ((last_Internal_WE_time < TWHDX) && (last_Internal_WE_time > 0))
$display("FLASH: [",$time,"] Timing Violation:Data hold time after write, Last Event %d",last_Internal_WE_time) ;
end
end
 
endmodule
 
 
/160b3ver/f160b3b.bkb
0,0 → 1,149
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the starting address of each block numbered from
// block 0 to nn for the bottom boot block component. The addresses are
// in hex. The address were taken from the Smart 3 Advanced Boot Block
// Flash Memory Family datasheet (Order Number 290580).
 
00000
01000
02000
03000
04000
05000
06000
07000
08000
10000
18000
20000
28000
30000
38000
40000
48000
50000
58000
60000
68000
70000
78000
80000
88000
90000
98000
A0000
A8000
B0000
B8000
C0000
C8000
D0000
D8000
E0000
E8000
F0000
F8000
/160b3ver/f160b3b.bkt
0,0 → 1,152
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the type of blocks from block 0 to nn for the
// bottom boot block component. The block types are as follows:
// MainBlock 2'b00
// LockBlock 2'b01
// ParamBlock 2'b10
// The block types were taken from the Smart 3 Advanced Boot
// Block Flash Memory Family datasheet (Order Number 290580).
 
1
1
2
2
2
2
2
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/160b3ver/f160b3t.bkb
0,0 → 1,149
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the starting address of each block numbered from
// block 0 to nn for the top boot block component. The addresses are in
// hex. The address were taken from the 16-MBit Smart 3 Advanced Boot
// Block Flash Memory Family datasheet (Order Number 290580).
 
00000
08000
10000
18000
20000
28000
30000
38000
40000
48000
50000
58000
60000
68000
70000
78000
80000
88000
90000
98000
A0000
A8000
B0000
B8000
C0000
C8000
D0000
D8000
E0000
E8000
F0000
F8000
F9000
FA000
FB000
FC000
FD000
FE000
FF000
/160b3ver/f160b3b.bke
0,0 → 1,149
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the ending address of each block numbered from block
// 0 to nn for the bottom boot block component. The addresses are in hex.
// The address were taken from the Smart 3 Advanced Boot Block Flash Memory
// Family datasheet (Order Number 290580).
 
00FFF
01FFF
02FFF
03FFF
04FFF
05FFF
06FFF
07FFF
0FFFF
17FFF
1FFFF
27FFF
2FFFF
37FFF
3FFFF
47FFF
4FFFF
57FFF
5FFFF
67FFF
6FFFF
77FFF
7FFFF
87FFF
8FFFF
97FFF
9FFFF
A7FFF
AFFFF
B7FFF
BFFFF
C7FFF
CFFFF
D7FFF
DFFFF
E7FFF
EFFFF
F7FFF
FFFFF
/160b3ver/f160b3t.bkt
0,0 → 1,152
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the type of blocks from block 0 to nn for the
// top boot block component. The block types are as follows:
// MainBlock 2'b00
// LockBlock 2'b01
// ParamBlock 2'b10
// The block types were taken from the Smart 3 Advanced Boot
// Block Flash Memory Family datasheet (Order Number 290580).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
2
2
2
2
2
1
1
/160b3ver/dp160b3b.v
0,0 → 1,187
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
//****************************************************************************
// This file contains the paramenters which define the part for the
// Smart 3 Advanced Boot Block memory model (adv_bb.v). The '2.7V Vcc Timing'
// parameters are representative of the 28F160B3-120 operating at 2.7-3.6V Vcc.
// These parameters need to be changed if the 28F160B3-150 operating at
// 2.7-3.6V Vcc is to be modeled. The parameters were taken from the Smart 3
// Advanced Boot Block Flash Memory Family datasheet (Order Number 290580).
 
// This file must be loaded before the main model, as it contains
// definitions required by the model.
 
//28F160B3-B
 
`define BlockFileBegin "f160b3b.bkb" //starting addresses of each block
`define BlockFileEnd "f160b3b.bke" //ending addresses of each block
`define BlockFileType "f160b3b.bkt" //block types
 
//Available Vcc supported by the device.
`define VccLevels 4 //Bit 0 - 5V, Bit 1 = 3.3V, Bit 2 = 2.7V
 
`define AddrSize 20 //number of address pins
`define MaxAddr `AddrSize'hFFFFF // device ending address
`define MainArraySize 0:`MaxAddr //array definition in bytes
//include A-1 for 8 bit mode
`define MaxOutputs 16 //number of output pins
`define NumberOfBlocks 39 //number of blocks in the array
 
`define ID_DeviceCodeB 'h8891 //160B3 Bottom
`define ID_ManufacturerB 'h0089
 
// Timing parameters. See the data sheet for definition of the parameter.
// Only the WE# controlled write timing parameters are used since their
// respective CE# controlled write timing parameters have the same value.
// The model does not differentiate between the two types of writes.
 
//2.7V Vcc Timing
`define TAVAV_27 120
`define TAVQV_27 120
`define TELQV_27 120
`define TPHQV_27 600
`define TGLQV_27 65
`define TELQX_27 0
`define TEHQZ_27 55
`define TGLQX_27 0
`define TGHQZ_27 45
`define TOH_27 0
`define TPHWL_27 600
`define TWLWH_27 90
`define TDVWH_27 70
`define TAVWH_27 90
`define TWHDX_27 0
`define TWHAX_27 0
`define TWHWL_27 30
`define TVPWH_27 200
 
// The following constants control how long it take an algorithm to run
// to scale all times together (for making simulation run faster
// change the constant later listed as TimerPeriod. The actual delays
// are TimerPeriod*xxx_Time, except for the suspend latency times.
 
`define TimerPeriod_ 1000 //1 usec = 1000ns requires for
//following times to be accurate
 
// The typical values given in the datasheet are used.
 
// reducing the following will reduce simulation time
 
//2.7V Vcc, 12V Vpp
`define AC_ProgramTime_Word_27_12 8 //usecs
`define AC_EraseTime_Param_27_12 800000 //0.8secs
`define AC_EraseTime_Main_27_12 1100000 //1.1secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_12 5000 //5 usecs
`define AC_Erase_Suspend_27_12 10000 //10 usecs
 
//2.7V Vcc 2.7V Vpp
`define AC_ProgramTime_Word_27_27 22 //usecs
`define AC_EraseTime_Param_27_27 1000000 //1sec
`define AC_EraseTime_Main_27_27 1800000 //1.8secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_27 6000 //6 usecs
`define AC_Erase_Suspend_27_27 13000 //13 usecs
/160b3ver/f160b3t.bke
0,0 → 1,149
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
// This file contains the ending address of each block numbered from block
// 0 to nn for the top boot block component. The addresses are in hex. The
// addresses were taken from the Smart 3 Advanced Boot Block Flash Memory
// Family datasheet (Order Number 290580).
 
07FFF
0FFFF
17FFF
1FFFF
27FFF
2FFFF
37FFF
3FFFF
47FFF
4FFFF
57FFF
5FFFF
67FFF
6FFFF
77FFF
7FFFF
87FFF
8FFFF
97FFF
9FFFF
A7FFF
AFFFF
B7FFF
BFFFF
C7FFF
CFFFF
D7FFF
DFFFF
E7FFF
EFFFF
F7FFF
F8FFF
F9FFF
FAFFF
FBFFF
FCFFF
FDFFF
FEFFF
FFFFF
/160b3ver/t160b3b.v
0,0 → 1,935
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
`timescale 1ns/1ns
 
 
module test28F160B3B();
 
reg [`AddrSize-1:0] address;
 
reg [31:0] vcc,
vpp;
 
reg ceb,
oeb,
web,
wpb,
rpb;
 
reg [`MaxOutputs-1:0] dq_reg;
wire [`MaxOutputs-1:0] dq = dq_reg;
 
IntelAdvBoot IFlash (dq, address, ceb, oeb, web, rpb, wpb, vpp, vcc);
 
initial
begin
// $dumpfile("f160b3b.dmp");
// $dumpoff;
// $dumpvars(???,dq,address,ceb,oeb,web,rpb,wpb);
dq_reg = `MaxOutputs'hz;
powerup;
ReadID;
//Verify READS with loose timing (OE Toggling)
#200
SetReadMode;
#200
$display("READ DATA, Loose Timing, toggle OE");
#200
ReadData(`AddrSize'h0);
#200
ReadData(`AddrSize'h01000);
#200
ReadData(`AddrSize'h02000);
#200
ReadData(`AddrSize'h03000);
#200
ReadData(`AddrSize'h04000);
#200
ReadData(`AddrSize'hE8000);
#200
ReadData(`AddrSize'hF0000);
#200
ReadData(`AddrSize'hF8000);
$display("READ DATA, Loose Timing, toggle Addr");
//Verify Reads (OE LOW)
#200
address = `AddrSize'h00F00;
#200
address = `AddrSize'h01F00;
#200
address = `AddrSize'h02F00;
#200
address = `AddrSize'h03FFF;
#200
address = `AddrSize'h04FFF;
#200
address = `AddrSize'hEFFFF;
#200
address = `AddrSize'hF4000;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
$display("PROGRAM DATA, Loose Timing, Boot Locked");
#200
ProgramData(`AddrSize'h00000, `MaxOutputs'h0000); //LockBlock
#200
ProgramData(`AddrSize'h01000, `MaxOutputs'h0001); //LockBlock
#200
ProgramData(`AddrSize'h02000, `MaxOutputs'h0002);
#200
ProgramData(`AddrSize'h03000, `MaxOutputs'h0003);
#200
ProgramData(`AddrSize'h04000, `MaxOutputs'h0004);
#200
ProgramData(`AddrSize'hE8000, `MaxOutputs'h0036);
#200
ProgramData(`AddrSize'hF0000, `MaxOutputs'h0037);
#200
ProgramData(`AddrSize'hF8000, `MaxOutputs'h0038);
#200
ProgramData(`AddrSize'h00F00, `MaxOutputs'h0005); //LockBlock
#200
ProgramData(`AddrSize'h01F00, `MaxOutputs'h0006); //LockBlock
#200
ProgramData(`AddrSize'h02F00, `MaxOutputs'h0007);
#200
ProgramData(`AddrSize'h03FFF, `MaxOutputs'h0008);
#200
ProgramData2(`AddrSize'h04FFF, `MaxOutputs'h0009);
#200
ProgramData2(`AddrSize'hEFFFF, `MaxOutputs'h000A);
#200
ProgramData2(`AddrSize'hF4000, `MaxOutputs'h000B);
#200
ProgramData2(`AddrSize'hFFFFF, `MaxOutputs'h000C);
$display("READ DATA, Loose Timing, toggle OE");
#200
SetReadMode;
#200
ReadData(`AddrSize'h0);
#200
ReadData(`AddrSize'h01000);
#200
ReadData(`AddrSize'h02000);
#200
ReadData(`AddrSize'h03000);
#200
ReadData(`AddrSize'h04000);
#200
ReadData(`AddrSize'hE8000);
#200
ReadData(`AddrSize'hF0000);
#200
ReadData(`AddrSize'hF8000);
$display("READ DATA, Loose Timing, toggle Addr");
//Verify Reads (OE LOW)
#200
address = `AddrSize'h00F00;
#200
address = `AddrSize'h01F00;
#200
address = `AddrSize'h02F00;
#200
address = `AddrSize'h03FFF;
#200
address = `AddrSize'h04FFF;
#200
address = `AddrSize'hEFFFF;
#200
address = `AddrSize'hF4000;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
$display("Unlock BOOT (WP#)");
#200
wpb = `VIH; //UNLOCK
$display("PROGRAM DATA, Boot Unlocked");
#200
ProgramData(`AddrSize'h00000, `MaxOutputs'h005A);
#200
ProgramData(`AddrSize'h01000, `MaxOutputs'h0001);
#200
ProgramData(`AddrSize'h00F00, `MaxOutputs'h0005);
#200
ProgramData(`AddrSize'h01F00, `MaxOutputs'h0006);
$display("READ DATA, Loose Timing, Toggle OE");
#200
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
address = `AddrSize'h01000;
#200
address = `AddrSize'h00F00;
#200
address = `AddrSize'h01F00;
#200
oeb = `VIH;
$display("WRITE SUSPEND TEST");
begin: WriteSuspend
#200
StartProgram(`AddrSize'h05000, `MaxOutputs'h5000);
#200
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'h04FFF);
#200
ReadData(`AddrSize'hFFFFF);
#200
ReadData(`AddrSize'h05000);
#200
oeb = `VIH;
#200
StartProgram(`AddrSize'hA0000, `MaxOutputs'hAAAA);
#300
Resume;
#200
oeb = `VIL;
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'h05001);
#200
ReadData(`AddrSize'h05000);
#200
ReadData(`AddrSize'hA0000);
#200
oeb = `VIH;
end //WriteSuspend
$display("ERASE Block");
#200
EraseBlock(`AddrSize'h04F00);
$display("READ DATA, Loose Timing");
#300
SetReadMode;
#200
ReadData(`AddrSize'h04000);
#200
address = `AddrSize'h03FFF;
#200
address = `AddrSize'h04FFF;
#200
oeb = `VIH;
$display("ERASE Locked Block");
#200
wpb = `VIL;
#500
EraseBlock(`AddrSize'h01F00);
#200
wpb = `VIH;
$display("READ DATA, Loose Timing");
#300
SetReadMode;
#200
ReadData(`AddrSize'h01000);
#200
address = `AddrSize'h01F00;
#200
oeb = `VIH;
//Bad Erase Confirm
$display("BAD Erase confirm test");
begin: BadErase
#200
address = `AddrSize'hEA000;
#200
dq_reg = `EraseBlockCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `ReadArrayCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#1000
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
end // BadErase
#500
ReadCSRMode;
#500
ClearCSRMode;
#500
ReadCSRMode;
#500
SetReadMode;
#200
ReadData(`AddrSize'hE8000);
#200
oeb = `VIH;
$display("Erase Suspend test");
begin: EraseSuspendTest
#200
StartErase(`AddrSize'hEA000);
#1000
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
ReadCSRMode;
#200
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
ReadData(`AddrSize'h02000);
#200
ReadData(`AddrSize'hEFFFF);
#200
oeb = `VIH;
#200
ProgramData(`AddrSize'h50000, `MaxOutputs'h0055);
#1000
Resume;
#200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'hE8000);
#200
address = `AddrSize'h50000;
#200
address = `AddrSize'hEFFFF;
#200
oeb = `VIH;
end // EraseSuspendTest
#500
$display("Embedded Suspend Mode");
begin: EraseSuspend_
#100
StartErase(`AddrSize'hF5000);
#1000
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'hF8000);
#200
oeb = `VIH;
begin: WriteSuspend_
$display("EMBEDDED WRITE SUSPEND TEST");
#200
StartProgram(`AddrSize'h00000, `MaxOutputs'h00A5);
#200
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'h01000);
#200
ReadData(`AddrSize'h00F00);
#200
oeb = `VIH;
#500
Resume; //Write Operation
#200
oeb = `VIL;
// #500
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-2000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
oeb = `VIH;
end //WriteSuspend_
#300
Resume; //Erase Operation
#200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end
end
#200
ClearCSRMode;
#300
SetReadMode;
#200
ReadData(`AddrSize'h03000);
#200
address = `AddrSize'hF0000;
#200
address = `AddrSize'h03FFF;
#200
address = `AddrSize'hF4000;
#200
oeb = `VIH;
end //EraseSuspend_
$display("LOW Vpp OPERATION TEST");
#200
vpp =1300;
#100
ProgramData(`AddrSize'h33333, `MaxOutputs'h3333);
#200
EraseBlock(`AddrSize'hF8F00);
#200
vpp = 12000;
#200
SetReadMode;
#200
ReadData(`AddrSize'h33333);
#200
address = `AddrSize'hF8000;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
#1000
powerdown;
#1000 $finish;
end
 
always @(dq or address or ceb or rpb or oeb or web or wpb or vcc or vpp)
begin
$display(
"%d Addr = %h, Data = %h, CEb=%b, RPb=%b, OEb=%b, WEb=%d, WPb=%b, vcc=%d, vpp = %d",
$time, address, dq, ceb, rpb, oeb, web, wpb, vcc, vpp);
end
 
task powerup;
begin
$display(" POWERUP TASK");
rpb = `VIL; //reset
#200
address = 0;
#200
web = `VIH; //write enable high
#200
oeb = `VIH; //output ts
#200
ceb = `VIH; //disabled
#200
vcc = 3300; //power up vcc
#5000
vpp = 12000; //ramp up vpp
#5000
rpb = `VIH; //out of reset
#500
wpb = `VIL; //blocks locked
#200
oeb = `VIL; //enable outputs
#200
ceb = `VIL; //enable chip
end
endtask
 
 
task powerdown;
begin
$display(" POWERDOWN TASK");
address = 0;
#200
rpb = `VIL; //reset
#200
oeb = `VIH; //output ts
#200
web = `VIH; //we high
#200
ceb = `VIH; //disabled
#200
vpp = 0; //power down vpp
#5000
vcc = 0; //ramp down vcc
end
endtask
 
 
task ReadData;
input [`AddrSize-1:0] addr;
begin
$display(" READDATA TASK");
oeb = `VIH;
#200
address = addr;
#200
oeb = `VIL;
end
endtask
 
task SetReadMode;
begin
$display(" SETREADMODE TASK");
oeb = `VIH;
#200
dq_reg = `ReadArrayCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
task ReadID;
begin
$display(" READID TASK");
oeb = `VIH;
#200
address = `AddrSize'h0;
#200
dq_reg = `ReadIDCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#200
address = `AddrSize'h1;
end
endtask
 
 
task ReadCSRMode;
begin
$display(" READCSR MODE TASK");
oeb = `VIH;
#200
dq_reg = `ReadCSRCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
end
endtask
 
task ClearCSRMode;
begin
$display(" CLEARCSRMODE TASK");
oeb = `VIH;
#200
dq_reg = `ClearCSRCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task StartProgram;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" STARTPROGRAM TASK");
#200
address = addr;
#200
dq_reg = `Program2Cmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = data;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task ProgramData;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" PROGRAMDATA TASK");
StartProgram(addr, data);
#200
oeb = `VIL;
#((`AC_ProgramTime_Word_27_12*`TimerPeriod_)-500)
begin: Poll
forever
begin
oeb = `VIH;
#200
oeb = `VIL;
#200
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
 
task StartProgram2;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" STARTPROGRAM2 TASK");
#200
address = addr;
#200
dq_reg = `Program2Cmd;
#200
web = `VIL;
#10
ceb = `VIL;
#200
ceb = `VIH;
#10
web = `VIH;
#200
dq_reg = data;
#200
web = `VIL;
#10
ceb = `VIL;
#200
ceb = `VIH;
#10
web = `VIH;
#200
ceb = `VIL;
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task ProgramData2;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" PROGRAMDATA2 TASK");
ceb = `VIH;
StartProgram2(addr, data);
#200
oeb = `VIL;
#((`AC_ProgramTime_Word_27_12*`TimerPeriod_)-500)
begin: Poll
forever
begin
oeb = `VIH;
#200
oeb = `VIL;
#200
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
 
task StartErase;
input [`AddrSize-1:0] BlockAddr;
begin
$display(" STARTERASE TASK");
#200
address = BlockAddr;
#200
dq_reg = `EraseBlockCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `ConfirmCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task EraseBlock;
input [`AddrSize-1:0] BlockAddr;
time EraseTime;
begin
$display(" ERASEBLOCK TASK");
StartErase(BlockAddr);
#200
oeb = `VIL;
if (BlockAddr < `AddrSize'h08000)
EraseTime = ((`AC_EraseTime_Param_27_12*`TimerPeriod_)-5000);
else
EraseTime = ((`AC_EraseTime_Main_27_12*`TimerPeriod_)-5000);
#EraseTime
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
task Suspend;
begin
$display(" SUSPEND TASK");
#200
dq_reg = `SuspendCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#3000
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
task Resume;
begin
$display(" RESUME TASK");
#200
dq_reg = `ResumeCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
/* #200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
*/
end
endtask
 
endmodule
/160b3ver/dp160b3t.v
0,0 → 1,187
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
//****************************************************************************
// This file contains the paramenters which define the part for the
// Smart 3 Advanced Boot Block memory model (adv_bb.v). The '2.7V Vcc Timing'
// parameters are representative of the 28F160B3-120 operating at 2.7-3.6V Vcc.
// These parameters need to be changed if the 28F160B3-150 operating at
// 2.7-3.6V Vcc is to be modeled. The parameters were taken from the Smart 3
// Advanced Boot Block Flash Memory Family datasheet (Order Number 290580).
 
// This file must be loaded before the main model, as it contains
// definitions required by the model.
 
//28F160B3-T
 
`define BlockFileBegin "F160B3T.BKB" //starting addresses of each block
`define BlockFileEnd "F160B3T.BKE" //ending addresses of each block
`define BlockFileType "F160B3T.BKT" //block types
 
//Available Vcc supported by the device.
`define VccLevels 4 //Bit 0 - 5V, Bit 1 = 3.3V, Bit 2 = 2.7V
 
`define AddrSize 20 //number of address pins
`define MaxAddr `AddrSize'hFFFFF // device ending address
`define MainArraySize 0:`MaxAddr //array definition in bytes
//include A-1 for 8 bit mode
`define MaxOutputs 16 //number of output pins
`define NumberOfBlocks 39 //number of blocks in the array
 
`define ID_DeviceCodeB 'h8890 //160B3 Top
`define ID_ManufacturerB 'h0089
 
// Timing parameters. See the data sheet for definition of the parameter.
// Only the WE# controlled write timing parameters are used since their
// respective CE# controlled write timing parameters have the same value.
// The model does not differentiate between the two types of writes.
 
//2.7V Vcc Timing
`define TAVAV_27 120
`define TAVQV_27 120
`define TELQV_27 120
`define TPHQV_27 600
`define TGLQV_27 65
`define TELQX_27 0
`define TEHQZ_27 55
`define TGLQX_27 0
`define TGHQZ_27 45
`define TOH_27 0
`define TPHWL_27 600
`define TWLWH_27 90
`define TDVWH_27 70
`define TAVWH_27 90
`define TWHDX_27 0
`define TWHAX_27 0
`define TWHWL_27 30
`define TVPWH_27 200
 
// The following constants control how long it take an algorithm to run
// to scale all times together (for making simulation run faster
// change the constant later listed as TimerPeriod. The actual delays
// are TimerPeriod*xxx_Time, except for the suspend latency times.
 
`define TimerPeriod_ 1000 //1 usec = 1000ns requires for
//following times to be accurate
 
// The typical values given in the datasheet are used.
 
// reducing the following will reduce simulation time
 
//2.7V Vcc, 12V Vpp
`define AC_ProgramTime_Word_27_12 8 //usecs
`define AC_EraseTime_Param_27_12 800000 //0.8secs
`define AC_EraseTime_Main_27_12 1100000 //1.1secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_12 5000 //5 usecs
`define AC_Erase_Suspend_27_12 10000 //10 usecs
 
//2.7V Vcc 2.7V Vpp
`define AC_ProgramTime_Word_27_27 22 //usecs
`define AC_EraseTime_Param_27_27 1000000 //1sec
`define AC_EraseTime_Main_27_27 1800000 //1.8secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_27 6000 //6 usecs
`define AC_Erase_Suspend_27_27 13000 //13 usecs
/160b3ver/t160b3t.v
0,0 → 1,936
/*
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
*/
 
`timescale 1ns/1ns
 
 
module test28F160B3T();
 
reg [`AddrSize-1:0] address;
 
reg [31:0] vcc,
vpp;
 
reg ceb,
oeb,
web,
wpb,
rpb;
 
reg [`MaxOutputs-1:0] dq_reg;
wire [`MaxOutputs-1:0] dq = dq_reg;
 
IntelAdvBoot IFlash (dq, address, ceb, oeb, web, rpb, wpb, vpp, vcc);
 
initial
begin
// $dumpfile("f160b3t.dmp");
// $dumpoff;
// $dumpvars(???,dq,address,ceb,oeb,web,rpb,wpb);
dq_reg = `MaxOutputs'hz;
powerup;
ReadID;
//Verify READS with loose timing (OE Toggling)
#200
SetReadMode;
#200
$display("READ DATA, Loose Timing, toggle OE");
#200
ReadData(`AddrSize'h0);
#200
ReadData(`AddrSize'h08000);
#200
ReadData(`AddrSize'h10000);
#200
ReadData(`AddrSize'hFB000);
#200
ReadData(`AddrSize'hFC000);
#200
ReadData(`AddrSize'hFD000);
#200
ReadData(`AddrSize'hFE000);
#200
ReadData(`AddrSize'hFF000);
$display("READ DATA, Loose Timing, toggle Addr");
//Verify Reads (OE LOW)
#200
address = `AddrSize'h07FFF;
#200
address = `AddrSize'h0A000;
#200
address = `AddrSize'h17FFF;
#200
address = `AddrSize'hFBFFF;
#200
address = `AddrSize'hFCFFF;
#200
address = `AddrSize'hFDF00;
#200
address = `AddrSize'hFEF00;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
$display("PROGRAM DATA, Loose Timing, Boot Locked");
#200
ProgramData(`AddrSize'h00000, `MaxOutputs'h0000);
#200
ProgramData(`AddrSize'h08000, `MaxOutputs'h0001);
#200
ProgramData(`AddrSize'h10000, `MaxOutputs'h0002);
#200
ProgramData(`AddrSize'hFB000, `MaxOutputs'h0034);
#200
ProgramData(`AddrSize'hFC000, `MaxOutputs'h0035);
#200
ProgramData(`AddrSize'hFD000, `MaxOutputs'h0036);
#200
ProgramData(`AddrSize'hFE000, `MaxOutputs'h0037); //LockBlock
#200
ProgramData(`AddrSize'hFF000, `MaxOutputs'h0038); //LockBlock
#200
ProgramData(`AddrSize'h07FFF, `MaxOutputs'h1001);
#200
ProgramData(`AddrSize'h0A000, `MaxOutputs'h1000);
#200
ProgramData(`AddrSize'h17FFF, `MaxOutputs'h2000);
#200
ProgramData(`AddrSize'hFBFFF, `MaxOutputs'h3400);
#200
ProgramData2(`AddrSize'hFCFFF, `MaxOutputs'h3500);
#200
ProgramData2(`AddrSize'hFDF00, `MaxOutputs'h3600);
#200
ProgramData2(`AddrSize'hFEF00, `MaxOutputs'h3700); //LockBlock
#200
ProgramData2(`AddrSize'hFFFFF, `MaxOutputs'h3800); //LockBlock
$display("READ DATA, Loose Timing, toggle OE");
#200
SetReadMode;
#200
ReadData(`AddrSize'h0);
#200
ReadData(`AddrSize'h08000);
#200
ReadData(`AddrSize'h10000);
#200
ReadData(`AddrSize'hFB000);
#200
ReadData(`AddrSize'hFC000);
#200
ReadData(`AddrSize'hFD000);
#200
ReadData(`AddrSize'hFE000);
#200
ReadData(`AddrSize'hFF000);
$display("READ DATA, Loose Timing, toggle Addr");
//Verify Reads (OE LOW)
#200
address = `AddrSize'h07FFF;
#200
address = `AddrSize'h0A000;
#200
address = `AddrSize'h17FFF;
#200
address = `AddrSize'hFBFFF;
#200
address = `AddrSize'hFCFFF;
#200
address = `AddrSize'hFDF00;
#200
address = `AddrSize'hFEF00;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
$display("Unlock BOOT (WP#)");
#200
wpb = `VIH; //UNLOCK
$display("PROGRAM DATA, Boot Unlocked");
#200
ProgramData(`AddrSize'hFE000, `MaxOutputs'h0037);
#200
ProgramData(`AddrSize'hFF000, `MaxOutputs'h0038);
#200
ProgramData(`AddrSize'hFEF00, `MaxOutputs'h3700);
#200
ProgramData(`AddrSize'hFFFFF, `MaxOutputs'h3800);
$display("READ DATA, Loose Timing, Toggle OE");
#200
SetReadMode;
#200
ReadData(`AddrSize'hFE000);
#200
address = `AddrSize'hFF000;
#200
address = `AddrSize'hFEF00;
#200
address = `AddrSize'hFFFFF;
#200
oeb = `VIH;
$display("WRITE SUSPEND TEST");
begin: WriteSuspend
#200
StartProgram(`AddrSize'hFA000, `MaxOutputs'h3300);
#200
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'hF9FFF);
#200
ReadData(`AddrSize'hFFFFF);
#200
ReadData(`AddrSize'hFA000);
#200
oeb = `VIH;
#200
StartProgram(`AddrSize'hA0000, `MaxOutputs'hAAAA);
#300
Resume;
#200
oeb = `VIL;
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'hFA001);
#200
ReadData(`AddrSize'hFA000);
#200
ReadData(`AddrSize'hA0000);
#200
oeb = `VIH;
end //WriteSuspend
$display("ERASE Block");
#200
EraseBlock(`AddrSize'hFBF00);
$display("READ DATA, Loose Timing");
#300
SetReadMode;
#200
ReadData(`AddrSize'hFB000);
#200
address = `AddrSize'hFCFFF;
#200
address = `AddrSize'hFBFFF;
#200
oeb = `VIH;
$display("ERASE Locked Block");
#200
wpb = `VIL;
#500
EraseBlock(`AddrSize'hFE500);
#200
wpb = `VIH;
$display("READ DATA, Loose Timing");
#300
SetReadMode;
#200
ReadData(`AddrSize'hFE000);
#200
address = `AddrSize'hFEF00;
#200
oeb = `VIH;
//Bad Erase Confirm
$display("BAD Erase confirm test");
begin: BadErase
#200
address = `AddrSize'h04000;
#200
dq_reg = `EraseBlockCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `ReadArrayCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#1000
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
end // BadErase
#500
ReadCSRMode;
#500
ClearCSRMode;
#500
ReadCSRMode;
#500
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
oeb = `VIH;
$display("Erase Suspend test");
begin: EraseSuspendTest
#200
StartErase(`AddrSize'h04000);
#1000
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
ReadCSRMode;
#200
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
ReadData(`AddrSize'h08000);
#200
ReadData(`AddrSize'hFDF00);
#200
oeb = `VIH;
#200
ProgramData(`AddrSize'h50000, `MaxOutputs'h0055);
#1000
Resume;
#200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'h00000);
#200
address = `AddrSize'h50000;
#200
address = `AddrSize'h07FFF;
#200
oeb = `VIH;
end // EraseSuspendTest
#500
$display("Embedded Suspend Mode");
begin: EraseSuspend_
#100
StartErase(`AddrSize'h0F000);
#1000
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'h10000);
#200
oeb = `VIH;
begin: WriteSuspend_
$display("EMBEDDED WRITE SUSPEND TEST");
#200
StartProgram(`AddrSize'hFF000, `MaxOutputs'h3800);
#200
oeb = `VIH;
#200
oeb = `VIL;
#200
oeb = `VIH;
#((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)
Suspend;
#200
SetReadMode;
#200
ReadData(`AddrSize'hFE000);
#200
ReadData(`AddrSize'hFFFFF);
#200
oeb = `VIH;
#500
Resume; //Write Operation
#200
oeb = `VIL;
// #500
#(((`AC_ProgramTime_Word_27_12/2)*`TimerPeriod_)-2000)
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end
end
#300
SetReadMode;
#200
ReadData(`AddrSize'hFF000);
#200
oeb = `VIH;
end //WriteSuspend_
#300
Resume; //Erase Operation
#200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end
end
#200
ClearCSRMode;
#300
SetReadMode;
#200
ReadData(`AddrSize'hFD000);
#200
address = `AddrSize'h08000;
#200
address = `AddrSize'hFCFFF;
#200
address = `AddrSize'h0A000;
#200
oeb = `VIH;
end //EraseSuspend_
$display("LOW Vpp OPERATION TEST");
#200
vpp =1300;
#100
ProgramData(`AddrSize'h33333, `MaxOutputs'h3333);
#200
EraseBlock(`AddrSize'h17000);
#200
vpp = 12000;
#200
SetReadMode;
#200
ReadData(`AddrSize'h33333);
#200
address = `AddrSize'h10000;
#200
address = `AddrSize'h17FFF;
#200
oeb = `VIH;
#1000
powerdown;
#1000
$finish;
end
 
always @(dq or address or ceb or rpb or oeb or web or wpb or vcc or vpp)
begin
$display(
"%d Addr = %h, Data = %h, CEb=%b, RPb=%b, OEb=%b, WEb=%d, WPb=%b, vcc=%d, vpp = %d",
$time, address, dq, ceb, rpb, oeb, web, wpb, vcc, vpp);
end
 
task powerup;
begin
$display(" POWERUP TASK");
rpb = `VIL; //reset
#200
address = 0;
#200
web = `VIH; //write enable high
#200
oeb = `VIH; //output ts
#200
ceb = `VIH; //disabled
#200
vcc = 3300; //power up vcc
#5000
vpp = 12000; //ramp up vpp
#5000
rpb = `VIH; //out of reset
#500
wpb = `VIL; //blocks locked
#200
oeb = `VIL; //enable outputs
#200
ceb = `VIL; //enable chip
end
endtask
 
 
task powerdown;
begin
$display(" POWERDOWN TASK");
address = 0;
#200
rpb = `VIL; //reset
#200
oeb = `VIH; //output ts
#200
web = `VIH; //we high
#200
ceb = `VIH; //disabled
#200
vpp = 0; //power down vpp
#5000
vcc = 0; //ramp down vcc
end
endtask
 
 
task ReadData;
input [`AddrSize-1:0] addr;
begin
$display(" READDATA TASK");
oeb = `VIH;
#200
address = addr;
#200
oeb = `VIL;
end
endtask
 
task SetReadMode;
begin
$display(" SETREADMODE TASK");
oeb = `VIH;
#200
dq_reg = `ReadArrayCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
task ReadID;
begin
$display(" READID TASK");
oeb = `VIH;
#200
address = `AddrSize'h0;
#200
dq_reg = `ReadIDCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#200
address = `AddrSize'h1;
end
endtask
 
 
task ReadCSRMode;
begin
$display(" READCSR MODE TASK");
oeb = `VIH;
#200
dq_reg = `ReadCSRCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
end
endtask
 
task ClearCSRMode;
begin
$display(" CLEARCSRMODE TASK");
oeb = `VIH;
#200
dq_reg = `ClearCSRCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task StartProgram;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" STARTPROGRAM TASK");
#200
address = addr;
#200
dq_reg = `Program2Cmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = data;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task ProgramData;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" PROGRAMDATA TASK");
StartProgram(addr, data);
#200
oeb = `VIL;
#((`AC_ProgramTime_Word_27_12*`TimerPeriod_)-500)
begin: Poll
forever
begin
oeb = `VIH;
#200
oeb = `VIL;
#200
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
 
task StartProgram2;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" STARTPROGRAM2 TASK");
#200
address = addr;
#200
dq_reg = `Program2Cmd;
#200
web = `VIL;
#10
ceb = `VIL;
#200
ceb = `VIH;
#10
web = `VIH;
#200
dq_reg = data;
#200
web = `VIL;
#10
ceb = `VIL;
#200
ceb = `VIH;
#10
web = `VIH;
#200
ceb = `VIL;
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task ProgramData2;
input [`AddrSize-1:0] addr;
input [`MaxOutputs-1:0] data;
begin
$display(" PROGRAMDATA2 TASK");
ceb = `VIH;
StartProgram2(addr, data);
#200
oeb = `VIL;
#((`AC_ProgramTime_Word_27_12*`TimerPeriod_)-500)
begin: Poll
forever
begin
oeb = `VIH;
#200
oeb = `VIL;
#200
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
 
task StartErase;
input [`AddrSize-1:0] BlockAddr;
begin
$display(" STARTERASE TASK");
#200
address = BlockAddr;
#200
dq_reg = `EraseBlockCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `ConfirmCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
end
endtask
 
 
task EraseBlock;
input [`AddrSize-1:0] BlockAddr;
time EraseTime;
begin
$display(" ERASEBLOCK TASK");
StartErase(BlockAddr);
#200
oeb = `VIL;
if (BlockAddr < `AddrSize'h08000)
EraseTime = ((`AC_EraseTime_Param_27_12*`TimerPeriod_)-5000);
else
EraseTime = ((`AC_EraseTime_Main_27_12*`TimerPeriod_)-5000);
#EraseTime
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
task Suspend;
begin
$display(" SUSPEND TASK");
#200
dq_reg = `SuspendCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
#200
oeb = `VIL;
#3000
begin: Poll
forever
begin
oeb = `VIH;
#500
oeb = `VIL;
#500
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
end
endtask
 
task Resume;
begin
$display(" RESUME TASK");
#200
dq_reg = `ResumeCmd;
#200
web = `VIL;
#200
web = `VIH;
#200
dq_reg = `MaxOutputs'hz;
/* #200
oeb = `VIL;
#(((`AC_EraseTime_Main_27_12/2)*`TimerPeriod_)-1000)
begin: Poll
forever
begin
oeb = `VIH;
#1000
oeb = `VIL;
#1000
if (dq[7] == `VIH)
disable Poll;
end //forever
end //Poll
#300
ClearCSRMode;
*/
end
endtask
 
endmodule
/160b3ver/DP160B3B_RU.V
0,0 → 1,86
 
//****************************************************************************
// This file contains the paramenters which define the part for the
// Smart 3 Advanced Boot Block memory model (adv_bb.v). The '2.7V Vcc Timing'
// parameters are representative of the 28F160B3-120 operating at 2.7-3.6V Vcc.
// These parameters need to be changed if the 28F160B3-150 operating at
// 2.7-3.6V Vcc is to be modeled. The parameters were taken from the Smart 3
// Advanced Boot Block Flash Memory Family datasheet (Order Number 290580).
 
// This file must be loaded before the main model, as it contains
// definitions required by the model.
 
//28F160B3-B
 
`define BlockFileBegin "f160b3b.bkb" //starting addresses of each block
`define BlockFileEnd "f160b3b.bke" //ending addresses of each block
`define BlockFileType "f160b3b.bkt" //block types
 
//Available Vcc supported by the device.
`define VccLevels 4 //Bit 0 - 5V, Bit 1 = 3.3V, Bit 2 = 2.7V
 
`define AddrSize 20 //number of address pins
`define MaxAddr `AddrSize'hFFFFF // device ending address
`define MainArraySize 0:`MaxAddr //array definition in bytes
//include A-1 for 8 bit mode
`define MaxOutputs 16 //number of output pins
`define NumberOfBlocks 39 //number of blocks in the array
 
`define ID_DeviceCodeB 'h8891 //160B3 Bottom
`define ID_ManufacturerB 'h0089
 
// Timing parameters. See the data sheet for definition of the parameter.
// Only the WE# controlled write timing parameters are used since their
// respective CE# controlled write timing parameters have the same value.
// The model does not differentiate between the two types of writes.
 
//2.7V Vcc Timing
 
// Changed the timings below to represent a "c3" device. --- RU 9/9/99
 
`define TAVAV_27 110
`define TAVQV_27 110
`define TELQV_27 110
`define TPHQV_27 150
`define TGLQV_27 0
`define TELQX_27 0
`define TEHQZ_27 20
`define TGLQX_27 0
`define TGHQZ_27 20
`define TOH_27 0
`define TPHWL_27 150
`define TWLWH_27 70
`define TDVWH_27 60
`define TAVWH_27 70
`define TWHDX_27 0
`define TWHAX_27 0
`define TWHWL_27 30
`define TVPWH_27 200
 
// The following constants control how long it take an algorithm to run
// to scale all times together (for making simulation run faster
// change the constant later listed as TimerPeriod. The actual delays
// are TimerPeriod*xxx_Time, except for the suspend latency times.
 
`define TimerPeriod_ 1000 //1 usec = 1000ns requires for
//following times to be accurate
 
// The typical values given in the datasheet are used.
 
// reducing the following will reduce simulation time
 
//2.7V Vcc, 12V Vpp
`define AC_ProgramTime_Word_27_12 8 //usecs
`define AC_EraseTime_Param_27_12 800000 //0.8secs
`define AC_EraseTime_Main_27_12 1100000 //1.1secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_12 5000 //5 usecs
`define AC_Erase_Suspend_27_12 10000 //10 usecs
 
//2.7V Vcc 2.7V Vpp
`define AC_ProgramTime_Word_27_27 22 //usecs
`define AC_EraseTime_Param_27_27 1000000 //1sec
`define AC_EraseTime_Main_27_27 1800000 //1.8secs
//Latency times are NOT multiplied by TimerPeriod_
`define AC_Program_Suspend_27_27 6000 //6 usecs
`define AC_Erase_Suspend_27_27 13000 //13 usecs
/160b3ver/read.me
0,0 → 1,124
INTEL DEVELOPER'S SOFTWARE LICENSE AGREEMENT
 
BY USING THIS SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THE TERMS OF
THIS AGREEMENT. DO NOT USE THE SOFTWARE UNTIL YOU HAVE CAREFULLY READ
AND AGREED TO THE FOLLOWING TERMS AND CONDITIONS. IF YOU DO NOT AGREE
TO THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN THE SOFTWARE PACKAGE AND
ANY ACCOMPANYING ITEMS.
 
IF YOU USE THIS SOFTWARE, YOU WILL BE BOUND BY THE TERMS OF THIS
AGREEMENT
 
LICENSE: Intel Corporation ("Intel") grants you the non-exclusive right
to use the enclosed software program ("Software"). You will not use,
copy, modify, rent, sell or transfer the Software or any portion
thereof, except as provided in this Agreement.
 
System OEM Developers may:
1. Copy the Software for support, backup or archival purposes;
2. Install, use, or distribute Intel owned Software in object code
only;
3. Modify and/or use Software source code that Intel directly makes
available to you as an OEM Developer;
4. Install, use, modify, distribute, and/or make or have made
derivatives ("Derivatives") of Intel owned Software under the
terms and conditions in this Agreement, ONLY if you are a System
OEM Developer and NOT an end-user.
 
RESTRICTIONS:
 
YOU WILL NOT:
1. Copy the Software, in whole or in part, except as provided for
in this Agreement;
2. Decompile or reverse engineer any Software provided in object
code format;
3. Distribute any Software or Derivative code to any end-users,
unless approved by Intel in a prior writing.
 
TRANSFER: You may transfer the Software to another OEM Developer if the
receiving party agrees to the terms of this Agreement at the sole risk
of any receiving party.
 
OWNERSHIP AND COPYRIGHT OF SOFTWARE: Title to the Software and all
copies thereof remain with Intel or its vendors. The Software is
copyrighted and is protected by United States and international
copyright laws. You will not remove the copyright notice from the
Software. You agree to prevent any unauthorized copying of the
Software.
 
DERIVATIVE WORK: OEM Developers that make or have made Derivatives will
not be required to provide Intel with a copy of the source or object
code. OEM Developers shall be authorized to use, market, sell, and/or
distribute Derivatives to other OEM Developers at their own risk and
expense. Title to Derivatives and all copies thereof shall be in the
particular OEM Developer creating the Derivative. Such OEMs shall
remove the Intel copyright notice from all Derivatives if such notice is
contained in the Software source code.
 
DUAL MEDIA SOFTWARE: If the Software package contains multiple media,
you may only use the medium appropriate for your system.
WARRANTY: Intel warrants that it has the right to license you to use,
modify, or distribute the Software as provided in this Agreement. The
Software is provided "AS IS". Intel makes no representations to
upgrade, maintain, or support the Software at any time. Intel warrants
that the media on which the Software is furnished will be free from
defects in material and workmanship for a period of one (1) year from
the date of purchase. Upon return of such defective media, Intel's
entire liability and your exclusive remedy shall be the replacement of
the Software.
 
THE ABOVE WARRANTIES ARE THE ONLY WARRANTIES OF ANY KIND, EITHER EXPRESS
OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
PARTICULAR PURPOSE.
 
LIMITATION OF LIABILITY: NEITHER INTEL NOR ITS VENDORS OR AGENTS SHALL
BE LIABLE FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF DATA,
INTERRUPTION OF BUSINESS, NOR FOR INDIRECT, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES OF ANY KIND WHETHER UNDER THIS AGREEMENT OR
OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 
TERMINATION OF THIS LICENSE: Intel reserves the right to conduct or have
conducted audits to verify your compliance with this Agreement. Intel
may terminate this Agreement at any time if you are in breach of any of
its terms and conditions. Upon termination, you will immediately
destroy, and certify in writing the destruction of, the Software or
return all copies of the Software and documentation to Intel.
 
U.S. GOVERNMENT RESTRICTED RIGHTS: The Software and documentation were
developed at private expense and are provided with "RESTRICTED RIGHTS".
Use, duplication or disclosure by the Government is subject to
restrictions as set forth in FAR52.227-14 and DFAR252.227-7013 et seq.
or its successor.
 
EXPORT LAWS: You agree that the distribution and export/re-export of the
Software is in compliance with the laws, regulations, orders or other
restrictions of the U.S. Export Administration Regulations.
 
APPLICABLE LAW: This Agreement is governed by the laws of the State of
California and the United States, including patent and copyright laws.
Any claim arising out of this Agreement will be brought in Santa Clara
County, California.
 
 
 
Intel's Smart 3 Advanced Boot Block verilog model consists of 5 files. One
file, "adv_bb.v" contains the basic model for the Smart 3 Advanced Boot Block
Flash Memory Family. The other files depend upon the device being modeled.
One file is used to parametize the model (dp*.v) for the specific device.
This file will call out other files to be loaded which contain:
 
*.bkb block begin addressed.
*.bke block end addresses.
*.bkt block type information.
 
The parameterization file will call out the names of the other files. This
file must be loaded into the simulator before the main model file "adv_bb.v"
as it contains definitions required for the model. Since the flash device
can have the boot block at the top or bottom, files containg the block
information (start address, end address and type) for both top and bottom
boot block components are included (f160b3b.* for bottom; f160b3t.* for top).
 
Test files, t160b3?.v, illustrating the interaction between the microprocessor
and the flash memory are also included. These test files can be changed to
test different scenarios representative of specific applications.
/sdram_models/16Mx16/mt48lc16m16a2.v
0,0 → 1,1019
/****************************************************************************************
*
* File Name: MT48LC16M16A2.V
* Version: 1.0a
* Date: August 4th, 2000
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC16M16A2 (4Meg x 16 x 4 Banks)
*
* Description: Micron 256Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" timescale
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 1.0a Son Huynh 208-368-3825 08/04/2000 - Improve alternate banks read/write
* Micron Technology Inc. access with auto precharge enable
*
* 0.0a Son Huynh 208-368-3825 04/29/1999 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc. - Simple testbench included
*
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc16m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 13; // 13 bits
parameter data_bits = 16; // 16 bits
parameter col_bits = 9; // 9 bits
parameter mem_sizes = 4194303; // 4 Mb
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [1 : 0] Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -7E and CAS Latency = 2
parameter tAC = 5.4;
parameter tHZ = 5.4;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 37.0;
parameter tRC = 60.0;
parameter tRCD = 15.0;
parameter tRP = 15.0;
parameter tRRD = 14.0;
parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
parameter tWRp = 14.0; // A2 Version - Manual precharge mode (14 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
 
 
integer n;
 
task mem_fill;
input size;
 
integer size;
 
begin
for(n=0;n<size;n=n+1)
begin
Bank0[n] = $random;
Bank1[n] = $random;
Bank2[n] = $random;
Bank3[n] = $random;
end
 
end
endtask
 
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
 
if (Cke == 1'b0 && (Data_in_enable == 1'b1 || Data_out_enable == 1'b1)) begin
$display ("at time %t ERROR: Illegal power down or self refresh. Please make sure data bus is idle.", $time);
end
 
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
 
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
 
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
 
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
 
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
 
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
 
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
 
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all banks", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all banks", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
if (Debug) $display ("at time %t NOTE : Precharge interrupt Write Bank %d.", $time, Bank);
if (Debug) $display ("at time %t NOTE : Make sure DQM is HIGH two cycles to meet tWR.", $time);
if (Debug) $display ("at time %t NOTE : We suggest to use Burst Terminate command instead.", $time);
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
 
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Read interrupt Read (terminate Read after CL-1)
if (Data_out_enable == 1'b1 && ((Cas_latency_2 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 1) ||
(Burst_length_4 == 1'b1 && Burst_counter < 3) ||
(Burst_length_8 == 1'b1 && Burst_counter < 7))) ||
(Cas_latency_3 == 1'b1 && ((Burst_length_4 == 1'b1 && Burst_counter < 2) ||
(Burst_length_8 == 1'b1 && Burst_counter < 6))))) begin
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 2'b11) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 2'b11) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -7E and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 7.5, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
/sdram_models/4Mx16/bank0.txt
0,0 → 1,50
00
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12
13
14
15
16
17
18
19
1a
1b
1c
1d
1e
1f
20
21
22
23
24
25
26
27
28
29
2a
2b
2c
2d
2e
2f
30
31
/sdram_models/4Mx16/bank1.txt
0,0 → 1,50
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51
52
53
54
55
56
57
58
59
5a
5b
5c
5d
5e
5f
60
61
62
63
/sdram_models/4Mx16/mt48lc4m16a2.v
0,0 → 1,979
/****************************************************************************************
*
* File Name: MT48LC4M16A2.V
* Version: 0.0g
* Date: September 3rd, 1999
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.2e PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC4M16A2 (1Meg x 16 x 4 Banks)
*
* Description: Micron 64Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0g Son Huynh 208-368-3825 09/03/1999 - Change tRAS + tWR timing check
* Micron Technology Inc. - Change some error messages
*
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc4m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12;
parameter data_bits = 16;
parameter col_bits = 8;
parameter mem_sizes = 1048575;
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [1 : 0] Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b0; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
parameter tAC = 6.0;
parameter tHZ = 7.0;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 44.0;
parameter tRC = 66.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode (1 Clk + 7.5 ns)
parameter tWRp = 15.0; // A2 Version - Manual precharge mode (15 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
 
 
integer n;
 
task mem_fill;
input size;
 
integer size;
 
begin
for(n=0;n<size;n=n+1)
begin
Bank0[n] = $random;
Bank1[n] = $random;
Bank2[n] = $random;
Bank3[n] = $random;
end
 
end
endtask
 
 
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
 
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
 
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 2'b11) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 2'b11) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
/sdram_models/4Mx16/bank2.txt
0,0 → 1,50
64
65
66
67
68
69
6a
6b
6c
6d
6e
6f
70
71
72
73
74
75
76
77
78
79
7a
7b
7c
7d
7e
7f
80
81
82
83
84
85
86
87
88
89
8a
8b
8c
8d
8e
8f
90
91
92
93
94
95
/sdram_models/4Mx16/bank3.txt
0,0 → 1,50
96
97
98
99
9a
9b
9c
9d
9e
9f
a0
a1
a2
a3
a4
a5
a6
a7
a8
a9
aa
ab
ac
ad
ae
af
b0
b1
b2
b3
b4
b5
b6
b7
b8
b9
ba
bb
bc
bd
be
bf
c0
c1
c2
c3
c4
c5
c6
c7
/sdram_models/32Mx8/mt48lc32m8a2.v
0,0 → 1,980
/****************************************************************************************
*
* File Name: MT48LC32M8A2.V
* Version: 1.0a
* Date: August 4th, 2000
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC32M8A2 (8Meg x 8 x 4 Banks)
*
* Description: Micron 256Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" timescale
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 1.0a Son Huynh 208-368-3825 08/04/2000 - Improve alternate banks read/write
* Micron Technology Inc. access with auto precharge enable
*
* 0.0a Son Huynh 208-368-3825 04/29/1999 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc. - Simple testbench included
*
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc32m8a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 13; // 13 bits
parameter data_bits = 8; // 8 bits
parameter col_bits = 10; // 10 bits
parameter mem_sizes = 8388607; // 8 Mb
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -7E and CAS Latency = 2
parameter tAC = 5.4;
parameter tHZ = 5.4;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 37.0;
parameter tRC = 60.0;
parameter tRCD = 15.0;
parameter tRP = 15.0;
parameter tRRD = 14.0;
parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
parameter tWRp = 14.0; // A2 Version - Manual precharge mode (14 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
if (Cke == 1'b0 && (Data_in_enable == 1'b1 || Data_out_enable == 1'b1)) begin
$display ("at time %t ERROR: Illegal power down or self refresh. Please make sure data bus is idle.", $time);
end
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
 
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
 
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
 
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
 
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
 
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
 
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
 
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all banks", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all banks", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
if (Debug) $display ("at time %t NOTE : Precharge interrupt Write Bank %d.", $time, Bank);
if (Debug) $display ("at time %t NOTE : Make sure DQM is HIGH two cycles to meet tWR.", $time);
if (Debug) $display ("at time %t NOTE : We suggest to use Burst Terminate command instead.", $time);
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
 
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Read interrupt Read (terminate Read after CL-1)
if (Data_out_enable == 1'b1 && ((Cas_latency_2 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 1) ||
(Burst_length_4 == 1'b1 && Burst_counter < 3) ||
(Burst_length_8 == 1'b1 && Burst_counter < 7))) ||
(Cas_latency_3 == 1'b1 && ((Burst_length_4 == 1'b1 && Burst_counter < 2) ||
(Burst_length_8 == 1'b1 && Burst_counter < 6))))) begin
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
if (Dqm == 1'b0) begin
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq;
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
if (Dqm_reg0 == 1'b0) begin
if (Bank == 2'b00) Dq_reg = #tAC Bank0[{Row, Col}];
if (Bank == 2'b01) Dq_reg = #tAC Bank1[{Row, Col}];
if (Bank == 2'b10) Dq_reg = #tAC Bank2[{Row, Col}];
if (Bank == 2'b11) Dq_reg = #tAC Bank3[{Row, Col}];
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq_reg);
end else begin
Dq_reg = #tHZ {data_bits{1'bz}};
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -7E and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 7.5, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
/sdram_models/16Mx8/mt48lc16m8a2.v
0,0 → 1,980
/****************************************************************************************
*
* File Name: MT48LC16M8A2.V
* Version: 1.0a
* Date: August 4th, 2000
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC16M8A2 (4Meg x 8 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" timescale
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 1.0a Son Huynh 208-368-3825 08/04/2000 - Improve alternate banks read/write
* Micron Technology Inc. access with auto precharge enable
*
* 0.0a Son Huynh 208-368-3825 04/29/1999 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc. - Simple testbench included
*
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc16m8a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12; // 12 bits
parameter data_bits = 8; // 8 bits
parameter col_bits = 10; // 10 bits
parameter mem_sizes = 4194303; // 4 Mb
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -7E and CAS Latency = 2
parameter tAC = 5.4;
parameter tHZ = 5.4;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 37.0;
parameter tRC = 60.0;
parameter tRCD = 15.0;
parameter tRP = 15.0;
parameter tRRD = 14.0;
parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
parameter tWRp = 14.0; // A2 Version - Manual precharge mode (14 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
if (Cke == 1'b0 && (Data_in_enable == 1'b1 || Data_out_enable == 1'b1)) begin
$display ("at time %t ERROR: Illegal power down or self refresh. Please make sure data bus is idle.", $time);
end
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
 
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
 
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
 
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
 
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
 
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
 
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
 
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all banks", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all banks", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
if (Debug) $display ("at time %t NOTE : Precharge interrupt Write Bank %d.", $time, Bank);
if (Debug) $display ("at time %t NOTE : Make sure DQM is HIGH two cycles to meet tWR.", $time);
if (Debug) $display ("at time %t NOTE : We suggest to use Burst Terminate command instead.", $time);
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
 
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Read interrupt Read (terminate Read after CL-1)
if (Data_out_enable == 1'b1 && ((Cas_latency_2 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 1) ||
(Burst_length_4 == 1'b1 && Burst_counter < 3) ||
(Burst_length_8 == 1'b1 && Burst_counter < 7))) ||
(Cas_latency_3 == 1'b1 && ((Burst_length_4 == 1'b1 && Burst_counter < 2) ||
(Burst_length_8 == 1'b1 && Burst_counter < 6))))) begin
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
if (Dqm == 1'b0) begin
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq;
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
if (Dqm_reg0 == 1'b0) begin
if (Bank == 2'b00) Dq_reg = #tAC Bank0[{Row, Col}];
if (Bank == 2'b01) Dq_reg = #tAC Bank1[{Row, Col}];
if (Bank == 2'b10) Dq_reg = #tAC Bank2[{Row, Col}];
if (Bank == 2'b11) Dq_reg = #tAC Bank3[{Row, Col}];
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq_reg);
end else begin
Dq_reg = #tHZ {data_bits{1'bz}};
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -7E and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 7.5, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
/sdram_models/8Mx16/mt48lc8m16a2.v
0,0 → 1,901
/****************************************************************************************
*
* File Name: MT48LC8M16A2.V
* Version: 0.0f
* Date: July 8th, 1999
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.2e PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC8M16A2 (2Meg x 16 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc.
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc8m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12;
parameter data_bits = 16;
parameter col_bits = 9;
parameter mem_sizes = 2097151; // 2 Meg
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [1 : 0] Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
parameter tAC = 6.0;
parameter tHZ = 7.0;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 44.0;
parameter tRC = 66.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp = 15.0; // A2 Version - Precharge mode only (15 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_chk [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 0, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
end
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is not Precharged.", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is not Precharged.", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) ||
($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chk[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
// Interrupting a Write with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin
RW_interrupt_write[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
end
 
// Interrupting a Read with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin
RW_interrupt_read[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 2'b11) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chk [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 2'b11) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (WR_counter[0]) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
#tWRa; // Wait for tWR
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
end
always @ (WR_counter[1]) begin
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
#tWRa; // Wait for tWR
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
end
always @ (WR_counter[2]) begin
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
#tWRa; // Wait for tWR
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
end
always @ (WR_counter[3]) begin
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
#tWRa; // Wait for tWR
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
/sdram_models/8Mx8/mt48lc8m8a2.v
0,0 → 1,991
/****************************************************************************************
*
* File Name: MT48LC8M8A2.V
* Version: 0.0g
* Date: January 5th, 2000
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.3)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC8M8A2 (2Meg x 8 x 4 Banks)
*
* Description: Micron 64Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0g Son Huynh 208-368-3825 01/05/2000 - Change tRAS + tWR timing check
* Micron Technology Inc. - Change some error messages
*
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0e Son Huynh 208-368-3825 12/17/1998 - Fix new problem in 0.0d
* Micron Technology Inc.
*
* 0.0d Son Huynh 208-368-3825 12/11/1998 - Fix tWR check for WRITE
* Micron Technology Inc. - Fix Precharge pipeline for R/W
* - Fix R/W with Concurrent Auto Precharge
*
* 0.0c Son Huynh 208-368-3825 09/28/1998 - Fix DQM problem
* Micron Technology Inc. - Fix Interleave Burst Mode
*
* 0.0b Son Huynh 208-368-3825 05/19/1998 - Improve model functionalities
* Micron Technology Inc. - Add more timing check
*
* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release
* Micron Technology Inc. - Simple testbench included
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc8m8a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12;
parameter data_bits = 8;
parameter col_bits = 9;
parameter mem_sizes = 2097151;
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b0; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -7E and CAS Latency = 2
parameter tAC = 5.4;
parameter tHZ = 5.4;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 37.0;
parameter tRC = 60.0;
parameter tRCD = 15.0;
parameter tRP = 15.0;
parameter tRRD = 14.0;
parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
parameter tWRp = 14.0; // A2 Version - Manual precharge mode (14 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
 
 
 
integer n;
 
task mem_fill;
input size;
 
integer size;
 
begin
for(n=0;n<size;n=n+1)
begin
Bank0[n] = $random;
Bank1[n] = $random;
Bank2[n] = $random;
Bank3[n] = $random;
end
 
end
endtask
 
 
 
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
 
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
 
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
 
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
 
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
 
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
 
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
 
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
 
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
if (Dqm == 1'b0) begin
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq;
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
if (Dqm_reg0 == 1'b0) begin
if (Bank == 2'b00) Dq_reg = #tAC Bank0[{Row, Col}];
if (Bank == 2'b01) Dq_reg = #tAC Bank1[{Row, Col}];
if (Bank == 2'b10) Dq_reg = #tAC Bank2[{Row, Col}];
if (Bank == 2'b11) Dq_reg = #tAC Bank3[{Row, Col}];
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d", $time, Bank, Row, Col, Dq_reg);
end else begin
Dq_reg = #tHZ {data_bits{1'bz}};
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -7E and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
/sdram_models/8Mx8/bank0.txt
0,0 → 1,50
00
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12
13
14
15
16
17
18
19
1a
1b
1c
1d
1e
1f
20
21
22
23
24
25
26
27
28
29
2a
2b
2c
2d
2e
2f
30
31
/sdram_models/8Mx8/bank1.txt
0,0 → 1,50
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51
52
53
54
55
56
57
58
59
5a
5b
5c
5d
5e
5f
60
61
62
63
/sdram_models/8Mx8/bank2.txt
0,0 → 1,50
64
65
66
67
68
69
6a
6b
6c
6d
6e
6f
70
71
72
73
74
75
76
77
78
79
7a
7b
7c
7d
7e
7f
80
81
82
83
84
85
86
87
88
89
8a
8b
8c
8d
8e
8f
90
91
92
93
94
95
/sdram_models/8Mx8/bank3.txt
0,0 → 1,50
96
97
98
99
9a
9b
9c
9d
9e
9f
a0
a1
a2
a3
a4
a5
a6
a7
a8
a9
aa
ab
ac
ad
ae
af
b0
b1
b2
b3
b4
b5
b6
b7
b8
b9
ba
bb
bc
bd
be
bf
c0
c1
c2
c3
c4
c5
c6
c7
/sdram_models/2Mx32/mt48lc2m32b2.v
0,0 → 1,1006
/****************************************************************************************
*
* File Name: MT48LC2M32B2.V
* Version: 0.0g
* Date: January 12th, 2000
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.3 PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC2M32B2 (2Meg x 32 x 4 Banks)
*
* Description: Micron 64Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0g Son Huynh 208-368-3825 01/12/2000 - Change tRAS + tWR timing check
* Micron Technology Inc. - Change some error messages
*
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0e Son Huynh 208-368-3825 12/22/1998 - Fix tWR check for WRITE
* Micron Technology Inc. - Fix Precharge pipeline for R/W
* - Fix R/W with Concurrent Auto Precharge
*
* 0.0a Son Huynh 208-368-3825 09/16/1998 - First Release
* Micron Technology Inc. - Simple testbench included
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc2m32b2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 11;
parameter data_bits = 32;
parameter col_bits = 8;
parameter mem_sizes = 524287;
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [3 : 0] Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [3 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_1 = ~Mode_reg[6] & ~Mode_reg[5] & Mode_reg[4];
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b0; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
//Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -7 and CAS Latency = 3
parameter tAC = 5.5;
parameter tHZ = 5.5;
parameter tOH = 2.5;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 42.0;
parameter tRC = 70.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 14.0;
parameter tWRa = 7.0; // A2 Version - Auto precharge mode only (1 Clk + 7.0 ns)
parameter tWRp = 14.0; // A2 Version - Precharge mode only (14 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 0, " ns", 12);
// $readmemh("bank0.txt", Bank0);
// $readmemh("bank1.txt", Bank1);
// $readmemh("bank2.txt", Bank2);
// $readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
integer n;
 
task mem_fill;
input size;
 
integer size;
 
begin
for(n=0;n<size;n=n+1)
begin
Bank0[n] = $random;
Bank1[n] = $random;
Bank2[n] = $random;
Bank3[n] = $random;
end
 
end
endtask
 
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("%m at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("%m at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("%m at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("%m at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("%m at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b001)
$display (" CAS Latency = 1");
else if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("%m at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("%m at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("%m at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("%m at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("%m at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("%m at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("%m at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("%m at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("%m at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("%m at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("%m at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("%m at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("%m at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("%m at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("%m at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("%m at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("%m at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("%m at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("%m at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("%m at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("%m at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("%m at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("%m at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("%m at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("%m at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("%m at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("%m at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("%m at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("%m at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("%m at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
 
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
 
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end else if (Cas_latency_1 == 1'b1) begin
Command[0] = `PRECH;
Bank_precharge[0] = Ba;
A10_precharge[0] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end else if (Cas_latency_1 == 1'b1) begin
Command[0] = `BST;
end
if (Debug) $display ("%m at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("%m at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("%m at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("%m at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("%m at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("%m at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end else if (Cas_latency_1 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `READ_A;
end else begin
Command[0] = `READ;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("%m at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("%m at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [31 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [31 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [31 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [31 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
if (Dqm[2] == 1'b0) Dq_dqm [23 : 16] = Dq [23 : 16];
if (Dqm[3] == 1'b0) Dq_dqm [31 : 24] = Dq [31 : 24];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm;
// Output result
if (Dqm == 4'b1111) begin
if (Debug) $display("%m at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("%m at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %x, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array Buffer
if (Bank == 2'b00) Dq_dqm = Bank0[{Row, Col}];
if (Bank == 2'b01) Dq_dqm = Bank1[{Row, Col}];
if (Bank == 2'b10) Dq_dqm = Bank2[{Row, Col}];
if (Bank == 2'b11) Dq_dqm = Bank3[{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
if (Dqm_reg0[2] == 1'b1) Dq_dqm [23 : 16] = 8'bz;
if (Dqm_reg0[3] == 1'b1) Dq_dqm [31 : 24] = 8'bz;
// Display Result
Dq_reg [31 : 0] = #tAC Dq_dqm [31 : 0];
if (Dqm_reg0 == 4'b1111) begin
if (Debug) $display("%m at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("%m at time %t READ : Bank = %d Row = %d, Col = %d, Data = %x, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("%m at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -7 and CAS Latency = 3
specify
specparam
tAH = 1.00, // Addr, Ba Hold Time
tAS = 2.00, // Addr, Ba Setup Time
tCH = 2.75, // Clock High-Level Width
tCL = 2.75, // Clock Low-Level Width
tCK = 7.00, // Clock Cycle Time
tDH = 1.00, // Data-in Hold Time
tDS = 2.00, // Data-in Setup Time
tCKH = 1.00, // CKE Hold Time
tCKS = 2.00, // CKE Setup Time
tCMH = 1.00, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 2.00; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
/sdram_models/2Mx32/bank0.txt
0,0 → 1,50
00
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12
13
14
15
16
17
18
19
1a
1b
1c
1d
1e
1f
20
21
22
23
24
25
26
27
28
29
2a
2b
2c
2d
2e
2f
30
31
/sdram_models/2Mx32/bank1.txt
0,0 → 1,50
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51
52
53
54
55
56
57
58
59
5a
5b
5c
5d
5e
5f
60
61
62
63
/sdram_models/2Mx32/bank2.txt
0,0 → 1,50
64
65
66
67
68
69
6a
6b
6c
6d
6e
6f
70
71
72
73
74
75
76
77
78
79
7a
7b
7c
7d
7e
7f
80
81
82
83
84
85
86
87
88
89
8a
8b
8c
8d
8e
8f
90
91
92
93
94
95
/sdram_models/2Mx32/bank3.txt
0,0 → 1,50
96
97
98
99
9a
9b
9c
9d
9e
9f
a0
a1
a2
a3
a4
a5
a6
a7
a8
a9
aa
ab
ac
ad
ae
af
b0
b1
b2
b3
b4
b5
b6
b7
b8
b9
ba
bb
bc
bd
be
bf
c0
c1
c2
c3
c4
c5
c6
c7
/sdram_models/4Mx32/mt48lc4m32b2.v
0,0 → 1,1007
/****************************************************************************************
*
* File Name: MT48LC4M32B2.V
* Version: 1.0a
* Date: September 12th, 2000
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC4M32B2 (1Meg x 32 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 1.0a Son Huynh 208-368-3825 09/12/2000 - First Release from 64Mb SDR SDRAM
* Micron Technology Inc. - Improve R/W termination with AP
*
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc4m32b2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12;
parameter data_bits = 32;
parameter col_bits = 8;
parameter mem_sizes = 1048575;
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [3 : 0] Dqm;
 
reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];
reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];
 
reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline
reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline
reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline
reg [3 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
reg [1 : 0] RW_interrupt_bank; // RW interrupt Bank
time Count_time [0 : 3]; // RW AutoPrecharge (time after tWR = 1)
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk, RAS_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_1 = ~Mode_reg[6] & ~Mode_reg[5] & Mode_reg[4];
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
wire Debug = 1'b1; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
//Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define WRITE 4
`define WRITE_A 5
`define PRECH 6
`define A_REF 7
`define BST 8
`define LMR 9
 
// Timing Parameters for -6 and CAS Latency = 2
parameter tAC = 7.5;
parameter tHZ = 7.5;
parameter tOH = 2.0;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 42.0;
parameter tRC = 60.0;
parameter tRCD = 18.0;
parameter tRP = 18.0;
parameter tRRD = 12.0;
parameter tWRa = 6.0; // A2 Version - Auto precharge mode only (1 Clk + 6.0 ns)
parameter tWRp = 12.0; // A2 Version - Precharge mode only (12 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_time [0 : 3];
time WR_chkp [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chkp[0], WR_chkp[1], WR_chkp[2], WR_chkp[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{WR_time[0], WR_time[1], WR_time[2], WR_time[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 1, " ns", 12);
// $readmemh("bank0.txt", Bank0);
// $readmemh("bank1.txt", Bank1);
// $readmemh("bank2.txt", Bank2);
// $readmemh("bank3.txt", Bank3);
RAS_clk = 1'b0;
end
 
// RAS Clk for checking tWR
always RAS_clk = #0.5 ~RAS_clk;
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// Auto Precharge Timer for tWR
if (Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) begin
if (Count_precharge[0] == 1) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 1) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 1) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 1) begin
Count_time[3] = $time;
end
end else if (Burst_length_2 == 1'b1) begin
if (Count_precharge[0] == 2) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 2) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 2) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 2) begin
Count_time[3] = $time;
end
end else if (Burst_length_4 == 1'b1) begin
if (Count_precharge[0] == 4) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 4) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 4) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 4) begin
Count_time[3] = $time;
end
end else if (Burst_length_8 == 1'b1) begin
if (Count_precharge[0] == 8) begin
Count_time[0] = $time;
end
if (Count_precharge[1] == 8) begin
Count_time[1] = $time;
end
if (Count_precharge[2] == 8) begin
Count_time[2] = $time;
end
if (Count_precharge[3] == 8) begin
Count_time[3] = $time;
end
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b001)
$display (" CAS Latency = 1");
else if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
$display ("at time %t ERROR: Bank 0 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
$display ("at time %t ERROR: Bank 1 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
$display ("at time %t ERROR: Bank 2 is already Activated (not Precharged)", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
$display ("at time %t ERROR: Bank 3 is already Activated (not Precharged)", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
$display ("at time %t ERROR: tRAS violation during Precharge all banks", $time);
end
// tWR violation check for write
if (($time - WR_chkp[0] < tWRp) || ($time - WR_chkp[1] < tWRp) ||
($time - WR_chkp[2] < tWRp) || ($time - WR_chkp[3] < tWRp)) begin
$display ("at time %t ERROR: tWR violation during Precharge all banks", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chkp[Ba] < tWRp) begin
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
 
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
if (Debug) $display ("at time %t NOTE : Precharge interrupt Write Bank %d.", $time, Bank);
if (Debug) $display ("at time %t NOTE : Make sure DQM is HIGH two cycles to meet tWR.", $time);
if (Debug) $display ("at time %t NOTE : We suggest to use Burst Terminate command instead.", $time);
end
 
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `PRECH;
Bank_precharge[1] = Ba;
A10_precharge[1] = Addr[10];
end else if (Cas_latency_1 == 1'b1) begin
Command[0] = `PRECH;
Bank_precharge[0] = Ba;
A10_precharge[0] = Addr[10];
end
end
// Burst terminate
if (Burst_term == 1'b1) begin
// Terminate a Write Immediately
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
// Terminate a Read Depend on CAS Latency
if (Cas_latency_3 == 1'b1) begin
Command[2] = `BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `BST;
end else if (Cas_latency_1 == 1'b1) begin
Command[0] = `BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end else if (Cas_latency_1 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `READ_A;
end else begin
Command[0] = `READ;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Read interrupt Read (terminate Read after CL-1)
if (Data_out_enable == 1'b1 && ((Cas_latency_1 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 2) ||
(Burst_length_4 == 1'b1 && Burst_counter < 4) ||
(Burst_length_8 == 1'b1 && Burst_counter < 8))) ||
(Cas_latency_2 == 1'b1 && ((Burst_length_2 == 1'b1 && Burst_counter < 1) ||
(Burst_length_4 == 1'b1 && Burst_counter < 3) ||
(Burst_length_8 == 1'b1 && Burst_counter < 7))) ||
(Cas_latency_3 == 1'b1 && ((Burst_length_4 == 1'b1 && Burst_counter < 2) ||
(Burst_length_8 == 1'b1 && Burst_counter < 6))))) begin
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Read Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
// Interrupting a Write with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Write_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_write[RW_interrupt_bank] = 1'b1;
WR_time[RW_interrupt_bank] = $time;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Write Bank %d", $time, Ba, Bank);
end
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
// Interrupting a Read with Autoprecharge
if (Auto_precharge[RW_interrupt_bank] == 1'b1 && Read_precharge[RW_interrupt_bank] == 1'b1) begin
RW_interrupt_read[RW_interrupt_bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
else
if (Debug) $display ("at time %t NOTE : Write Bank %d interrupt Read Bank %d", $time, Ba, Bank);
end
end
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks
if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
end else if (Command[0] == `BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [31 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [31 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [31 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [31 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8];
if (Dqm[2] == 1'b0) Dq_dqm [23 : 16] = Dq [23 : 16];
if (Dqm[3] == 1'b0) Dq_dqm [31 : 24] = Dq [31 : 24];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm;
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm;
// Output result
if (Dqm == 4'b1111) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chkp [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array Buffer
if (Bank == 2'b00) Dq_dqm = Bank0[{Row, Col}];
if (Bank == 2'b01) Dq_dqm = Bank1[{Row, Col}];
if (Bank == 2'b10) Dq_dqm = Bank2[{Row, Col}];
if (Bank == 2'b11) Dq_dqm = Bank3[{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz;
if (Dqm_reg0[2] == 1'b1) Dq_dqm [23 : 16] = 8'bz;
if (Dqm_reg0[3] == 1'b1) Dq_dqm [31 : 24] = 8'bz;
// Display Result
Dq_reg [31 : 0] = #tAC Dq_dqm [31 : 0];
if (Dqm_reg0 == 4'b1111) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (RAS_clk) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1 && $time - Count_time[0] >= tWRa) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2 && $time - Count_time[0] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4 && $time - Count_time[0] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8 && $time - Count_time[0] >= tWRa))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 1 && $time - WR_time[0] >= tWRa)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1 && $time - Count_time[1] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2 && $time - Count_time[1] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4 && $time - Count_time[1] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8 && $time - Count_time[1] >= tWRa))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 1 && $time - WR_time[1] >= tWRa)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1 && $time - Count_time[2] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2 && $time - Count_time[2] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4 && $time - Count_time[2] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8 && $time - Count_time[2] >= tWRa))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 1 && $time - WR_time[2] >= tWRa)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1 && $time - Count_time[3] >= tWRa) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2 && $time - Count_time[3] >= tWRa) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4 && $time - Count_time[3] >= tWRa) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8 && $time - Count_time[3] >= tWRa))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 1 && $time - WR_time[3] >= tWRa)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -6 and CAS Latency = 2
specify
specparam
tAH = 1.00, // Addr, Ba Hold Time
tAS = 1.50, // Addr, Ba Setup Time
tCH = 2.50, // Clock High-Level Width
tCL = 2.50, // Clock Low-Level Width
tCK = 10.00, // Clock Cycle Time
tDH = 1.00, // Data-in Hold Time
tDS = 1.50, // Data-in Setup Time
tCKH = 1.00, // CKE Hold Time
tCKS = 1.50, // CKE Setup Time
tCMH = 1.00, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.50; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
/sync_cs_dev.v
0,0 → 1,125
/////////////////////////////////////////////////////////////////////
//// ////
//// Synchronous Chip Select Device Model ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: sync_cs_dev.v,v 1.1 2001-07-29 07:34:40 rudi Exp $
//
// $Date: 2001-07-29 07:34:40 $
// $Revision: 1.1 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2001/05/13 09:36:38 rudi
// Created Directory Structure
//
//
//
//
 
module sync_cs_dev(clk, addr, dq, cs_, we_, oe_, ack_ );
input clk;
input [15:0] addr;
inout [31:0] dq;
input cs_, we_, oe_;
output ack_;
 
reg [31:0] data_o;
reg [31:0] mem[0:1024];
wire rd, wr;
 
integer rd_del;
reg [31:0] rd_r;
wire rd_d;
 
integer wr_del;
reg [31:0] wr_r;
wire wr_d;
 
integer ack_del;
reg [31:0] ack_r;
wire ack_d;
 
initial ack_del = 2;
initial rd_del = 7;
initial wr_del = 3;
 
task mem_fill;
 
integer n;
 
begin
 
for(n=0;n<1024;n=n+1)
mem[n] = $random;
 
end
endtask
 
 
assign dq = rd_d ? data_o : 32'hzzzz_zzzz;
 
assign rd = ~cs_ & we_ & ~oe_;
assign wr = ~cs_ & ~we_;
 
always @(posedge clk)
if(~rd) rd_r <= #1 0;
else rd_r <= #1 {rd_r[30:0], rd};
assign rd_d = rd_r[rd_del] & rd;
 
always @(posedge clk)
if(~wr) wr_r <= #1 0;
else wr_r <= #1 {wr_r[30:0], wr};
assign wr_d = wr_r[wr_del] & wr;
 
always @(posedge clk)
data_o <= #1 mem[addr[9:0]];
 
always @(posedge clk)
if(wr_d) mem[addr[9:0]] <= #1 dq;
 
assign ack_d = rd | wr;
always @(posedge clk)
if(~rd & ~wr) ack_r <= #1 0;
else ack_r <= #1 {ack_r[30:0], ack_d};
 
assign ack_ = ack_r[ack_del] & ack_d;
 
endmodule
/wb_model_defines.v
0,0 → 1,58
/////////////////////////////////////////////////////////////////////
//// ////
//// WISHBONE Model Definitions ////
//// ////
//// ////
//// Author: Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// ////
//// Downloaded from: http://www.opencores.org/cores/mem_ctrl/ ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2000 Rudolf Usselmann ////
//// rudi@asics.ws ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
 
// CVS Log
//
// $Id: wb_model_defines.v,v 1.1 2001-07-29 07:34:40 rudi Exp $
//
// $Date: 2001-07-29 07:34:40 $
// $Revision: 1.1 $
// $Author: rudi $
// $Locker: $
// $State: Exp $
//
// Change History:
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1 2001/05/13 09:36:32 rudi
// Created Directory Structure
//
//
//
//
//
 
`timescale 1ns / 10ps

powered by: WebSVN 2.1.0

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