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 |