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

Subversion Repositories sdr_ctrl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /sdr_ctrl
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/trunk/verif/model/mt48lc2m32b2.v
0,0 → 1,1096
/**************************************************************************
*
* File Name: MT48LC2M32B2.V
* Version: 2.1
* Date: June 6th, 2002
* Model: BUS Functional
* Simulator: Model Technology
*
* Dependencies: None
*
* Email: modelsupport@micron.com
* Company: Micron Technology, Inc.
* Model: MT48LC2M32B2 (512K 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 Date Changes
* --- -------------------------- ---------------------------------------
* 2.1 SH 06/06/2002 - Typo in bank multiplex
* Micron Technology Inc.
*
* 2.0 SH 04/30/2002 - Second release
* Micron Technology Inc.
*
**************************************************************************/
 
`timescale 1ns / 1ps
 
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 Auto Precharge (Bank)
reg Read_precharge [0 : 3]; // R Auto Precharge
reg Write_precharge [0 : 3]; // W Auto Precharge
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
integer RW_interrupt_counter [0 : 3]; // RW Interrupt Counter
integer Count_precharge [0 : 3]; // RW Auto Precharge Counter
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Prev_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];
wire Burst_length_f = 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 WRITE 3
`define PRECH 4
`define A_REF 5
`define BST 6
`define LMR 7
 
// Timing Parameters for -6 CL3
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 = 60.0;
parameter tRCD = 18.0;
parameter tRFC = 60.0;
parameter tRP = 18.0;
parameter tRRD = 12.0;
parameter tWRa = 6.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
parameter tWRm = 12.0; // A2 Version - Manual precharge mode (14 ns)
 
// Timing Check variable
time MRD_chk;
time WR_chkm [0 : 3];
time RFC_chk, RRD_chk;
time RC_chk0, RC_chk1, RC_chk2, RC_chk3;
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 = 0; Data_out_enable = 0;
Act_b0 = 1; Act_b1 = 1; Act_b2 = 1; Act_b3 = 1;
Pc_b0 = 0; Pc_b1 = 0; Pc_b2 = 0; Pc_b3 = 0;
WR_chkm[0] = 0; WR_chkm[1] = 0; WR_chkm[2] = 0; WR_chkm[3] = 0;
RW_interrupt_read[0] = 0; RW_interrupt_read[1] = 0; RW_interrupt_read[2] = 0; RW_interrupt_read[3] = 0;
RW_interrupt_write[0] = 0; RW_interrupt_write[1] = 0; RW_interrupt_write[2] = 0; RW_interrupt_write[3] = 0;
MRD_chk = 0; RFC_chk = 0; RRD_chk = 0;
RAS_chk0 = 0; RAS_chk1 = 0; RAS_chk2 = 0; RAS_chk3 = 0;
RCD_chk0 = 0; RCD_chk1 = 0; RCD_chk2 = 0; RCD_chk3 = 0;
RC_chk0 = 0; RC_chk1 = 0; RC_chk2 = 0; RC_chk3 = 0;
RP_chk0 = 0; RP_chk1 = 0; RP_chk2 = 0; RP_chk3 = 0;
$timeformat (-9, 1, " ns", 12);
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
 
// Read or Write Interrupt Counter
if (RW_interrupt_write[0] === 1'b1) begin
RW_interrupt_counter[0] = RW_interrupt_counter[0] + 1;
end
if (RW_interrupt_write[1] === 1'b1) begin
RW_interrupt_counter[1] = RW_interrupt_counter[1] + 1;
end
if (RW_interrupt_write[2] === 1'b1) begin
RW_interrupt_counter[2] = RW_interrupt_counter[2] + 1;
end
if (RW_interrupt_write[3] === 1'b1) begin
RW_interrupt_counter[3] = RW_interrupt_counter[3] + 1;
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// Auto Refresh
if (Aref_enable === 1'b1) begin
if (Debug) begin
$display ("%m : at time %t AREF : Auto Refresh", $time);
end
 
// Auto Refresh to Auto Refresh
if ($time - RFC_chk < tRFC) begin
$display ("%m : at time %t ERROR: tRFC 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
 
// Load Mode Register to Auto Refresh
if (MRD_chk < tMRD) begin
$display ("%m : at time %t ERROR: tMRD violation during Auto Refresh", $time);
end
 
// Record Current tRFC time
RFC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable === 1'b1) begin
// Register Mode
Mode_reg = Addr;
 
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Debug) begin
$display ("%m : at time %t LMR : Load Mode Register", $time);
// CAS Latency
case (Addr[6 : 4])
3'b001 : $display ("%m : CAS Latency = 1");
3'b010 : $display ("%m : CAS Latency = 2");
3'b011 : $display ("%m : CAS Latency = 3");
default : $display ("%m : CAS Latency = Reserved");
endcase
 
// Burst Length
case (Addr[2 : 0])
3'b000 : $display ("%m : Burst Length = 1");
3'b001 : $display ("%m : Burst Length = 2");
3'b010 : $display ("%m : Burst Length = 4");
3'b011 : $display ("%m : Burst Length = 8");
3'b111 : $display ("%m : Burst Length = Full");
default : $display ("%m : Burst Length = Reserved");
endcase
 
// Burst Type
if (Addr[3] === 1'b0) begin
$display ("%m : Burst Type = Sequential");
end else if (Addr[3] === 1'b1) begin
$display ("%m : Burst Type = Interleaved");
end else begin
$display ("%m : Burst Type = Reserved");
end
 
// Write Burst Mode
if (Addr[9] === 1'b0) begin
$display ("%m : Write Burst Mode = Programmed Burst Length");
end else if (Addr[9] === 1'b1) begin
$display ("%m : Write Burst Mode = Single Location Access");
end else begin
$display ("%m : Write Burst Mode = Reserved");
end
end
 
// Precharge to Load Mode Register
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 Load Mode Register", $time);
end
 
// Precharge to Load Mode Register
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 Load Mode Register", $time);
end
 
// Auto Refresh to Load Mode Register
if ($time - RFC_chk < tRFC) begin
$display ("%m : at time %t ERROR: tRFC violation during Load Mode Register", $time);
end
 
// Load Mode Register to Load Mode Register
if (MRD_chk < tMRD) begin
$display ("%m : at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
 
// Reset MRD Counter
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable === 1'b1) begin
// Activate an open bank can corrupt data
if ((Ba === 2'b00 && Act_b0 === 1'b1) || (Ba === 2'b01 && Act_b1 === 1'b1) ||
(Ba === 2'b10 && Act_b2 === 1'b1) || (Ba === 2'b11 && Act_b3 === 1'b1)) begin
$display ("%m : at time %t ERROR: Bank already activated -- data can be corrupted", $time);
end
 
// Activate Bank 0
if (Ba === 2'b00 && Pc_b0 === 1'b1) begin
// Debug Message
if (Debug) begin
$display ("%m : at time %t ACT : Bank = 0 Row = %d", $time, Addr);
end
 
// ACTIVE to ACTIVE command period
if ($time - RC_chk0 < tRC) begin
$display ("%m : at time %t ERROR: tRC violation during Activate bank 0", $time);
end
 
// 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
 
// Record variables
Act_b0 = 1'b1;
Pc_b0 = 1'b0;
B0_row_addr = Addr [addr_bits - 1 : 0];
RAS_chk0 = $time;
RC_chk0 = $time;
RCD_chk0 = $time;
end
 
if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
// Debug Message
if (Debug) begin
$display ("%m : at time %t ACT : Bank = 1 Row = %d", $time, Addr);
end
 
// ACTIVE to ACTIVE command period
if ($time - RC_chk1 < tRC) begin
$display ("%m : at time %t ERROR: tRC violation during Activate bank 1", $time);
end
 
// 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
 
// Record variables
Act_b1 = 1'b1;
Pc_b1 = 1'b0;
B1_row_addr = Addr [addr_bits - 1 : 0];
RAS_chk1 = $time;
RC_chk1 = $time;
RCD_chk1 = $time;
end
 
if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
// Debug Message
if (Debug) begin
$display ("%m : at time %t ACT : Bank = 2 Row = %d", $time, Addr);
end
 
// ACTIVE to ACTIVE command period
if ($time - RC_chk2 < tRC) begin
$display ("%m : at time %t ERROR: tRC violation during Activate bank 2", $time);
end
 
// 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
 
// Record variables
Act_b2 = 1'b1;
Pc_b2 = 1'b0;
B2_row_addr = Addr [addr_bits - 1 : 0];
RAS_chk2 = $time;
RC_chk2 = $time;
RCD_chk2 = $time;
end
 
if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
// Debug Message
if (Debug) begin
$display ("%m : at time %t ACT : Bank = 3 Row = %d", $time, Addr);
end
 
// ACTIVE to ACTIVE command period
if ($time - RC_chk3 < tRC) begin
$display ("%m : at time %t ERROR: tRC violation during Activate bank 3", $time);
end
 
// 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
 
// Record variables
Act_b3 = 1'b1;
Pc_b3 = 1'b0;
B3_row_addr = Addr [addr_bits - 1 : 0];
RAS_chk3 = $time;
RC_chk3 = $time;
RCD_chk3 = $time;
end
 
// Active Bank A to Active Bank B
if ((Prev_bank != Ba) && ($time - RRD_chk < tRRD)) begin
$display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
 
// Auto Refresh to Activate
if ($time - RFC_chk < tRFC) begin
$display ("%m : at time %t ERROR: tRFC 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
 
// Record variables for checking violation
RRD_chk = $time;
Prev_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
// Load Mode Register to Precharge
if ($time - MRD_chk < tMRD) begin
$display ("%m : at time %t ERROR: tMRD violaiton during Precharge", $time);
end
 
// Precharge Bank 0
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b00)) && Act_b0 === 1'b1) begin
Act_b0 = 1'b0;
Pc_b0 = 1'b1;
RP_chk0 = $time;
 
// Activate to Precharge
if ($time - RAS_chk0 < tRAS) begin
$display ("%m : at time %t ERROR: tRAS violation during Precharge", $time);
end
 
// tWR violation check for write
if ($time - WR_chkm[0] < tWRm) begin
$display ("%m : at time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge Bank 1
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b01)) && Act_b1 === 1'b1) begin
Act_b1 = 1'b0;
Pc_b1 = 1'b1;
RP_chk1 = $time;
 
// Activate to Precharge
if ($time - RAS_chk1 < tRAS) begin
$display ("%m : at time %t ERROR: tRAS violation during Precharge", $time);
end
 
// tWR violation check for write
if ($time - WR_chkm[1] < tWRm) begin
$display ("%m : at time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge Bank 2
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b10)) && Act_b2 === 1'b1) begin
Act_b2 = 1'b0;
Pc_b2 = 1'b1;
RP_chk2 = $time;
 
// Activate to Precharge
if ($time - RAS_chk2 < tRAS) begin
$display ("%m : at time %t ERROR: tRAS violation during Precharge", $time);
end
 
// tWR violation check for write
if ($time - WR_chkm[2] < tWRm) begin
$display ("%m : at time %t ERROR: tWR violation during Precharge", $time);
end
end
 
// Precharge Bank 3
if ((Addr[10] === 1'b1 || (Addr[10] === 1'b0 && Ba === 2'b11)) && Act_b3 === 1'b1) begin
Act_b3 = 1'b0;
Pc_b3 = 1'b1;
RP_chk3 = $time;
 
// Activate to Precharge
if ($time - RAS_chk3 < tRAS) begin
$display ("%m : at time %t ERROR: tRAS violation during Precharge", $time);
end
 
// tWR violation check for write
if ($time - WR_chkm[3] < tWRm) begin
$display ("%m : at time %t ERROR: tWR violation during Precharge", $time);
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
 
// Display debug message
if (Debug) begin
$display ("%m : at time %t BST : Burst Terminate",$time);
end
end
// Read, Write, Column Latch
if (Read_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: Bank is not Activated for Read", $time);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD) ||
(Ba == 2'b01) && ($time - RCD_chk1 < tRCD) ||
(Ba == 2'b10) && ($time - RCD_chk2 < tRCD) ||
(Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) begin
$display("%m : at time %t ERROR: tRCD violation during Read", $time);
end
 
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
Command[2] = `READ;
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `READ;
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end else if (Cas_latency_1 == 1'b1) begin
Command[0] = `READ;
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;
RW_interrupt_counter[RW_interrupt_bank] = 0;
 
// Display debug message
if (Debug) begin
$display ("%m : at time %t NOTE : Read interrupt Write with Autoprecharge", $time);
end
end
end
 
// Read with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
Read_precharge[Ba] = 1'b1;
end
end
 
// Write Command
if (Write_enable == 1'b1) begin
// Activate to Write
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: Bank is not Activated for Write", $time);
end
 
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD) ||
(Ba == 2'b01) && ($time - RCD_chk1 < tRCD) ||
(Ba == 2'b10) && ($time - RCD_chk2 < tRCD) ||
(Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) begin
$display("%m : at time %t ERROR: tRCD violation during Read", $time);
end
 
// Latch Write command, Bank, and Column
Command[0] = `WRITE;
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;
 
// Display debug message
if (Debug) begin
$display ("%m : at time %t NOTE : Read Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
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;
 
// Display debug message
if (Debug) begin
$display ("%m : at time %t NOTE : Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, RW_interrupt_bank);
end
end
end
 
// Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
RW_interrupt_bank = Ba;
Write_precharge[Ba] = 1'b1;
end
end
 
/*
Write with Auto Precharge Calculation
The device start internal precharge when:
1. Meet minimum tRAS requirement
and 2. tWR cycle(s) after last valid data
or 3. Interrupt by a Read or Write (with or without Auto Precharge)
 
Note: Model is starting the internal precharge 1 cycle after they meet all the
requirement but tRP will be compensate for the time after the 1 cycle.
*/
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 1
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 2
(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 && RW_interrupt_counter[0] >= 1)) begin // Case 3
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 + tWRa;
if (Debug) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
end
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) && // Case 1
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || // Case 2
(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 && RW_interrupt_counter[1] >= 1)) begin // Case 3
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 + tWRa;
if (Debug) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
end
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) && // Case 1
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || // Case 2
(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 && RW_interrupt_counter[2] >= 1)) begin // Case 3
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 + tWRa;
if (Debug) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
end
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) && // Case 1
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || // Case 2
(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 && RW_interrupt_counter[3] >= 1)) begin // Case 3
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 + tWRa;
if (Debug) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. Meet minimum tRAS requirement
// and 2. CAS Latency - 1 cycles before last burst
// 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 1
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 2
(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) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
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) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
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) begin
$display ("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
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) begin
$display("%m : at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
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) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
case (Bank_addr[0])
2'b00 : Row = B0_row_addr;
2'b01 : Row = B1_row_addr;
2'b10 : Row = B2_row_addr;
2'b11 : Row = B3_row_addr;
endcase
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `WRITE) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
case (Bank_addr[0])
2'b00 : Row = B0_row_addr;
2'b01 : Row = B1_row_addr;
2'b10 : Row = B2_row_addr;
2'b11 : Row = B3_row_addr;
endcase
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
case (Bank)
2'b00 : Dq_dqm = Bank0 [{Row, Col}];
2'b01 : Dq_dqm = Bank1 [{Row, Col}];
2'b10 : Dq_dqm = Bank2 [{Row, Col}];
2'b11 : Dq_dqm = Bank3 [{Row, Col}];
endcase
 
// Dqm operation
if (Dqm[0] == 1'b0) begin
Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
end
if (Dqm[1] == 1'b0) begin
Dq_dqm [15 : 8] = Dq [15 : 8];
end
if (Dqm[2] == 1'b0) begin
Dq_dqm [23 : 16] = Dq [23 : 16];
end
if (Dqm[3] == 1'b0) begin
Dq_dqm [31 : 24] = Dq [31 : 24];
end
 
// Write to memory
case (Bank)
2'b00 : Bank0 [{Row, Col}] = Dq_dqm;
2'b01 : Bank1 [{Row, Col}] = Dq_dqm;
2'b10 : Bank2 [{Row, Col}] = Dq_dqm;
2'b11 : Bank3 [{Row, Col}] = Dq_dqm;
endcase
 
// Display debug message
if (Dqm !== 4'b1111) begin
// Record tWR for manual precharge
WR_chkm [Bank] = $time;
 
if (Debug) begin
$display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h", $time, Bank, Row, Col, Dq_dqm);
end
end else begin
if (Debug) begin
$display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
end
 
// Advance burst counter subroutine
#tHZ Burst_decode;
 
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
case (Bank)
2'b00 : Dq_dqm = Bank0[{Row, Col}];
2'b01 : Dq_dqm = Bank1[{Row, Col}];
2'b10 : Dq_dqm = Bank2[{Row, Col}];
2'b11 : Dq_dqm = Bank3[{Row, Col}];
endcase
 
// Dqm operation
if (Dqm_reg0 [0] == 1'b1) begin
Dq_dqm [ 7 : 0] = 8'bz;
end
if (Dqm_reg0 [1] == 1'b1) begin
Dq_dqm [15 : 8] = 8'bz;
end
if (Dqm_reg0 [2] == 1'b1) begin
Dq_dqm [23 : 16] = 8'bz;
end
if (Dqm_reg0 [3] == 1'b1) begin
Dq_dqm [31 : 24] = 8'bz;
end
 
// Display debug message
if (Dqm_reg0 !== 4'b1111) begin
Dq_reg = #tAC Dq_dqm;
if (Debug) begin
$display("%m : at time %t READ : Bank = %d Row = %d, Col = %d, Data = %h", $time, Bank, Row, Col, Dq_reg);
end
end else begin
Dq_reg = #tHZ {data_bits{1'bz}};
if (Debug) begin
$display("%m : at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end
end
 
// Advance burst counter subroutine
Burst_decode;
end
end
 
// Burst counter decode
task Burst_decode;
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 CL3
specify
specparam
tAH = 1.0, // 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 = 6.0, // Clock Cycle Time
tDH = 1.0, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 1.0, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 1.0, // 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
trunk/verif/model/mt48lc2m32b2.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/verif/model/mt48lc4m16.v =================================================================== --- trunk/verif/model/mt48lc4m16.v (nonexistent) +++ trunk/verif/model/mt48lc4m16.v (revision 7) @@ -0,0 +1,1624 @@ +////////////////////////////////////////////////////////////////////////////// +// File name : mt48lc4m16.v +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2008 Free Model Foundry; http://www.freemodelfoundry.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// MODIFICATION HISTORY: +// +// version: | author: | mod date: | changes made: +// V1.0 S.Janevski 08 Feb 27 Initial release +// V1.1 S.Janevski 08 Mar 26 Assertions of wrong DQM settings during powerup removed +////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: RAM +// Technology: LVTTL +// Part: mt48lc4m16 +// +// Description: 1M x 16 x 4Banks SDRAM +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns/100 ps + +module mt48lc4m16 + ( + A11 , + A10 , + A9 , + A8 , + A7 , + A6 , + A5 , + A4 , + A3 , + A2 , + A1 , + A0 , + + DQ15 , + DQ14 , + DQ13 , + DQ12 , + DQ11 , + DQ10 , + DQ9 , + DQ8 , + DQ7 , + DQ6 , + DQ5 , + DQ4 , + DQ3 , + DQ2 , + DQ1 , + DQ0 , + + BA0 , + BA1 , + DQMH , + DQML , + CLK , + CKE , + WENeg , + RASNeg , + CSNeg , + CASNeg ); + + //////////////////////////////////////////////////////////////////////// + // Port / Part Pin Declarations + //////////////////////////////////////////////////////////////////////// + input A11 ; + input A10 ; + input A9 ; + input A8 ; + input A7 ; + input A6 ; + input A5 ; + input A4 ; + input A3 ; + input A2 ; + input A1 ; + input A0 ; + + inout DQ15 ; + inout DQ14 ; + inout DQ13 ; + inout DQ12 ; + inout DQ11 ; + inout DQ10 ; + inout DQ9 ; + inout DQ8 ; + inout DQ7 ; + inout DQ6 ; + inout DQ5 ; + inout DQ4 ; + inout DQ3 ; + inout DQ2 ; + inout DQ1 ; + inout DQ0 ; + + input BA0 ; + input BA1 ; + input DQMH ; + input DQML ; + input CLK ; + input CKE ; + input WENeg ; + input RASNeg ; + input CSNeg ; + input CASNeg ; + + // interconnect path delay signals + wire A11_ipd ; + wire A10_ipd ; + wire A9_ipd ; + wire A8_ipd ; + wire A7_ipd ; + wire A6_ipd ; + wire A5_ipd ; + wire A4_ipd ; + wire A3_ipd ; + wire A2_ipd ; + wire A1_ipd ; + wire A0_ipd ; + + wire [11 : 0] A; + assign A = {A11_ipd, + A10_ipd, + A9_ipd, + A8_ipd, + A7_ipd, + A6_ipd, + A5_ipd, + A4_ipd, + A3_ipd, + A2_ipd, + A1_ipd, + A0_ipd }; + + wire DQ15_ipd ; + wire DQ14_ipd ; + wire DQ13_ipd ; + wire DQ12_ipd ; + wire DQ11_ipd ; + wire DQ10_ipd ; + wire DQ9_ipd ; + wire DQ8_ipd ; + wire DQ7_ipd ; + wire DQ6_ipd ; + wire DQ5_ipd ; + wire DQ4_ipd ; + wire DQ3_ipd ; + wire DQ2_ipd ; + wire DQ1_ipd ; + wire DQ0_ipd ; + + wire [15 : 0 ] DQIn; + assign DQIn = { DQ15_ipd, + DQ14_ipd, + DQ13_ipd, + DQ12_ipd, + DQ11_ipd, + DQ10_ipd, + DQ9_ipd, + DQ8_ipd, + DQ7_ipd, + DQ6_ipd, + DQ5_ipd, + DQ4_ipd, + DQ3_ipd, + DQ2_ipd, + DQ1_ipd, + DQ0_ipd }; + + wire [15 : 0] DQOut; + assign DQOut = { DQ15, + DQ14, + DQ13, + DQ12, + DQ11, + DQ10, + DQ9, + DQ8, + DQ7, + DQ6, + DQ5, + DQ4, + DQ3, + DQ2, + DQ1, + DQ0 }; + + wire BA0_ipd ; + wire BA1_ipd ; + wire DQM1_ipd ; + wire DQM0_ipd ; + wire CLK_ipd ; + wire CKE_ipd ; + wire WENeg_ipd ; + wire RASNeg_ipd ; + wire CSNeg_ipd ; + wire CASNeg_ipd ; + + integer bank; + integer bank_tmp; + + // internal delays + reg rct_in ; + reg rct_out; + reg [3:0] rcdt_in ; + reg [3:0] rcdt_out; + reg pre_in ; + reg pre_out ; + reg refreshed_in ; + reg refreshed_out ; + reg rcar_out ; + reg rcar_in ; + reg [3:0] ras_in = 1'b0; + reg [3:0] ras_out = 1'b0; + + reg [15 : 0] DQ_zd = 16'bz; + assign {DQ15_zd, + DQ14_zd, + DQ13_zd, + DQ12_zd, + DQ11_zd, + DQ10_zd, + DQ9_zd, + DQ8_zd, + DQ7_zd, + DQ6_zd, + DQ5_zd, + DQ4_zd, + DQ3_zd, + DQ2_zd, + DQ1_zd, + DQ0_zd } = DQ_zd; + + parameter UserPreload = 1'b1; + parameter mem_file_name = "none"; //"mt48lc4m16.mem"; + parameter TimingModel = "DefaultTimingModel"; + parameter PartID = "mt48lc4m16"; + parameter hi_bank = 3; + parameter depth = 25'h100000; + + reg PoweredUp = 1'b0; + reg CKEreg = 1'b0; + reg CAS_Lat ; + reg CAS_Lat2; + reg [15:0] DataDrive = 16'bz ; + + // Memory array declaration + integer Mem [0:(hi_bank+1)*depth*2-1]; + + // Type definition for state machine + parameter pwron = 5'd0; + parameter precharge = 5'd1; + parameter idle = 5'd2; + parameter mode_set = 5'd3; + parameter self_refresh = 5'd4; + parameter auto_refresh = 5'd5; + parameter pwrdwn = 5'd6; + parameter bank_act = 5'd7; + parameter bank_act_pwrdwn = 5'd8; + parameter write = 5'd9; + parameter write_suspend = 5'd10; + parameter read = 5'd11; + parameter read_suspend = 5'd12; + parameter write_auto_pre = 5'd13; + parameter read_auto_pre = 5'd14; + + reg [4:0] statebank [hi_bank:0]; + + // Type definition for commands + parameter desl = 4'd0; + parameter nop = 4'd1; + parameter bst = 4'd2; + parameter rd = 4'd3; + parameter writ = 4'd4; + parameter act = 4'd5; + parameter pre = 4'd6; + parameter mrs = 4'd7; + parameter ref = 4'd8; + + reg [3:0] command = desl; + + // burst type + parameter sequential = 1'b0; + parameter interleave = 1'b1; + reg Burst ; + + // write burst mode + parameter programmed = 1'b0; + parameter single = 1'b1; + reg WB ; + + //burst sequences + integer intab [0:63]; + + reg [19:0] MemAddr [hi_bank:0]; + integer BurstCnt [hi_bank:0]; + integer StartAddr [hi_bank:0]; + integer BurstInc [hi_bank:0]; + integer BaseLoc [hi_bank:0]; + + integer Loc; + integer BurstLen; + integer Burst_Bits; + + reg written = 1'b0; + reg chip_en = 1'b0; + + integer cur_bank; + reg [11:0] ModeReg ; + integer Ref_Cnt = 0; + + time Next_Ref = 0; + reg [8*8:1] BankString ; + + reg Viol = 1'b0; + reg [15:0] DataDriveOut = 16'bz; + reg [15:0] DataDrive1 = 16'bz; + reg [15:0] DataDrive2 = 16'bz; + reg [15:0] DataDrive3 = 16'bz; + + reg DQM0_reg0 ; + reg DQM0_reg1 ; + reg DQM0_reg2 ; + reg DQM1_reg0 ; + reg DQM1_reg1 ; + reg DQM1_reg2 ; + + // tdevice values: values for internal delays + time tdevice_TRASmin = 0; + time tdevice_TRASmax = 0; + time tdevice_TRC = 0; + time tdevice_TRCAR = 0; + time tdevice_TRCD = 0; + time tdevice_TRP = 0; + + /////////////////////////////////////////////////////////////////////////// + //Interconnect Path Delay Section + /////////////////////////////////////////////////////////////////////////// + buf (A11_ipd, A11); + buf (A10_ipd, A10); + buf (A9_ipd , A9 ); + buf (A8_ipd , A8 ); + buf (A7_ipd , A7 ); + buf (A6_ipd , A6 ); + buf (A5_ipd , A5 ); + buf (A4_ipd , A4 ); + buf (A3_ipd , A3 ); + buf (A2_ipd , A2 ); + buf (A1_ipd , A1 ); + buf (A0_ipd , A0 ); + + buf (DQ15_ipd , DQ15 ); + buf (DQ14_ipd , DQ14 ); + buf (DQ13_ipd , DQ13 ); + buf (DQ12_ipd , DQ12 ); + buf (DQ11_ipd , DQ11 ); + buf (DQ10_ipd , DQ10 ); + buf (DQ9_ipd , DQ9 ); + buf (DQ8_ipd , DQ8 ); + buf (DQ7_ipd , DQ7 ); + buf (DQ6_ipd , DQ6 ); + buf (DQ5_ipd , DQ5 ); + buf (DQ4_ipd , DQ4 ); + buf (DQ3_ipd , DQ3 ); + buf (DQ2_ipd , DQ2 ); + buf (DQ1_ipd , DQ1 ); + buf (DQ0_ipd , DQ0 ); + + buf (CASNeg_ipd, CASNeg); + buf (RASNeg_ipd, RASNeg); + buf (BA0_ipd , BA0 ); + buf (BA1_ipd , BA1 ); + buf (DQM0_ipd , DQML ); + buf (DQM1_ipd , DQMH ); + buf (CLK_ipd , CLK ); + buf (CKE_ipd , CKE ); + buf (WENeg_ipd , WENeg ); + buf (CSNeg_ipd , CSNeg ); + + /////////////////////////////////////////////////////////////////////////// + // Propagation delay Section + /////////////////////////////////////////////////////////////////////////// + nmos (DQ15 , DQ15_zd , 1); + nmos (DQ14 , DQ14_zd , 1); + nmos (DQ13 , DQ13_zd , 1); + nmos (DQ12 , DQ12_zd , 1); + nmos (DQ11 , DQ11_zd , 1); + nmos (DQ10 , DQ10_zd , 1); + nmos (DQ9 , DQ9_zd , 1); + nmos (DQ8 , DQ8_zd , 1); + nmos (DQ7 , DQ7_zd , 1); + nmos (DQ6 , DQ6_zd , 1); + nmos (DQ5 , DQ5_zd , 1); + nmos (DQ4 , DQ4_zd , 1); + nmos (DQ3 , DQ3_zd , 1); + nmos (DQ2 , DQ2_zd , 1); + nmos (DQ1 , DQ1_zd , 1); + nmos (DQ0 , DQ0_zd , 1); + + wire deg; + wire chip_act; + assign chip_act = chip_en; + + wire chip_act_deg; + assign chip_act_deg = chip_act && deg; + + wire cas_latency2; + wire cas_latency3; + + assign cas_latency2 = ~CAS_Lat && CAS_Lat2; + assign cas_latency3 = CAS_Lat && CAS_Lat2; + + specify + // tipd delays: interconnect path delays, mapped to input port delays. + // In Verilog it is not necessary to declare any tipd delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_CLK_DQ0 = 1; + specparam tpd_CLK_DQ1 = 1; + + // tpw values: pulse widths + specparam tpw_CLK_posedge = 1; + specparam tpw_CLK_negedge = 1; + + // tsetup values: setup times + specparam tsetup_DQ0_CLK = 1; // tDS + + // thold values: hold times + specparam thold_DQ0_CLK = 1; // tDH + + // tperiod_min: minimum clock period = 1/max freq + specparam tperiod_CLK_cl1_eq_1_posedge = 1; + specparam tperiod_CLK_cl2_eq_1_posedge = 1; + + // tdevice values: values for internal delays + specparam tdevice_REF = 15625 ; + + /////////////////////////////////////////////////////////////////////// + // Input Port Delays don't require Verilog description + /////////////////////////////////////////////////////////////////////// + // Path delays // + /////////////////////////////////////////////////////////////////////// + + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ0; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ0; + + if (CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ1; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ1; + + //////////////////////////////////////////////////////////////////////// + // Timing Check Section + //////////////////////////////////////////////////////////////////////// + $setup (BA0 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (BA1 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQML, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQMH, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CKE , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (WENeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CSNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (RASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + + $setup (DQ0 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ1 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ2 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ3 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ4 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ5 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ6 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ7 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ8 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ9 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ10 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ11 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ12 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ13 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ14 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ15 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + + $setup (A0, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A1, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A2, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A3, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A4, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A5, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A6, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A7, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A8, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A9, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A10, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A11, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act, BA0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, BA1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQML, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQMH, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CKE , thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CASNeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, RASNeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, WENeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CSNeg, thold_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act, A0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A2, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A3, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A4, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A5, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A6, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A7, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A8, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A9, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A10, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A11, thold_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act_deg, DQ0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ2, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ3, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ4, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ5, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ6, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ7, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ8, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ9, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ10, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ11, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ12, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ13, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ14, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ15, thold_DQ0_CLK, Viol); + + $width (posedge CLK &&& chip_act, tpw_CLK_posedge); + $width (negedge CLK &&& chip_act, tpw_CLK_negedge); + + $period (posedge CLK &&& cas_latency2, tperiod_CLK_cl1_eq_1_posedge); + $period (posedge CLK &&& cas_latency3, tperiod_CLK_cl2_eq_1_posedge); + + endspecify + + task generate_out ; + output [15:0] DataDrive; + input Bank; + integer Bank; + integer location; + begin + location = Bank * depth * 2 + Loc; + + DataDrive[7:0] = 8'bx; + if (Mem[location] > -1) + DataDrive[7:0] = Mem[location]; + + DataDrive[15:8] = 8'bx; + if (Mem[location+1] > -1) + DataDrive[15:8] = Mem[location+1]; + + end + endtask + + task MemWrite; + input Bank; + integer Bank; + integer location; + begin + location = Bank * depth * 2 + Loc; + + if (~DQM0_ipd) + begin + Mem[location] = -1; + if (~Viol) + Mem[location] = DQIn[7:0]; + end + + if (~DQM1_ipd) + begin + Mem[location+1] = -1; + if (~Viol) + Mem[location+1] = DQIn[15:8]; + end + + end + endtask + + task BurstIncProc; + input Bank; + integer Bank; + begin + BurstInc[Bank] = 0; + if (Burst_Bits == 1) + BurstInc[Bank] = A[0:0]; + if (Burst_Bits == 2) + BurstInc[Bank] = A[1:0]; + if (Burst_Bits == 3) + BurstInc[Bank] = A[2:0]; + if (Burst_Bits == 7) + BurstInc[Bank] = A[6:0]; + end + endtask + + task NextStateAuto; + input Bank; + input state; + integer Bank; + reg [4:0] state; + begin + if (~A[10]) + statebank[Bank] = state; + else if (A[10]) + if (state == write) + statebank[Bank] = write_auto_pre; + else + statebank[Bank] = read_auto_pre; + end + endtask + + ////////////////////////////////////////////////////////////////////////// + // Main Behavior Block // + ////////////////////////////////////////////////////////////////////////// + + // chech when data is generated from model to avoid setup/hold check in + // those occasion + reg deq; + always @(DQIn, DQOut) + begin + if (DQIn==DQOut) + deq=1'b1; + else + deq=1'b0; + end + assign deg=deq; + + // initialize burst sequences + initial + begin + intab[0] = 0; + intab[1] = 1; + intab[2] = 2; + intab[3] = 3; + intab[4] = 4; + intab[5] = 5; + intab[6] = 6; + intab[7] = 7; + intab[8] = 1; + intab[9] = 0; + intab[10] = 3; + intab[11] = 2; + intab[12] = 5; + intab[13] = 4; + intab[14] = 7; + intab[15] = 6; + intab[16] = 2; + intab[17] = 3; + intab[18] = 0; + intab[19] = 1; + intab[20] = 6; + intab[21] = 7; + intab[22] = 4; + intab[23] = 5; + intab[24] = 3; + intab[25] = 2; + intab[26] = 1; + intab[27] = 0; + intab[28] = 7; + intab[29] = 6; + intab[30] = 5; + intab[31] = 4; + intab[32] = 4; + intab[33] = 5; + intab[34] = 6; + intab[35] = 7; + intab[36] = 0; + intab[37] = 1; + intab[38] = 2; + intab[39] = 3; + intab[40] = 5; + intab[41] = 4; + intab[42] = 7; + intab[43] = 6; + intab[44] = 1; + intab[45] = 0; + intab[46] = 3; + intab[47] = 2; + intab[48] = 6; + intab[49] = 7; + intab[50] = 4; + intab[51] = 5; + intab[52] = 2; + intab[53] = 3; + intab[54] = 0; + intab[55] = 1; + intab[56] = 7; + intab[57] = 6; + intab[58] = 5; + intab[59] = 4; + intab[60] = 3; + intab[61] = 2; + intab[62] = 1; + intab[63] = 0; + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + for (i=0; i<=((hi_bank+1)*depth*2 - 1); i=i+1) + begin + Mem[i] = -1; + end + // Memory preload file + // mt48lc4m16.mem file + // @bbbbbb - stands for address within memory, + // dd -
is word to be written at Mem(bbbbbb++) + // (bbbbbb is incremented at every load) + if (UserPreload && !(mem_file_name == "none")) + $readmemh(mem_file_name,Mem); + end + + //Power Up time 100 us; + initial + begin + PoweredUp = 1'b0; + statebank[0] = pwron; + statebank[1] = pwron; + statebank[2] = pwron; + statebank[3] = pwron; + #100000 PoweredUp = 1'b1; + end + + always @(posedge ras_in[0]) + begin:TRASrise0 + ras_out[0] <= #tdevice_TRASmin ras_in[0]; + end + + always @(negedge ras_in[0]) + begin:TRASfall0 + ras_out[0] <= #tdevice_TRASmax ras_in[0]; + end + + always @(posedge ras_in[1]) + begin:TRASrise1 + ras_out[1] <= #tdevice_TRASmin ras_in[1]; + end + + always @(negedge ras_in[1]) + begin:TRASfall1 + ras_out[1] <= #tdevice_TRASmax ras_in[1]; + end + + always @(posedge ras_in[2]) + begin:TRASrise2 + ras_out[2] <= #tdevice_TRASmin ras_in[2]; + end + always @(negedge ras_in[2]) + begin:TRASfall2 + ras_out[2] <= #tdevice_TRASmax ras_in[2]; + end + + always @(posedge ras_in[3]) + begin:TRASrise3 + ras_out[3] <= #tdevice_TRASmin ras_in[3]; + end + + always @(negedge ras_in[3]) + begin:TRASfall3 + ras_out[3] <= #tdevice_TRASmax ras_in[3]; + end + + always @(posedge rcdt_in[0]) + begin:TRCDrise0 + rcdt_out[0] <= #5 1'b1; + end + always @(negedge rcdt_in[0]) + begin:TRCDfall0 + rcdt_out[0] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[1]) + begin:TRCDrise1 + rcdt_out[1] <= #5 1'b1; + end + always @(negedge rcdt_in[1]) + begin:TRCDfall1 + rcdt_out[1] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[2]) + begin:TRCDrise2 + rcdt_out[2] <= #5 1'b1; + end + always @(negedge rcdt_in[2]) + begin:TRCDfall2 + rcdt_out[2] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[3]) + begin:TRCDrise3 + rcdt_out[3] <= #5 1'b1; + end + always @(negedge rcdt_in[3]) + begin:TRCDfall3 + rcdt_out[3] <= #tdevice_TRCD 1'b0; + end + + ///////////////////////////////////////////////////////////////////////// + // Functional Section + ///////////////////////////////////////////////////////////////////////// + always @(posedge CLK) + begin + if ($time > Next_Ref && PoweredUp && Ref_Cnt > 0) + begin + Ref_Cnt = Ref_Cnt - 1; + Next_Ref = $time + tdevice_REF; + end + if (CKEreg) + begin + if (~CSNeg_ipd) + chip_en = 1; + else + chip_en = 0; + end + + if (CKEreg && ~CSNeg_ipd) + begin + if (WENeg_ipd == 1'bx) + $display(" Unusable value for WENeg "); + if (RASNeg_ipd == 1'bx) + $display(" Unusable value for RASNeg "); + if (CASNeg_ipd == 1'bx) + $display(" Unusable value for CASNeg "); + + // Command Decode + if (RASNeg_ipd && CASNeg_ipd && WENeg_ipd) + command = nop; + else if (~RASNeg_ipd && CASNeg_ipd && WENeg_ipd) + command = act; + else if (RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd) + command = rd; + else if (RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd) + command = writ; + else if (RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd) + command = bst; + else if (~RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd) + command = pre; + else if (~RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd) + command = ref; + else if (~RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd) + command = mrs; + + // PowerUp Check + if (~(PoweredUp) && command != nop) + begin + $display (" Incorrect power up. Command issued before "); + $display (" power up complete. "); + end + + // Bank Decode + if (~BA0_ipd && ~BA1_ipd) + cur_bank = 0; + else if (BA0_ipd && ~BA1_ipd) + cur_bank = 1; + else if (~BA0_ipd && BA1_ipd) + cur_bank = 2; + else if (BA0_ipd && BA1_ipd) + cur_bank = 3; + else + begin + $display ("Could not decode bank selection - results"); + $display ("may be incorrect."); + end + end + + // The Big State Machine + if (CKEreg) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + + if (CSNeg_ipd) + command = nop; + + // DQM pipeline + DQM0_reg2 = DQM0_reg1; + DQM0_reg1 = DQM0_reg0; + DQM0_reg0 = DQM0_ipd; + DQM1_reg2 = DQM1_reg1; + DQM1_reg1 = DQM1_reg0; + DQM1_reg0 = DQM1_ipd; + + // by default data drive is Z, might get over written in one + // of the passes below + DataDrive = 16'bz; + + for (bank = 0; bank <= hi_bank; bank = bank + 1) + begin + case (statebank[bank]) + pwron : + begin + if (~PoweredUp) + begin + if (command != nop) + $display ("Only NOPs allowed during power up."); + DataDrive = 16'bz; + end + else if (command == pre && (cur_bank == bank || A[10])) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + end + + precharge : + begin + if (cur_bank == bank) + // It is only an error if this bank is selected + if (command != nop && command != pre) + begin + $display ("Illegal command received "); + $display ("during precharge.",$time); + end + end + + idle : + begin + if (command == nop || command == bst || command == pre + || cur_bank != bank) + begin + end + else if (command == mrs) + begin + if (statebank[0] == idle && statebank[1] == idle && + statebank[2] == idle && statebank[3] == idle) + begin + ModeReg = A; + statebank[bank] = mode_set; + end + end + else if (command == ref) + begin + if (statebank[0] == idle && statebank[1] == idle && + statebank[2] == idle && statebank[3] == idle) + if (CKE) + begin + statebank[bank] = auto_refresh; + statebank[bank] <= #tdevice_TRCAR idle; + end + else + begin + statebank[0] = self_refresh; + statebank[1] = self_refresh; + statebank[2] = self_refresh; + statebank[3] = self_refresh; + end + end + else if (command == act) + begin + statebank[bank] = bank_act; + ras_in[bank] = 1'b1; + ras_in [bank] <= #70 1'b0; + rct_in = 1'b1; + rct_in <= #1 1'b0; + rcdt_in[bank] = 1'b1; + rcdt_in[bank] <= #1 1'b0; + MemAddr[bank][19:8] = A; // latch row addr + end + else + $display ("Illegal command received in idle state.",$time); + end + + mode_set : + begin + if (ModeReg[7] != 0 || ModeReg[8] != 0) + $display ("Illegal operating mode set."); + if (command != nop) + begin + $display ("Illegal command received during mode"); + $display ("set.",$time); + end + + // read burst length + if (ModeReg[2:0] == 3'b000) + begin + BurstLen = 1; + Burst_Bits = 0; + end + else if (ModeReg[2:0] == 3'b001) + begin + BurstLen = 2; + Burst_Bits = 1; + end + else if (ModeReg[2:0] == 3'b010) + begin + BurstLen = 4; + Burst_Bits = 2; + end + else if (ModeReg[2:0] == 3'b011) + begin + BurstLen = 8; + Burst_Bits = 3; + end + else if (ModeReg[2:0] == 3'b111) + begin + BurstLen = 256; + Burst_Bits = 7; + end + else + $display ("Invalid burst length specified."); + + // read burst type + if (~ModeReg[3]) + Burst = sequential; + else if (ModeReg[3]) + Burst = interleave; + else + $display ("Invalid burst type specified."); + + // read CAS latency + if (ModeReg[6:4] == 3'b010) + begin + CAS_Lat = 1'b0; + CAS_Lat2 = 1'b1; + end + else if (ModeReg[6:4] == 3'b011) + begin + CAS_Lat = 1'b1; + CAS_Lat2 = 1'b1; + end + else + $display ("CAS Latency set incorrecty"); + + // write burst mode + if (~ModeReg[9]) + WB = programmed; + else if (ModeReg[9]) + WB = single; + else + $display ("Invalid burst type specified."); + + statebank[bank] = idle; + end + + auto_refresh : + begin + if (Ref_Cnt < 8192) + Ref_Cnt = Ref_Cnt + 1; + if (command != nop) + begin + $display ("Illegal command received during"); + $display ("auto_refresh.",$time); + end + end + + bank_act : + begin + if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("precharge command does not meet tRAS"); + $display ("time", $time); + end + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else if (command == nop || command == bst + || cur_bank != bank) + begin + end + else if (command == rd) + begin + if (rcdt_out[bank]) + begin + $display ("read command received too soon"); + $display ("after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during read command."); + $display ("Next state unknown."); + end + MemAddr[bank][7:0] = 8'b0;// clr old addr + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + BurstIncProc(bank); + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive,bank); + BurstCnt[bank] = 1; + NextStateAuto(bank, read); + bank_tmp = bank; + end + else if (command == writ) + begin + if (rcdt_out[bank]) + begin + $display ("write command received too soon"); + $display ("after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during write command."); + $display ("Next state unknown."); + end + MemAddr[bank][7:0] = 8'b0; // clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank, write); + written = 1'b1; + end + else if (cur_bank == bank || command == mrs) + begin + $display ("Illegal command received in"); + $display ("active state",$time); + end + end + + write : + begin + if (command == bst) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + end + else if (command == rd) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank, read); + end + else + statebank[bank] = bank_act; + else if (command == writ) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + if (A[10]) + statebank[bank] = write_auto_pre; + end + else + statebank[bank] = bank_act; + else if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("precharge command does not meet tRAS time",$time); + end + if (~DQM0_ipd) + begin + $display ("DQM0 should be held high, data is"); + $display ("lost.",$time); + end + if (~DQM1_ipd) + begin + $display ("DQM1 should be held high, data is"); + $display ("lost.",$time); + end + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else if (command == nop || cur_bank != bank) + if (BurstCnt[bank] == BurstLen || WB == single) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + else if (cur_bank == bank) + $display ("Illegal command received in write state",$time); + end + + read : + begin + if (command == bst) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + end + else if (command == rd) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank, read); + end + else + statebank[bank] = bank_act; + else if (command == writ) + if (cur_bank == bank) + begin + if (rcdt_out[bank]) + begin + $display ("write command received too soon after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during write command."); + $display ("Next state unknown."); + end + + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank,write); + end + else + statebank[bank] = bank_act; + + else if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("Precharge command does not meet tRAS time",$time); + end + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + + else if (command == nop || cur_bank != bank) + begin + if (BurstCnt[bank] == BurstLen) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + end + else if (cur_bank == bank) + $display ("Illegal command received in read state",$time); + end + + write_auto_pre : + begin + if (command == nop || cur_bank != bank) + if (BurstCnt[bank] == BurstLen || WB == single) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + else + $display ("Illegal command received in write state.",$time); + end + + read_auto_pre : + begin + if (command == nop || (cur_bank != bank && command != rd + && command != writ)) + if (BurstCnt[bank] == BurstLen) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 2*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + else if ((command == rd || command == writ) && cur_bank + != bank) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else + $display ("Illegal command received in read state",$time); + end + endcase + end + + // Check Refresh Status + if (written && (Ref_Cnt == 0)) + $display ("memory not refreshed (by ref_cnt)", $time); + + DataDrive3 = DataDrive2; + DataDrive2 = DataDrive1; + DataDrive1 = DataDrive; + + end + + // Latency adjustments and DQM read masking + if (~DQM0_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[7:0] = DataDrive3[7:0]; + else + DataDriveOut[7:0] = DataDrive2[7:0]; + else + DataDriveOut[7:0] = 8'bz; + + if (~DQM1_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[15:8] = DataDrive3[15:8]; + else + DataDriveOut[15:8] = DataDrive2[15:8]; + else + DataDriveOut[15:8] = 8'bz; + + // The Powering-up State Machine + if (~CKEreg && CKE_ipd) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + if (CSNeg_ipd) + command = nop; + + case (statebank[cur_bank]) + write_suspend : + begin + statebank[cur_bank] = write; + end + + read_suspend : + begin + statebank[cur_bank] = read; + end + + self_refresh : + begin + statebank[0] <= #tdevice_TRP idle; + statebank[1] <= #tdevice_TRP idle; + statebank[2] <= #tdevice_TRP idle; + statebank[3] <= #tdevice_TRP idle; + Ref_Cnt = 8192; + if (command != nop) + begin + $display ("Illegal command received during self"); + $display ("refresh",$time); + end + end + + pwrdwn : + begin + statebank[0] = idle; + statebank[1] = idle; + statebank[2] = idle; + statebank[3] = idle; + end + + bank_act_pwrdwn : + begin + statebank[cur_bank] = bank_act; + end + endcase + end + + // The Powering-down State Machine + if (CKEreg && ~CKE_ipd) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + if (CSNeg_ipd) + command = nop; + + case (statebank[cur_bank]) + idle : + begin + if (command == nop) + begin + statebank[0] = pwrdwn; + statebank[1] = pwrdwn; + statebank[2] = pwrdwn; + statebank[3] = pwrdwn; + end + end + + write : + begin + statebank[cur_bank] = write_suspend; + end + + read : + begin + statebank[cur_bank] = read_suspend; + end + + bank_act : + begin + statebank[cur_bank] = bank_act_pwrdwn; + end + endcase + end + + CKEreg = CKE_ipd; + end + + always @(DataDriveOut) + begin + DQ_zd = DataDriveOut; + end + + reg TRASMIN_In, TRASMAX_In, TRC_In , TRCAR_In; + reg TRCD_In , TRP_In , TWR_In; + wire TRASMIN_Out,TRASMAX_Out,TRC_Out,TRCAR_Out, TRCD_Out, TRP_Out, TWR_Out; + + BUFFER BUF_TRASMIN (TRASMIN_Out , TRASMIN_In); + BUFFER BUF_TRASMAX (TRASMAX_Out , TRASMAX_In); + BUFFER BUF_TRC (TRC_Out , TRC_In); + BUFFER BUF_TRCAR (TRCAR_Out, TRCAR_In); + BUFFER BUF_TRCD (TRCD_Out , TRCD_In); + BUFFER BUF_TRP (TRP_Out , TRP_In); + + initial + begin + TRASMIN_In = 1; + TRASMAX_In = 1; + TRC_In = 1; + TRCAR_In = 1; + TRCD_In = 1'b1; + TRP_In = 1; + TWR_In = 1; + end + + always @(posedge TRC_Out) + begin + tdevice_TRC = $time; + end + + always @(posedge TRASMIN_Out) + begin + tdevice_TRASmin = $time; + end + + always @(posedge TRASMAX_Out) + begin + tdevice_TRASmax = $time; + end + + always @(posedge TRCAR_Out) + begin + tdevice_TRCAR = $time; + end + + always @(posedge TRCD_Out) + begin + tdevice_TRCD = $time; + end + + always @(posedge TRP_Out) + begin + tdevice_TRP = $time; + end + +endmodule + +module BUFFER (OUT,IN); + input IN; + output OUT; + buf (OUT, IN); +endmodule
trunk/verif/model/mt48lc4m16.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/verif/model/mt48lc4m32b2.v =================================================================== --- trunk/verif/model/mt48lc4m32b2.v (nonexistent) +++ trunk/verif/model/mt48lc4m32b2.v (revision 7) @@ -0,0 +1,1976 @@ +////////////////////////////////////////////////////////////////////////////// +// File name : mt48lc4m32b2.v +////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2006 Free Model Foundry; http://www.freemodelfoundry.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// MODIFICATION HISTORY: +// +// version: | author: | mod date: | changes made: +// V1.0 I.Milutinovic 06 Apr 18 Initial release +// +////////////////////////////////////////////////////////////////////////////// +// PART DESCRIPTION: +// +// Library: RAM +// Technology: LVTTL +// Part: MT48LC4M32B2 +// +// Description: 1M x 32 x 4Banks SDRAM +// +////////////////////////////////////////////////////////////////////////////// +// Known Bugs: +// +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// +// MODULE DECLARATION // +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns/100 ps + +module mt48lc4m32b2 + ( + A11 , + A10 , + A9 , + A8 , + A7 , + A6 , + A5 , + A4 , + A3 , + A2 , + A1 , + A0 , + + DQ31 , + DQ30 , + DQ29 , + DQ28 , + DQ27 , + DQ26 , + DQ25 , + DQ24 , + DQ23 , + DQ22 , + DQ21 , + DQ20 , + DQ19 , + DQ18 , + DQ17 , + DQ16 , + DQ15 , + DQ14 , + DQ13 , + DQ12 , + DQ11 , + DQ10 , + DQ9 , + DQ8 , + DQ7 , + DQ6 , + DQ5 , + DQ4 , + DQ3 , + DQ2 , + DQ1 , + DQ0 , + + BA0 , + BA1 , + DQM3 , + DQM2 , + DQM1 , + DQM0 , + CLK , + CKE , + WENeg , + RASNeg , + CSNeg , + CASNeg ); + + //////////////////////////////////////////////////////////////////////// + // Port / Part Pin Declarations + //////////////////////////////////////////////////////////////////////// + input A11 ; + input A10 ; + input A9 ; + input A8 ; + input A7 ; + input A6 ; + input A5 ; + input A4 ; + input A3 ; + input A2 ; + input A1 ; + input A0 ; + + inout DQ31 ; + inout DQ30 ; + inout DQ29 ; + inout DQ28 ; + inout DQ27 ; + inout DQ26 ; + inout DQ25 ; + inout DQ24 ; + inout DQ23 ; + inout DQ22 ; + inout DQ21 ; + inout DQ20 ; + inout DQ19 ; + inout DQ18 ; + inout DQ17 ; + inout DQ16 ; + inout DQ15 ; + inout DQ14 ; + inout DQ13 ; + inout DQ12 ; + inout DQ11 ; + inout DQ10 ; + inout DQ9 ; + inout DQ8 ; + inout DQ7 ; + inout DQ6 ; + inout DQ5 ; + inout DQ4 ; + inout DQ3 ; + inout DQ2 ; + inout DQ1 ; + inout DQ0 ; + + input BA0 ; + input BA1 ; + input DQM3 ; + input DQM2 ; + input DQM1 ; + input DQM0 ; + input CLK ; + input CKE ; + input WENeg ; + input RASNeg ; + input CSNeg ; + input CASNeg ; + + // interconnect path delay signals + wire A11_ipd ; + wire A10_ipd ; + wire A9_ipd ; + wire A8_ipd ; + wire A7_ipd ; + wire A6_ipd ; + wire A5_ipd ; + wire A4_ipd ; + wire A3_ipd ; + wire A2_ipd ; + wire A1_ipd ; + wire A0_ipd ; + + wire [11 : 0] A; + assign A = {A11_ipd, + A10_ipd, + A9_ipd, + A8_ipd, + A7_ipd, + A6_ipd, + A5_ipd, + A4_ipd, + A3_ipd, + A2_ipd, + A1_ipd, + A0_ipd }; + + wire DQ31_ipd ; + wire DQ30_ipd ; + wire DQ29_ipd ; + wire DQ28_ipd ; + wire DQ27_ipd ; + wire DQ26_ipd ; + wire DQ25_ipd ; + wire DQ24_ipd ; + wire DQ23_ipd ; + wire DQ22_ipd ; + wire DQ21_ipd ; + wire DQ20_ipd ; + wire DQ19_ipd ; + wire DQ18_ipd ; + wire DQ17_ipd ; + wire DQ16_ipd ; + wire DQ15_ipd ; + wire DQ14_ipd ; + wire DQ13_ipd ; + wire DQ12_ipd ; + wire DQ11_ipd ; + wire DQ10_ipd ; + wire DQ9_ipd ; + wire DQ8_ipd ; + wire DQ7_ipd ; + wire DQ6_ipd ; + wire DQ5_ipd ; + wire DQ4_ipd ; + wire DQ3_ipd ; + wire DQ2_ipd ; + wire DQ1_ipd ; + wire DQ0_ipd ; + + wire [31 : 0 ] DQIn; + assign DQIn = { DQ31_ipd, + DQ30_ipd, + DQ29_ipd, + DQ28_ipd, + DQ27_ipd, + DQ26_ipd, + DQ25_ipd, + DQ24_ipd, + DQ23_ipd, + DQ22_ipd, + DQ21_ipd, + DQ20_ipd, + DQ19_ipd, + DQ18_ipd, + DQ17_ipd, + DQ16_ipd, + DQ15_ipd, + DQ14_ipd, + DQ13_ipd, + DQ12_ipd, + DQ11_ipd, + DQ10_ipd, + DQ9_ipd, + DQ8_ipd, + DQ7_ipd, + DQ6_ipd, + DQ5_ipd, + DQ4_ipd, + DQ3_ipd, + DQ2_ipd, + DQ1_ipd, + DQ0_ipd }; + + wire [31 : 0] DQOut; + assign DQOut = { DQ31, + DQ30, + DQ29, + DQ28, + DQ27, + DQ26, + DQ25, + DQ24, + DQ23, + DQ22, + DQ21, + DQ20, + DQ19, + DQ18, + DQ17, + DQ16, + DQ15, + DQ14, + DQ13, + DQ12, + DQ11, + DQ10, + DQ9, + DQ8, + DQ7, + DQ6, + DQ5, + DQ4, + DQ3, + DQ2, + DQ1, + DQ0 }; + + wire BA0_ipd ; + wire BA1_ipd ; + wire DQM3_ipd ; + wire DQM2_ipd ; + wire DQM1_ipd ; + wire DQM0_ipd ; + wire CLK_ipd ; + wire CKE_ipd ; + wire WENeg_ipd ; + wire RASNeg_ipd ; + wire CSNeg_ipd ; + wire CASNeg_ipd ; + + integer bank; + integer bank_tmp; + + // internal delays + reg rct_in ; + reg rct_out; + reg [3:0] rcdt_in ; + reg [3:0] rcdt_out; + reg pre_in ; + reg pre_out ; + reg refreshed_in ; + reg refreshed_out ; + reg rcar_out ; + reg rcar_in ; + reg wrt_in ; + reg wrt_out ; + reg [3:0] ras_in = 1'b0; + reg [3:0] ras_out = 1'b0; + + reg [31 : 0] DQ_zd = 32'bz; + assign {DQ31_zd, + DQ30_zd, + DQ29_zd, + DQ28_zd, + DQ27_zd, + DQ26_zd, + DQ25_zd, + DQ24_zd, + DQ23_zd, + DQ22_zd, + DQ21_zd, + DQ20_zd, + DQ19_zd, + DQ18_zd, + DQ17_zd, + DQ16_zd, + DQ15_zd, + DQ14_zd, + DQ13_zd, + DQ12_zd, + DQ11_zd, + DQ10_zd, + DQ9_zd, + DQ8_zd, + DQ7_zd, + DQ6_zd, + DQ5_zd, + DQ4_zd, + DQ3_zd, + DQ2_zd, + DQ1_zd, + DQ0_zd } = DQ_zd; + + parameter UserPreload = 1'b1; + parameter mem_file_name = "none"; //"mt48lc4m32b2.mem"; + parameter TimingModel = "DefaultTimingModel"; + parameter PartID = "mt48lc4m32b2"; + parameter hi_bank = 3; + parameter depth = 25'h100000; + + reg PoweredUp = 1'b0; + reg CKEreg = 1'b0; + reg CAS_Lat ; + reg CAS_Lat2; + reg [31:0] DataDrive = 32'bz ; + + // Memory array declaration + integer Mem [0:(hi_bank+1)*depth*4-1]; + + // Type definition for state machine + parameter pwron = 5'd0; + parameter precharge = 5'd1; + parameter idle = 5'd2; + parameter mode_set = 5'd3; + parameter self_refresh = 5'd4; + parameter auto_refresh = 5'd5; + parameter pwrdwn = 5'd6; + parameter bank_act = 5'd7; + parameter bank_act_pwrdwn = 5'd8; + parameter write = 5'd9; + parameter write_suspend = 5'd10; + parameter read = 5'd11; + parameter read_suspend = 5'd12; + parameter write_auto_pre = 5'd13; + parameter read_auto_pre = 5'd14; + + reg [4:0] statebank [hi_bank:0]; + + // Type definition for commands + parameter desl = 4'd0; + parameter nop = 4'd1; + parameter bst = 4'd2; + parameter rd = 4'd3; + parameter writ = 4'd4; + parameter act = 4'd5; + parameter pre = 4'd6; + parameter mrs = 4'd7; + parameter ref = 4'd8; + + reg [3:0] command = desl; + + // burst type + parameter sequential = 1'b0; + parameter interleave = 1'b1; + reg Burst ; + + // write burst mode + parameter programmed = 1'b0; + parameter single = 1'b1; + reg WB ; + + //burst sequences + integer intab [0:63]; + + reg [19:0] MemAddr [hi_bank:0]; + integer BurstCnt [hi_bank:0]; + integer StartAddr [hi_bank:0]; + integer BurstInc [hi_bank:0]; + integer BaseLoc [hi_bank:0]; + + integer Loc; + integer BurstLen; + integer Burst_Bits; + + reg written = 1'b0; + reg chip_en = 1'b0; + + integer cur_bank; + reg [11:0] ModeReg ; + integer Ref_Cnt = 0; + + time Next_Ref = 0; + reg [8*8:1] BankString ; + + reg Viol = 1'b0; + reg [31:0] DataDriveOut = 32'bz; + reg [31:0] DataDrive1 = 32'bz; + reg [31:0] DataDrive2 = 32'bz; + reg [31:0] DataDrive3 = 32'bz; + + reg DQM0_reg0 ; + reg DQM0_reg1 ; + reg DQM0_reg2 ; + reg DQM1_reg0 ; + reg DQM1_reg1 ; + reg DQM1_reg2 ; + reg DQM2_reg0 ; + reg DQM2_reg1 ; + reg DQM2_reg2 ; + reg DQM3_reg0 ; + reg DQM3_reg1 ; + reg DQM3_reg2 ; + + // tdevice values: values for internal delays + time tdevice_TRC = 0; + time tdevice_TRCAR = 0; + time tdevice_TRCD = 0; + time tdevice_TRP = 0; + time tdevice_TWR = 0; + + /////////////////////////////////////////////////////////////////////////// + //Interconnect Path Delay Section + /////////////////////////////////////////////////////////////////////////// + buf (A11_ipd, A11); + buf (A10_ipd, A10); + buf (A9_ipd , A9 ); + buf (A8_ipd , A8 ); + buf (A7_ipd , A7 ); + buf (A6_ipd , A6 ); + buf (A5_ipd , A5 ); + buf (A4_ipd , A4 ); + buf (A3_ipd , A3 ); + buf (A2_ipd , A2 ); + buf (A1_ipd , A1 ); + buf (A0_ipd , A0 ); + + buf (DQ31_ipd , DQ31 ); + buf (DQ30_ipd , DQ30 ); + buf (DQ29_ipd , DQ29 ); + buf (DQ28_ipd , DQ28 ); + buf (DQ27_ipd , DQ27 ); + buf (DQ26_ipd , DQ26 ); + buf (DQ25_ipd , DQ25 ); + buf (DQ24_ipd , DQ24 ); + buf (DQ23_ipd , DQ23 ); + buf (DQ22_ipd , DQ22 ); + buf (DQ21_ipd , DQ21 ); + buf (DQ20_ipd , DQ20 ); + buf (DQ19_ipd , DQ19 ); + buf (DQ18_ipd , DQ18 ); + buf (DQ17_ipd , DQ17 ); + buf (DQ16_ipd , DQ16 ); + buf (DQ15_ipd , DQ15 ); + buf (DQ14_ipd , DQ14 ); + buf (DQ13_ipd , DQ13 ); + buf (DQ12_ipd , DQ12 ); + buf (DQ11_ipd , DQ11 ); + buf (DQ10_ipd , DQ10 ); + buf (DQ9_ipd , DQ9 ); + buf (DQ8_ipd , DQ8 ); + buf (DQ7_ipd , DQ7 ); + buf (DQ6_ipd , DQ6 ); + buf (DQ5_ipd , DQ5 ); + buf (DQ4_ipd , DQ4 ); + buf (DQ3_ipd , DQ3 ); + buf (DQ2_ipd , DQ2 ); + buf (DQ1_ipd , DQ1 ); + buf (DQ0_ipd , DQ0 ); + + buf (CASNeg_ipd, CASNeg); + buf (RASNeg_ipd, RASNeg); + buf (BA0_ipd , BA0 ); + buf (BA1_ipd , BA1 ); + buf (DQM0_ipd , DQM0 ); + buf (DQM1_ipd , DQM1 ); + buf (DQM2_ipd , DQM2 ); + buf (DQM3_ipd , DQM3 ); + buf (CLK_ipd , CLK ); + buf (CKE_ipd , CKE ); + buf (WENeg_ipd , WENeg ); + buf (CSNeg_ipd , CSNeg ); + + /////////////////////////////////////////////////////////////////////////// + // Propagation delay Section + /////////////////////////////////////////////////////////////////////////// + nmos (DQ31 , DQ31_zd , 1); + nmos (DQ30 , DQ30_zd , 1); + nmos (DQ29 , DQ29_zd , 1); + nmos (DQ28 , DQ28_zd , 1); + nmos (DQ27 , DQ27_zd , 1); + nmos (DQ26 , DQ26_zd , 1); + nmos (DQ25 , DQ25_zd , 1); + nmos (DQ24 , DQ24_zd , 1); + nmos (DQ23 , DQ23_zd , 1); + nmos (DQ22 , DQ22_zd , 1); + nmos (DQ21 , DQ21_zd , 1); + nmos (DQ20 , DQ20_zd , 1); + nmos (DQ19 , DQ19_zd , 1); + nmos (DQ18 , DQ18_zd , 1); + nmos (DQ17 , DQ17_zd , 1); + nmos (DQ16 , DQ16_zd , 1); + nmos (DQ15 , DQ15_zd , 1); + nmos (DQ14 , DQ14_zd , 1); + nmos (DQ13 , DQ13_zd , 1); + nmos (DQ12 , DQ12_zd , 1); + nmos (DQ11 , DQ11_zd , 1); + nmos (DQ10 , DQ10_zd , 1); + nmos (DQ9 , DQ9_zd , 1); + nmos (DQ8 , DQ8_zd , 1); + nmos (DQ7 , DQ7_zd , 1); + nmos (DQ6 , DQ6_zd , 1); + nmos (DQ5 , DQ5_zd , 1); + nmos (DQ4 , DQ4_zd , 1); + nmos (DQ3 , DQ3_zd , 1); + nmos (DQ2 , DQ2_zd , 1); + nmos (DQ1 , DQ1_zd , 1); + nmos (DQ0 , DQ0_zd , 1); + + wire deg; + wire chip_act; + assign chip_act = chip_en; + + wire chip_act_deg; + assign chip_act_deg = chip_act && deg; + + wire cas_latency1; + wire cas_latency2; + wire cas_latency3; + + assign cas_latency1 = CAS_Lat && ~CAS_Lat2; + assign cas_latency2 = ~CAS_Lat && CAS_Lat2; + assign cas_latency3 = CAS_Lat && CAS_Lat2; + + specify + // tipd delays: interconnect path delays, mapped to input port delays. + // In Verilog it is not necessary to declare any tipd delay variables, + // they can be taken from SDF file + // With all the other delays real delays would be taken from SDF file + + // tpd delays + specparam tpd_CLK_DQ1 = 1; + specparam tpd_CLK_DQ2 = 1; + specparam tpd_CLK_DQ3 = 1; + + // tpw values: pulse widths + specparam tpw_CLK_posedge = 1; + specparam tpw_CLK_negedge = 1; + + // tsetup values: setup times + specparam tsetup_DQ0_CLK = 1; // tDS + + // thold values: hold times + specparam thold_DQ0_CLK = 1; // tDH + + // tperiod_min: minimum clock period = 1/max freq + specparam tperiod_CLK_cl0_eq_1_posedge = 1; //tCK + specparam tperiod_CLK_cl1_eq_1_posedge = 1; + specparam tperiod_CLK_cl2_eq_1_posedge = 1; + + // tdevice values: values for internal delays + specparam tdevice_REF = 15625 ; + specparam tdevice_TRASmin = 42; + specparam tdevice_TRASmax = 120000; + + /////////////////////////////////////////////////////////////////////// + // Input Port Delays don't require Verilog description + /////////////////////////////////////////////////////////////////////// + // Path delays // + /////////////////////////////////////////////////////////////////////// + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ1; + if (CAS_Lat && ~CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ1; + + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ2; + if (~CAS_Lat && CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ2; + + if (CAS_Lat && CAS_Lat2) (CLK *> DQ0) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ1) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ2) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ3) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ4) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ5) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ6) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ7) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ8) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ9) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ10) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ11) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ12) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ13) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ14) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ15) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ16) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ17) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ18) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ19) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ20) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ21) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ22) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ23) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ24) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ25) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ26) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ27) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ28) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ29) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ30) = tpd_CLK_DQ3; + if (CAS_Lat && CAS_Lat2) (CLK *> DQ31) = tpd_CLK_DQ3; + + //////////////////////////////////////////////////////////////////////// + // Timing Check Section + //////////////////////////////////////////////////////////////////////// + $setup (BA0 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (BA1 , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQM0, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQM1, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQM2, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (DQM3, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CKE , posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (WENeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CSNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (CASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (RASNeg, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + + $setup (DQ0 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ1 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ2 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ3 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ4 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ5 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ6 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ7 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ8 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ9 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ10 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ11 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ12 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ13 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ14 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ15 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ16 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ17 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ18 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ19 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ20 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ21 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ22 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ23 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ24 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ25 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ26 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ27 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ28 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ29 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ30 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + $setup (DQ31 ,posedge CLK &&& chip_act_deg, tsetup_DQ0_CLK, Viol); + + $setup (A0, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A1, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A2, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A3, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A4, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A5, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A6, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A7, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A8, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A9, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A10, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + $setup (A11, posedge CLK &&& chip_act, tsetup_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act, BA0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, BA1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQM0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQM1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQM2, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, DQM3, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CKE , thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CASNeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, RASNeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, WENeg, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, CSNeg, thold_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act, A0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A2, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A3, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A4, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A5, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A6, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A7, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A8, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A9, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A10, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act, A11, thold_DQ0_CLK, Viol); + + $hold (posedge CLK &&& chip_act_deg, DQ0, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ1, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ2, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ3, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ4, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ5, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ6, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ7, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ8, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ9, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ10, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ11, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ12, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ13, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ14, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ15, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ16, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ17, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ18, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ19, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ20, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ21, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ22, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ23, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ24, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ25, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ26, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ27, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ28, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ29, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ30, thold_DQ0_CLK, Viol); + $hold (posedge CLK &&& chip_act_deg, DQ31, thold_DQ0_CLK, Viol); + + $width (posedge CLK &&& chip_act, tpw_CLK_posedge); + $width (negedge CLK &&& chip_act, tpw_CLK_negedge); + + $period (posedge CLK &&& cas_latency1, tperiod_CLK_cl0_eq_1_posedge); + $period (posedge CLK &&& cas_latency2, tperiod_CLK_cl1_eq_1_posedge); + $period (posedge CLK &&& cas_latency3, tperiod_CLK_cl2_eq_1_posedge); + + endspecify + + task generate_out ; + output [31:0] DataDrive; + input Bank; + integer Bank; + integer location; + begin + location = Bank * depth * 4 + Loc; + + DataDrive[7:0] = 8'bx; + if (Mem[location] > -1) + DataDrive[7:0] = Mem[location]; + + DataDrive[15:8] = 8'bx; + if (Mem[location+1] > -1) + DataDrive[15:8] = Mem[location+1]; + + DataDrive[23:16] = 8'bx; + if (Mem[location+2] > -1) + DataDrive[23:16] = Mem[location+2]; + + DataDrive[31:24] = 8'bx; + if (Mem[location+3] > -1) + DataDrive[31:24] = Mem[location+3]; + end + endtask + + task MemWrite; + input Bank; + integer Bank; + integer location; + begin + location = Bank * depth * 4 + Loc; + + if (~DQM0_ipd) + begin + Mem[location] = -1; + if (~Viol) + Mem[location] = DQIn[7:0]; + end + + if (~DQM1_ipd) + begin + Mem[location+1] = -1; + if (~Viol) + Mem[location+1] = DQIn[15:8]; + end + + if (~DQM2_ipd) + begin + Mem[location+2] = -1; + if (~Viol) + Mem[location+2] = DQIn[23:16]; + end + + if (~DQM3_ipd) + begin + Mem[location+3] = -1; + if (~Viol) + Mem[location+3] = DQIn[31:24]; + end + end + endtask + + task BurstIncProc; + input Bank; + integer Bank; + begin + BurstInc[Bank] = 0; + if (Burst_Bits == 1) + BurstInc[Bank] = A[0:0]; + if (Burst_Bits == 2) + BurstInc[Bank] = A[1:0]; + if (Burst_Bits == 3) + BurstInc[Bank] = A[2:0]; + if (Burst_Bits == 7) + BurstInc[Bank] = A[6:0]; + end + endtask + + task NextStateAuto; + input Bank; + input state; + integer Bank; + reg [4:0] state; + begin + if (~A[10]) + statebank[Bank] = state; + else if (A[10]) + if (state == write) + statebank[Bank] = write_auto_pre; + else + statebank[Bank] = read_auto_pre; + end + endtask + + ////////////////////////////////////////////////////////////////////////// + // Main Behavior Block // + ////////////////////////////////////////////////////////////////////////// + + // chech when data is generated from model to avoid setup/hold check in + // those occasion + reg deq; + always @(DQIn, DQOut) + begin + if (DQIn==DQOut) + deq=1'b1; + else + deq=1'b0; + end + assign deg=deq; + + // initialize burst sequences + initial + begin + intab[0] = 0; + intab[1] = 1; + intab[2] = 2; + intab[3] = 3; + intab[4] = 4; + intab[5] = 5; + intab[6] = 6; + intab[7] = 7; + intab[8] = 1; + intab[9] = 0; + intab[10] = 3; + intab[11] = 2; + intab[12] = 5; + intab[13] = 4; + intab[14] = 7; + intab[15] = 6; + intab[16] = 2; + intab[17] = 3; + intab[18] = 0; + intab[19] = 1; + intab[20] = 6; + intab[21] = 7; + intab[22] = 4; + intab[23] = 5; + intab[24] = 3; + intab[25] = 2; + intab[26] = 1; + intab[27] = 0; + intab[28] = 7; + intab[29] = 6; + intab[30] = 5; + intab[31] = 4; + intab[32] = 4; + intab[33] = 5; + intab[34] = 6; + intab[35] = 7; + intab[36] = 0; + intab[37] = 1; + intab[38] = 2; + intab[39] = 3; + intab[40] = 5; + intab[41] = 4; + intab[42] = 7; + intab[43] = 6; + intab[44] = 1; + intab[45] = 0; + intab[46] = 3; + intab[47] = 2; + intab[48] = 6; + intab[49] = 7; + intab[50] = 4; + intab[51] = 5; + intab[52] = 2; + intab[53] = 3; + intab[54] = 0; + intab[55] = 1; + intab[56] = 7; + intab[57] = 6; + intab[58] = 5; + intab[59] = 4; + intab[60] = 3; + intab[61] = 2; + intab[62] = 1; + intab[63] = 0; + end + + // initialize memory and load preload files if any + initial + begin: InitMemory + integer i; + for (i=0; i<=((hi_bank+1)*depth*4 - 1); i=i+1) + begin + Mem[i] = -1; + end + // Memory preload file + // mt48lc4m32b2.mem file + // @bbbbbb - stands for address within memory, + // dd -
is word to be written at Mem(bbbbbb++) + // (bbbbbb is incremented at every load) + if (UserPreload && !(mem_file_name == "none")) + $readmemh(mem_file_name,Mem); + end + + //Power Up time 100 us; + initial + begin + PoweredUp = 1'b0; + statebank[0] = pwron; + statebank[1] = pwron; + statebank[2] = pwron; + statebank[3] = pwron; + #100000 PoweredUp = 1'b1; + end + + always @(posedge wrt_in) + begin:TWRrise + #tdevice_TWR wrt_out = wrt_in; + end + + always @(negedge wrt_in) + begin:TWRfall + #1 wrt_out = wrt_in; + end + + always @(posedge ras_in[0]) + begin:TRASrise0 + ras_out[0] <= #tdevice_TRASmin ras_in[0]; + end + + always @(negedge ras_in[0]) + begin:TRASfall0 + ras_out[0] <= #tdevice_TRASmax ras_in[0]; + end + + always @(posedge ras_in[1]) + begin:TRASrise1 + ras_out[1] <= #tdevice_TRASmin ras_in[1]; + end + + always @(negedge ras_in[1]) + begin:TRASfall1 + ras_out[1] <= #tdevice_TRASmax ras_in[1]; + end + + always @(posedge ras_in[2]) + begin:TRASrise2 + ras_out[2] <= #tdevice_TRASmin ras_in[2]; + end + always @(negedge ras_in[2]) + begin:TRASfall2 + ras_out[2] <= #tdevice_TRASmax ras_in[2]; + end + + always @(posedge ras_in[3]) + begin:TRASrise3 + ras_out[3] <= #tdevice_TRASmin ras_in[3]; + end + + always @(negedge ras_in[3]) + begin:TRASfall3 + ras_out[3] <= #tdevice_TRASmax ras_in[3]; + end + + always @(posedge rcdt_in[0]) + begin:TRCDrise0 + rcdt_out[0] <= #5 1'b1; + end + always @(negedge rcdt_in[0]) + begin:TRCDfall0 + rcdt_out[0] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[1]) + begin:TRCDrise1 + rcdt_out[1] <= #5 1'b1; + end + always @(negedge rcdt_in[1]) + begin:TRCDfall1 + rcdt_out[1] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[2]) + begin:TRCDrise2 + rcdt_out[2] <= #5 1'b1; + end + always @(negedge rcdt_in[2]) + begin:TRCDfall2 + rcdt_out[2] <= #tdevice_TRCD 1'b0; + end + + always @(posedge rcdt_in[3]) + begin:TRCDrise3 + rcdt_out[3] <= #5 1'b1; + end + always @(negedge rcdt_in[3]) + begin:TRCDfall3 + rcdt_out[3] <= #tdevice_TRCD 1'b0; + end + + ///////////////////////////////////////////////////////////////////////// + // Functional Section + ///////////////////////////////////////////////////////////////////////// + always @(posedge CLK) + begin + if ($time > Next_Ref && PoweredUp && Ref_Cnt > 0) + begin + Ref_Cnt = Ref_Cnt - 1; + Next_Ref = $time + tdevice_REF; + end + if (CKEreg) + begin + if (~CSNeg_ipd) + chip_en = 1; + else + chip_en = 0; + end + + if (CKEreg && ~CSNeg_ipd) + begin + if (DQM0_ipd == 1'bx) + $display(" Unusable value for DQM0 "); + if (DQM1_ipd == 1'bx) + $display(" Unusable value for DQM1 "); + if (DQM2_ipd == 1'bx) + $display(" Unusable value for DQM2 "); + if (DQM3_ipd == 1'bx) + $display(" Unusable value for DQM3 "); + if (WENeg_ipd == 1'bx) + $display(" Unusable value for WENeg "); + if (RASNeg_ipd == 1'bx) + $display(" Unusable value for RASNeg "); + if (CASNeg_ipd == 1'bx) + $display(" Unusable value for CASNeg "); + + // Command Decode + if (RASNeg_ipd && CASNeg_ipd && WENeg_ipd) + command = nop; + else if (~RASNeg_ipd && CASNeg_ipd && WENeg_ipd) + command = act; + else if (RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd) + command = rd; + else if (RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd) + command = writ; + else if (RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd) + command = bst; + else if (~RASNeg_ipd && CASNeg_ipd && ~WENeg_ipd) + command = pre; + else if (~RASNeg_ipd && ~CASNeg_ipd && WENeg_ipd) + command = ref; + else if (~RASNeg_ipd && ~CASNeg_ipd && ~WENeg_ipd) + command = mrs; + + // PowerUp Check + if (~(PoweredUp) && command != nop) + begin + $display (" Incorrect power up. Command issued before "); + $display (" power up complete. "); + end + + // Bank Decode + if (~BA0_ipd && ~BA1_ipd) + cur_bank = 0; + else if (BA0_ipd && ~BA1_ipd) + cur_bank = 1; + else if (~BA0_ipd && BA1_ipd) + cur_bank = 2; + else if (BA0_ipd && BA1_ipd) + cur_bank = 3; + else + begin + $display ("Could not decode bank selection - results"); + $display ("may be incorrect."); + end + end + + // The Big State Machine + if (CKEreg) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + + if (CSNeg_ipd) + command = nop; + + // DQM pipeline + DQM0_reg2 = DQM0_reg1; + DQM0_reg1 = DQM0_reg0; + DQM0_reg0 = DQM0_ipd; + DQM1_reg2 = DQM1_reg1; + DQM1_reg1 = DQM1_reg0; + DQM1_reg0 = DQM1_ipd; + DQM2_reg2 = DQM2_reg1; + DQM2_reg1 = DQM2_reg0; + DQM2_reg0 = DQM2_ipd; + DQM3_reg2 = DQM3_reg1; + DQM3_reg1 = DQM3_reg0; + DQM3_reg0 = DQM3_ipd; + + // by default data drive is Z, might get over written in one + // of the passes below + DataDrive = 32'bz; + + for (bank = 0; bank <= hi_bank; bank = bank + 1) + begin + case (statebank[bank]) + pwron : + begin + if (~DQM0_ipd) + begin + $display ("DQM0 must be held high during"); + $display ("initialization."); + end + if (~DQM1_ipd) + begin + $display ("DQM1 must be held high during"); + $display ("initialization."); + end + if (~DQM2_ipd) + begin + $display ("DQM2 must be held high during"); + $display ("initialization."); + end + if (~DQM3_ipd) + begin + $display ("DQM3 must be held high during"); + $display ("initialization."); + end + + if (~PoweredUp) + begin + if (command != nop) + $display ("Only NOPs allowed during power up."); + DataDrive = 32'bz; + end + else if (command == pre && (cur_bank == bank || A[10])) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + end + + precharge : + begin + if (cur_bank == bank) + // It is only an error if this bank is selected + if (command != nop && command != pre) + begin + $display ("Illegal command received "); + $display ("during precharge.",$time); + end + end + + idle : + begin + if (command == nop || command == bst || command == pre + || cur_bank != bank) + begin + end + else if (command == mrs) + begin + if (statebank[0] == idle && statebank[1] == idle && + statebank[2] == idle && statebank[3] == idle) + begin + ModeReg = A; + statebank[bank] = mode_set; + end + end + else if (command == ref) + begin + if (statebank[0] == idle && statebank[1] == idle && + statebank[2] == idle && statebank[3] == idle) + if (CKE) + begin + statebank[bank] = auto_refresh; + statebank[bank] <= #tdevice_TRCAR idle; + end + else + begin + statebank[0] = self_refresh; + statebank[1] = self_refresh; + statebank[2] = self_refresh; + statebank[3] = self_refresh; + end + end + else if (command == act) + begin + statebank[bank] = bank_act; + ras_in[bank] = 1'b1; + ras_in [bank] <= #70 1'b0; + rct_in = 1'b1; + rct_in <= #1 1'b0; + rcdt_in[bank] = 1'b1; + rcdt_in[bank] <= #1 1'b0; + MemAddr[bank][19:8] = A; // latch row addr + end + else + $display ("Illegal command received in idle state.",$time); + end + + mode_set : + begin + if (ModeReg[7] != 0 || ModeReg[8] != 0) + $display ("Illegal operating mode set."); + if (command != nop) + begin + $display ("Illegal command received during mode"); + $display ("set.",$time); + end + + // read burst length + if (ModeReg[2:0] == 3'b000) + begin + BurstLen = 1; + Burst_Bits = 0; + end + else if (ModeReg[2:0] == 3'b001) + begin + BurstLen = 2; + Burst_Bits = 1; + end + else if (ModeReg[2:0] == 3'b010) + begin + BurstLen = 4; + Burst_Bits = 2; + end + else if (ModeReg[2:0] == 3'b011) + begin + BurstLen = 8; + Burst_Bits = 3; + end + else if (ModeReg[2:0] == 3'b111) + begin + BurstLen = 256; + Burst_Bits = 7; + end + else + $display ("Invalid burst length specified."); + + // read burst type + if (~ModeReg[3]) + Burst = sequential; + else if (ModeReg[3]) + Burst = interleave; + else + $display ("Invalid burst type specified."); + + // read CAS latency + if (ModeReg[6:4] == 3'b001) + begin + CAS_Lat = 1'b1; + CAS_Lat2 = 1'b0; + end + else if (ModeReg[6:4] == 3'b010) + begin + CAS_Lat = 1'b0; + CAS_Lat2 = 1'b1; + end + else if (ModeReg[6:4] == 3'b011) + begin + CAS_Lat = 1'b1; + CAS_Lat2 = 1'b1; + end + else + $display ("CAS Latency set incorrecty"); + + // write burst mode + if (~ModeReg[9]) + WB = programmed; + else if (ModeReg[9]) + WB = single; + else + $display ("Invalid burst type specified."); + + statebank[bank] = idle; + end + + auto_refresh : + begin + if (Ref_Cnt < 4096) + Ref_Cnt = Ref_Cnt + 1; + if (command != nop) + begin + $display ("Illegal command received during"); + $display ("auto_refresh.",$time); + end + end + + bank_act : + begin + if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("precharge command does not meet tRAS"); + $display ("time", $time); + end + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else if (command == nop || command == bst + || cur_bank != bank) + begin + end + else if (command == rd) + begin + if (rcdt_out[bank]) + begin + $display ("read command received too soon"); + $display ("after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during read command."); + $display ("Next state unknown."); + end + MemAddr[bank][7:0] = 8'b0;// clr old addr + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + BurstIncProc(bank); + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive,bank); + BurstCnt[bank] = 1; + NextStateAuto(bank, read); + bank_tmp = bank; + end + else if (command == writ) + begin + if (rcdt_out[bank]) + begin + $display ("write command received too soon"); + $display ("after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during write command."); + $display ("Next state unknown."); + end + MemAddr[bank][7:0] = 8'b0; // clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + wrt_in = 1'b1; + NextStateAuto(bank, write); + written = 1'b1; + end + else if (cur_bank == bank || command == mrs) + begin + $display ("Illegal command received in"); + $display ("active state",$time); + end + end + + write : + begin + if (command == bst) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + end + else if (command == rd) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank, read); + end + else + statebank[bank] = bank_act; + else if (command == writ) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + wrt_in = 1'b1; + if (A[10]) + statebank[bank] = write_auto_pre; + end + else + statebank[bank] = bank_act; + else if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("precharge command does not meet tRAS time",$time); + end + if (~DQM0_ipd) + begin + $display ("DQM0 should be held high, data is"); + $display ("lost.",$time); + end + if (~DQM1_ipd) + begin + $display ("DQM1 should be held high, data is"); + $display ("lost.",$time); + end + if (~DQM2_ipd) + begin + $display ("DQM2 should be held high, data is"); + $display ("lost.",$time); + end + if (~DQM2_ipd) + begin + $display ("DQM2 should be held high, data is"); + $display ("lost.",$time); + end + wrt_in = 1'b0; + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else if (command == nop || cur_bank != bank) + if (BurstCnt[bank] == BurstLen || WB == single) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + wrt_in = 1'b1; + end + else if (cur_bank == bank) + $display ("Illegal command received in write state",$time); + end + + read : + begin + if (command == bst) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + end + else if (command == rd) + if (cur_bank == bank) + begin + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = 1'b1; + NextStateAuto(bank, read); + end + else + statebank[bank] = bank_act; + else if (command == writ) + if (cur_bank == bank) + begin + if (rcdt_out[bank]) + begin + $display ("write command received too soon after active",$time); + end + if (A[10] == 1'bx) + begin + $display ("A(10) = X during write command."); + $display ("Next state unknown."); + end + + MemAddr[bank][7:0] = 8'b0;// clr old addr + BurstIncProc(bank); + // latch col addr + if (Burst_Bits == 0) + MemAddr[bank][7:0] = A[7:0]; + if (Burst_Bits == 1) + MemAddr[bank][7:1] = A[7:1]; + if (Burst_Bits == 2) + MemAddr[bank][7:2] = A[7:2]; + if (Burst_Bits == 3) + MemAddr[bank][7:3] = A[7:3]; + if (Burst_Bits == 7) + MemAddr[bank][7:7] = A[7:7]; + StartAddr[bank] = BurstInc[bank] % 8; + BaseLoc[bank] = MemAddr[bank]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = 1'b1; + wrt_in = 1'b1; + NextStateAuto(bank,write); + end + else + statebank[bank] = bank_act; + + else if (command == pre && (cur_bank == bank || A[10])) + begin + if (~ras_out[bank]) + begin + $display ("Precharge command does not meet tRAS time",$time); + end + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + + else if (command == nop || cur_bank != bank) + begin + if (BurstCnt[bank] == BurstLen) + begin + statebank[bank] = bank_act; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + end + else if (cur_bank == bank) + $display ("Illegal command received in read state",$time); + end + + write_auto_pre : + begin + if (command == nop || cur_bank != bank) + if (BurstCnt[bank] == BurstLen || WB == single) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + MemWrite(bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + wrt_in = 1'b1; + end + else + $display ("Illegal command received in write state.",$time); + end + + read_auto_pre : + begin + if (command == nop || (cur_bank != bank && command != rd + && command != writ)) + if (BurstCnt[bank] == BurstLen) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + BurstCnt[bank] = 1'b0; + ras_in[bank] = 1'b1; + end + else + begin + if (Burst == sequential) + BurstInc[bank] = (BurstInc[bank]+1) % BurstLen; + else + BurstInc[bank] = + intab[StartAddr[bank]*8 + BurstCnt[bank]]; + Loc = 4*(BaseLoc[bank] + BurstInc[bank]); + generate_out(DataDrive, bank); + BurstCnt[bank] = BurstCnt[bank] + 1; + end + else if ((command == rd || command == writ) && cur_bank + != bank) + begin + statebank[bank] = precharge; + statebank[bank] <= #tdevice_TRP idle; + end + else + $display ("Illegal command received in read state",$time); + end + endcase + end + + // Check Refresh Status + if (written && (Ref_Cnt == 0)) + $display ("memory not refreshed (by ref_cnt)", $time); + + DataDrive3 = DataDrive2; + DataDrive2 = DataDrive1; + DataDrive1 = DataDrive; + + end + + // Latency adjustments and DQM read masking + if (~DQM0_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[7:0] = DataDrive3[7:0]; + else if (~CAS_Lat && CAS_Lat2) + DataDriveOut[7:0] = DataDrive2[7:0]; + else + DataDriveOut[7:0] = DataDrive1[7:0]; + else + DataDriveOut[7:0] = 8'bz; + + if (~DQM1_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[15:8] = DataDrive3[15:8]; + else if (~CAS_Lat && CAS_Lat2) + DataDriveOut[15:8] = DataDrive2[15:8]; + else + DataDriveOut[15:8] = DataDrive1[15:8]; + else + DataDriveOut[15:8] = 8'bz; + + if (~DQM2_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[23:16] = DataDrive3[23:16]; + else if (~CAS_Lat && CAS_Lat2) + DataDriveOut[23:16] = DataDrive2[23:16]; + else + DataDriveOut[23:16] = DataDrive1[23:16]; + else + DataDriveOut[23:16] = 8'bz; + + if (~DQM3_reg1) + if (CAS_Lat && CAS_Lat2) + DataDriveOut[31:24] = DataDrive3[31:24]; + else if (~CAS_Lat && CAS_Lat2) + DataDriveOut[31:24] = DataDrive2[31:24]; + else + DataDriveOut[31:24] = DataDrive1[31:24]; + else + DataDriveOut[31:24] = 8'bz; + + // The Powering-up State Machine + if (~CKEreg && CKE_ipd) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + if (CSNeg_ipd) + command = nop; + + case (statebank[cur_bank]) + write_suspend : + begin + statebank[cur_bank] = write; + end + + read_suspend : + begin + statebank[cur_bank] = read; + end + + self_refresh : + begin + statebank[0] <= #tdevice_TRP idle; + statebank[1] <= #tdevice_TRP idle; + statebank[2] <= #tdevice_TRP idle; + statebank[3] <= #tdevice_TRP idle; + Ref_Cnt = 4096; + if (command != nop) + begin + $display ("Illegal command received during self"); + $display ("refresh",$time); + end + end + + pwrdwn : + begin + statebank[0] = idle; + statebank[1] = idle; + statebank[2] = idle; + statebank[3] = idle; + end + + bank_act_pwrdwn : + begin + statebank[cur_bank] = bank_act; + end + endcase + end + + // The Powering-down State Machine + if (CKEreg && ~CKE_ipd) + begin + if (CSNeg_ipd == 1'bx) + $display ("Unusable value for CSNeg"); + if (CSNeg_ipd) + command = nop; + + case (statebank[cur_bank]) + idle : + begin + if (command == nop) + begin + statebank[0] = pwrdwn; + statebank[1] = pwrdwn; + statebank[2] = pwrdwn; + statebank[3] = pwrdwn; + end + end + + write : + begin + statebank[cur_bank] = write_suspend; + end + + read : + begin + statebank[cur_bank] = read_suspend; + end + + bank_act : + begin + statebank[cur_bank] = bank_act_pwrdwn; + end + endcase + end + + CKEreg = CKE_ipd; + end + + always @(DataDriveOut) + begin + DQ_zd = DataDriveOut; + end + + reg TRC_In , TRCAR_In; + reg TRCD_In , TRP_In , TWR_In; + wire TRC_Out, TRCAR_Out, TRCD_Out, TRP_Out, TWR_Out; + + BUFFER BUF_TRC (TRC_Out , TRC_In); + BUFFER BUF_TRCAR (TRCAR_Out, TRCAR_In); + BUFFER BUF_TRCD (TRCD_Out , TRCD_In); + BUFFER BUF_TRP (TRP_Out , TRP_In); + BUFFER BUF_TWR (TWR_Out , TWR_In); + + initial + begin + TRC_In = 1; + TRCAR_In = 1; + TRCD_In = 1'b1; + TRP_In = 1; + TWR_In = 1; + end + + always @(posedge TRC_Out) + begin + tdevice_TRC = $time; + end + + always @(posedge TRCAR_Out) + begin + tdevice_TRCAR = $time; + end + + always @(posedge TRCD_Out) + begin + tdevice_TRCD = $time; + end + + always @(posedge TRP_Out) + begin + tdevice_TRP = $time; + end + + always @(posedge TWR_Out) + begin + tdevice_TWR = $time; + end + +endmodule + +module BUFFER (OUT,IN); + input IN; + output OUT; + buf (OUT, IN); +endmodule
trunk/verif/model/mt48lc4m32b2.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: trunk/verif/model/IS42VM16400K.V =================================================================== --- trunk/verif/model/IS42VM16400K.V (nonexistent) +++ trunk/verif/model/IS42VM16400K.V (revision 7) @@ -0,0 +1,1728 @@ +/************************************************************************ +* +* Copyright(c) ISSI Inc., 2010 +* +* == 64M Low power SDRAM behavioral Model by ESC == +* +* Address : 1940 Zanker Road San Jose,CA95112-4216,U.S.A. +* Tel : +1-408-969-6600, Fax : +1-408-969-7800 +* +* Revision : Rev0.0 (2010.10.4) +* +* Running Options +* +S50 : Set AC timing parameter for -50(200MHz ) +* +S60 : Set AC timing parameter for -60(166MHz ) +* +S75 : Set AC timing parameter for -75(133MHz ) +* +VERBOSE : Display internal operation status +* +************************************************************************/ + +`timescale 1ns / 1ps + + module IS42VM16400K (dq, addr, ba, clk, cke, csb, rasb, casb, web, dqm); + + parameter no_of_bank = 2; + parameter no_of_addr = 12; + parameter no_of_data = 16; + parameter no_of_col = 8; + parameter no_of_dqm = 2; + parameter mem_sizes = 1048575; + + + // Timing Parameters for -50 PC200 + `ifdef S50 + parameter tAC3 = 5.0; + parameter tHZ3 = 5.0; + parameter tAC2 = 8.0; + parameter tHZ2 = 8.0; + parameter tOH = 2.0; + parameter tMRD = 2.0; + parameter tRAS = 40.0; + parameter tRC = 55.0; + parameter tRCD = 18.0; + parameter tRFC = 60.0; + parameter tXSR = 60.0; + parameter tRP = 15.0; + parameter tRRD = 10.0; + parameter tDPLa = 5.0; + parameter tDPLm = 12.0; + parameter tDPDX = 100000.0; + `endif + + + // Timing Parameters for -60 PC166 + `ifdef S60 + parameter tAC3 = 5.5; + parameter tHZ3 = 5.5; + parameter tAC2 = 8.0; + parameter tHZ2 = 8.0; + parameter tOH = 2.5; + parameter tMRD = 2.0; + parameter tRAS = 42.0; + parameter tRC = 60.0; + parameter tRCD = 18.0; + parameter tRFC = 66.0; + parameter tXSR = 66.0; + parameter tRP = 18.0; + parameter tRRD = 12.0; + parameter tDPLa = 6.0; + parameter tDPLm = 12.0; + parameter tDPDX = 100000.0; + `endif + + // Timing Parameters for -75 PC133 + `ifdef S75 + parameter tAC3 = 6.0; + parameter tHZ3 = 6.0; + parameter tAC2 = 8.0; + parameter tHZ2 = 8.0; + parameter tOH = 2.5; + parameter tMRD = 2.0; + parameter tRAS = 45.0; + parameter tRC = 67.5; + parameter tRCD = 22.5; + parameter tRFC = 67.5; + parameter tXSR = 67.5; + parameter tRP = 22.5; + parameter tRRD = 15.0; + parameter tDPLa = 7.5; + parameter tDPLm = 15.0; + parameter tDPDX = 100000.0; + `endif + + + inout [no_of_data - 1 : 0] dq; + input [no_of_addr - 1 : 0] addr; + input [no_of_bank - 1 : 0] ba; + input clk; + input cke; + input csb; + input rasb; + input casb; + input web; + input [no_of_dqm - 1 : 0] dqm; + +`protect + + reg [no_of_data - 1 : 0] bank0 [0 : mem_sizes]; + reg [no_of_data - 1 : 0] bank1 [0 : mem_sizes]; + reg [no_of_data - 1 : 0] bank2 [0 : mem_sizes]; + reg [no_of_data - 1 : 0] bank3 [0 : mem_sizes]; + + reg [no_of_bank - 1 : 0] bank_addr [0 : 3]; // bank address Pipeline + reg [no_of_col - 1 : 0] Col_addr [0 : 3]; // Column address Pipeline + reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline + reg [no_of_dqm - 1 : 0] dqm_reg0, dqm_reg1; // DQM Operation Pipeline + reg [no_of_dqm - 1 : 0] dqm_save [0 : 3]; // DQM Operation Pipeline + reg [no_of_addr - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; + + reg [no_of_addr - 1 : 0] Mode_reg; + reg [no_of_addr - 1 : 0] EMode_reg; + reg [no_of_data - 1 : 0] dq_reg, dq_dqm; + reg [no_of_col - 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 Auto Precharge (bank) + reg Read_precharge [0 : 3]; // R Auto Precharge + reg Write_precharge [0 : 3]; // W Auto Precharge + 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 + integer RW_interrupt_counter [0 : 3]; // RW Interrupt Counter + integer Count_precharge [0 : 3]; // RW Auto Precharge Counter + + reg Data_in_enable; + reg Data_out_enable; + + reg [no_of_bank - 1 : 0] bank, Prev_bank; + reg [no_of_addr - 1 : 0] Row; + reg [no_of_col - 1 : 0] Col, Col_brst; + + reg [19:0] ccc; + reg [3:0] bit; + reg [2:0] CL; + reg [8:0] BL; + reg RIW_violate; + reg Dout_Drive_Flag; + reg Pre_Dout_Drive_Flag; + reg [10:0] Count_at_Read; + reg Read_cmd_received; + reg Read_cmd_received_cke; + reg Write_cmd_received_cke; + reg state_act_pwrdn,state_pre_pwrdn,state_dpdn,state_self; + reg dpdn_check_start; + reg [10:0] Read_cmd_count; + reg [10:0] Read_cmd_count_cke; + reg [10:0] Write_cmd_count_cke; + reg [3:0] cmp_count; + // Internal system clock + reg ckeZ, Sys_clk; + + // Commands Decode + wire Active_enable = ~csb & ~rasb & casb & web ; + wire Aref_enable = ~csb & ~rasb & ~casb & web & cke; + wire Sref_enable = ~csb & ~rasb & ~casb & web & ~cke; + wire Burst_term = ~csb & rasb & casb & ~web & cke; + wire Deep_pwrdn = ~csb & rasb & casb & ~web & ~cke; + wire Mode_reg_enable = ~csb & ~rasb & ~casb & ~web & ~ba[1] & ~ba[0]; + wire EMode_reg_enable = ~csb & ~rasb & ~casb & ~web & ba[1] & ~ba[0]; + wire Prech_enable = ~csb & ~rasb & casb & ~web ; + wire Read_enable = ~csb & rasb & ~casb & web ; + wire Write_enable = ~csb & rasb & ~casb & ~web ; + + // 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]; + wire Burst_length_f = 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]; + +`ifdef VERBOSE + wire Debug = 1'b1; // Debug messages : 1 = On +`else + wire Debug = 1'b0; // Debug messages : 1 = On +`endif + + wire dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ + + // CKE function + wire clk_suspend_write= (Act_b0 | Act_b1 | Act_b2 | Act_b3) & Write_cmd_received_cke; + wire clk_suspend_read = (Act_b0 | Act_b1 | Act_b2 | Act_b3) & Read_cmd_received_cke; + wire act_pwrdn = (Act_b0 | Act_b1 | Act_b2 | Act_b3) & (~Read_cmd_received_cke & ~Write_cmd_received_cke); + wire pch_pwrdn = (Pc_b0 & Pc_b1 & Pc_b2 & Pc_b3) & (~Read_cmd_received_cke | ~Write_cmd_received_cke); + + assign dq = dq_reg; // DQ buffer + + // Commands Operation + `define ACT 0 + `define NOP 1 + `define READ 2 + `define WRITE 3 + `define PRECH 4 + `define A_REF 5 + `define BST 6 + `define LMR 7 + + // Timing Check variable + real MRD_chk; + real WR_chkm0, WR_chkm1, WR_chkm2, WR_chkm3; + real RFC_chk, RRD_chk; + real RC_chk0, RC_chk1, RC_chk2, RC_chk3 ; + real RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3 ; + real RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3 ; + real RP_chk0, RP_chk1, RP_chk2, RP_chk3 ; + real SELF_chk, DPDN_chk ; + + initial begin + mem_init; + dq_reg = {no_of_data{1'bz}}; + Data_in_enable = 0; Data_out_enable = 0; + Act_b0 = 1; Act_b1 = 1; Act_b2 = 1; Act_b3 = 1; + Pc_b0 = 0; Pc_b1 = 0; Pc_b2 = 0; Pc_b3 = 0; + WR_chkm0 = 0; WR_chkm1 = 0; WR_chkm2 = 0; WR_chkm3 = 0; + RW_interrupt_read[0] = 0; RW_interrupt_read[1] = 0; RW_interrupt_read[2] = 0; RW_interrupt_read[3] = 0; + RW_interrupt_write[0] = 0; RW_interrupt_write[1] = 0; RW_interrupt_write[2] = 0; RW_interrupt_write[3] = 0; + MRD_chk = 0; RFC_chk = 0; RRD_chk = 0; + RAS_chk0 = 0; RAS_chk1 = 0; RAS_chk2 = 0; RAS_chk3 = 0; + RCD_chk0 = 0; RCD_chk1 = 0; RCD_chk2 = 0; RCD_chk3 = 0; + RC_chk0 = 0; RC_chk1 = 0; RC_chk2 = 0; RC_chk3 = 0; + RP_chk0 = 0; RP_chk1 = 0; RP_chk2 = 0; RP_chk3 = 0; + SELF_chk = 0; DPDN_chk = 0; + Read_cmd_received=0; + Read_cmd_count=0; + Read_cmd_received_cke=0; + Read_cmd_count_cke=0; + Write_cmd_received_cke=0; + Write_cmd_count_cke=0; + state_act_pwrdn=0; + state_pre_pwrdn=0; + state_dpdn=0; + state_self=0; + dpdn_check_start=0; + EMode_reg=0; + Mode_reg=0; + Count_at_Read=0; + + $timeformat (-9, 2, " ns", 12); + 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 clk) begin + // CKE Exit + if (cke === 1'b1) begin + if (state_self === 1'b1) begin + state_self = 1'b0; + SELF_chk=$realtime; + if (Debug) $display ("Time = %t : OPERATION = SREFX : Self Refresh exit", $realtime); + end else if (state_dpdn == 1'b1) begin + state_dpdn = 1'b0; + DPDN_chk=$realtime; + if (Debug) $display ("Time = %t : OPERATION = DPDNX : Deep Powerdown exit", $realtime); + end else if (state_act_pwrdn == 1'b1) begin + state_act_pwrdn = 1'b0; + if (Debug) $display ("Time = %t : OPERATION = APDNX : Active Power down exit", $realtime); + end else if (state_pre_pwrdn == 1'b1) begin + state_pre_pwrdn = 1'b0; + if (Debug) $display ("Time = %t : OPERATION = PPDNX : Precharge Power down exit", $realtime); + end + end + end + + + always @ (Dout_Drive_Flag) begin + + if(Cas_latency_2 ==1) begin + + Pre_Dout_Drive_Flag <= #tHZ2 Dout_Drive_Flag; + + end else if(Cas_latency_3 ==1) begin + + Pre_Dout_Drive_Flag <= #tHZ3 Dout_Drive_Flag; + + 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] = {no_of_col{1'b0}}; + + bank_addr[0] = bank_addr[1]; + bank_addr[1] = bank_addr[2]; + bank_addr[2] = bank_addr[3]; + bank_addr[3] = 2'b00; + + bank_precharge[0] = bank_precharge[1]; + bank_precharge[1] = bank_precharge[2]; + bank_precharge[2] = bank_precharge[3]; + bank_precharge[3] = 2'b00; + + 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; + + dqm_save[3]=dqm_save[2]; + dqm_save[2]=dqm_save[1]; + dqm_save[1]=dqm_save[0]; + dqm_save[0]=dqm; + + + if (Read_cmd_received == 1'b1) begin + Read_cmd_count = Read_cmd_count + 1; + end + else begin + Read_cmd_count = 4'b0; + end + //if (Read_cmd_count == (BL+CL+1)) begin + if (Read_cmd_count == Count_at_Read+(BL+CL+1)) begin + Read_cmd_received = 1'b0; + end + + // Count for CKE + if (Read_cmd_received_cke == 1'b1) begin + Read_cmd_count_cke = Read_cmd_count_cke + 1; + end + else begin + Read_cmd_count_cke = 4'b0; + end + if (Read_cmd_count_cke == (BL+CL-1)) begin + Read_cmd_received_cke = 1'b0; + end + + // Count for CKE + if (Write_cmd_received_cke == 1'b1) begin + Write_cmd_count_cke = Write_cmd_count_cke + 1; + end + else begin + Write_cmd_count_cke = 4'b0; + end + if (Write_cmd_count_cke == BL) begin + Write_cmd_received_cke = 1'b0; + end + + + + // 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 + + // Read or Write Interrupt Counter + if (RW_interrupt_write[0] === 1'b1) begin + RW_interrupt_counter[0] = RW_interrupt_counter[0] + 1; + end + if (RW_interrupt_write[1] === 1'b1) begin + RW_interrupt_counter[1] = RW_interrupt_counter[1] + 1; + end + if (RW_interrupt_write[2] === 1'b1) begin + RW_interrupt_counter[2] = RW_interrupt_counter[2] + 1; + end + if (RW_interrupt_write[3] === 1'b1) begin + RW_interrupt_counter[3] = RW_interrupt_counter[3] + 1; + end + + // tMRD Counter + MRD_chk = MRD_chk + 1; + + // Auto Refresh + if (Aref_enable === 1'b1) begin + if (Debug) begin + //$display ("%m : at time %t AREF : Auto Refresh", $realtime); + $display ("Time = %t : OPERATION = AREF : Auto Refresh", $realtime); + end + + // DPDXN to Auto Refresh + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to AREF)", $realtime); + end + + // Self exit to Auto Refresh + if ($realtime - SELF_chk < tXSR) begin + $display ("Time = %t : ERROR : tXSR violation(SREFX to AREF)", $realtime); + end + + // Auto Refresh to Auto Refresh + if ($realtime - RFC_chk < tRFC) begin + //$display ("%m : at time %t ERROR: tRFC violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tRFC violation(AREF to AREF)", $realtime); + end + + // Precharge to Auto Refresh + if (($realtime - RP_chk0 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE0 to AREF)", $realtime); + end + if (($realtime - RP_chk1 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE1 to AREF)", $realtime); + end + if (($realtime - RP_chk2 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE2 to AREF)", $realtime); + end + if (($realtime - RP_chk3 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE3 to AREF)", $realtime); + 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", $realtime); + $display ("Time = %t : ERROR : All banks must be Precharged before AREF", $realtime); + end + + // Load Mode Register to Auto Refresh + if (MRD_chk < tMRD) begin + //$display ("%m : at time %t ERROR: tMRD violation during Auto Refresh", $realtime); + $display ("Time = %t : ERROR : tMRD violation(MRS to AREF)", $realtime); + end + + // Record Current tRFC time + RFC_chk = $realtime; + end + + // Load Mode Register + if (Mode_reg_enable === 1'b1) begin + // Register Mode + Mode_reg = addr; + + // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode + if (Debug) begin + //$display ("%m : at time %t LMR : Load Mode Register", $realtime); + $display ("Time = %t : OPERATION = MRS : Load Mode Register", $realtime); + // CAS Latency + case (addr[6 : 4]) + 3'b010 : $display (" CAS Latency = 2"); + 3'b011 : $display (" CAS Latency = 3"); + default : $display (" CAS Latency = Reserved"); + endcase + case (addr[6 : 4]) + 3'b010 : CL=2; + 3'b011 : CL=3; + default : CL=3; + endcase + + // Burst Length + case (addr[2 : 0]) + 3'b000 : $display (" Burst Length = 1"); + 3'b001 : $display (" Burst Length = 2"); + 3'b010 : $display (" Burst Length = 4"); + 3'b011 : $display (" Burst Length = 8"); + 3'b111 : $display (" Burst Length = Full"); + default : $display (" Burst Length = Reserved"); + endcase + + case (addr[2 : 0]) + 3'b000 : BL=1; + 3'b001 : BL=2; + 3'b010 : BL=4; + 3'b011 : BL=8; + 3'b111 : BL=512; + default : BL=4; + endcase + + + // Burst Type + if (addr[3] === 1'b0) begin + $display (" Burst Type = Sequential"); + end else if (addr[3] === 1'b1) begin + $display (" Burst Type = Interleaved"); + end else begin + $display (" Burst Type = Reserved"); + end + + // Write Burst Mode + if (addr[9] === 1'b0) begin + $display (" Write Burst Mode = Programmed Burst Length"); + end else if (addr[9] === 1'b1) begin + $display (" Write Burst Mode = Single Location Access"); + end else begin + $display (" Write Burst Mode = Reserved"); + end + end + + // Precharge to Load Mode Register + 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 Load Mode Register", $realtime); + $display ("Time = %t : ERROR : all banks must be Precharge before Load Mode Register", $realtime); + end + + // Precharge to Load Mode Register + if (($realtime - RP_chk0 < tRP) || ($realtime - RP_chk1 < tRP) || + ($realtime - RP_chk2 < tRP) || ($realtime - RP_chk3 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE to MRS)", $realtime); + end + + // Auto Refresh to Load Mode Register + if ($realtime - RFC_chk < tRFC) begin + //$display ("%m : at time %t ERROR: tRFC violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tRFC violation(AREF to MRS)", $realtime); + end + + // Load Mode Register to Load Mode Register + if (MRD_chk < tMRD) begin + //$display ("%m : at time %t ERROR: tMRD violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tMRD violation(MRS to MRS)", $realtime); + end + + // Reset MRD Counter + MRD_chk = 0; + end + + // Load Extended Mode Register + if (EMode_reg_enable === 1'b1) begin + // Register Mode + EMode_reg = addr; + + // Decode Driver Strength, Maximum Case Temp, Self Refresh Coverage + if (Debug) begin + //$display ("%m : at time %t LMR : Load Mode Register", $realtime); + $display ("Time = %t : OPERATION = EMRS : Load Extended Mode Register", $realtime); + // Driver Strength + case (addr[6 : 5]) + 2'b00 : $display (" Driver Strength = Full"); + 2'b01 : $display (" Driver Strength = 1/2"); + 2'b10 : $display (" Driver Strength = 1/4"); + 2'b11 : $display (" Driver Strength = 1/8"); + default : $display (" Driver Strength = Reserved"); + endcase + + // Self Refresh Coverage + case (addr[2 : 0]) + 3'b000 : $display (" Self Refresh Coverage = All Banks"); + 3'b001 : $display (" Self Refresh Coverage = TWO Bank"); + 3'b010 : $display (" Self Refresh Coverage = One Bank"); + 3'b101 : $display (" Self Refresh Coverage = Half of one Banks"); + 3'b110 : $display (" Self Refresh Coverage = Quater of one Banks"); + default : $display (" Self Refresh Coverage = Reserved"); + endcase + + end + + // Precharge to Load Mode Register + 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 Load Mode Register", $realtime); + $display ("Time = %t : ERROR : all banks must be Precharge before Load Mode Register", $realtime); + end + + // Precharge to Load Mode Register + if (($realtime - RP_chk0 < tRP) || ($realtime - RP_chk1 < tRP) || + ($realtime - RP_chk2 < tRP) || ($realtime - RP_chk3 < tRP)) begin + //$display ("%m : at time %t ERROR: tRP violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tRP violation(PRECHARGE to EMRS)", $realtime); + end + + // Auto Refresh to Load Mode Register + if ($realtime - RFC_chk < tRFC) begin + //$display ("%m : at time %t ERROR: tRFC violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tRFC violation(AREF to EMRS)", $realtime); + end + + // Load Mode Register to Load Mode Register + if (MRD_chk < tMRD) begin + //$display ("%m : at time %t ERROR: tMRD violation during Load Mode Register", $realtime); + $display ("Time = %t : ERROR : tMRD violation(MRS to EMRS)", $realtime); + end + + // Reset MRD Counter + MRD_chk = 0; + end + + // Active Block (Latch bank address and Row address) + if (Active_enable === 1'b1) begin + // Activate an open bank can corrupt data + if ((ba === 2'b00 && Act_b0 === 1'b1) || (ba === 2'b01 && Act_b1 === 1'b1) || + (ba === 2'b10 && Act_b2 === 1'b1) || (ba === 2'b11 && Act_b3 === 1'b1)) begin + //$display ("%m : at time %t ERROR: bank already activated -- data can be corrupted", $realtime); + $display ("Time = %t : ERROR : bank already activated -- data could be corrupted", $realtime); + // $display ("Time = %t : Bank = %d, Act_b0 = %d, Act_b2 = %d", $realtime, ba, Act_b0, Act_b2); + end + + // Activate bank 0 + if (ba === 2'b00 && Pc_b0 === 1'b1) begin + // Debug Message + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 0 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = ACT : bank = 0 Row = 'h%h", $realtime, addr); + end + + // Self exit to ACTIVE + if ($realtime - SELF_chk < tXSR) begin + $display ("Time = %t : ERROR : tXSR violation(SREFX to ACT0)", $realtime); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to ACT0)", $realtime); + end + + // ACTIVE to ACTIVE command period + if ($realtime - RC_chk0 < tRC) begin + //$display ("%m : at time %t ERROR: tRC violation during Activate bank 0", $realtime); + $display ("Time = %t : ERROR : tRC violation (ACT0 to ACT0) ", $realtime); + end + + // Precharge to Activate bank 0 + if ($realtime - RP_chk0 < tRP) begin + //$display ("%m : at time %t ERROR: tRP violation during Activate bank 0", $realtime); + $display ("Time = %t : ERROR : tRP violation (PRECHARGE0 to PRECHARGE0) ", $realtime); + end + + // Record variables + Act_b0 = 1'b1; + Pc_b0 = 1'b0; + B0_row_addr = addr [no_of_addr - 1 : 0]; + RAS_chk0 = $realtime; + RC_chk0 = $realtime; + RCD_chk0 = $realtime; + end + + // Activate bank 1 + if (ba === 2'b01 && Pc_b1 === 1'b1) begin + // Debug Message + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 1 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = ACT : bank = 1 Row = 'h%h", $realtime, addr); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to ACT1)", $realtime); + end + + // Self exit to ACTIVE + if ($realtime - SELF_chk < tXSR) begin + $display ("Time = %t : ERROR : tXSR violation(SREFX to ACT1)", $realtime); + end + + // ACTIVE to ACTIVE command period + if ($realtime - RC_chk1 < tRC) begin + //$display ("%m : at time %t ERROR: tRC violation during Activate bank 1", $realtime); + $display ("Time = %t : ERROR : tRC violation (ACT1 to ACT1) ", $realtime); + end + + // Precharge to Activate bank 1 + if ($realtime - RP_chk1 < tRP) begin + //$display ("%m : at time %t ERROR: tRP violation during Activate bank 1", $realtime); + $display ("Time = %t : ERROR : tRP violation (PRECHARGE1 to PRECHARGE1) ", $realtime); + end + + // Record variables + Act_b1 = 1'b1; + Pc_b1 = 1'b0; + B1_row_addr = addr [no_of_addr - 1 : 0]; + RAS_chk1 = $realtime; + RC_chk1 = $realtime; + RCD_chk1 = $realtime; + end + + // Activate bank 2 + if (ba === 2'b10 && Pc_b2 === 1'b1) begin + // Debug Message + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 2 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = ACT : bank = 2 Row = 'h%h", $realtime, addr); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to ACT2)", $realtime); + end + + // Self exit to ACTIVE + if ($realtime - SELF_chk < tXSR) begin + $display ("Time = %t : ERROR : tXSR violation(SREFX to ACT2)", $realtime); + end + + // ACTIVE to ACTIVE command period + if ($realtime - RC_chk2 < tRC) begin + //$display ("%m : at time %t ERROR: tRC violation during Activate bank 2", $realtime); + $display ("Time = %t : ERROR : tRC violation (ACT2 to ACT2) ", $realtime); + end + + // Precharge to Activate bank 2 + if ($realtime - RP_chk2 < tRP) begin + //$display ("%m : at time %t ERROR: tRP violation during Activate bank 2", $realtime); + $display ("Time = %t : ERROR : tRP violation (PRECHARGE2 to PRECHARGE2) ", $realtime); + end + + // Record variables + Act_b2 = 1'b1; + Pc_b2 = 1'b0; + B2_row_addr = addr [no_of_addr - 1 : 0]; + RAS_chk2 = $realtime; + RC_chk2 = $realtime; + RCD_chk2 = $realtime; + end + + // Activate bank 3 + if (ba === 2'b11 && Pc_b3 === 1'b1) begin + // Debug Message + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 3 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = ACT : bank = 3 Row = 'h%h", $realtime, addr); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to ACT3)", $realtime); + end + + // Self exit to ACTIVE + if ($realtime - SELF_chk < tXSR) begin + $display ("Time = %t : ERROR : tXSR violation(SREFX to ACT3)", $realtime); + end + + // ACTIVE to ACTIVE command period + if ($realtime - RC_chk3 < tRC) begin + //$display ("%m : at time %t ERROR: tRC violation during Activate bank 3", $realtime); + $display ("Time = %t : ERROR : tRC violation (ACT1 to ACT3) ", $realtime); + end + + // Precharge to Activate bank 3 + if ($realtime - RP_chk3 < tRP) begin + //$display ("%m : at time %t ERROR: tRP violation during Activate bank 3", $realtime); + $display ("Time = %t : ERROR : tRP violation (PRECHARGE3 to PRECHARGE3) ", $realtime); + end + + // Record variables + Act_b3 = 1'b1; + Pc_b3 = 1'b0; + B3_row_addr = addr [no_of_addr - 1 : 0]; + RAS_chk3 = $realtime; + RC_chk3 = $realtime; + RCD_chk3 = $realtime; + end + + // Active other bank to Active bank A + if ((Prev_bank != ba) && ($realtime - RRD_chk < tRRD) && (ba === 2'b00)) begin + //$display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tRRD violation(ACT Others to ACT0) ", $realtime); + end + + // Active other bank to Active bank B + if ((Prev_bank != ba) && ($realtime - RRD_chk < tRRD) && (ba === 2'b01)) begin + //$display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tRRD violation(ACT Others to ACT1) ", $realtime); + end + + // Active other bank to Active bank C + if ((Prev_bank != ba) && ($realtime - RRD_chk < tRRD) && (ba === 2'b10)) begin + //$display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tRRD violation(ACT Others to ACT2) ", $realtime); + end + + // Active other bank to Active bank D + if ((Prev_bank != ba) && ($realtime - RRD_chk < tRRD) && (ba === 2'b11)) begin + //$display ("%m : at time %t ERROR: tRRD violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tRRD violation(ACT Others to ACT3) ", $realtime); + end + + // Auto Refresh to Activate + if ($realtime - RFC_chk < tRFC) begin + //$display ("%m : at time %t ERROR: tRFC violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tRFC violation(AREF to ACT)", $realtime); + end + + // Load Mode Register to Active + if (MRD_chk < tMRD ) begin + //$display ("%m : at time %t ERROR: tMRD violation during Activate bank = %d", $realtime, ba); + $display ("Time = %t : ERROR : tMRD violation(MRS to ACT)", $realtime); + end + + // Record variables for checking violation + RRD_chk = $realtime; + Prev_bank = ba; + end + + // Precharge Block + if (Prech_enable == 1'b1) begin + // Load Mode Register to Precharge + if ($realtime - MRD_chk < tMRD) begin + //$display ("%m : at time %t ERROR: tMRD violaiton during Precharge", $realtime); + $display ("Time = %t : ERROR : tMRD violation(MRS to PRECHARGE)", $realtime); + end + + //Precharge bank 0 + + if ((addr[10] === 1'b1 || (addr[10] === 1'b0 && ba === 2'b00)) && Act_b0 === 1'b1) begin + Act_b0 = 1'b0; + Pc_b0 = 1'b1; + RP_chk0 = $realtime; + + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 0 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = PCHG : bank = 0 ", $realtime); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to PRECHARGE0)", $realtime); + end + + // Activate to Precharge + if ($realtime - RAS_chk0 < tRAS) begin + //$display ("%m : at time %t ERROR: tRAS violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tRAS violation(ACT0 to PRECHARGE0)", $realtime); + end + + // tWR violation check for write + if ($realtime - WR_chkm0 < tDPLm) begin + //$display ("%m : at time %t ERROR: tWR violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tDPL violation(LAST DATA to PRECHARGE0)", $realtime); + end + end + + // Precharge bank 1 + + if ((addr[10] === 1'b1 || (addr[10] === 1'b0 && ba === 2'b01)) && Act_b1 === 1'b1) begin + Act_b1 = 1'b0; + Pc_b1 = 1'b1; + RP_chk1 = $realtime; + + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 1 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = PCHG : bank = 1 ", $realtime); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to PRECHARGE1)", $realtime); + end + + // Activate to Precharge + if ($realtime - RAS_chk1 < tRAS) begin + //$display ("%m : at time %t ERROR: tRAS violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tRAS violation(ACT1 to PRECHARGE1)", $realtime); + end + + // tWR violation check for write + if ($realtime - WR_chkm1 < tDPLm) begin + //$display ("%m : at time %t ERROR: tWR violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tDPL violation(LAST DATA to PRECHARGE1)", $realtime); + end + end + + // Precharge bank 2 + + if ((addr[10] === 1'b1 || (addr[10] === 1'b0 && ba === 2'b10)) && Act_b2 === 1'b1) begin + Act_b2 = 1'b0; + Pc_b2 = 1'b1; + RP_chk2 = $realtime; + + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 2 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = PCHG : bank = 2 ", $realtime); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to PRECHARGE2)", $realtime); + end + + // Activate to Precharge + if ($realtime - RAS_chk2 < tRAS) begin + //$display ("%m : at time %t ERROR: tRAS violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tRAS violation(ACT2 to PRECHARGE2)", $realtime); + end + + // tWR violation check for write + if ($realtime - WR_chkm2 < tDPLm) begin + //$display ("%m : at time %t ERROR: tWR violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tDPL violation(LAST DATA to PRECHARGE2)", $realtime); + end + end + + // Precharge bank 3 + + if ((addr[10] === 1'b1 || (addr[10] === 1'b0 && ba === 2'b11)) && Act_b3 === 1'b1) begin + Act_b3 = 1'b0; + Pc_b3 = 1'b1; + RP_chk3 = $realtime; + + if (Debug) begin + //$display ("%m : at time %t ACT : bank = 3 Row = %d", $realtime, addr); + $display ("Time = %t : OPERATION = PCHG : bank = 3 ", $realtime); + end + + // DPDXN to Precharge + if (($realtime - DPDN_chk < tDPDX) && (dpdn_check_start)) begin + $display ("Time = %t : ERROR : Pwrup violation(DPDX to PRECHARGE3)", $realtime); + end + + // Activate to Precharge + if ($realtime - RAS_chk3 < tRAS) begin + //$display ("%m : at time %t ERROR: tRAS violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tRAS violation(ACT3 to PRECHARGE3)", $realtime); + end + + // tWR violation check for write + if ($realtime - WR_chkm3 < tDPLm) begin + //$display ("%m : at time %t ERROR: tWR violation during Precharge", $realtime); + $display ("Time = %t : ERROR : tDPL violation(LAST DATA to PRECHARGE3)", $realtime); + 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 + + // Display debug message + if (Debug) begin + //$display ("%m : at time %t BST : Burst Terminate",$realtime); + $display ("Time = %t : OPERATION = BST : Burst Stop", $realtime); + end + end + + // Read, Write, Column Latch + if (Read_enable === 1'b1) begin + + Read_cmd_received = 1'b1; + Read_cmd_received_cke = 1'b1; + //Read_cmd_count = 0; + Count_at_Read = Read_cmd_count; + Read_cmd_count_cke = 0; + Write_cmd_received_cke = 1'b0; + + // 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: bank is not Activated for Read", $realtime); + $display ("Time = %t : ERROR : bank is not Activated for Read", $realtime); + end + + // Activate to Read or Write + if ((ba == 2'b00) && ($realtime - RCD_chk0 < tRCD) || + (ba == 2'b01) && ($realtime - RCD_chk1 < tRCD) || + (ba == 2'b10) && ($realtime - RCD_chk2 < tRCD) || + (ba == 2'b11) && ($realtime - RCD_chk3 < tRCD)) begin + //$display("%m : at time %t ERROR: tRCD violation during Read", $realtime); + $display ("Time = %t : ERROR : tRCD violation(ACT to READ)", $realtime); + end + + // CAS Latency pipeline + if (Cas_latency_3 == 1'b1) begin + Command[2] = `READ; + Col_addr[2] = addr; + bank_addr[2] = ba; + end else if (Cas_latency_2 == 1'b1) begin + Command[1] = `READ; + 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; + RW_interrupt_counter[RW_interrupt_bank] = 0; + + // Display debug message + if (Debug) begin + //$display ("%m : at time %t NOTE : Read interrupt Write with Autoprecharge", $realtime); + $display ("Time = %t : OPERATION = Read interrupt Write with Autoprecharge", $realtime); + end + end + end + + // Read with Auto Precharge + if (addr[10] == 1'b1) begin + Auto_precharge[ba] = 1'b1; + Count_precharge[ba] = 0; + RW_interrupt_bank = ba; + Read_precharge[ba] = 1'b1; + end + end + + // Write Command + if (Write_enable == 1'b1) begin + + RIW_violate=1'b0; + if ((Pre_Dout_Drive_Flag == 1'b1) || (Dout_Drive_Flag == 1'b1)) begin + $display ("Time = %t : ERROR : Read and Write Data collision", $realtime); + end + else if ((Data_out_enable == 1'b1) && (&(dqm_save[1]) != 1'b1)) begin + $display ("Time = %t : ERROR : Read and Write Data collision", $realtime); + end + + + Write_cmd_received_cke=1'b1; + Read_cmd_received=1'b0; + Read_cmd_received_cke=1'b0; + Write_cmd_count_cke=1'b0; + + // Activate to Write + 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: bank is not Activated for Write", $realtime); + $display ("Time = %t : ERROR : bank is not Activated for Write", $realtime); + end + + if ((ba == 2'b00) && ($realtime - RCD_chk0 < tRCD)) begin + $display ("Time = %t : ERROR = %t, %t: tRCD violation(ACT0 to WRITE)", $realtime, RCD_chk0,$realtime-RCD_chk0); + end + if ((ba == 2'b01) && ($realtime - RCD_chk1 < tRCD)) begin + $display ("Time = %t : ERROR = %t, %t: tRCD violation(ACT1 to WRITE)", $realtime, RCD_chk1,$realtime-RCD_chk1); + end + if ((ba == 2'b10) && ($realtime - RCD_chk2 < tRCD)) begin + $display ("Time = %t : ERROR = %t, %t: tRCD violation(ACT2 to WRITE)", $realtime, RCD_chk2,$realtime-RCD_chk2); + end + if ((ba == 2'b11) && ($realtime - RCD_chk3 < tRCD)) begin + $display ("Time = %t : ERROR = %t, %t: tRCD violation(ACT3 to WRITE)", $realtime, RCD_chk3,$realtime-RCD_chk3); + end + + + // Latch Write command, bank, and Column + Command[0] = `WRITE; + Command[1] = `NOP; + 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; + + // Display debug message + if (Debug) begin + //$display ("%m : at time %t NOTE : Read bank %d interrupt Write bank %d with Autoprecharge", $realtime, ba, RW_interrupt_bank); + $display ("Time = %t : OPERATION = Write bank %d interrupt Write bank %d with Autoprecharge", $realtime, ba, RW_interrupt_bank); + + end + 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; + + // Display debug message + if (Debug) begin + //$display ("%m : at time %t NOTE : Write bank %d interrupt Read bank %d with Autoprecharge", $realtime, ba, RW_interrupt_bank); + $display ("Time = %t : OPERATION = Write bank %d interrupt Read bank %d with Autoprecharge", $realtime, ba, RW_interrupt_bank); + end + end + end + + // Write with Auto Precharge + if (addr[10] == 1'b1) begin + Auto_precharge[ba] = 1'b1; + Count_precharge[ba] = 0; + RW_interrupt_bank = ba; + Write_precharge[ba] = 1'b1; + end + end + + /* + Write with Auto Precharge Calculation + The device start internal precharge when: + 1. Meet minimum tRAS requirement + and 2. tWR cycle(s) after last valid data + or 3. Interrupt by a Read or Write (with or without Auto Precharge) + + Note: Model is starting the internal precharge 1 cycle after they meet all the + requirement but tRP will be compensate for the time after the 1 cycle. + */ + if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin + if ((($realtime - RAS_chk0 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 2 + (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 && RW_interrupt_counter[0] >= 1)) begin // Case 3 + 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 = $realtime + tDPLa; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 0", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 0", $realtime+tDPLa); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin + if ((($realtime - RAS_chk1 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || // Case 2 + (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 && RW_interrupt_counter[1] >= 1)) begin // Case 3 + 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 = $realtime + tDPLa; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 1", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 1", $realtime+tDPLa); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin + if ((($realtime - RAS_chk2 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || // Case 2 + (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 && RW_interrupt_counter[2] >= 1)) begin // Case 3 + 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 = $realtime + tDPLa; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 2", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 2", $realtime+tDPLa); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin + if ((($realtime - RAS_chk3 >= tRAS) && // Case 1 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || // Case 2 + (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 && RW_interrupt_counter[3] >= 1)) begin // Case 3 + 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 = $realtime + tDPLa; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 3", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 3", $realtime+tDPLa); + end + end + end + + // Read with Auto Precharge Calculation + // The device start internal precharge: + // 1. Meet minimum tRAS requirement + // and 2. CAS Latency - 1 cycles before last burst + // 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 ((($realtime - RAS_chk0 >= tRAS) && // Case 1 + ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 2 + (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 = $realtime; + Auto_precharge[0] = 1'b0; + Read_precharge[0] = 1'b0; + RW_interrupt_read[0] = 1'b0; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 0", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 0", $realtime); + end + end + end + if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin + if ((($realtime - 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 = $realtime; + Auto_precharge[1] = 1'b0; + Read_precharge[1] = 1'b0; + RW_interrupt_read[1] = 1'b0; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 1", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 1", $realtime); + end + end + end + if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin + if ((($realtime - 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 = $realtime; + Auto_precharge[2] = 1'b0; + Read_precharge[2] = 1'b0; + RW_interrupt_read[2] = 1'b0; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 2", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 2", $realtime); + end + end + end + if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin + if ((($realtime - 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 = $realtime; + Auto_precharge[3] = 1'b0; + Read_precharge[3] = 1'b0; + RW_interrupt_read[3] = 1'b0; + if (Debug) begin + //$display ("%m : at time %t NOTE : Start Internal Auto Precharge for bank 3", $realtime); + $display ("Time = %t : OPERATION = Start Internal Auto Precharge for bank 3", $realtime); + end + end + end + + // CKE Function + if (cke === 1'b0) begin + if (Sref_enable === 1'b1) begin + state_self = 1'b1; + if (Debug) begin + $display ("Time = %t : OPERATION = SREF : Self Refresh", $realtime); + if (EMode_reg[2:0]==3'b000) $display (" Refresh Full Bank"); + + if (EMode_reg[2:0]==3'b001) begin + $display (" Refresh Only TWO Bank"); + abbank_init; + end + + if (EMode_reg[2:0]==3'b010) begin + $display (" Refresh Only One Bank(BANK A)"); + bbank_init; + end + if (EMode_reg[2:0]==3'b101) begin + $display (" Refresh Only half of one Bank(BANK A, A10=0)"); + half_init; + end + if (EMode_reg[2:0]==3'b110) begin + $display (" Refresh Only Quarter of one Bank(BANK A, A10=0)"); + quat_init; + end + end + + // Precharge to Auto Refresh + if (($realtime - RP_chk0 < tRP) || ($realtime - RP_chk1 < tRP) || + ($realtime - RP_chk2 < tRP) || ($realtime - RP_chk3 < tRP)) + $display ("Time = %t : ERROR : tRP violation(PRECHARGE to SREF)", $realtime); + + // Precharge to Refresh + if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) + $display ("Time = %t : ERROR : All banks must be Precharged before SREF", $realtime); + + // Load Mode Register to Self Refresh + if (MRD_chk < tMRD) + $display ("Time = %t : ERROR : tMRD violation(MRS to SREF)", $realtime); + + end else if (Deep_pwrdn == 1'b1) begin + state_dpdn = 1'b1; + dpdn_check_start = 1'b1; + Act_b0 = 0; Act_b1 = 0; Act_b2 = 0; Act_b3 = 0; + Pc_b0 = 1; Pc_b1 = 1; Pc_b2 = 1; Pc_b3 = 1; + mem_init; + if (Debug) $display ("Time = %t : OPERATION = DPDN : Deep Powerdown", $realtime); + + // Precharge to Auto Refresh + if (($realtime - RP_chk0 < tRP) || ($realtime - RP_chk1 < tRP) || + ($realtime - RP_chk2 < tRP) || ($realtime - RP_chk3 < tRP)) + $display ("Time = %t : ERROR : tRP violation(PRECHARGE to DPDN)", $realtime); + + // Precharge to Refresh + if (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) + $display ("Time = %t : ERROR : All banks must be Precharged before DPDN", $realtime); + + end else if (act_pwrdn == 1'b1) begin + state_act_pwrdn = 1'b1; + if (Debug) $display ("Time = %t : OPERATION = APDN : Active Power down", $realtime); + end else if (pch_pwrdn == 1'b1) begin + state_pre_pwrdn = 1'b1; + if (Debug) $display ("Time = %t : OPERATION = PPDN : Precharge Power down", $realtime); + end else if (clk_suspend_write == 1'b1) begin + if (Debug) $display ("Time = %t : OPERATION = CKSW : Clock Suspend during Write", $realtime); + end else if (clk_suspend_read == 1'b1) begin + if (Debug) $display ("Time = %t : OPERATION = CKSR : Clock Suspend during Read", $realtime); + 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 {no_of_data{1'bz}}; + Dout_Drive_Flag <= #tOH 1'b0; + end + + // Detect Read or Write command + if (Command[0] == `READ) begin + bank = bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + + endcase + Burst_counter = 0; + Data_in_enable = 1'b0; + Data_out_enable = 1'b1; + end else if (Command[0] == `WRITE) begin + bank = bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + case (bank_addr[0]) + 2'b00 : Row = B0_row_addr; + 2'b01 : Row = B1_row_addr; + 2'b10 : Row = B2_row_addr; + 2'b11 : Row = B3_row_addr; + endcase + 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 + case (bank) + 2'b00 : dq_dqm = bank0 [{Row, Col}]; + 2'b01 : dq_dqm = bank1 [{Row, Col}]; + 2'b10 : dq_dqm = bank2 [{Row, Col}]; + 2'b11 : dq_dqm = bank3 [{Row, Col}]; + endcase + + // dqm operation + if (dqm[0] == 1'b0) begin + dq_dqm [ 7 : 0] = dq [ 7 : 0 ] & dq [ 7 : 0 ]; + end + if (dqm[1] == 1'b0) begin + dq_dqm [15 : 8] = dq [15 : 8] & dq [15 : 8]; + end + + + + // Write to memory + case (bank) + 2'b00 : bank0 [{Row, Col}] = dq_dqm; + 2'b01 : bank1 [{Row, Col}] = dq_dqm; + 2'b10 : bank2 [{Row, Col}] = dq_dqm; + 2'b11 : bank3 [{Row, Col}] = dq_dqm; + endcase + + // Display debug message + if (dqm !== 2'b11) begin + // Record tWR for manual precharge + if (bank == 2'b00) WR_chkm0 = $realtime; + if (bank == 2'b01) WR_chkm1 = $realtime; + if (bank == 2'b10) WR_chkm2 = $realtime; + if (bank == 2'b11) WR_chkm3 = $realtime; + + if (Debug) begin + //$display("%m : at time %t WRITE: bank = %d Row = %d, Col = %d, Data = %d", $realtime, bank, Row, Col, dq_dqm); + $display ("Time = %t : OPERATION = WRITE : bank = %d Row = 'h%h, Col = 'h%h, Data = 'h%h", $realtime, bank, Row, Col, dq_dqm); + end + end else begin + if (Debug) begin + //$display("%m : at time %t WRITE: bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + $display ("Time = %t : OPERATION = WRITE : bank = %d Row = 'h%h, Col = 'h%h, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + end + end + + // Advance burst counter subroutine + + if(Cas_latency_2 == 1) begin + + #tHZ2 Burst_decode; + + end else if(Cas_latency_3 == 1) begin + + #tHZ3 Burst_decode; + + end + + + end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory + // Array buffer + case (bank) + 2'b00 : dq_dqm = bank0[{Row, Col}]; + 2'b01 : dq_dqm = bank1[{Row, Col}]; + 2'b10 : dq_dqm = bank2[{Row, Col}]; + 2'b11 : dq_dqm = bank3[{Row, Col}]; + endcase + + + // dqm operation + if (dqm_reg0 [0] == 1'b1) begin + dq_dqm [ 7 : 0] = 8'bz; + end + if (dqm_reg0 [1] == 1'b1) begin + dq_dqm [15 : 8] = 8'bz; + end + + if(Cas_latency_2 ==1) begin + + // Display debug message + if ( &(dqm_reg0) != 1'b1) begin + dq_reg = #tAC2 dq_dqm; + Dout_Drive_Flag = 1'b1; + if (Debug) begin + //$display("%m : at time %t READ : bank = %d Row = %d, Col = %d, Data = %d", $realtime, bank, Row, Col, dq_reg); + $display ("Time = %t : OPERATION = READ : bank = %d Row = 'h%h, Col = 'h%h, Data = 'h%h", $realtime, bank, Row, Col, dq_reg); + end + end else begin + dq_reg = #tHZ2 {no_of_data{1'bz}}; + Dout_Drive_Flag = 1'b0; + if (Debug) begin + //$display("%m : at time %t READ : bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + $display ("Time = %t : OPERATION = READ : bank = %d Row = 'h%h, Col = 'h%h, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + + end + end + + end else if(Cas_latency_3 ==1) begin + + // Display debug message + if ( &(dqm_reg0) != 1'b1) begin + dq_reg = #tAC3 dq_dqm; + Dout_Drive_Flag = 1'b1; + if (Debug) begin + //$display("%m : at time %t READ : bank = %d Row = %d, Col = %d, Data = %d", $realtime, bank, Row, Col, dq_reg); + $display ("Time = %t : OPERATION = READ : bank = %d Row = 'h%h, Col = 'h%h, Data = 'h%h", $realtime, bank, Row, Col, dq_reg); + end + end else begin + dq_reg = #tHZ3 {no_of_data{1'bz}}; + Dout_Drive_Flag = 1'b0; + if (Debug) begin + //$display("%m : at time %t READ : bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + $display ("Time = %t : OPERATION = READ : bank = %d Row = 'h%h, Col = 'h%h, Data = Hi-Z due to DQM", $realtime, bank, Row, Col); + + end + end + + end + + // Advance burst counter subroutine + Burst_decode; + end + end + + // Burst counter decode + task Burst_decode; + 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 + + task mem_init; + begin + for (ccc=0;ccc<'b1000_0000_0000_0000_0000;ccc=ccc+1) + begin + bank0[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + bank1[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + bank2[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + bank3[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + //bank0[ccc]=16'b1111_1111_1111_1111; + //bank1[ccc]=16'b1111_1111_1111_1111; + end + end + endtask + + task abbank_init; + begin + for (ccc=0;ccc<'b1000_0000_0000_0000_0000;ccc=ccc+1) + begin + bank0[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + bank1[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + end + end + endtask + + + task bbank_init; + begin + for (ccc=0;ccc<'b1000_0000_0000_0000_0000;ccc=ccc+1) + begin + bank1[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + end + end + endtask + + task half_init; + begin + bbank_init; + for (ccc='b0100_0000_0000_0000_0000;ccc<'b1000_0000_0000_0000_0000;ccc=ccc+1) + begin + bank0[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + end + end + endtask + + task quat_init; + begin + bbank_init; + for (ccc='b0010_0000_0000_0000_0000;ccc<'b1000_0000_0000_0000_0000;ccc=ccc+1) + begin + bank0[ccc]=32'bxxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx; + end + end + endtask +`endprotect + + // Timing Parameters + specify + specparam + `ifdef S50 + tAH = 1.0, // 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 = 5.0, // Clock Cycle Time + tDH = 1.0, // Data-in Hold Time + tDS = 1.5, // Data-in Setup Time + tCKH = 1.0, // CKE Hold Time + tCKS = 1.5, // CKE Setup Time + tCMH = 1.0, // CSB, RASB, CASB, WEB, DQMB Hold Time + tCMS = 1.5; // CSB, RASB, CASB, WEB, DQMB Setup Time + `endif + + `ifdef S60 + tAH = 1.0, // 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 = 6.0, // Clock Cycle Time + tDH = 1.0, // Data-in Hold Time + tDS = 1.5, // Data-in Setup Time + tCKH = 1.0, // CKE Hold Time + tCKS = 1.5, // CKE Setup Time + tCMH = 1.0, // CSB, RASB, CASB, WEB, DQMB Hold Time + tCMS = 1.5; // CSB, RASB, CASB, WEB, DQMB Setup Time + `endif + + `ifdef S75 + tAH = 1.0, // addr, ba Hold Time + tAS = 2.0, // 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 = 1.0, // Data-in Hold Time + tDS = 2.0, // Data-in Setup Time + tCKH = 1.0, // CKE Hold Time + tCKS = 2.0, // CKE Setup Time + tCMH = 1.0, // CSB, RASB, CASB, WEB, DQMB Hold Time + tCMS = 2.0; // CSB, RASB, CASB, WEB, DQMB Setup Time + `endif + + + $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, csb, tCMS, tCMH); + $setuphold(posedge clk, casb, tCMS, tCMH); + $setuphold(posedge clk, rasb, tCMS, tCMH); + $setuphold(posedge clk, web, 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
trunk/verif/model/IS42VM16400K.V Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property

powered by: WebSVN 2.1.0

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