/**************************************************************************************** * * File Name: tb.v * * Dependencies: ddr2.v, ddr2_parameters.vh * * Description: Micron SDRAM DDR2 (Double Data Rate 2) test bench * * Note: -Set simulator resolution to "ps" accuracy * -Set Debug = 0 to disable $display messages * * Disclaimer This software code and all associated documentation, comments or other * of Warranty: information (collectively "Software") is provided "AS IS" without * warranty of any kind. MICRON TECHNOLOGY, INC. ("MTI") EXPRESSLY * DISCLAIMS ALL WARRANTIES EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO, NONINFRINGEMENT OF THIRD PARTY RIGHTS, AND ANY IMPLIED WARRANTIES * OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. MTI DOES NOT * WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OR THAT THE * OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE. * FURTHERMORE, MTI DOES NOT MAKE ANY REPRESENTATIONS REGARDING THE USE OR * THE RESULTS OF THE USE OF THE SOFTWARE IN TERMS OF ITS CORRECTNESS, * ACCURACY, RELIABILITY, OR OTHERWISE. THE ENTIRE RISK ARISING OUT OF USE * OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU. IN NO EVENT SHALL MTI, * ITS AFFILIATED COMPANIES OR THEIR SUPPLIERS BE LIABLE FOR ANY DIRECT, * INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR SPECIAL DAMAGES (INCLUDING, * WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, * OR LOSS OF INFORMATION) ARISING OUT OF YOUR USE OF OR INABILITY TO USE * THE SOFTWARE, EVEN IF MTI HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. Because some jurisdictions prohibit the exclusion or * limitation of liability for consequential or incidental damages, the * above limitation may not apply to you. * * Copyright 2003 Micron Technology, Inc. All rights reserved. * ****************************************************************************************/ // DO NOT CHANGE THE TIMESCALE `timescale 1ps / 1ps module tb; `include "ddr2_parameters.vh" // ports reg ck; wire ck_n = ~ck; reg cke; reg cs_n; reg ras_n; reg cas_n; reg we_n; reg [BA_BITS-1:0] ba; reg [ADDR_BITS-1:0] a; wire [DM_BITS-1:0] dm; wire [DQ_BITS-1:0] dq; wire [DQS_BITS-1:0] dqs; wire [DQS_BITS-1:0] dqs_n; wire [DQS_BITS-1:0] rdqs_n; reg odt; // mode registers reg [ADDR_BITS-1:0] mode_reg0; //Mode Register reg [ADDR_BITS-1:0] mode_reg1; //Extended Mode Register wire [2:0] cl = mode_reg0[6:4]; //CAS Latency wire bo = mode_reg0[3]; //Burst Order wire [7:0] bl = (1< $rtoi(number)) ceil = $rtoi(number) + 1; else ceil = number; endfunction function integer max; input arg1; input arg2; integer arg1; integer arg2; if (arg1 > arg2) max = arg1; else max = arg2; endfunction task power_up; begin cke <= 1'b0; odt <= 1'b0; repeat(10) @(negedge ck); cke <= 1'b1; nop (400000/tck+1); end endtask task load_mode; input [BA_BITS-1:0] bank; input [ADDR_BITS-1:0] addr; begin case (bank) 0: mode_reg0 = addr; 1: mode_reg1 = addr; endcase cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b0; cas_n <= 1'b0; we_n <= 1'b0; ba <= bank; a <= addr; @(negedge ck); end endtask task refresh; begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b0; cas_n <= 1'b0; we_n <= 1'b1; @(negedge ck); end endtask task precharge; input [BA_BITS-1:0] bank; input ap; //precharge all begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b0; cas_n <= 1'b1; we_n <= 1'b0; ba <= bank; a <= (ap<<10); @(negedge ck); end endtask task activate; input [BA_BITS-1:0] bank; input [ROW_BITS-1:0] row; begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b0; cas_n <= 1'b1; we_n <= 1'b1; ba <= bank; a <= row; @(negedge ck); end endtask //write task supports burst lengths <= 8 task write; input [BA_BITS-1:0] bank; input [COL_BITS-1:0] col; input ap; //Auto Precharge input [8*DM_BITS-1:0] dm; input [8*DQ_BITS-1:0] dq; reg [ADDR_BITS-1:0] atemp [1:0]; integer i; begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b1; cas_n <= 1'b0; we_n <= 1'b0; ba <= bank; atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] a <= atemp[0] | atemp[1] | (ap<<10); for (i=0; i<=bl; i=i+1) begin dqs_en <= #(wl*tck + i*tck/2) 1'b1; if (i%2 == 0) begin dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b0}}; end else begin dqs_out <= #(wl*tck + i*tck/2) {DQS_BITS{1'b1}}; end dq_en <= #(wl*tck + i*tck/2 + tck/4) 1'b1; dm_out <= #(wl*tck + i*tck/2 + tck/4) dm>>i*DM_BITS; dq_out <= #(wl*tck + i*tck/2 + tck/4) dq>>i*DQ_BITS; end dqs_en <= #(wl*tck + bl*tck/2 + tck/2) 1'b0; dq_en <= #(wl*tck + bl*tck/2 + tck/4) 1'b0; @(negedge ck); end endtask // read without data verification task read; input [BA_BITS-1:0] bank; input [COL_BITS-1:0] col; input ap; //Auto Precharge reg [ADDR_BITS-1:0] atemp [1:0]; begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b1; cas_n <= 1'b0; we_n <= 1'b1; ba <= bank; atemp[0] = col & 10'h3ff; //addr[ 9: 0] = COL[ 9: 0] atemp[1] = (col>>10)<<11; //addr[ N:11] = COL[ N:10] a <= atemp[0] | atemp[1] | (ap<<10); @(negedge ck); end endtask task nop; input [31:0] count; begin cke <= 1'b1; cs_n <= 1'b0; ras_n <= 1'b1; cas_n <= 1'b1; we_n <= 1'b1; repeat(count) @(negedge ck); end endtask task deselect; input [31:0] count; begin cke <= 1'b1; cs_n <= 1'b1; ras_n <= 1'b1; cas_n <= 1'b1; we_n <= 1'b1; repeat(count) @(negedge ck); end endtask task power_down; input [31:0] count; begin cke <= 1'b0; cs_n <= 1'b1; ras_n <= 1'b1; cas_n <= 1'b1; we_n <= 1'b1; repeat(count) @(negedge ck); end endtask task self_refresh; input [31:0] count; begin cke <= 1'b0; cs_n <= 1'b0; ras_n <= 1'b0; cas_n <= 1'b0; we_n <= 1'b1; cs_n <= #(tck) 1'b1; ras_n <= #(tck) 1'b1; cas_n <= #(tck) 1'b1; we_n <= #(tck) 1'b1; repeat(count) @(negedge ck); end endtask // read with data verification task read_verify; input [BA_BITS-1:0] bank; input [COL_BITS-1:0] col; input ap; //Auto Precharge input [8*DM_BITS-1:0] dm; //Expected Data Mask input [8*DQ_BITS-1:0] dq; //Expected Data integer i; begin read (bank, col, ap); for (i=0; i> (i*DM_BITS); dq_fifo[2*rl + i] = dq >> (i*DQ_BITS); end end endtask // receiver(s) for data_verify process dqrx dqrx[DQS_BITS-1:0] (dqs, dq, q0, q1, q2, q3); // perform data verification as a result of read_verify task call always @(ck) begin:data_verify integer i; integer j; reg [DQ_BITS-1:0] bit_mask; reg [DM_BITS-1:0] dm_temp; reg [DQ_BITS-1:0] dq_temp; for (i = !ck; (i < 2/(2.0 - !ck)); i=i+1) begin if (dm_fifo[i] === {DM_BITS{1'bx}}) begin burst_cntr = 0; end else begin dm_temp = dm_fifo[i]; for (j=0; j