1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072 |
- /**************************************************************************
- *
- * File Name: MT48LC16M16A2.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: MT48LC16M16A2 (4Meg x 16 x 4 Banks)
- *
- * Description: Micron 256Mb SDRAM Verilog model
- *
- * Limitation: - Doesn't check for 8192 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 © 2001 Micron Semiconductor Products, Inc.
- * 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 mt48lc16m16a2 (Dq, Addr, Ba, Clk, Cke, Cs_n, Ras_n, Cas_n, We_n, Dqm);
- parameter addr_bits = 13;
- parameter data_bits = 16;
- parameter col_bits = 9;
- parameter mem_sizes = 4194303;
- 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 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_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];
- wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];
- // Write Burst Mode
- wire Write_burst_mode = Mode_reg[9];
- wire Debug = 1'b0; // Debug messages : 1 = On
- wire Dq_chk = Sys_clk & Data_in_enable; // Check setup/hold time for DQ
-
- assign Dq = Dq_reg; // DQ buffer
- // Commands Operation
- `define ACT 0
- `define NOP 1
- `define READ 2
- `define WRITE 3
- `define PRECH 4
- `define A_REF 5
- `define BST 6
- `define LMR 7
- // Timing Parameters for -7E PC133 CL2
- parameter tAC = 6.0;
- parameter tHZ = 6.0;
- parameter tOH = 5.0;
- parameter tMRD = 2.0; // 2 Clk Cycles
- parameter tRAS = 42.0;
- parameter tRC = 60.0;
- parameter tRCD = 15.0;
- parameter tRFC = 64.0;
- parameter tRP = 15.0;
- parameter tRRD = 14.0;
- parameter tWRa = 7.0; // A2 Version - Auto precharge mode (1 Clk + 7 ns)
- parameter tWRm = 14.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'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
- 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",$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
- // 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
- // Write 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
- // 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
- WR_chkm [Bank] = $time;
- if (Debug) begin
- $display("%m : at time %t WRITE: Bank = %d Row = %d, Col = %d, Data = %d", $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
- // Display debug message
- if (Dqm_reg0 !== 2'b11) begin
- Dq_reg = #tAC Dq_dqm;
- if (Debug) begin
- $display("%m : at time %t READ : Bank = %d Row = %d, Col = %d, Data = %d", $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 -7E (133 MHz @ CL2)
- specify
- specparam
- tAH = 0.8, // Addr, Ba Hold Time
- tAS = 1.5, // Addr, Ba Setup Time
- tCH = 2.5, // Clock High-Level Width
- tCL = 2.5, // Clock Low-Level Width
- tCK = 7.0, // 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
|