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/trunk/verif/model
    from Rev 7 to Rev 17
    Reverse comparison

Rev 7 → Rev 17

/mt48lc8m8a2.v
0,0 → 1,961
/****************************************************************************************
*
* File Name: MT48LC8M8A2.V
* Version: 0.0f
* Date: July 8th, 1999
* Model: BUS Functional
* Simulator: Model Technology (PC version 5.2e PE)
*
* Dependencies: None
*
* Author: Son P. Huynh
* Email: sphuynh@micron.com
* Phone: (208) 368-3825
* Company: Micron Technology, Inc.
* Model: MT48LC8M16A2 (2Meg x 8 x 4 Banks)
*
* Description: Micron 128Mb SDRAM Verilog model
*
* Limitation: - Doesn't check for 4096 cycle refresh
*
* Note: - Set simulator resolution to "ps" accuracy
* - Set Debug = 0 to disable $display messages
*
* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
*
 
* All rights researved
*
* Rev Author Phone Date Changes
* ---- ---------------------------- ---------- ---------------------------------------
* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto)
* Micron Technology Inc. - Fix tWR = 15 ns (Manual)
* - Fix tRP (Autoprecharge to AutoRefresh)
*
* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e)
* Micron Technology Inc.
****************************************************************************************/
 
`timescale 1ns / 100ps
 
module mt48lc8m8a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
 
parameter addr_bits = 12;
parameter data_bits = 8;
parameter col_bits = 9;
parameter mem_sizes = 2097151; // 2 Meg
 
inout [data_bits - 1 : 0] Dq;
input [addr_bits - 1 : 0] Addr;
input [1 : 0] Ba;
input Clk;
input Cke;
input Cs_n;
input Ras_n;
input Cas_n;
input We_n;
input [0 : 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 [0 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline
reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;
 
reg [addr_bits - 1 : 0] Mode_reg;
reg [data_bits - 1 : 0] Dq_reg, Dq_dqm;
reg [col_bits - 1 : 0] Col_temp, Burst_counter;
 
reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate
reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge
 
reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command
reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks)
reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank)
reg Read_precharge [0 : 3]; // R AutoPrecharge
reg Write_precharge [0 : 3]; // W AutoPrecharge
integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter)
reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge
reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge
 
reg Data_in_enable;
reg Data_out_enable;
 
reg [1 : 0] Bank, Previous_bank;
reg [addr_bits - 1 : 0] Row;
reg [col_bits - 1 : 0] Col, Col_brst;
 
// Internal system clock
reg CkeZ, Sys_clk;
 
// Commands Decode
wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;
wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;
wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;
wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n;
wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;
wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;
wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;
 
// Burst Length Decode
wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];
wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];
wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];
 
// CAS Latency Decode
wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
 
// Write Burst Mode
wire Write_burst_mode = Mode_reg[9];
 
reg Debug; // Debug messages : 1 = On
wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
 
assign Dq = Dq_reg; // DQ buffer
 
// Commands Operation
`define ACT 0
`define NOP 1
`define READ 2
`define READ_A 3
`define SDRAM_WRITE 4
`define WRITE_A 5
`define SDRAM_PRECH 6
`define SDRAM_A_REF 7
`define SDRAM_BST 8
`define SDRAM_LMR 9
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
parameter tAC = 6.0;
parameter tHZ = 7.0;
parameter tOH = 2.7;
parameter tMRD = 2.0; // 2 Clk Cycles
parameter tRAS = 44.0;
parameter tRC = 66.0;
parameter tRCD = 20.0;
parameter tRP = 20.0;
parameter tRRD = 15.0;
parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns)
parameter tWRp = 15.0; // A2 Version - Precharge mode only (15 ns)
 
// Timing Check variable
integer MRD_chk;
integer WR_counter [0 : 3];
time WR_chk [0 : 3];
time RC_chk, RRD_chk;
time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3;
time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3;
time RP_chk0, RP_chk1, RP_chk2, RP_chk3;
 
initial begin
Debug = 1'b0;
Dq_reg = {data_bits{1'bz}};
{Data_in_enable, Data_out_enable} = 0;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;
{WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0;
{WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0;
{RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0;
{RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0;
{MRD_chk, RC_chk, RRD_chk} = 0;
{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0;
{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0;
{RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0;
$timeformat (-9, 0, " ns", 12);
//$readmemh("bank0.txt", Bank0);
//$readmemh("bank1.txt", Bank1);
//$readmemh("bank2.txt", Bank2);
//$readmemh("bank3.txt", Bank3);
end
 
// System clock generator
always begin
@ (posedge Clk) begin
Sys_clk = CkeZ;
CkeZ = Cke;
end
@ (negedge Clk) begin
Sys_clk = 1'b0;
end
end
 
always @ (posedge Sys_clk) begin
// Internal Commamd Pipelined
Command[0] = Command[1];
Command[1] = Command[2];
Command[2] = Command[3];
Command[3] = `NOP;
 
Col_addr[0] = Col_addr[1];
Col_addr[1] = Col_addr[2];
Col_addr[2] = Col_addr[3];
Col_addr[3] = {col_bits{1'b0}};
 
Bank_addr[0] = Bank_addr[1];
Bank_addr[1] = Bank_addr[2];
Bank_addr[2] = Bank_addr[3];
Bank_addr[3] = 2'b0;
 
Bank_precharge[0] = Bank_precharge[1];
Bank_precharge[1] = Bank_precharge[2];
Bank_precharge[2] = Bank_precharge[3];
Bank_precharge[3] = 2'b0;
 
A10_precharge[0] = A10_precharge[1];
A10_precharge[1] = A10_precharge[2];
A10_precharge[2] = A10_precharge[3];
A10_precharge[3] = 1'b0;
 
// Dqm pipeline for Read
Dqm_reg0 = Dqm_reg1;
Dqm_reg1 = Dqm;
 
// Read or Write with Auto Precharge Counter
if (Auto_precharge[0] == 1'b1) begin
Count_precharge[0] = Count_precharge[0] + 1;
end
if (Auto_precharge[1] == 1'b1) begin
Count_precharge[1] = Count_precharge[1] + 1;
end
if (Auto_precharge[2] == 1'b1) begin
Count_precharge[2] = Count_precharge[2] + 1;
end
if (Auto_precharge[3] == 1'b1) begin
Count_precharge[3] = Count_precharge[3] + 1;
end
 
// tMRD Counter
MRD_chk = MRD_chk + 1;
 
// tWR Counter for Write
WR_counter[0] = WR_counter[0] + 1;
WR_counter[1] = WR_counter[1] + 1;
WR_counter[2] = WR_counter[2] + 1;
WR_counter[3] = WR_counter[3] + 1;
 
// Auto Refresh
if (Aref_enable == 1'b1) begin
if (Debug) $display ("at time %t AREF : Auto Refresh", $time);
// Auto Refresh to Auto Refresh
if ($time - RC_chk < tRC) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);
end
// Precharge to Auto Refresh
if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);
end
// Precharge to Refresh
if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin
//->tb.test_control.error_detected;
$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);
end
// Record Current tRC time
RC_chk = $time;
end
// Load Mode Register
if (Mode_reg_enable == 1'b1) begin
// Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode
if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin
Mode_reg = Addr;
if (Debug) begin
$display ("at time %t LMR : Load Mode Register", $time);
// CAS Latency
if (Addr[6 : 4] == 3'b010)
$display (" CAS Latency = 2");
else if (Addr[6 : 4] == 3'b011)
$display (" CAS Latency = 3");
else
$display (" CAS Latency = Reserved");
// Burst Length
if (Addr[2 : 0] == 3'b000)
$display (" Burst Length = 1");
else if (Addr[2 : 0] == 3'b001)
$display (" Burst Length = 2");
else if (Addr[2 : 0] == 3'b010)
$display (" Burst Length = 4");
else if (Addr[2 : 0] == 3'b011)
$display (" Burst Length = 8");
else if (Addr[3 : 0] == 4'b0111)
$display (" Burst Length = Full");
else
$display (" Burst Length = Reserved");
// Burst Type
if (Addr[3] == 1'b0)
$display (" Burst Type = Sequential");
else if (Addr[3] == 1'b1)
$display (" Burst Type = Interleaved");
else
$display (" Burst Type = Reserved");
// Write Burst Mode
if (Addr[9] == 1'b0)
$display (" Write Burst Mode = Programmed Burst Length");
else if (Addr[9] == 1'b1)
$display (" Write Burst Mode = Single Location Access");
else
$display (" Write Burst Mode = Reserved");
end
end else begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time);
end
// REF to LMR
if ($time - RC_chk < tRC) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Load Mode Register", $time);
end
// LMR to LMR
if (MRD_chk < tMRD) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);
end
MRD_chk = 0;
end
// Active Block (Latch Bank Address and Row Address)
if (Active_enable == 1'b1) begin
if (Ba == 2'b00 && Pc_b0 == 1'b1) begin
{Act_b0, Pc_b0} = 2'b10;
B0_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk0 = $time;
RAS_chk0 = $time;
if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr);
// Precharge to Activate Bank 0
if ($time - RP_chk0 < tRP) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);
end
end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin
{Act_b1, Pc_b1} = 2'b10;
B1_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk1 = $time;
RAS_chk1 = $time;
if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr);
// Precharge to Activate Bank 1
if ($time - RP_chk1 < tRP) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);
end
end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin
{Act_b2, Pc_b2} = 2'b10;
B2_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk2 = $time;
RAS_chk2 = $time;
if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr);
// Precharge to Activate Bank 2
if ($time - RP_chk2 < tRP) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 2", $time);
end
end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin
{Act_b3, Pc_b3} = 2'b10;
B3_row_addr = Addr [addr_bits - 1 : 0];
RCD_chk3 = $time;
RAS_chk3 = $time;
if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr);
// Precharge to Activate Bank 3
if ($time - RP_chk3 < tRP) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRP violation during Activate bank 3", $time);
end
end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 0 is not Precharged.", $time);
end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);
end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);
end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: Bank 3 is not Precharged.", $time);
end
// Active Bank A to Active Bank B
if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba);
end
// Load Mode Register to Active
if (MRD_chk < tMRD ) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba);
end
// Auto Refresh to Activate
if ($time - RC_chk < tRC) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba);
end
// Record variables for checking violation
RRD_chk = $time;
Previous_bank = Ba;
end
// Precharge Block
if (Prech_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;
{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;
RP_chk0 = $time;
RP_chk1 = $time;
RP_chk2 = $time;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = ALL",$time);
// Activate to Precharge all banks
if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||
($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time);
end
// tWR violation check for write
if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) ||
($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge all bank", $time);
end
end else if (Addr[10] == 1'b0) begin
if (Ba == 2'b00) begin
{Pc_b0, Act_b0} = 2'b10;
RP_chk0 = $time;
if (Debug) $display ("at time %t PRE : Bank = 0",$time);
// Activate to Precharge Bank 0
if ($time - RAS_chk0 < tRAS) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time);
end
end else if (Ba == 2'b01) begin
{Pc_b1, Act_b1} = 2'b10;
RP_chk1 = $time;
if (Debug) $display ("at time %t PRE : Bank = 1",$time);
// Activate to Precharge Bank 1
if ($time - RAS_chk1 < tRAS) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time);
end
end else if (Ba == 2'b10) begin
{Pc_b2, Act_b2} = 2'b10;
RP_chk2 = $time;
if (Debug) $display ("at time %t PRE : Bank = 2",$time);
// Activate to Precharge Bank 2
if ($time - RAS_chk2 < tRAS) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time);
end
end else if (Ba == 2'b11) begin
{Pc_b3, Act_b3} = 2'b10;
RP_chk3 = $time;
if (Debug) $display ("at time %t PRE : Bank = 3",$time);
// Activate to Precharge Bank 3
if ($time - RAS_chk3 < tRAS) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);
end
end
// tWR violation check for write
if ($time - WR_chk[Ba] < tWRp) begin
 
//->tb.test_control.error_detected;
$display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba);
end
end
// Terminate a Write Immediately (if same bank or all banks)
if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin
Data_in_enable = 1'b0;
end
// Precharge Command Pipeline for Read
if (Cas_latency_3 == 1'b1) begin
Command[2] = `SDRAM_PRECH;
Bank_precharge[2] = Ba;
A10_precharge[2] = Addr[10];
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `SDRAM_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] = `SDRAM_BST;
end else if (Cas_latency_2 == 1'b1) begin
Command[1] = `SDRAM_BST;
end
if (Debug) $display ("at time %t BST : Burst Terminate",$time);
end
// Read, Write, Column Latch
if (Read_enable == 1'b1 || Write_enable == 1'b1) begin
// Check to see if bank is open (ACT)
if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) ||
(Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin
 
//->tb.test_control.error_detected;
$display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba);
end
// Activate to Read or Write
if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time);
end
if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time);
end
if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time);
end
if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD))
begin
//->tb.test_control.error_detected;
$display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time);
end
// Read Command
if (Read_enable == 1'b1) begin
// CAS Latency pipeline
if (Cas_latency_3 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[2] = `READ_A;
end else begin
Command[2] = `READ;
end
Col_addr[2] = Addr;
Bank_addr[2] = Ba;
end else if (Cas_latency_2 == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[1] = `READ_A;
end else begin
Command[1] = `READ;
end
Col_addr[1] = Addr;
Bank_addr[1] = Ba;
end
 
// Read interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write Command
end else if (Write_enable == 1'b1) begin
if (Addr[10] == 1'b1) begin
Command[0] = `WRITE_A;
end else begin
Command[0] = `SDRAM_WRITE;
end
Col_addr[0] = Addr;
Bank_addr[0] = Ba;
 
// Write interrupt Write (terminate Write immediately)
if (Data_in_enable == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Write interrupt Read (terminate Read immediately)
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
// Interrupting a Write with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin
RW_interrupt_write[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank);
end
 
// Interrupting a Read with Autoprecharge
if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin
RW_interrupt_read[Bank] = 1'b1;
if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank);
end
 
// Read or Write with Auto Precharge
if (Addr[10] == 1'b1) begin
Auto_precharge[Ba] = 1'b1;
Count_precharge[Ba] = 0;
if (Read_enable == 1'b1) begin
Read_precharge[Ba] = 1'b1;
end else if (Write_enable == 1'b1) begin
Write_precharge[Ba] = 1'b1;
end
end
end
 
// Read with Auto Precharge Calculation
// The device start internal precharge:
// 1. CAS Latency - 1 cycles before last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) ||
(RW_interrupt_read[0] == 1'b1)) begin // Case 3
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
Auto_precharge[0] = 1'b0;
Read_precharge[0] = 1'b0;
RW_interrupt_read[0] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) ||
(RW_interrupt_read[1] == 1'b1)) begin
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
Auto_precharge[1] = 1'b0;
Read_precharge[1] = 1'b0;
RW_interrupt_read[1] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) ||
(RW_interrupt_read[2] == 1'b1)) begin
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
Auto_precharge[2] = 1'b0;
Read_precharge[2] = 1'b0;
RW_interrupt_read[2] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) ||
(RW_interrupt_read[3] == 1'b1)) begin
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
Auto_precharge[3] = 1'b0;
Read_precharge[3] = 1'b0;
RW_interrupt_read[3] = 1'b0;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
 
// Internal Precharge or Bst
if (Command[0] == `SDRAM_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] == `SDRAM_BST) begin // BST terminate a read to current bank
if (Data_out_enable == 1'b1) begin
Data_out_enable = 1'b0;
end
end
 
if (Data_out_enable == 1'b0) begin
Dq_reg <= #tOH {data_bits{1'bz}};
end
 
// Detect Read or Write command
if (Command[0] == `READ || Command[0] == `READ_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b0;
Data_out_enable = 1'b1;
end else if (Command[0] == `SDRAM_WRITE || Command[0] == `WRITE_A) begin
Bank = Bank_addr[0];
Col = Col_addr[0];
Col_brst = Col_addr[0];
if (Bank_addr[0] == 2'b00) begin
Row = B0_row_addr;
end else if (Bank_addr[0] == 2'b01) begin
Row = B1_row_addr;
end else if (Bank_addr[0] == 2'b10) begin
Row = B2_row_addr;
end else if (Bank_addr[0] == 2'b11) begin
Row = B3_row_addr;
end
Burst_counter = 0;
Data_in_enable = 1'b1;
Data_out_enable = 1'b0;
end
 
// DQ buffer (Driver/Receiver)
if (Data_in_enable == 1'b1) begin // Writing Data to Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0];
// Write to memory
if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0];
if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0];
// Output result
if (Dqm == 1'b1) begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm);
// Record tWR time and reset counter
WR_chk [Bank] = $time;
WR_counter [Bank] = 0;
end
// Advance burst counter subroutine
#tHZ Burst;
end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory
// Array buffer
if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}];
if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}];
if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}];
if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}];
// Dqm operation
if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz;
// Display result
Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0];
if (Dqm_reg0 == 1'b1) begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col);
end else begin
if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0);
end
// Advance burst counter subroutine
Burst;
end
end
 
// Write with Auto Precharge Calculation
// The device start internal precharge:
// 1. tWR Clock after last burst
// and 2. Meet minimum tRAS requirement
// or 3. Interrupt by a Read or Write (with or without AutoPrecharge)
always @ (WR_counter[0]) begin
if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin
if ((($time - RAS_chk0 >= tRAS) && // Case 2
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1
(Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) ||
(RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt)
Auto_precharge[0] = 1'b0;
Write_precharge[0] = 1'b0;
RW_interrupt_write[0] = 1'b0;
#tWRa; // Wait for tWR
Pc_b0 = 1'b1;
Act_b0 = 1'b0;
RP_chk0 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time);
end
end
end
always @ (WR_counter[1]) begin
if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin
if ((($time - RAS_chk1 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) ||
(RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin
Auto_precharge[1] = 1'b0;
Write_precharge[1] = 1'b0;
RW_interrupt_write[1] = 1'b0;
#tWRa; // Wait for tWR
Pc_b1 = 1'b1;
Act_b1 = 1'b0;
RP_chk1 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time);
end
end
end
always @ (WR_counter[2]) begin
if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin
if ((($time - RAS_chk2 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) ||
(RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin
Auto_precharge[2] = 1'b0;
Write_precharge[2] = 1'b0;
RW_interrupt_write[2] = 1'b0;
#tWRa; // Wait for tWR
Pc_b2 = 1'b1;
Act_b2 = 1'b0;
RP_chk2 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time);
end
end
end
always @ (WR_counter[3]) begin
if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin
if ((($time - RAS_chk3 >= tRAS) &&
(((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) ||
(Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) ||
(Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) ||
(Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) ||
(RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin
Auto_precharge[3] = 1'b0;
Write_precharge[3] = 1'b0;
RW_interrupt_write[3] = 1'b0;
#tWRa; // Wait for tWR
Pc_b3 = 1'b1;
Act_b3 = 1'b0;
RP_chk3 = $time;
if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time);
end
end
end
 
task Burst;
begin
// Advance Burst Counter
Burst_counter = Burst_counter + 1;
 
// Burst Type
if (Mode_reg[3] == 1'b0) begin // Sequential Burst
Col_temp = Col + 1;
end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst
Col_temp[2] = Burst_counter[2] ^ Col_brst[2];
Col_temp[1] = Burst_counter[1] ^ Col_brst[1];
Col_temp[0] = Burst_counter[0] ^ Col_brst[0];
end
 
// Burst Length
if (Burst_length_2) begin // Burst Length = 2
Col [0] = Col_temp [0];
end else if (Burst_length_4) begin // Burst Length = 4
Col [1 : 0] = Col_temp [1 : 0];
end else if (Burst_length_8) begin // Burst Length = 8
Col [2 : 0] = Col_temp [2 : 0];
end else begin // Burst Length = FULL
Col = Col_temp;
end
 
// Burst Read Single Write
if (Write_burst_mode == 1'b1) begin
Data_in_enable = 1'b0;
end
 
// Data Counter
if (Burst_length_1 == 1'b1) begin
if (Burst_counter >= 1) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_2 == 1'b1) begin
if (Burst_counter >= 2) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_4 == 1'b1) begin
if (Burst_counter >= 4) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end else if (Burst_length_8 == 1'b1) begin
if (Burst_counter >= 8) begin
Data_in_enable = 1'b0;
Data_out_enable = 1'b0;
end
end
end
endtask
 
// Timing Parameters for -75 (PC133) and CAS Latency = 2
specify
specparam
tAH = 0.8, // Addr, Ba Hold Time
tAS = 1.5, // Addr, Ba Setup Time
tCH = 2.5, // Clock High-Level Width
tCL = 2.5, // Clock Low-Level Width
tCK = 10, // Clock Cycle Time
tDH = 0.8, // Data-in Hold Time
tDS = 1.5, // Data-in Setup Time
tCKH = 0.8, // CKE Hold Time
tCKS = 1.5, // CKE Setup Time
tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time
tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time
$width (posedge Clk, tCH);
$width (negedge Clk, tCL);
$period (negedge Clk, tCK);
$period (posedge Clk, tCK);
$setuphold(posedge Clk, Cke, tCKS, tCKH);
$setuphold(posedge Clk, Cs_n, tCMS, tCMH);
$setuphold(posedge Clk, Cas_n, tCMS, tCMH);
$setuphold(posedge Clk, Ras_n, tCMS, tCMH);
$setuphold(posedge Clk, We_n, tCMS, tCMH);
$setuphold(posedge Clk, Addr, tAS, tAH);
$setuphold(posedge Clk, Ba, tAS, tAH);
$setuphold(posedge Clk, Dqm, tCMS, tCMH);
$setuphold(posedge Dq_chk, Dq, tDS, tDH);
endspecify
 
endmodule
 
mt48lc8m8a2.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: mt48lc8m16a2.v =================================================================== --- mt48lc8m16a2.v (nonexistent) +++ mt48lc8m16a2.v (revision 17) @@ -0,0 +1,963 @@ +/**************************************************************************************** +* +* File Name: MT48LC8M16A2.V +* Version: 0.0f +* Date: July 8th, 1999 +* Model: BUS Functional +* Simulator: Model Technology (PC version 5.2e PE) +* +* Dependencies: None +* +* Author: Son P. Huynh +* Email: sphuynh@micron.com +* Phone: (208) 368-3825 +* Company: Micron Technology, Inc. +* Model: MT48LC8M16A2 (2Meg x 16 x 4 Banks) +* +* Description: Micron 128Mb SDRAM Verilog model +* +* Limitation: - Doesn't check for 4096 cycle refresh +* +* Note: - Set simulator resolution to "ps" accuracy +* - Set Debug = 0 to disable $display messages +* +* Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY +* WHATSOEVER AND MICRON SPECIFICALLY DISCLAIMS ANY +* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR +* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT. +* +* Copyright © 1998 Micron Semiconductor Products, Inc. +* All rights researved +* +* Rev Author Phone Date Changes +* ---- ---------------------------- ---------- --------------------------------------- +* 0.0f Son Huynh 208-368-3825 07/08/1999 - Fix tWR = 1 Clk + 7.5 ns (Auto) +* Micron Technology Inc. - Fix tWR = 15 ns (Manual) +* - Fix tRP (Autoprecharge to AutoRefresh) +* +* 0.0a Son Huynh 208-368-3825 05/13/1998 - First Release (from 64Mb rev 0.0e) +* Micron Technology Inc. +****************************************************************************************/ + +`timescale 1ns / 100ps + +module mt48lc8m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm); + + parameter addr_bits = 12; + parameter data_bits = 16; + parameter col_bits = 9; + parameter mem_sizes = 2097151; // 2 Meg + + inout [data_bits - 1 : 0] Dq; + input [addr_bits - 1 : 0] Addr; + input [1 : 0] Ba; + input Clk; + input Cke; + input Cs_n; + input Ras_n; + input Cas_n; + input We_n; + input [1 : 0] Dqm; + + reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes]; + reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes]; + reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes]; + reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes]; + + reg [1 : 0] Bank_addr [0 : 3]; // Bank Address Pipeline + reg [col_bits - 1 : 0] Col_addr [0 : 3]; // Column Address Pipeline + reg [3 : 0] Command [0 : 3]; // Command Operation Pipeline + reg [1 : 0] Dqm_reg0, Dqm_reg1; // DQM Operation Pipeline + reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr; + + reg [addr_bits - 1 : 0] Mode_reg; + reg [data_bits - 1 : 0] Dq_reg, Dq_dqm; + reg [col_bits - 1 : 0] Col_temp, Burst_counter; + + reg Act_b0, Act_b1, Act_b2, Act_b3; // Bank Activate + reg Pc_b0, Pc_b1, Pc_b2, Pc_b3; // Bank Precharge + + reg [1 : 0] Bank_precharge [0 : 3]; // Precharge Command + reg A10_precharge [0 : 3]; // Addr[10] = 1 (All banks) + reg Auto_precharge [0 : 3]; // RW AutoPrecharge (Bank) + reg Read_precharge [0 : 3]; // R AutoPrecharge + reg Write_precharge [0 : 3]; // W AutoPrecharge + integer Count_precharge [0 : 3]; // RW AutoPrecharge (Counter) + reg RW_interrupt_read [0 : 3]; // RW Interrupt Read with Auto Precharge + reg RW_interrupt_write [0 : 3]; // RW Interrupt Write with Auto Precharge + + reg Data_in_enable; + reg Data_out_enable; + + reg [1 : 0] Bank, Previous_bank; + reg [addr_bits - 1 : 0] Row; + reg [col_bits - 1 : 0] Col, Col_brst; + + // Internal system clock + reg CkeZ, Sys_clk; + + // Commands Decode + wire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n; + wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n; + wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n; + wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n; + wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n; + wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n; + wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n; + + // Burst Length Decode + wire Burst_length_1 = ~Mode_reg[2] & ~Mode_reg[1] & ~Mode_reg[0]; + wire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0]; + wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0]; + wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0]; + + // CAS Latency Decode + wire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4]; + wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4]; + + // Write Burst Mode + wire Write_burst_mode = Mode_reg[9]; + + reg Debug; // Debug messages : 1 = On + wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ + + assign Dq = Dq_reg; // DQ buffer + + // Commands Operation + `define ACT 0 + `define NOP 1 + `define READ 2 + `define READ_A 3 + `define WRITE 4 + `define WRITE_A 5 + `define PRECH 6 + `define A_REF 7 + `define BST 8 + `define LMR 9 + + // Timing Parameters for -75 (PC133) and CAS Latency = 2 + parameter tAC = 6.0; + parameter tHZ = 7.0; + parameter tOH = 2.7; + parameter tMRD = 2.0; // 2 Clk Cycles + parameter tRAS = 44.0; + parameter tRC = 66.0; + parameter tRCD = 20.0; + parameter tRP = 20.0; + parameter tRRD = 15.0; + parameter tWRa = 7.5; // A2 Version - Auto precharge mode only (1 Clk + 7.5 ns) + parameter tWRp = 15.0; // A2 Version - Precharge mode only (15 ns) + + // Timing Check variable + integer MRD_chk; + integer WR_counter [0 : 3]; + time WR_chk [0 : 3]; + time RC_chk, RRD_chk; + time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; + time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; + time RP_chk0, RP_chk1, RP_chk2, RP_chk3; + + initial begin + Debug = 1'b0; + + Dq_reg = {data_bits{1'bz}}; + {Data_in_enable, Data_out_enable} = 0; + {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; + {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000; + {WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 0; + {WR_counter[0], WR_counter[1], WR_counter[2], WR_counter[3]} = 0; + {RW_interrupt_read[0], RW_interrupt_read[1], RW_interrupt_read[2], RW_interrupt_read[3]} = 0; + {RW_interrupt_write[0], RW_interrupt_write[1], RW_interrupt_write[2], RW_interrupt_write[3]} = 0; + {MRD_chk, RC_chk, RRD_chk} = 0; + {RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 0; + {RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 0; + {RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 0; + $timeformat (-9, 0, " ns", 12); + //$readmemh("bank0.txt", Bank0); + //$readmemh("bank1.txt", Bank1); + //$readmemh("bank2.txt", Bank2); + //$readmemh("bank3.txt", Bank3); + end + + // System clock generator + always begin + @ (posedge Clk) begin + Sys_clk = CkeZ; + CkeZ = Cke; + end + @ (negedge Clk) begin + Sys_clk = 1'b0; + end + end + + always @ (posedge Sys_clk) begin + // Internal Commamd Pipelined + Command[0] = Command[1]; + Command[1] = Command[2]; + Command[2] = Command[3]; + Command[3] = `NOP; + + Col_addr[0] = Col_addr[1]; + Col_addr[1] = Col_addr[2]; + Col_addr[2] = Col_addr[3]; + Col_addr[3] = {col_bits{1'b0}}; + + Bank_addr[0] = Bank_addr[1]; + Bank_addr[1] = Bank_addr[2]; + Bank_addr[2] = Bank_addr[3]; + Bank_addr[3] = 2'b0; + + Bank_precharge[0] = Bank_precharge[1]; + Bank_precharge[1] = Bank_precharge[2]; + Bank_precharge[2] = Bank_precharge[3]; + Bank_precharge[3] = 2'b0; + + A10_precharge[0] = A10_precharge[1]; + A10_precharge[1] = A10_precharge[2]; + A10_precharge[2] = A10_precharge[3]; + A10_precharge[3] = 1'b0; + + // Dqm pipeline for Read + Dqm_reg0 = Dqm_reg1; + Dqm_reg1 = Dqm; + + // Read or Write with Auto Precharge Counter + if (Auto_precharge[0] == 1'b1) begin + Count_precharge[0] = Count_precharge[0] + 1; + end + if (Auto_precharge[1] == 1'b1) begin + Count_precharge[1] = Count_precharge[1] + 1; + end + if (Auto_precharge[2] == 1'b1) begin + Count_precharge[2] = Count_precharge[2] + 1; + end + if (Auto_precharge[3] == 1'b1) begin + Count_precharge[3] = Count_precharge[3] + 1; + end + + // tMRD Counter + MRD_chk = MRD_chk + 1; + + // tWR Counter for Write + WR_counter[0] = WR_counter[0] + 1; + WR_counter[1] = WR_counter[1] + 1; + WR_counter[2] = WR_counter[2] + 1; + WR_counter[3] = WR_counter[3] + 1; + + // Auto Refresh + if (Aref_enable == 1'b1) begin + if (Debug) $display ("at time %t AREF : Auto Refresh", $time); + // Auto Refresh to Auto Refresh + if ($time - RC_chk < tRC) begin + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRC violation during Auto Refresh", $time); + end + // Precharge to Auto Refresh + if ($time - RP_chk0 < tRP || $time - RP_chk1 < tRP || $time - RP_chk2 < tRP || $time - RP_chk3 < tRP) begin + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRP violation during Auto Refresh", $time); + end + // Precharge to Refresh + if (Pc_b0 == 1'b0 || Pc_b1 == 1'b0 || Pc_b2 == 1'b0 || Pc_b3 == 1'b0) begin + //->tb.test_control.error_detected; + $display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time); + end + // Record Current tRC time + RC_chk = $time; + end + + // Load Mode Register + if (Mode_reg_enable == 1'b1) begin + // Decode CAS Latency, Burst Length, Burst Type, and Write Burst Mode + if (Pc_b0 == 1'b1 && Pc_b1 == 1'b1 && Pc_b2 == 1'b1 && Pc_b3 == 1'b1) begin + Mode_reg = Addr; + if (Debug) begin + $display ("at time %t LMR : Load Mode Register", $time); + // CAS Latency + if (Addr[6 : 4] == 3'b010) + $display (" CAS Latency = 2"); + else if (Addr[6 : 4] == 3'b011) + $display (" CAS Latency = 3"); + else + $display (" CAS Latency = Reserved"); + // Burst Length + if (Addr[2 : 0] == 3'b000) + $display (" Burst Length = 1"); + else if (Addr[2 : 0] == 3'b001) + $display (" Burst Length = 2"); + else if (Addr[2 : 0] == 3'b010) + $display (" Burst Length = 4"); + else if (Addr[2 : 0] == 3'b011) + $display (" Burst Length = 8"); + else if (Addr[3 : 0] == 4'b0111) + $display (" Burst Length = Full"); + else + $display (" Burst Length = Reserved"); + // Burst Type + if (Addr[3] == 1'b0) + $display (" Burst Type = Sequential"); + else if (Addr[3] == 1'b1) + $display (" Burst Type = Interleaved"); + else + $display (" Burst Type = Reserved"); + // Write Burst Mode + if (Addr[9] == 1'b0) + $display (" Write Burst Mode = Programmed Burst Length"); + else if (Addr[9] == 1'b1) + $display (" Write Burst Mode = Single Location Access"); + else + $display (" Write Burst Mode = Reserved"); + end + end else begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); + end + // REF to LMR + if ($time - RC_chk < tRC) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRC violation during Load Mode Register", $time); + end + // LMR to LMR + if (MRD_chk < tMRD) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tMRD violation during Load Mode Register", $time); + end + MRD_chk = 0; + end + + // Active Block (Latch Bank Address and Row Address) + if (Active_enable == 1'b1) begin + if (Ba == 2'b00 && Pc_b0 == 1'b1) begin + {Act_b0, Pc_b0} = 2'b10; + B0_row_addr = Addr [addr_bits - 1 : 0]; + RCD_chk0 = $time; + RAS_chk0 = $time; + if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d", $time, Addr); + // Precharge to Activate Bank 0 + if ($time - RP_chk0 < tRP) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRP violation during Activate bank 0", $time); + end + end else if (Ba == 2'b01 && Pc_b1 == 1'b1) begin + {Act_b1, Pc_b1} = 2'b10; + B1_row_addr = Addr [addr_bits - 1 : 0]; + RCD_chk1 = $time; + RAS_chk1 = $time; + if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d", $time, Addr); + // Precharge to Activate Bank 1 + if ($time - RP_chk1 < tRP) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRP violation during Activate bank 1", $time); + end + end else if (Ba == 2'b10 && Pc_b2 == 1'b1) begin + {Act_b2, Pc_b2} = 2'b10; + B2_row_addr = Addr [addr_bits - 1 : 0]; + RCD_chk2 = $time; + RAS_chk2 = $time; + if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d", $time, Addr); + // Precharge to Activate Bank 2 + if ($time - RP_chk2 < tRP) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRP violation during Activate bank 2", $time); + end + end else if (Ba == 2'b11 && Pc_b3 == 1'b1) begin + {Act_b3, Pc_b3} = 2'b10; + B3_row_addr = Addr [addr_bits - 1 : 0]; + RCD_chk3 = $time; + RAS_chk3 = $time; + if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d", $time, Addr); + // Precharge to Activate Bank 3 + if ($time - RP_chk3 < tRP) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRP violation during Activate bank 3", $time); + end + end else if (Ba == 2'b00 && Pc_b0 == 1'b0) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: Bank 0 is not Precharged.", $time); + end else if (Ba == 2'b01 && Pc_b1 == 1'b0) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: Bank 1 is not Precharged.", $time); + end else if (Ba == 2'b10 && Pc_b2 == 1'b0) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: Bank 2 is not Precharged.", $time); + end else if (Ba == 2'b11 && Pc_b3 == 1'b0) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: Bank 3 is not Precharged.", $time); + end + // Active Bank A to Active Bank B + if ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRRD violation during Activate bank = %d", $time, Ba); + end + // Load Mode Register to Active + if (MRD_chk < tMRD ) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tMRD violation during Activate bank = %d", $time, Ba); + end + // Auto Refresh to Activate + if ($time - RC_chk < tRC) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRC violation during Activate bank = %d", $time, Ba); + end + // Record variables for checking violation + RRD_chk = $time; + Previous_bank = Ba; + end + + // Precharge Block + if (Prech_enable == 1'b1) begin + if (Addr[10] == 1'b1) begin + {Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111; + {Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000; + RP_chk0 = $time; + RP_chk1 = $time; + RP_chk2 = $time; + RP_chk3 = $time; + if (Debug) $display ("at time %t PRE : Bank = ALL",$time); + // Activate to Precharge all banks + if (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) || + ($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRAS violation during Precharge all bank", $time); + end + // tWR violation check for write + if (($time - WR_chk[0] < tWRp) || ($time - WR_chk[1] < tWRp) || + ($time - WR_chk[2] < tWRp) || ($time - WR_chk[3] < tWRp)) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tWR violation during Precharge all bank", $time); + end + end else if (Addr[10] == 1'b0) begin + if (Ba == 2'b00) begin + {Pc_b0, Act_b0} = 2'b10; + RP_chk0 = $time; + if (Debug) $display ("at time %t PRE : Bank = 0",$time); + // Activate to Precharge Bank 0 + if ($time - RAS_chk0 < tRAS) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time); + end + end else if (Ba == 2'b01) begin + {Pc_b1, Act_b1} = 2'b10; + RP_chk1 = $time; + if (Debug) $display ("at time %t PRE : Bank = 1",$time); + // Activate to Precharge Bank 1 + if ($time - RAS_chk1 < tRAS) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time); + end + end else if (Ba == 2'b10) begin + {Pc_b2, Act_b2} = 2'b10; + RP_chk2 = $time; + if (Debug) $display ("at time %t PRE : Bank = 2",$time); + // Activate to Precharge Bank 2 + if ($time - RAS_chk2 < tRAS) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time); + end + end else if (Ba == 2'b11) begin + {Pc_b3, Act_b3} = 2'b10; + RP_chk3 = $time; + if (Debug) $display ("at time %t PRE : Bank = 3",$time); + // Activate to Precharge Bank 3 + if ($time - RAS_chk3 < tRAS) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time); + end + end + // tWR violation check for write + if ($time - WR_chk[Ba] < tWRp) begin + + //->tb.test_control.error_detected; + $display ("at time %t ERROR: tWR violation during Precharge bank %d", $time, Ba); + end + end + // Terminate a Write Immediately (if same bank or all banks) + if (Data_in_enable == 1'b1 && (Bank == Ba || Addr[10] == 1'b1)) begin + Data_in_enable = 1'b0; + end + // Precharge Command Pipeline for Read + if (Cas_latency_3 == 1'b1) begin + Command[2] = `PRECH; + Bank_precharge[2] = Ba; + A10_precharge[2] = Addr[10]; + end else if (Cas_latency_2 == 1'b1) begin + Command[1] = `PRECH; + Bank_precharge[1] = Ba; + A10_precharge[1] = Addr[10]; + end + end + + // Burst terminate + if (Burst_term == 1'b1) begin + // Terminate a Write Immediately + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + end + // Terminate a Read Depend on CAS Latency + if (Cas_latency_3 == 1'b1) begin + Command[2] = `BST; + end else if (Cas_latency_2 == 1'b1) begin + Command[1] = `BST; + end + if (Debug) $display ("at time %t BST : Burst Terminate",$time); + end + + // Read, Write, Column Latch + if (Read_enable == 1'b1 || Write_enable == 1'b1) begin + // Check to see if bank is open (ACT) + if ((Ba == 2'b00 && Pc_b0 == 1'b1) || (Ba == 2'b01 && Pc_b1 == 1'b1) || + (Ba == 2'b10 && Pc_b2 == 1'b1) || (Ba == 2'b11 && Pc_b3 == 1'b1)) begin + + //->tb.test_control.error_detected; + $display("at time %t ERROR: Cannot Read or Write - Bank %d is not Activated", $time, Ba); + end + // Activate to Read or Write + if ((Ba == 2'b00) && ($time - RCD_chk0 < tRCD)) + begin + //->tb.test_control.error_detected; + $display("at time %t ERROR: tRCD violation during Read or Write to Bank 0", $time); + end + + if ((Ba == 2'b01) && ($time - RCD_chk1 < tRCD)) + begin + //->tb.test_control.error_detected; + $display("at time %t ERROR: tRCD violation during Read or Write to Bank 1", $time); + end + if ((Ba == 2'b10) && ($time - RCD_chk2 < tRCD)) + begin + //->tb.test_control.error_detected; + $display("at time %t ERROR: tRCD violation during Read or Write to Bank 2", $time); + end + if ((Ba == 2'b11) && ($time - RCD_chk3 < tRCD)) + begin + //->tb.test_control.error_detected; + $display("at time %t ERROR: tRCD violation during Read or Write to Bank 3", $time); + end + // Read Command + if (Read_enable == 1'b1) begin + // CAS Latency pipeline + if (Cas_latency_3 == 1'b1) begin + if (Addr[10] == 1'b1) begin + Command[2] = `READ_A; + end else begin + Command[2] = `READ; + end + Col_addr[2] = Addr; + Bank_addr[2] = Ba; + end else if (Cas_latency_2 == 1'b1) begin + if (Addr[10] == 1'b1) begin + Command[1] = `READ_A; + end else begin + Command[1] = `READ; + end + Col_addr[1] = Addr; + Bank_addr[1] = Ba; + end + + // Read interrupt Write (terminate Write immediately) + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Write Command + end else if (Write_enable == 1'b1) begin + if (Addr[10] == 1'b1) begin + Command[0] = `WRITE_A; + end else begin + Command[0] = `WRITE; + end + Col_addr[0] = Addr; + Bank_addr[0] = Ba; + + // Write interrupt Write (terminate Write immediately) + if (Data_in_enable == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Write interrupt Read (terminate Read immediately) + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + + // Interrupting a Write with Autoprecharge + if (Auto_precharge[Bank] == 1'b1 && Write_precharge[Bank] == 1'b1) begin + RW_interrupt_write[Bank] = 1'b1; + if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Write Bank %d with Autoprecharge", $time, Ba, Bank); + end + + // Interrupting a Read with Autoprecharge + if (Auto_precharge[Bank] == 1'b1 && Read_precharge[Bank] == 1'b1) begin + RW_interrupt_read[Bank] = 1'b1; + if (Debug) $display ("at time %t NOTE : Read/Write Bank %d interrupt Read Bank %d with Autoprecharge", $time, Ba, Bank); + end + + // Read or Write with Auto Precharge + if (Addr[10] == 1'b1) begin + Auto_precharge[Ba] = 1'b1; + Count_precharge[Ba] = 0; + if (Read_enable == 1'b1) begin + Read_precharge[Ba] = 1'b1; + end else if (Write_enable == 1'b1) begin + Write_precharge[Ba] = 1'b1; + end + end + end + + // Read with Auto Precharge Calculation + // The device start internal precharge: + // 1. CAS Latency - 1 cycles before last burst + // and 2. Meet minimum tRAS requirement + // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) + if ((Auto_precharge[0] == 1'b1) && (Read_precharge[0] == 1'b1)) begin + if ((($time - RAS_chk0 >= tRAS) && // Case 2 + ((Burst_length_1 == 1'b1 && Count_precharge[0] >= 1) || // Case 1 + (Burst_length_2 == 1'b1 && Count_precharge[0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[0] >= 8))) || + (RW_interrupt_read[0] == 1'b1)) begin // Case 3 + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time; + Auto_precharge[0] = 1'b0; + Read_precharge[0] = 1'b0; + RW_interrupt_read[0] = 1'b0; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + if ((Auto_precharge[1] == 1'b1) && (Read_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[1] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[1] >= 8))) || + (RW_interrupt_read[1] == 1'b1)) begin + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time; + Auto_precharge[1] = 1'b0; + Read_precharge[1] = 1'b0; + RW_interrupt_read[1] = 1'b0; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + if ((Auto_precharge[2] == 1'b1) && (Read_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[2] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[2] >= 8))) || + (RW_interrupt_read[2] == 1'b1)) begin + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time; + Auto_precharge[2] = 1'b0; + Read_precharge[2] = 1'b0; + RW_interrupt_read[2] = 1'b0; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + if ((Auto_precharge[3] == 1'b1) && (Read_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && + ((Burst_length_1 == 1'b1 && Count_precharge[3] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge[3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge[3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge[3] >= 8))) || + (RW_interrupt_read[3] == 1'b1)) begin + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time; + Auto_precharge[3] = 1'b0; + Read_precharge[3] = 1'b0; + RW_interrupt_read[3] = 1'b0; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + + // Internal Precharge or Bst + if (Command[0] == `PRECH) begin // Precharge terminate a read with same bank or all banks + if (Bank_precharge[0] == Bank || A10_precharge[0] == 1'b1) begin + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + end else if (Command[0] == `BST) begin // BST terminate a read to current bank + if (Data_out_enable == 1'b1) begin + Data_out_enable = 1'b0; + end + end + + if (Data_out_enable == 1'b0) begin + Dq_reg <= #tOH {data_bits{1'bz}}; + end + + // Detect Read or Write command + if (Command[0] == `READ || Command[0] == `READ_A) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + if (Bank_addr[0] == 2'b00) begin + Row = B0_row_addr; + end else if (Bank_addr[0] == 2'b01) begin + Row = B1_row_addr; + end else if (Bank_addr[0] == 2'b10) begin + Row = B2_row_addr; + end else if (Bank_addr[0] == 2'b11) begin + Row = B3_row_addr; + end + Burst_counter = 0; + Data_in_enable = 1'b0; + Data_out_enable = 1'b1; + end else if (Command[0] == `WRITE || Command[0] == `WRITE_A) begin + Bank = Bank_addr[0]; + Col = Col_addr[0]; + Col_brst = Col_addr[0]; + if (Bank_addr[0] == 2'b00) begin + Row = B0_row_addr; + end else if (Bank_addr[0] == 2'b01) begin + Row = B1_row_addr; + end else if (Bank_addr[0] == 2'b10) begin + Row = B2_row_addr; + end else if (Bank_addr[0] == 2'b11) begin + Row = B3_row_addr; + end + Burst_counter = 0; + Data_in_enable = 1'b1; + Data_out_enable = 1'b0; + end + + // DQ buffer (Driver/Receiver) + if (Data_in_enable == 1'b1) begin // Writing Data to Memory + // Array buffer + if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}]; + if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}]; + if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}]; + if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}]; + // Dqm operation + if (Dqm[0] == 1'b0) Dq_dqm [ 7 : 0] = Dq [ 7 : 0]; + if (Dqm[1] == 1'b0) Dq_dqm [15 : 8] = Dq [15 : 8]; + // Write to memory + if (Bank == 2'b00) Bank0 [{Row, Col}] = Dq_dqm [15 : 0]; + if (Bank == 2'b01) Bank1 [{Row, Col}] = Dq_dqm [15 : 0]; + if (Bank == 2'b10) Bank2 [{Row, Col}] = Dq_dqm [15 : 0]; + if (Bank == 2'b11) Bank3 [{Row, Col}] = Dq_dqm [15 : 0]; + // Output result + if (Dqm == 2'b11) begin + if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); + end else begin + if (Debug) $display("at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_dqm, Dqm); + // Record tWR time and reset counter + WR_chk [Bank] = $time; + WR_counter [Bank] = 0; + end + // Advance burst counter subroutine + #tHZ Burst; + end else if (Data_out_enable == 1'b1) begin // Reading Data from Memory + // Array buffer + if (Bank == 2'b00) Dq_dqm [15 : 0] = Bank0 [{Row, Col}]; + if (Bank == 2'b01) Dq_dqm [15 : 0] = Bank1 [{Row, Col}]; + if (Bank == 2'b10) Dq_dqm [15 : 0] = Bank2 [{Row, Col}]; + if (Bank == 2'b11) Dq_dqm [15 : 0] = Bank3 [{Row, Col}]; + // Dqm operation + if (Dqm_reg0[0] == 1'b1) Dq_dqm [ 7 : 0] = 8'bz; + if (Dqm_reg0[1] == 1'b1) Dq_dqm [15 : 8] = 8'bz; + // Display result + Dq_reg [15 : 0] = #tAC Dq_dqm [15 : 0]; + if (Dqm_reg0 == 2'b11) begin + if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = Hi-Z due to DQM", $time, Bank, Row, Col); + end else begin + if (Debug) $display("at time %t READ : Bank = %d Row = %d, Col = %d, Data = %h, Dqm = %b", $time, Bank, Row, Col, Dq_reg, Dqm_reg0); + end + // Advance burst counter subroutine + Burst; + end + end + + // Write with Auto Precharge Calculation + // The device start internal precharge: + // 1. tWR Clock after last burst + // and 2. Meet minimum tRAS requirement + // or 3. Interrupt by a Read or Write (with or without AutoPrecharge) + always @ (WR_counter[0]) begin + if ((Auto_precharge[0] == 1'b1) && (Write_precharge[0] == 1'b1)) begin + if ((($time - RAS_chk0 >= tRAS) && // Case 2 + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [0] >= 1) || // Case 1 + (Burst_length_2 == 1'b1 && Count_precharge [0] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [0] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [0] >= 8))) || + (RW_interrupt_write[0] == 1'b1 && WR_counter[0] >= 2)) begin // Case 3 (stop count when interrupt) + Auto_precharge[0] = 1'b0; + Write_precharge[0] = 1'b0; + RW_interrupt_write[0] = 1'b0; + #tWRa; // Wait for tWR + Pc_b0 = 1'b1; + Act_b0 = 1'b0; + RP_chk0 = $time; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 0", $time); + end + end + end + always @ (WR_counter[1]) begin + if ((Auto_precharge[1] == 1'b1) && (Write_precharge[1] == 1'b1)) begin + if ((($time - RAS_chk1 >= tRAS) && + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [1] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge [1] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [1] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [1] >= 8))) || + (RW_interrupt_write[1] == 1'b1 && WR_counter[1] >= 2)) begin + Auto_precharge[1] = 1'b0; + Write_precharge[1] = 1'b0; + RW_interrupt_write[1] = 1'b0; + #tWRa; // Wait for tWR + Pc_b1 = 1'b1; + Act_b1 = 1'b0; + RP_chk1 = $time; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 1", $time); + end + end + end + always @ (WR_counter[2]) begin + if ((Auto_precharge[2] == 1'b1) && (Write_precharge[2] == 1'b1)) begin + if ((($time - RAS_chk2 >= tRAS) && + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [2] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge [2] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [2] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [2] >= 8))) || + (RW_interrupt_write[2] == 1'b1 && WR_counter[2] >= 2)) begin + Auto_precharge[2] = 1'b0; + Write_precharge[2] = 1'b0; + RW_interrupt_write[2] = 1'b0; + #tWRa; // Wait for tWR + Pc_b2 = 1'b1; + Act_b2 = 1'b0; + RP_chk2 = $time; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 2", $time); + end + end + end + always @ (WR_counter[3]) begin + if ((Auto_precharge[3] == 1'b1) && (Write_precharge[3] == 1'b1)) begin + if ((($time - RAS_chk3 >= tRAS) && + (((Burst_length_1 == 1'b1 || Write_burst_mode == 1'b1) && Count_precharge [3] >= 1) || + (Burst_length_2 == 1'b1 && Count_precharge [3] >= 2) || + (Burst_length_4 == 1'b1 && Count_precharge [3] >= 4) || + (Burst_length_8 == 1'b1 && Count_precharge [3] >= 8))) || + (RW_interrupt_write[3] == 1'b1 && WR_counter[3] >= 2)) begin + Auto_precharge[3] = 1'b0; + Write_precharge[3] = 1'b0; + RW_interrupt_write[3] = 1'b0; + #tWRa; // Wait for tWR + Pc_b3 = 1'b1; + Act_b3 = 1'b0; + RP_chk3 = $time; + if (Debug) $display ("at time %t NOTE : Start Internal Auto Precharge for Bank 3", $time); + end + end + end + + task Burst; + begin + // Advance Burst Counter + Burst_counter = Burst_counter + 1; + + // Burst Type + if (Mode_reg[3] == 1'b0) begin // Sequential Burst + Col_temp = Col + 1; + end else if (Mode_reg[3] == 1'b1) begin // Interleaved Burst + Col_temp[2] = Burst_counter[2] ^ Col_brst[2]; + Col_temp[1] = Burst_counter[1] ^ Col_brst[1]; + Col_temp[0] = Burst_counter[0] ^ Col_brst[0]; + end + + // Burst Length + if (Burst_length_2) begin // Burst Length = 2 + Col [0] = Col_temp [0]; + end else if (Burst_length_4) begin // Burst Length = 4 + Col [1 : 0] = Col_temp [1 : 0]; + end else if (Burst_length_8) begin // Burst Length = 8 + Col [2 : 0] = Col_temp [2 : 0]; + end else begin // Burst Length = FULL + Col = Col_temp; + end + + // Burst Read Single Write + if (Write_burst_mode == 1'b1) begin + Data_in_enable = 1'b0; + end + + // Data Counter + if (Burst_length_1 == 1'b1) begin + if (Burst_counter >= 1) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_2 == 1'b1) begin + if (Burst_counter >= 2) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_4 == 1'b1) begin + if (Burst_counter >= 4) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end else if (Burst_length_8 == 1'b1) begin + if (Burst_counter >= 8) begin + Data_in_enable = 1'b0; + Data_out_enable = 1'b0; + end + end + end + endtask + + // Timing Parameters for -75 (PC133) and CAS Latency = 2 + specify + specparam + tAH = 0.8, // Addr, Ba Hold Time + tAS = 1.5, // Addr, Ba Setup Time + tCH = 2.5, // Clock High-Level Width + tCL = 2.5, // Clock Low-Level Width + tCK = 10, // Clock Cycle Time + tDH = 0.8, // Data-in Hold Time + tDS = 1.5, // Data-in Setup Time + tCKH = 0.8, // CKE Hold Time + tCKS = 1.5, // CKE Setup Time + tCMH = 0.8, // CS#, RAS#, CAS#, WE#, DQM# Hold Time + tCMS = 1.5; // CS#, RAS#, CAS#, WE#, DQM# Setup Time + $width (posedge Clk, tCH); + $width (negedge Clk, tCL); + $period (negedge Clk, tCK); + $period (posedge Clk, tCK); + $setuphold(posedge Clk, Cke, tCKS, tCKH); + $setuphold(posedge Clk, Cs_n, tCMS, tCMH); + $setuphold(posedge Clk, Cas_n, tCMS, tCMH); + $setuphold(posedge Clk, Ras_n, tCMS, tCMH); + $setuphold(posedge Clk, We_n, tCMS, tCMH); + $setuphold(posedge Clk, Addr, tAS, tAH); + $setuphold(posedge Clk, Ba, tAS, tAH); + $setuphold(posedge Clk, Dqm, tCMS, tCMH); + $setuphold(posedge Dq_chk, Dq, tDS, tDH); + endspecify + +endmodule +
mt48lc8m16a2.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.