/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
/****************************************************************************
* 64-bit DRAM module
***************************************************************************/
module RAM64
( mem_size, b_memdata, b_mempar,
memaddr, ras_l, cas_l, moe_l, mwe_l, ram_output, simm32_sel
);
output [63:00] mem_size
; /* Return `SIZE to top module as 63-bit.*/
output ram_output
; // ram output enable signal for tri-state driver check
inout [63:00] b_memdata
; // 64-bit bi-dir data bus
inout [01:00] b_mempar
; // 2-bit bi-dir parity bus
input [10:00] memaddr
;
input [07:00] ras_l
;
input [03:00] cas_l
;
input moe_l
;
input mwe_l
;
input simm32_sel
;
wire [63:00] FPM_mem_size
;
wire [63:00] EDO_mem_size
;
wire FPM_ram_output
;
wire EDO_ram_output
;
wire [63:00] FPM_rd_data
;
wire [63:00] EDO_rd_data
;
wire [01:00] FPM_rd_par
;
tri [01:00] EDO_rd_par_tmp
; //rdv
tri [01:00] FPM_rd_par_tmp
; //rdv
wire par_addr_ok
; //rdv
wire [01:00] EDO_rd_par
;
wire [63:00] BOTH_wr_data
;
wire [01:00] BOTH_wr_par
;
wire [07:00] FPM_ras_l
;
wire [07:00] EDO_ras_l
;
wire [03:00] FPM_cas_l
;
wire [03:00] EDO_cas_l
;
wire [10:00] FPM_memaddr
;
wire [10:00] EDO_memaddr
;
wire FPM_moe_l
;
wire EDO_moe_l
;
wire FPM_mwe_l
;
wire EDO_mwe_l
;
integer memHandle
, parHandle
;
/****************************************************************************
* Init sparse memory model
*
* In sunergy, the vfront command 'start_test', among other things, changes
* the current working directory and sets the signal '.new_working_dir'.
* this triggers the following task which frees up any previously allocated
* sparse memory data structures and sets up the new ones.
*
***************************************************************************/
//Add parity testing hooks (via run -testpar option) -rdv
reg testpar
;
initial begin
$GetEnv("testpar",testpar);
end
always @Mclocks.new_working_dir sparse_mem_init ;
task sparse_mem_init;
begin
$mm_mem_cfree ();
memHandle = $mem_setup();
$display("doing $mem_setup()...memHandle: %g", memHandle);
parHandle = $mem_setup();
$display("doing $mem_setup()...parHandle: %g", parHandle);
end
endtask
RAM RamWord1 ( FPM_mem_size, , , FPM_rd_data, BOTH_wr_data, FPM_rd_par, BOTH_wr_par,
FPM_memaddr, FPM_ras_l, FPM_cas_l, FPM_moe_l, FPM_mwe_l, FPM_ram_output,
simm32_sel);
EDO_DRAM RamWord2 (EDO_mem_size, EDO_rd_data, BOTH_wr_data, EDO_rd_par, BOTH_wr_par,
EDO_memaddr, EDO_ras_l, EDO_cas_l, EDO_moe_l, EDO_mwe_l, EDO_ram_output);
assign mem_size = (simm32_sel) ? EDO_mem_size : FPM_mem_size;
assign ram_output = (simm32_sel) ? EDO_ram_output : FPM_ram_output;
assign b_memdata = (simm32_sel) ? EDO_rd_data : FPM_rd_data;
//add par_addr_ok flag (must use with run -testpar switch
//with PA[31:4]=F400000x to cause parity error) -rdv
assign par_addr_ok = ram_output ? (simm32_sel ?
(RamWord2.Addr[27:4]==24'h400000) :
(RamWord1.Addr[27:4]==24'h400000)) : 1'b0 ;
//add testpar mux (must use with run -testpar switch
//with PA[31:4]=F400000x to cause parity error) -rdv
assign EDO_rd_par_tmp = (testpar & par_addr_ok) ? ~EDO_rd_par : EDO_rd_par;
assign FPM_rd_par_tmp = (testpar & par_addr_ok) ? ~FPM_rd_par : FPM_rd_par;
//assign b_mempar = (simm32_sel) ? EDO_rd_par : FPM_rd_par;
assign b_mempar = (simm32_sel) ? EDO_rd_par_tmp : FPM_rd_par_tmp;
assign BOTH_wr_data = b_memdata;
assign BOTH_wr_par = b_mempar;
assign FPM_ras_l = (simm32_sel) ? 1 : ras_l;
assign EDO_ras_l = (simm32_sel) ? ras_l : 1;
assign FPM_cas_l = (simm32_sel) ? 1 : cas_l;
assign EDO_cas_l = (simm32_sel) ? cas_l : 1;
assign FPM_memaddr = (simm32_sel) ? 11'b0 : memaddr;
assign EDO_memaddr = (simm32_sel) ? memaddr : 11'b0;
assign FPM_moe_l = (simm32_sel) ? 1 : moe_l;
assign EDO_moe_l = (simm32_sel) ? moe_l : 1;
assign FPM_mwe_l = (simm32_sel) ? 1 : mwe_l;
assign EDO_mwe_l = (simm32_sel) ? mwe_l : 1;
endmodule
/*=======================================================================*/
`define tRC 110 // random read or write cycle time
`define tRAC 75 // Access time from RAS
`define tCAC 30 // Access time from CAS
`define tAA 45 // Access time from column address
// tCEZ monitors not required,because RAS turns off after CAS tREZ is the
// data turn off parameter.
`define tCEZ_MIN 15 // Output buffer turn off delay from CAS
`define tCEZ_MAX 30 // Output buffer turn off delay from CAS
`define tT_MIN 2 // CHECK Transition time (rise and fall)
`define tT_MAX 50 // CHECK Transition time (rise and fall)
`define tRP 40 // RAS precharge time
`define tRAS_MIN 60 // RAS pulse width
`define tRAS_MAX 10000 // RAS pulse width
`define tRSH 17 // RAS hold time
`define tCSH 50 // CAS hold time
`define tCAS_MIN 10 // CAS pulse width
`define tCAS_MAX 10000 // CAS pulse width
`define tRCD_MIN 20 // RAS to CAS delay time
`define tRCD_MAX 45 // RAS to CAS delay time
`define tRAD_MIN 15 // RAS to column address delay time
`define tRAD_MAX 30 // RAS to column address delay time
`define tCRP 5 // CAS to RAS precharge time
`define tASR 0 // Row address set up time
`define tRAH 10 // Row address hold time
`define tASC 0 // Column address set up time
`define tCAH 10 // Column address hold time
`define tRAL 30 // Column address to RAS lead time
`define tRCS 5 // Read command set_up time
`define tRCH 5 // Read command hold time referenced to CAS
`define tRRH 5 // Read command hold time referenced to RAS
`define tWCH 10 // Write command hold time
`define tWP 10 // Write command pulse width
`define tRWL 15 // Write command to RAS lead time
`define tCWL 10 // Write command to CAS lead time
`define tDS 0 // Data set_up time
`define tDH 10 // Data hold time
`define tREF_MAX 64 // CHECK Refresh period
`define tWCS 0 // Write command set up time
`define tCPWD 60 // CHECK CAS precharge to W delay time
`define tCSR 10 // CAS set up time (CAS_Before_RAS refresh)
`define tCHR 10 // CAS hold time (CAS_Before_RAS refresh)
`define tRPC 5 // ADD MONITOR RAS to CAS precharge time
`define tCPA 39 // Access time from CAS precharge
`define tHPC 25 // same as tPC of Micron data sheet Hyper page cycle time
`define tCP 10 // CAS precharge time (Hyper page cycle)
`define tRASP_MAX 100000 // RAS pulse width (Hyper page cycle)
`define tRASP_MIN 60 // RAS pulse width (Hyper page cycle)
`define tRHCP 35 // ADD to EDO.SIMM.v {tCP + tRSH} RAS hold time from CAS precharge
`define tOED 15 // OE to data delay
`define tOEH 15 // OE command hold time
`define tWRP 10 // W to RAS precharge time
`define tWRH 10 // W to RAS hold time (C-B-R refresh)
`define tDOH 9 // same as tCOH of Micron data sheet Output data hold time
`define tREZ_MIN 18 // same as tOFF Output buffer turn off delay from RAS
`define tREZ_MAX 30 // same as tOFF Output buffer turn off delay from RAS
`define tOEP 5 // OE precharge time
`define tWEZ_MIN 0 // only for read/write mixed cycle Output buffer turn off delay from W
`define tWEZ_MAX 15 // only for read/write mixed cycle Output buffer turn off delay from W
`define tOCH 5 // OE to CAS hold time
`define tCHO 5 // CAS hold time to OE
`define tWPE 10 // applicable only for read/write mixed cycle W pulse width (Hyper Page cycle
`define tOEA 30 // OE is permanently tied to gnd OE access time
`define tOEZ_MAX 30 // OE is permanently tied to gnd Output buffer turn off delay time from OE
`define tOEZ_MIN 15 // OE is permanently tied to gnd Output buffer turn off delay time from OE
`define tCWD 40 // since we don't do rmw at dram CAS to W delay time
`define tRWD 85 // since we don't do rmw at dram RAS to W delay time
`define tAWD 55 // since we don't do rmw at dram Column address to W delay time
`define tCLZ 0 // CAS to output in Low-z
`define tOLZ 0 // OE to output in Low-z
`define tHPRWC 79 // Hyper page mode read-modify-write cycle time, not required
`define tRWC 155 // read-modify-write cycle time, not required because
// we don't do rmw at dram
// From Micron's data sheet
//`define tACH 15
//`define tCHD 10
//`define tDHR 45
//`define tORD 0
//`define tPRWC 75
//`define tRASS 100
//`define tREFs 128
//`define tREF 32
//`define tRPS 110
//`define tWCR 45
//`define tWPZ 10
/***************************************************************************
* File name: EDO_DRAM.v
*
* Description: Eagel dram model
*
* based on Sabre SIMM model
*
***************************************************************************/
module EDO_DRAM
(EDO_mem_size, EDO_rd_data, EDO_wr_data, EDO_rd_par, EDO_wr_par, EDO_memaddr, EDO_ras_l, EDO_cas_l, EDO_moe_l, EDO_mwe_l, EDO_ram_output);
//`include "quit.h"
//`include "monitor.h"
output EDO_mem_size
;
output EDO_ram_output
;
output [63:00] EDO_rd_data
;
output [01:00] EDO_rd_par
;
input [63:00] EDO_wr_data
;
input [01:00] EDO_wr_par
;
input [10:00] EDO_memaddr
;
input [07:00] EDO_ras_l
;
input [03:00] EDO_cas_l
;
input EDO_moe_l
;
input EDO_mwe_l
;
`define ASSERTED 1
`define NEGATED 0
wire [3:0] rasb_l
;
wire [3:0] rast_l
;
wire [63:00] EDO_mem_size;
reg EDO_ram_output;
parameter RAM_DELAY_EDO = 25;
integer ParUpdateFlag
;
assign rasb_l = { EDO_ras_l[6], EDO_ras_l[4], EDO_ras_l[2], EDO_ras_l[0] }; // Used for even bank YS
assign rast_l = { EDO_ras_l[7], EDO_ras_l[5], EDO_ras_l[3], EDO_ras_l[1] }; // Used for odd bank YS
assign EDO_mem_size = 64'b0;
reg mem_trace
; // enable or disable mem traces
reg [31:0] mem_mcd
; // file descriptor for mem trace
reg [27:03] Addr
; // used for forming the address.
reg [32:00] Index
; // 33 bits for sparse memory requirement
reg address_done
;
reg [31:0] full_address
;
reg [31:0] full_address2
;
//----------------------------------------
task gen_full_addrs;
input [31:0] row;
input [31:0] colm;
output [31:0] faddrs;
reg [31:0] ffaddrs;
begin
ffaddrs = 32'b0;
begin
{ffaddrs[24], ffaddrs[22], ffaddrs[20:12]} = row[10:0];
{ffaddrs[23], ffaddrs[21], ffaddrs[11:03]} = colm[10:0];
end
faddrs = ffaddrs;
end
endtask
initial begin
address_done = 1'b0;
ParUpdateFlag = `NEGATED ;
EDO_ram_output = 1'b0 ;
$display ("\nModule EDO_dram.v - RAM initial block\n");
mem_trace = 0;
// Wait for working dir, etc., to be initialized before opening
// the trace file.
#1;
mem_mcd = $fopen({Mclocks.working_dir,"/mem_trace.v"});
if (!mem_mcd)
$display ("EDO_dram: unable to open 'mem_trace.v'");
end
// When is the time to read.
always @(posedge simm0.start_read)
begin
full_address = 32'b0;
gen_full_addrs(simm0.row_addrs, simm0.colm_addrs, full_address);
if ((rasb_l[0] == 1'b0) && (rast_l[0] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[0] and rast_l[0] can't be asserted at the same time.\n");
end
if (rasb_l[0] == 1'b0)
full_address[27:25] = 3'b000;
if (rast_l[0] == 1'b0)
full_address[27:25] = 3'b001;
Index = {7'b0, full_address[27:03]};
Addr[27:03] = full_address[27:03];
$display("\nDRAM INFO: Read, Addrs=%h\n", full_address);
$mem_read(Msystem.TheRam.memHandle, Index, 8'b11111111, simm0.rd_data);
$mem_read(Msystem.TheRam.parHandle, Index, 8'b00000011, simm0.rd_parity);
$display("\nDRAM INFO:data Read=%h[%h]\n", simm0.rd_data, simm0.rd_parity);
ParUpdateFlag = `NEGATED;
if (simm0.rd_parity[1] == 1'b0) begin
simm0.rd_parity[1] = 1'b1;
simm0.rd_parity[0] = ^simm0.rd_data[31:0];
ParUpdateFlag = `ASSERTED;
end
if (simm0.rd_parity[9] == 1'b0) begin
simm0.rd_parity[9] = 1'b1;
simm0.rd_parity[8] = ^simm0.rd_data[63:32];
ParUpdateFlag = `ASSERTED;
end
if (ParUpdateFlag == `ASSERTED) begin
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000011, simm0.rd_parity);
end
address_done = 1'b1;
`ifdef DEBUG
$display("TIME=%t, SIMM0, Full address=%h, Data0=%h\n",$stime, full_address, simm0.rd_data);
$display("============================================\n");
`endif
simm0.start_read <= #1 1'b0; // Reset for next time.
simm0.tAA_met <= #1 0;
simm0.tAA_done <= #1 1;
simm0.tCPA_met <= #1 0;
simm0.tCAC_met <= #1 0;
simm0.cac_met <= #1 0;
simm0.cpa_met <= #1 0;
simm0.colm_addrs = 32'hFFFF;
address_done <= #1 1'b0;
end
// When is the time to read.
always @(posedge simm1.start_read)
begin
full_address = 32'b0;
gen_full_addrs(simm1.row_addrs, simm1.colm_addrs, full_address);
if ((rasb_l[1] == 1'b0) && (rast_l[1] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[1] and rast_l[1] can't be asserted at the same time.\n");
end
if (rasb_l[1] == 1'b0)
full_address[27:25] = 3'b010;
if (rast_l[1] == 1'b0)
full_address[27:25] = 3'b011;
Index = {7'b0, full_address[27:03]};
Addr[27:03] = full_address[27:03];
$display("\nDRAM INFO: Read, Addrs=%h\n", full_address);
$mem_read(Msystem.TheRam.memHandle, Index, 8'b11111111, simm1.rd_data);
$mem_read(Msystem.TheRam.parHandle, Index, 8'b00000011, simm1.rd_parity);
$display("\nDRAM INFO:data Read=%h[%h]\n", simm1.rd_data, simm1.rd_parity);
ParUpdateFlag = `NEGATED;
if (simm1.rd_parity[1] == 1'b0) begin
simm1.rd_parity[1] = 1'b1;
simm1.rd_parity[0] = ^simm1.rd_data[31:0];
ParUpdateFlag = `ASSERTED;
end
if (simm1.rd_parity[9] == 1'b0) begin
simm1.rd_parity[9] = 1'b1;
simm1.rd_parity[8] = ^simm1.rd_data[63:32];
ParUpdateFlag = `ASSERTED;
end
if (ParUpdateFlag == `ASSERTED) begin
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000011, simm1.rd_parity);
end
address_done = 1'b1;
$display("\nDRAM INFO:data Read=%h[%h]\n", simm1.rd_data, simm1.rd_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM2, Full address=%h, Data0=%h\n",$stime, full_address, simm1.rd_data);
$display("============================================\n");
`endif
simm1.start_read <= #1 1'b0; // Reset for next time.
simm1.tAA_met <= #1 0;
simm1.tAA_done <= #1 1;
simm1.tCPA_met <= #1 0;
simm1.tCAC_met <= #1 0;
simm1.cac_met <= #1 0;
simm1.cpa_met <= #1 0;
simm1.colm_addrs = 32'hFFFF;
address_done <= #1 1'b0;
end
// When is the time to read.
always @(posedge simm2.start_read)
begin
full_address = 32'b0;
gen_full_addrs(simm2.row_addrs, simm2.colm_addrs, full_address);
if ((rasb_l[2] == 1'b0) && (rast_l[2] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[2] and rast_l[2] can't be asserted at the same time.\n");
end
if (rasb_l[2] == 1'b0)
full_address[27:25] = 3'b100;
if (rast_l[2] == 1'b0)
full_address[27:25] = 3'b101;
$display("\nDRAM INFO: Read, Addrs=%h\n", full_address);
Index = {7'b0, full_address[27:03]};
Addr[27:03] = full_address[27:03];
$mem_read(Msystem.TheRam.memHandle, Index, 8'b11111111, simm2.rd_data);
$mem_read(Msystem.TheRam.parHandle, Index, 8'b00000011, simm2.rd_parity);
$display("\nDRAM INFO:data Read=%h[%h]\n", simm2.rd_data, simm2.rd_parity);
ParUpdateFlag = `NEGATED;
if (simm2.rd_parity[1] == 1'b0) begin
simm2.rd_parity[1] = 1'b1;
simm2.rd_parity[0] = ^simm2.rd_data[31:0];
ParUpdateFlag = `ASSERTED;
end
if (simm2.rd_parity[9] == 1'b0) begin
simm2.rd_parity[9] = 1'b1;
simm2.rd_parity[8] = ^simm2.rd_data[63:32];
ParUpdateFlag = `ASSERTED;
end
if (ParUpdateFlag == `ASSERTED) begin
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000011, simm2.rd_parity);
end
address_done = 1'b1;
$display("\nDRAM INFO:data Read=%h[%h]\n", simm2.rd_data, simm2.rd_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM4, Full address=%h, Data0=%h\n",$stime, full_address, simm2.rd_data);
$display("============================================\n");
`endif
simm2.start_read <= #1 1'b0; // Reset for next time.
simm2.tAA_met <= #1 0;
simm2.tAA_done <= #1 1;
simm2.tCPA_met <= #1 0;
simm2.tCAC_met <= #1 0;
simm2.cac_met <= #1 0;
simm2.cpa_met <= #1 0;
simm2.colm_addrs = 32'hFFFF;
address_done <= #1 1'b0;
end
// When is the time to read.
always @(posedge simm3.start_read)
begin
full_address = 32'b0;
gen_full_addrs(simm3.row_addrs, simm3.colm_addrs, full_address);
if ((rasb_l[3] == 1'b0) && (rast_l[3] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[3] and rast_l[3] can't be asserted at the same time.\n");
end
if (rasb_l[3] == 1'b0)
full_address[27:25] = 3'b110;
if (rast_l[3] == 1'b0)
full_address[27:25] = 3'b111;
Index = {7'b0, full_address[27:03]};
Addr[27:03] = full_address[27:03];
$mem_read(Msystem.TheRam.memHandle, Index, 8'b11111111, simm3.rd_data);
$mem_read(Msystem.TheRam.parHandle, Index, 8'b00000011, simm3.rd_parity);
$display("\nDRAM INFO:data Read=%h[%h]\n", simm3.rd_data, simm3.rd_parity);
ParUpdateFlag = `NEGATED;
if (simm3.rd_parity[1] == 1'b0) begin
simm3.rd_parity[1] = 1'b1;
simm3.rd_parity[0] = ^simm3.rd_data[31:0];
ParUpdateFlag = `ASSERTED;
end
if (simm3.rd_parity[9] == 1'b0) begin
simm3.rd_parity[9] = 1'b1;
simm3.rd_parity[8] = ^simm3.rd_data[63:32];
ParUpdateFlag = `ASSERTED;
end
if (ParUpdateFlag == `ASSERTED) begin
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000011, simm3.rd_parity);
end
address_done = 1'b1;
`ifdef DEBUG
$display("TIME=%t, SIMM6, Full address=%h, Data0=%h\n",$stime, full_address, simm6.rd_data);
$display("============================================\n");
`endif
simm3.start_read <= #1 1'b0; // Reset for next time.
simm3.tAA_met <= #1 0;
simm3.tAA_done <= #1 1;
simm3.tCPA_met <= #1 0;
simm3.tCAC_met <= #1 0;
simm3.cac_met <= #1 0;
simm3.cpa_met <= #1 0;
simm3.colm_addrs = 32'hFFFF;
address_done <= #1 1'b0;
end
// Start writes now.
always @(posedge simm0.start_write)
begin
full_address2 = 32'b0;
gen_full_addrs(simm0.row_addr, simm0.colm_addrs, full_address2);
if ((rasb_l[0] == 1'b0) && (rast_l[0] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[0]&rast_l[0] can't be asserted at the same time.\n");
end
if (rasb_l[0] == 1'b0)
full_address2[27:25] = 3'b000;
if (rast_l[0] == 1'b0)
full_address2[27:25] = 3'b001;
Index = {7'b0, full_address2[27:03]};
Addr[27:03] = full_address2[27:03];
if ((EDO_cas_l[0] === 1'b0 ) || (EDO_cas_l[2] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b11110000, simm0.wr_data);
mem_dump(full_address2[27:03],simm0.wr_data[63:32],0);
simm0.wr_parity[9] = 1'b1; // valid bit for bank 0 (63:32) is 9
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000010, simm0.wr_parity);
end
if ((EDO_cas_l[1] === 1'b0)|| (EDO_cas_l[3] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b00001111, simm0.wr_data);
mem_dump(full_address2[27:03],simm0.wr_data[31:0],1);
simm0.wr_parity[1] = 1'b1; // valid bit for bank 1 (31:0) is 1
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000001, simm0.wr_parity);
end
$display("\nDRAM INFO:Write DATA=%h[%h]\n", simm0.wr_data, simm0.wr_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM0, Write, Full addr=%h, data0=%h\n",$stime,full_address2, simm0.wr_data);
$display("============================================\n");
`endif
simm0.start_write <= #1 1'b0;
simm0.colm_addrs = 32'hFFFF;
end
always @(posedge simm1.start_write)
begin
full_address2 = 32'b0;
gen_full_addrs(simm1.row_addr, simm1.colm_addrs, full_address2);
if ((rasb_l[1] == 1'b0) && (rast_l[1] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[1]&rast_l[1] can't be asserted at the same time.\n");
end
if (rasb_l[1] == 1'b0)
full_address2[27:25] = 3'b010;
if (rast_l[1] == 1'b0)
full_address2[27:25] = 3'b011;
Index = {7'b0, full_address2[27:03]};
Addr[27:03] = full_address2[27:03];
if ((EDO_cas_l[0] === 1'b0 ) || (EDO_cas_l[2] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b11110000, simm1.wr_data);
mem_dump(full_address2[27:03],simm1.wr_data[63:32],0);
simm1.wr_parity[9] = 1'b1; // valid bit for bank 0 (63:32) is 9
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000010, simm1.wr_parity);
end
if ((EDO_cas_l[1] === 1'b0)|| (EDO_cas_l[3] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b00001111, simm1.wr_data);
mem_dump(full_address2[27:03],simm1.wr_data[31:0],1);
simm1.wr_parity[1] = 1'b1; // valid bit for bank 1 (31:0) is 1
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000001, simm1.wr_parity);
end
$display("\nDRAM INFO:Write DATA=%h[%h]\n", simm1.wr_data, simm1.wr_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM2, Write, Full addr=%h, data0=%h\n",$stime,full_address2, simm1.wr_data);
$display("============================================\n");
`endif
simm1.start_write <= #1 1'b0;
simm1.colm_addrs = 32'hFFFF;
end
always @(posedge simm2.start_write)
begin
full_address2 = 32'b0;
gen_full_addrs(simm2.row_addr, simm2.colm_addrs, full_address2);
if ((rasb_l[2] == 1'b0) && (rast_l[2] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[2]&rast_l[2] can't be asserted at the same time.\n");
end
if (rasb_l[2] == 1'b0)
full_address2[27:25] = 3'b100;
if (rast_l[2] == 1'b0)
full_address2[27:25] = 3'b101;
Index = {7'b0, full_address2[27:03]};
Addr[27:03] = full_address2[27:03];
if ((EDO_cas_l[0] === 1'b0 ) || (EDO_cas_l[2] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b11110000, simm2.wr_data);
mem_dump(full_address2[27:03],simm2.wr_data[63:32],0);
simm2.wr_parity[9] = 1'b1; // valid bit for bank 0 (63:32) is 9
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000010, simm2.wr_parity);
end
if ((EDO_cas_l[1] === 1'b0)|| (EDO_cas_l[3] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b00001111, simm2.wr_data);
mem_dump(full_address2[27:03],simm2.wr_data[31:0],1);
simm2.wr_parity[1] = 1'b1; // valid bit for bank 1 (31:0) is 1
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000001, simm2.wr_parity);
end
$display("\nDRAM INFO:Write DATA=%h[%h]\n", simm2.wr_data, simm2.wr_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM2, Write, Full addr=%h, data0=%h\n",$stime,full_address2, simm2.wr_data);
$display("============================================\n");
`endif
simm2.start_write <= #1 1'b0;
simm2.colm_addrs = 32'hFFFF;
end
always @(posedge simm3.start_write)
begin
full_address2 = 32'b0;
gen_full_addrs(simm3.row_addr, simm3.colm_addrs, full_address2);
if ((rasb_l[3] == 1'b0) && (rast_l[3] == 1'b0))
begin
$display("\nDRAM Error:[%h]\n", $stime);
$display("\nBoth rasb_l[3] & rast_l[3] can't be asserted at the same time.\n");
end
if (rasb_l[3] == 1'b0)
full_address2[27:25] = 3'b110;
if (rast_l[3] == 1'b0)
full_address2[27:25] = 3'b111;
Index = {7'b0, full_address2[27:03]};
Addr[27:03] = full_address2[27:03];
if ((EDO_cas_l[0] === 1'b0 ) || (EDO_cas_l[2] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b11110000, simm3.wr_data);
mem_dump(full_address2[27:03],simm3.wr_data[63:32],0);
simm3.wr_parity[9] = 1'b1; // valid bit for bank 0 (63:32) is 9
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000010, simm3.wr_parity);
end
if ((EDO_cas_l[1] === 1'b0)|| (EDO_cas_l[3] === 1'b0)) begin
$mem_write(Msystem.TheRam.memHandle, Index, 8'b00001111, simm3.wr_data);
mem_dump(full_address2[27:03],simm3.wr_data[31:0],1);
simm3.wr_parity[1] = 1'b1; // valid bit for bank 1 (31:0) is 1
$mem_write(Msystem.TheRam.parHandle, Index, 8'b00000001, simm3.wr_parity);
end
$display("\nDRAM INFO:Write DATA=%h[%h]\n", simm3.wr_data, simm3.wr_parity);
`ifdef DEBUG
$display("TIME=%t, SIMM3, Write, Full addr=%h, data0=%h\n",$stime,full_address2, simm3.wr_data);
$display("============================================\n");
`endif
simm3.start_write <= #1 1'b0;
simm3.colm_addrs = 32'hFFFF;
end
always @(negedge EDO_cas_l[0] or negedge EDO_cas_l[1] or negedge EDO_cas_l[2] or negedge EDO_cas_l[3]) begin
if ((EDO_ras_l != 8'hff) && EDO_mwe_l) begin
EDO_ram_output = 1'b1;
end
end
always @(posedge EDO_cas_l[0] or posedge EDO_cas_l[1] or posedge EDO_cas_l[2] or posedge EDO_cas_l[3]) begin
if (EDO_ram_output) begin
EDO_ram_output = # RAM_DELAY_EDO 1'b0 ;
end
end
simm simm0(
.data_out (EDO_rd_data[63:0]),
.data_in (EDO_wr_data[63:0]),
.parity_out (EDO_rd_par[1:0]),
.parity_in (EDO_wr_par[1:0]),
//.data (b_memdata[63:0]),
//.parity (b_mempar[1:0]),
.simm_address (EDO_memaddr[10:0]),
.rast_l (rast_l[0]),
.rasb_l (rasb_l[0]),
.cas0_l (EDO_cas_l[0]),
.cas1_l (EDO_cas_l[1]),
.oe_l (EDO_moe_l),
.we_l (EDO_mwe_l)
);
simm simm1(
.data_out (EDO_rd_data[63:0]),
.data_in (EDO_wr_data[63:0]),
.parity_out (EDO_rd_par[1:0]),
.parity_in (EDO_wr_par[1:0]),
//.data (b_memdata[63:0]),
//.parity (b_mempar[1:0]),
.simm_address (EDO_memaddr[10:0]),
.rast_l (rast_l[1]),
.rasb_l (rasb_l[1]),
.cas0_l (EDO_cas_l[0]),
.cas1_l (EDO_cas_l[1]),
.oe_l (EDO_moe_l),
.we_l (EDO_mwe_l)
);
simm simm2(
.data_out (EDO_rd_data[63:0]),
.data_in (EDO_wr_data[63:0]),
.parity_out (EDO_rd_par[1:0]),
.parity_in (EDO_wr_par[1:0]),
//.data (b_memdata[63:0]),
//.parity (b_mempar[1:0]),
.simm_address (EDO_memaddr[10:0]),
.rast_l (rast_l[2]),
.rasb_l (rasb_l[2]),
.cas0_l (EDO_cas_l[0]),
.cas1_l (EDO_cas_l[1]),
.oe_l (EDO_moe_l),
.we_l (EDO_mwe_l)
);
simm simm3(
.data_out (EDO_rd_data[63:0]),
.data_in (EDO_wr_data[63:0]),
.parity_out (EDO_rd_par[1:0]),
.parity_in (EDO_wr_par[1:0]),
//.data (b_memdata[63:0]),
//.parity (b_mempar[1:0]),
.simm_address (EDO_memaddr[10:0]),
.rast_l (rast_l[3]),
.rasb_l (rasb_l[3]),
.cas0_l (EDO_cas_l[0]),
.cas1_l (EDO_cas_l[1]),
.oe_l (EDO_moe_l),
.we_l (EDO_mwe_l)
);
task mem_dump;
input [27:3] addr;
input [31:0] data;
input odd_word;
begin
if (~mem_trace) begin
if (mem_mcd != 0) begin
$fclose(mem_mcd);
mem_mcd = 0;
end
end
else begin
if (mem_mcd == 0)
mem_mcd = $fopen({Mclocks.working_dir,"/mem_trace.v"});
if (mem_mcd != 0) begin
if (odd_word)
$fdisplay(mem_mcd, "0x%h 0x%h %g",{4'b0, addr[27:03],3'b100},data,Mclocks.cycle_count);
else
$fdisplay(mem_mcd, "0x%h 0x%h %g",{4'b0, addr[27:03],3'b000},data,Mclocks.cycle_count);
end
else $display( "dram: unable to open 'mem_trace.v'") ;
end
end
endtask
endmodule
/***********************************************************************************************************************************************
* File name: simm.v
*
* Description: Sabre simm model
*
*
* Sun Proprietary!!
*
************************************************************************************************************************************************/
![[Up: EDO_DRAM simm0]](v2html-up.gif)
![[Up: EDO_DRAM simm1]](v2html-up.gif)
![[Up: EDO_DRAM simm2]](v2html-up.gif)
module simm
(
data_out,
data_in,
parity_out,
parity_in,
simm_address,
rast_l,
rasb_l,
cas0_l,
cas1_l,
oe_l, // YS
we_l
);
parameter
//asize = 13,
capacity = 128;
output [63:0] data_out
; // data out of each simm is only 64 bits.
output [1:0] parity_out
; // 2 parity bits
input [63:0] data_in
; // data out of each simm is only 64 bits.
input [1:0] parity_in
; // 2 parity bits
input [10:0] simm_address
; // address to Dram.
input rasb_l
; // ras for bottom stack
input rast_l
; // ras for top stack
input cas0_l
;
input cas1_l
;
input oe_l
; // output enable. YS
input we_l
; // write enable.
// rasb_l and rast_l are needed for stacked simms which need
// special DRAMS which have 2 die in a single package or maybe
// two packages glued together.
// rasb_l selects bottom stack, rast_ selects top stack.
reg [63:0] rd_data
; // data from a read
reg [63:0] rd_parity
; // parity from a read
reg [63:0] wr_data
; // write data
reg [63:0] wr_parity
; // write parity
reg [31:0] row_addr
;
reg [31:0] first_col_addr
;
reg [31:0] prev_simm_addr
;
reg [31:0] curr_simm_addr
;
wire cas_l
= cas1_l & cas0_l; // multiple copies of the same cas_l
reg write_done
; // tells you when write completed
reg data_turn_off
; // tells you when to trigger tREZ monitor
reg tRAC_met
; // indicates when tRAC is met(RAS low to DATA)
reg rac_met
;
reg tCAC_met
; // indicates when tCAC is met(Cas low to DATA)
reg cac_met
;
reg tAA_met
; // indicates first_access time is met
reg tAA_start
; // indicates first_access time is met
reg tAA_done
;
reg tCPA_met
; // indicates first_access time from cas precharge is met
reg cpa_met
;
reg first_access
;
reg data_valid
; // to keep data on o/p port for tDOH after cas low.
reg [2:0] type_op
; // write operation if a 001, read if 010, refresh if 100.
reg tOEA_met
; // indicates when tOEA met (Oe_l low to DATA) YS
reg oea_met
; // YS
reg oez_min_met
; // indicates when tOEZ_MIN (oe_l high to DATA OFF min time) YS
reg oez_max_met
; // indicates when tOEZ_MIN (oe_l high to DATA OFF max time) YS
reg oez_met
; // any time between tOEZ min and max to turn data off YS
reg [31:0] rand
; // random value generated for oez_met YS
reg [1:0] whichRASprevAsserted
;
reg tRAD_max_rasb_chk_done
; // needed because tRAD check is a one time check after ras goes low
// set this flag as soon as its checked once
reg tRAD_min_rasb_chk_done
; // needed because tRAD min check is one time check
reg tRAD_min_rast_chk_done
;
reg tRAD_max_rast_chk_done
;
reg tRCD_chkd
;
reg tRAC_chkd
;
reg tRAH_chkd
;
reg tRP_chkd
;
reg tCSH_chkd
;
reg twrh_chk
; // required because twrh is a one time check
reg row_address
; // tells you whether the address is row or column
reg [31:0] row_addrs
;
reg [31:0] colm_addrs
;
// YS wire oe_l = 0; // output enable tied to ground
integer size8
; // indicates # of bytes of data
integer size1
; // indicates # of bytes of parity
integer n
;
real ticks_per_ns
;
initial
begin
ticks_per_ns = 1.4; // simulation ticks per nanosec
end
reg start_write
, start_read
;
integer oe_high_cycle
; // record cycle# @ posedge of oe_l
integer oe_low_cycle
; // record cycle# @ negedge of oe_l
integer we_high_cycle
; // record cycle# @ posedge of we_l
integer we_low_cycle
; // record cycle# @ negedge of we_l
integer tRP
;
integer tRAS
;
integer cas_high_cycle
; // record cycle# @ posedge of cas_l
integer cas_low_cycle
; // record cycle# @ negedge of cas_l
integer cas_prev_low_cycle
; // required in cases where data and subsequent cas low happen
integer cas_prev_high_cycle
; // required to monitor tHPC.
This page: |
Created: | Thu Aug 19 12:01:39 1999 |
| From: |
../../../sparc_v8/system/rtl/dram.v
|