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

Subversion Repositories common

[/] [common/] [trunk/] [ddr_2_dram_for_debugging.v] - Diff between revs 32 and 48

Show entire file | Details | Blame | View Log

Rev 32 Rev 48
Line 1... Line 1...
 
//////////////////////////////////////////////////////////////////////
 
////                                                              ////
 
//// ddr_2_dram #(frequency, latency,                             ////
 
////              num_addr_bits, num_col_bits,                    ////
 
////              num_data_bits, num_words_in_test_memory)        ////
 
////                                                              ////
 
//// This file is part of the general opencores effort.           ////
 
//// <http://www.opencores.org/cores/misc/>                       ////
 
////                                                              ////
 
//// Module Description:                                          ////
 
////   A fake DDR DRAM with a small amount of memory.  Useful in  ////
 
////   getting a DDR DRAM controller working.                     ////
 
////                                                              ////
 
//// The DDR DRAM uses a tricky clocking scheme.  Unfortunately,  ////
 
////   this will require a tricky controller.                     ////
 
////                                                              ////
 
//// The CLK_P and CLK_N signals provide a time-base for the      ////
 
////   external IO pins on the DRAM, and may or may not be used   ////
 
////   as a timebase for internal DRAM activity.                  ////
 
////                                                              ////
 
//// The DDR DRAM transfers data on both edges of the CLK_*.      ////
 
////   However, in order to make the design insensitive to layout ////
 
////   and loading concerns, the data is NOT latched by the CLK_P ////
 
////   activity.                                                  ////
 
////                                                              ////
 
//// Instead the new signal DQS is used as a clock which runs in  ////
 
////   parallel with, and uses the same loading as, the Data      ////
 
////   wires DQ.                                                  ////
 
////                                                              ////
 
//// In the case of writes from a controller to the DDR DRAM, the ////
 
////   controller is responsible for placing the edges of DQS so  ////
 
////   that the edges arrive in the MIDDLE of the data valid      ////
 
////   period at the DRAMs.                                       ////
 
////                                                              ////
 
//// The DDR DRAM specs seem to call out that the controller will ////
 
////   place the DQS transitions between 0.75 and 1.25 of a clock ////
 
////   period after the rising edge of CLK_* which initiates a    ////
 
////   write.  The obvious place to put the DQS signal is right   ////
 
////   at that edge.  This means that the DATA for the write must ////
 
////   be sent 1/4 clock EARLIER!                                 ////
 
////                                                              ////
 
//// In the case of reads from a DDR DRAM to a controller, the    ////
 
////   DRAM sends out data and data clock (DQ and DQS) with the   ////
 
////   same timing.  The edges for these signals should be at the ////
 
////   same time.  The Controller has to internally delay the DQS ////
 
////   signal by 1/2 of a bit time, and then use the INTERNAL     ////
 
////   DELAYED DQS signal to latch the DQ wires.                  ////
 
////                                                              ////
 
//// The DDR DRAM specs seem to call out that the DRAM will drive ////
 
////   DQS between -0.75 and +0.75 nSec of the edges of CLK_*.    ////
 
////   Of course, it will get to the controller some time later   ////
 
////   than that.                                                 ////
 
////                                                              ////
 
//// To provide bad timing, this DRAM model will measure the      ////
 
////   period of the CLK_P clock (assuming that it is 50% duty    ////
 
////   cycle).  It will then deliver data from 0.75 nSec AFTER    ////
 
////   the clock changes till 0.75 nSec BEFORE it changes again.  ////
 
////   This will prevent the controller from using the CLK_*      ////
 
////   signal to latch the data.                                  ////
 
////                                                              ////
 
//// Author(s):                                                   ////
 
//// - Anonymous                                                  ////
 
////                                                              ////
 
//////////////////////////////////////////////////////////////////////
 
////                                                              ////
 
//// Copyright (C) 2000 Anonymous and OPENCORES.ORG               ////
 
////                                                              ////
 
//// This source file may be used and distributed without         ////
 
//// restriction provided that this copyright statement is not    ////
 
//// removed from the file and that any derivative work contains  ////
 
//// the original copyright notice and the associated disclaimer. ////
 
////                                                              ////
 
//// This source file is free software; you can redistribute it   ////
 
//// and/or modify it under the terms of the GNU Lesser General   ////
 
//// Public License as published by the Free Software Foundation; ////
 
//// either version 2.1 of the License, or (at your option) any   ////
 
//// later version.                                               ////
 
////                                                              ////
 
//// This source is distributed in the hope that it will be       ////
 
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
 
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
 
//// PURPOSE. See the GNU Lesser General Public License for more  ////
 
//// details.                                                     ////
 
////                                                              ////
 
//// You should have received a copy of the GNU Lesser General    ////
 
//// Public License along with this source; if not, download it   ////
 
//// from <http://www.opencores.org/lgpl.shtml>                   ////
 
////                                                              ////
 
//////////////////////////////////////////////////////////////////////
 
//
 
// $Id: ddr_2_dram_for_debugging.v,v 1.8 2001-11-06 12:33:15 bbeaver Exp $
 
//
 
// CVS Revision History
 
//
 
// $Log: not supported by cvs2svn $
 
// Revision 1.10  2001/11/06 12:41:27  Blue Beaver
 
// no message
 
//
 
// Revision 1.9  2001/11/02 11:59:30  Blue Beaver
 
// no message
 
//
 
// Revision 1.8  2001/11/01 13:33:03  Blue Beaver
 
// no message
 
//
 
// Revision 1.7  2001/11/01 12:44:03  Blue Beaver
 
// no message
 
//
 
// Revision 1.6  2001/11/01 11:33:04  Blue Beaver
 
// no message
 
//
 
// Revision 1.5  2001/11/01 09:38:43  Blue Beaver
 
// no message
 
//
 
// Revision 1.4  2001/10/31 12:30:01  Blue Beaver
 
// no message
 
//
 
// Revision 1.3  2001/10/30 12:44:03  Blue Beaver
 
// no message
 
//
 
// Revision 1.2  2001/10/30 08:56:18  Blue Beaver
 
// no message
 
//
 
// Revision 1.1  2001/10/29 13:45:02  Blue Beaver
 
// no message
 
//
 
 
 
`timescale 1ns / 1ps
 
 
 
module ddr_2_dram (
 
  DQ, DQS,
 
  DM,
 
  A, BA,
 
  RAS_L,
 
  CAS_L,
 
  WE_L,
 
  CS_L,
 
  CKE,
 
  CLK_P, CLK_N
 
);
 
 
 
// Constant Parameters
 
parameter FREQUENCY = 133.0;  // might be 100, 125, 166, any other frequency
 
parameter LATENCY = 2.0;  // might be 2.0, 2.5, 3.0, 3.5, 4.0
 
parameter NUM_ADDR_BITS = 13;
 
parameter NUM_COL_BITS  = 11;
 
parameter NUM_DATA_BITS =  4;
 
parameter NUM_WORDS_IN_TEST_MEMORY = 32;
 
parameter ENABLE_TIMING_CHECKS = 1;
 
 
 
  inout  [NUM_DATA_BITS - 1 : 0] DQ;
 
  inout   DQS;
 
  input   DM;
 
  input  [NUM_ADDR_BITS - 1 : 0] A;
 
  input  [1 : 0] BA;
 
  input   RAS_L;
 
  input   CAS_L;
 
  input   WE_L;
 
  input   CS_L;
 
  input   CKE;
 
  input   CLK_P, CLK_N;
 
 
 
// These signals can be accessed by upper scopes to detect chip-to-chip OE conflicts.
 
  wire    DEBUG_DQ_OE, DEBUG_DQS_OE;
 
 
 
// Try to measure the input clock, to correctly apply X's on
 
//   the data wires near when the outputs change.
 
// I have to try to make X's BEFORE the next clock edge!
 
// This measurement is irrespective of the frequency parameter,
 
//   which is used only to set the number of cycles between events.
 
 
 
  time    present_rising_time, high_period;
 
  time    present_falling_time, low_period;
 
  reg     data_delay1, data_delay2;
 
 
 
  initial
 
  begin
 
    present_rising_time = 0;
 
    present_falling_time = 0;
 
    high_period = 0;
 
    low_period = 0;
 
    data_delay1 = 1'b0;
 
    data_delay2 = 1'b0;
 
  end
 
 
 
  always @(CLK_P)
 
  begin
 
    if (CLK_P === 1'b1)  // rising edge
 
    begin
 
      present_rising_time = $time;
 
      if ((present_rising_time !== 0) & (present_falling_time !== 0))
 
      begin
 
        high_period = present_rising_time - present_falling_time - (2 * 750);
 
      end
 
    end
 
    if (CLK_P === 1'b0)  // falling edge
 
    begin
 
      present_falling_time = $time;
 
      if ((present_rising_time !== 0) & (present_falling_time !== 0))
 
      begin
 
        low_period = present_falling_time - present_rising_time - (2 * 750);
 
      end
 
    end
 
  end
 
 
 
// Once the period of the clock is known, start making X's whenever possible
 
  always @(posedge CLK_P)
 
  begin
 
    if (high_period !== 0)
 
    begin  // Make X's after rising edge, and before falling edge
 
      #750          data_delay1 = 1'b1;
 
      #high_period  data_delay2 = 1'b1;
 
    end
 
    else
 
    begin
 
      data_delay1 = 1'b1;
 
      data_delay2 = 1'b1;
 
    end
 
    if (CLK_N !== 1'b0)
 
    begin
 
      $display ("*** %m DDR DRAM needs to have CLK_N transition with CLK_P at time %t", $time);
 
    end
 
  end
 
 
 
  always @(negedge CLK_P)
 
  begin
 
    if (low_period !== 0)
 
    begin  // Make X's after falling edge, and before rising edge
 
      #750         data_delay1 = 1'b0;
 
      #low_period  data_delay2 = 1'b0;
 
    end
 
    else
 
    begin
 
      data_delay1 = 1'b0;
 
      data_delay2 = 1'b0;
 
    end
 
    if (CLK_N !== 1'b1)
 
    begin
 
      $display ("*** %m DDR DRAM needs to have CLK_N transition with CLK_P at time %t", $time);
 
    end
 
  end
 
 
 
  wire    force_x = (data_delay1 == data_delay2);
 
 
 
// Watch for cases where both banks are driving the Data bus at once.
 
// Normally, the second read would terminate the first read.  This
 
//   module, since it is only for debugging, only understands complete
 
//   4-word burst transfers.
 
 
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_E_out_0;
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_O_out_0;
 
  wire    DQ_E_oe_0, DQS_E_out_0, DQS_E_oe_0, Timing_Error_0;
 
  wire    DQ_O_oe_0, DQS_O_out_0, DQS_O_oe_0;
 
 
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_E_out_1;
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_O_out_1;
 
  wire    DQ_E_oe_1, DQS_E_out_1, DQS_E_oe_1, Timing_Error_1;
 
  wire    DQ_O_oe_1, DQS_O_out_1, DQS_O_oe_1;
 
 
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_E_out_2;
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_O_out_2;
 
  wire    DQ_E_oe_2, DQS_E_out_2, DQS_E_oe_2, Timing_Error_2;
 
  wire    DQ_O_oe_2, DQS_O_out_2, DQS_O_oe_2;
 
 
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_E_out_3;
 
  wire   [NUM_DATA_BITS - 1 : 0] DQ_O_out_3;
 
  wire    DQ_E_oe_3, DQS_E_out_3, DQS_E_oe_3, Timing_Error_3;
 
  wire    DQ_O_oe_3, DQS_O_out_3, DQS_O_oe_3;
 
 
 
  always @(    DQ_E_oe_0   or DQ_E_oe_1   or DQ_E_oe_2   or DQ_E_oe_3
 
            or DQS_E_out_0 or DQS_E_out_1 or DQS_E_out_2 or DQS_E_out_3
 
            or DQS_E_oe_0  or DQS_E_oe_1  or DQS_E_oe_2  or DQS_E_oe_3
 
            or DQ_O_oe_0   or DQ_O_oe_1   or DQ_O_oe_2   or DQ_O_oe_3
 
            or DQS_O_out_0 or DQS_O_out_1 or DQS_O_out_2 or DQS_O_out_3
 
            or DQS_O_oe_0  or DQS_O_oe_1  or DQS_O_oe_2  or DQS_O_oe_3 )
 
 
 
  begin
 
    if (   (DQ_E_oe_0 & DQ_E_oe_1) | (DQ_E_oe_0 & DQ_E_oe_2) | (DQ_E_oe_0 & DQ_E_oe_3)
 
         | (DQ_E_oe_1 & DQ_E_oe_2) | (DQ_E_oe_1 & DQ_E_oe_3) | (DQ_E_oe_2 & DQ_E_oe_3)
 
         | (DQ_O_oe_0 & DQ_O_oe_1) | (DQ_O_oe_0 & DQ_O_oe_2) | (DQ_O_oe_0 & DQ_O_oe_3)
 
         | (DQ_O_oe_1 & DQ_O_oe_2) | (DQ_O_oe_1 & DQ_O_oe_3) | (DQ_O_oe_2 & DQ_O_oe_3) )
 
 
 
    begin
 
      $display ("*** %m DDR DRAM has multiple banks driving DQ at the same time at %x %t",
 
                    {DQ_E_oe_3, DQ_O_oe_3, DQ_E_oe_2, DQ_O_oe_2, DQ_E_oe_1, DQ_O_oe_1, DQ_E_oe_0, DQ_O_oe_0}, $time);
 
    end
 
    if (   ((DQS_E_oe_0 & DQS_E_oe_1) & ((DQS_E_out_0 != 1'b0) | (DQS_E_out_1 != 1'b0)))
 
         | ((DQS_E_oe_0 & DQS_E_oe_2) & ((DQS_E_out_0 != 1'b0) | (DQS_E_out_2 != 1'b0)))
 
         | ((DQS_E_oe_0 & DQS_E_oe_3) & ((DQS_E_out_0 != 1'b0) | (DQS_E_out_3 != 1'b0)))
 
         | ((DQS_E_oe_1 & DQS_E_oe_2) & ((DQS_E_out_1 != 1'b0) | (DQS_E_out_2 != 1'b0)))
 
         | ((DQS_E_oe_1 & DQS_E_oe_3) & ((DQS_E_out_1 != 1'b0) | (DQS_E_out_3 != 1'b0)))
 
         | ((DQS_E_oe_2 & DQS_E_oe_3) & ((DQS_E_out_2 != 1'b0) | (DQS_E_out_3 != 1'b0))) )
 
    begin
 
      $display ("*** %m DDR DRAM Even has multiple banks driving DQS at the same time at %x %x %t",
 
                    {DQS_E_oe_3, DQS_E_oe_2, DQS_E_oe_1, DQS_E_oe_0},
 
                    {DQS_E_out_3, DQS_E_out_2, DQS_E_out_1, DQS_E_out_0}, $time);
 
    end
 
    if (   ((DQS_O_oe_0 & DQS_O_oe_1) & ((DQS_O_out_0 != 1'b0) | (DQS_O_out_1 != 1'b0)))
 
         | ((DQS_O_oe_0 & DQS_O_oe_2) & ((DQS_O_out_0 != 1'b0) | (DQS_O_out_2 != 1'b0)))
 
         | ((DQS_O_oe_0 & DQS_O_oe_3) & ((DQS_O_out_0 != 1'b0) | (DQS_O_out_3 != 1'b0)))
 
         | ((DQS_O_oe_1 & DQS_O_oe_2) & ((DQS_O_out_1 != 1'b0) | (DQS_O_out_2 != 1'b0)))
 
         | ((DQS_O_oe_1 & DQS_O_oe_3) & ((DQS_O_out_1 != 1'b0) | (DQS_O_out_3 != 1'b0)))
 
         | ((DQS_O_oe_2 & DQS_O_oe_3) & ((DQS_O_out_2 != 1'b0) | (DQS_O_out_3 != 1'b0))) )
 
    begin
 
      $display ("*** %m DDR DRAM Odd has multiple banks driving DQS at the same time at %x %x %t",
 
                    {DQS_O_oe_3, DQS_O_oe_2, DQS_O_oe_1, DQS_O_oe_0},
 
                    {DQS_O_out_3, DQS_O_out_2, DQS_O_out_1, DQS_O_out_0}, $time);
 
    end
 
  end
 
 
 
  assign  DEBUG_DQ_OE =  DQ_E_oe_0  | DQ_E_oe_1  | DQ_E_oe_2  | DQ_E_oe_3
 
                      |  DQ_O_oe_0  | DQ_O_oe_1  | DQ_O_oe_2  | DQ_O_oe_3;
 
  assign  DEBUG_DQS_OE = DQS_E_oe_0 | DQS_E_oe_1 | DQS_E_oe_2 | DQS_E_oe_3
 
                       | DQS_O_oe_0 | DQS_O_oe_1 | DQS_O_oe_2 | DQS_O_oe_3;
 
 
 
// The top-level code here is responsible for delaying the data as needed
 
//   to meet the LATENCY requirement.
 
 
 
//    LATENCY,
 
//parameter LATENCY = 2.0;  // might be 2.0, 2.5, 3.0, 3.5, 4.0
 
 
 
ddr_2_dram_single_bank
 
# ( FREQUENCY,
 
    LATENCY,
 
    NUM_ADDR_BITS,
 
    NUM_COL_BITS,
 
    NUM_DATA_BITS,
 
    NUM_WORDS_IN_TEST_MEMORY,
 
    1  // enable_timing_checks
 
  ) ddr_2_dram_single_bank_0 (
 
  .DQ                         (DQ[NUM_DATA_BITS - 1 : 0]),
 
  .DQS                        (DQS),
 
  .DQ_E_out                   (DQ_E_out_0[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_O_out                   (DQ_O_out_0[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_E_oe                    (DQ_E_oe_0),
 
  .DQ_O_oe                    (DQ_O_oe_0),
 
  .DQS_E_out                  (DQS_E_out_0),
 
  .DQS_O_out                  (DQS_O_out_0),
 
  .DQS_E_oe                   (DQS_E_oe_0),
 
  .DQS_O_oe                   (DQS_O_oe_0),
 
  .Timing_Error               (Timing_Error_0),
 
  .DM                         (DM),
 
  .A                          (A[12:0]),
 
  .BA                         (BA[1:0]),
 
  .RAS_L                      (RAS_L),
 
  .CAS_L                      (CAS_L),
 
  .WE_L                       (WE_L),
 
  .CS_L                       (CS_L),
 
  .CKE                        (CKE),
 
  .CLK_P                      (CLK_P),
 
  .CLK_N                      (CLK_N),
 
  .bank_num                   (2'b00)
 
);
 
 
 
ddr_2_dram_single_bank
 
# ( FREQUENCY,
 
    LATENCY,
 
    NUM_ADDR_BITS,
 
    NUM_COL_BITS,
 
    NUM_DATA_BITS,
 
    NUM_WORDS_IN_TEST_MEMORY,
 
    0  // enable_timing_checks
 
  ) ddr_2_dram_single_bank_1 (
 
  .DQ                         (DQ[NUM_DATA_BITS - 1 : 0]),
 
  .DQS                        (DQS),
 
  .DQ_E_out                   (DQ_E_out_1[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_O_out                   (DQ_O_out_1[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_E_oe                    (DQ_E_oe_1),
 
  .DQ_O_oe                    (DQ_O_oe_1),
 
  .DQS_E_out                  (DQS_E_out_1),
 
  .DQS_O_out                  (DQS_O_out_1),
 
  .DQS_E_oe                   (DQS_E_oe_1),
 
  .DQS_O_oe                   (DQS_O_oe_1),
 
  .Timing_Error               (Timing_Error_1),
 
  .DM                         (DM),
 
  .A                          (A[12:0]),
 
  .BA                         (BA[1:0]),
 
  .RAS_L                      (RAS_L),
 
  .CAS_L                      (CAS_L),
 
  .WE_L                       (WE_L),
 
  .CS_L                       (CS_L),
 
  .CKE                        (CKE),
 
  .CLK_P                      (CLK_P),
 
  .CLK_N                      (CLK_N),
 
  .bank_num                   (2'b01)
 
);
 
 
 
ddr_2_dram_single_bank
 
# ( FREQUENCY,
 
    LATENCY,
 
    NUM_ADDR_BITS,
 
    NUM_COL_BITS,
 
    NUM_DATA_BITS,
 
    NUM_WORDS_IN_TEST_MEMORY,
 
    0  // enable_timing_checks
 
  ) ddr_2_dram_single_bank_2 (
 
  .DQ                         (DQ[NUM_DATA_BITS - 1 : 0]),
 
  .DQS                        (DQS),
 
  .DQ_E_out                   (DQ_E_out_2[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_O_out                   (DQ_O_out_2[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_E_oe                    (DQ_E_oe_2),
 
  .DQ_O_oe                    (DQ_O_oe_2),
 
  .DQS_E_out                  (DQS_E_out_2),
 
  .DQS_O_out                  (DQS_O_out_2),
 
  .DQS_E_oe                   (DQS_E_oe_2),
 
  .DQS_O_oe                   (DQS_O_oe_2),
 
  .Timing_Error               (Timing_Error_2),
 
  .DM                         (DM),
 
  .A                          (A[12:0]),
 
  .BA                         (BA[1:0]),
 
  .RAS_L                      (RAS_L),
 
  .CAS_L                      (CAS_L),
 
  .WE_L                       (WE_L),
 
  .CS_L                       (CS_L),
 
  .CKE                        (CKE),
 
  .CLK_P                      (CLK_P),
 
  .CLK_N                      (CLK_N),
 
  .bank_num                   (2'b10)
 
);
 
 
 
ddr_2_dram_single_bank
 
# ( FREQUENCY,
 
    LATENCY,
 
    NUM_ADDR_BITS,
 
    NUM_COL_BITS,
 
    NUM_DATA_BITS,
 
    NUM_WORDS_IN_TEST_MEMORY,
 
    0  // enable_timing_checks
 
  ) ddr_2_dram_single_bank_3 (
 
  .DQ                         (DQ[NUM_DATA_BITS - 1 : 0]),
 
  .DQS                        (DQS),
 
  .DQ_E_out                   (DQ_E_out_3[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_O_out                   (DQ_O_out_3[NUM_DATA_BITS - 1 : 0]),
 
  .DQ_E_oe                    (DQ_E_oe_3),
 
  .DQ_O_oe                    (DQ_O_oe_3),
 
  .DQS_E_out                  (DQS_E_out_3),
 
  .DQS_O_out                  (DQS_O_out_3),
 
  .DQS_E_oe                   (DQS_E_oe_3),
 
  .DQS_O_oe                   (DQS_O_oe_3),
 
  .Timing_Error               (Timing_Error_3),
 
  .DM                         (DM),
 
  .A                          (A[12:0]),
 
  .BA                         (BA[1:0]),
 
  .RAS_L                      (RAS_L),
 
  .CAS_L                      (CAS_L),
 
  .WE_L                       (WE_L),
 
  .CS_L                       (CS_L),
 
  .CKE                        (CKE),
 
  .CLK_P                      (CLK_P),
 
  .CLK_N                      (CLK_N),
 
  .bank_num                   (2'b11)
 
);
 
 
 
endmodule
 
 
 
module ddr_2_dram_single_bank (
 
  DQ, DQS,
 
  DQ_E_out, DQ_O_out, DQ_E_oe, DQ_O_oe,
 
  DQS_E_out, DQS_O_out, DQS_E_oe, DQS_O_oe,
 
  Timing_Error,
 
  DM,
 
  A, BA,
 
  RAS_L,
 
  CAS_L,
 
  WE_L,
 
  CS_L,
 
  CKE,
 
  CLK_P, CLK_N,
 
  bank_num
 
);
 
 
 
// Constant Parameters
 
parameter FREQUENCY = 133.0;  // might be 100, 125, 166, any other frequency
 
parameter LATENCY = 2.0;  // might be 2.0, 2.5, 3.0, 3.5, 4.0, 4.5
 
parameter NUM_ADDR_BITS = 13;
 
parameter NUM_COL_BITS  = 12;
 
parameter NUM_DATA_BITS =  4;
 
parameter NUM_WORDS_IN_TEST_MEMORY = 32;
 
parameter ENABLE_TIMING_CHECKS = 1;
 
 
 
  input  [NUM_DATA_BITS - 1 : 0] DQ;
 
  input   DQS;
 
  output [NUM_DATA_BITS - 1 : 0] DQ_E_out;
 
  output [NUM_DATA_BITS - 1 : 0] DQ_O_out;
 
  output  DQ_E_oe, DQ_O_oe;
 
  output  DQS_E_out, DQS_O_out, DQS_E_oe, DQS_O_oe;
 
  output  Timing_Error;
 
  input   DM;
 
  input  [NUM_ADDR_BITS - 1 : 0] A;
 
  input  [1 : 0] BA;
 
  input   RAS_L;
 
  input   CAS_L;
 
  input   WE_L;
 
  input   CS_L;
 
  input   CKE;
 
  input   CLK_P, CLK_N;
 
  input  [1:0] bank_num;
 
 
 
// DDR DRAMs always capture their command on the RISING EDGE of CLK_P;
 
// This fake DDR DRAM understands:  Idle, Activate, Read, Write, Automatic Refresh
 
// This fake DDR DRAM assumes that all Reads and Writes do automatic precharge.
 
// This fake DDR DRAM understands writes to the control register
 
// This fake DDR DRAM always does 4-word bursts.  The first word of data
 
//           is always the legal one.  The next 3 are that first word inverted.
 
// DDR DRAMs always capture their data on BOTH EDGES of DQS
 
// DDR DRAMs always output enable the DQS wire to 1'h0 1 clock before
 
//           they start sending data
 
// DDR DRAMs will be allowed to have a latency of 2, 2.5, 3, 3.5, 4, 4.5
 
//           from the read command.
 
 
 
// DDR DRAM commands are made by using the following sighals:
 
//   {CKE, CS_L, RAS_L, CAS_L, WS_L}
 
//     0    X     X      X     X      power-down
 
//     1    1     X      X     X      NOOP
 
//     1    0     1      1     1      NOOP
 
//     1    0     0      1     1      ACTIVATE
 
//     1    0     1      0     1      READ      (A10)
 
//     1    0     1      0     0      WRITE     (A10)
 
//     1    0     0      1     0      PRECHARGE (A10)
 
//     1    0     0      0     1      AUTO REFRESH
 
//     1    0     0      0     0      LOAD MODE REGISTER
 
//     1    0     1      1     0      not used?
 
 
 
parameter NOOP           = 5'h17;
 
parameter LOAD_MODE      = 5'h10;
 
parameter ACTIVATE_BANK  = 5'h13;
 
parameter READ_BANK      = 5'h15;
 
parameter WRITE_BANK     = 5'h14;
 
parameter PRECHARGE_BANK = 5'h12;
 
parameter REFRESH_BANK   = 5'h11;
 
 
 
  wire   [4:0] control_wires = {CKE, CS_L, RAS_L, CAS_L, WE_L};
 
 
 
// This simple-minded DRAM assumes that all transactions are valid.
 
// Therefore, it always captures RAS and CAS address information, even
 
//   if there is an obvious protocol violation.
 
 
 
  reg    [NUM_ADDR_BITS - 1 : 0] Captured_RAS_Address;
 
  reg    [1:0] Captured_RAS_Bank_Selects;
 
 
 
  reg    [NUM_ADDR_BITS - 1 : 0] Captured_CAS_Address;
 
  reg    [1:0] Captured_CAS_Bank_Selects;
 
 
 
  reg     RAS_Address_Valid;
 
  reg     Full_Address_Valid;
 
  reg     DRAM_Read_Requested;
 
 
 
// synopsys translate_off
 
  initial
 
  begin  // only for debug
 
    RAS_Address_Valid <= 1'b0;
 
    Full_Address_Valid <= 1'b0;
 
  end
 
// synopsys translate_on
 
 
 
// Capture RAS and CAS address information
 
  always @(posedge CLK_P)
 
  begin
 
    if ((control_wires[4:0] == ACTIVATE_BANK) & (BA[1:0] == bank_num[1:0]))
 
    begin
 
      Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0] <= A[NUM_ADDR_BITS - 1 : 0];
 
      Captured_RAS_Bank_Selects[1:0] <= BA[1 : 0];
 
      RAS_Address_Valid <= 1'b1;
 
      Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_CAS_Bank_Selects[1:0] <= Captured_CAS_Bank_Selects[1:0];
 
      DRAM_Read_Requested <= 1'b0;
 
      Full_Address_Valid <= 1'b0;
 
    end
 
    else if ((control_wires[4:0] == READ_BANK) & (BA[1:0] == bank_num[1:0]))
 
    begin
 
      Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_RAS_Bank_Selects[1:0] <= Captured_RAS_Bank_Selects[1:0];
 
      if (A[10] == 1'b1) // automatic precharge
 
        RAS_Address_Valid <= 1'b0;
 
      else
 
        RAS_Address_Valid <= 1'b1;
 
      Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0] <= A[NUM_ADDR_BITS - 1 : 0];
 
      Captured_CAS_Bank_Selects[1:0] <= BA[1 : 0];
 
      DRAM_Read_Requested <= 1'b1;
 
      Full_Address_Valid <= 1'b1;
 
      if (RAS_Address_Valid == 1'b0)
 
      begin
 
        $display ("*** %m DRAM accessed for Read without first doing an Activate %t", $time);
 
      end
 
    end
 
    else if ((control_wires[4:0] == WRITE_BANK) & (BA[1:0] == bank_num[1:0]))
 
    begin
 
      Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_RAS_Bank_Selects[1:0] <= Captured_RAS_Bank_Selects[1:0];
 
      if (A[10] == 1'b1) // automatic precharge
 
        RAS_Address_Valid <= 1'b0;
 
      else
 
        RAS_Address_Valid <= 1'b1;
 
      Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0] <= A[NUM_ADDR_BITS - 1 : 0];
 
      Captured_CAS_Bank_Selects[1:0] <= BA[1 : 0];
 
      DRAM_Read_Requested <= 1'b0;
 
      Full_Address_Valid <= 1'b1;
 
      if (RAS_Address_Valid == 1'b0)
 
      begin
 
        $display ("*** %m DRAM accessed for Write without first doing an Activate %t", $time);
 
      end
 
    end
 
    else if (   (control_wires[4:0] == PRECHARGE_BANK)
 
              & ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1)))
 
    begin
 
      Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_RAS_Bank_Selects[1:0] <= Captured_RAS_Bank_Selects[1:0];
 
      RAS_Address_Valid <= 1'b0;
 
      Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_CAS_Bank_Selects[1:0] <= Captured_CAS_Bank_Selects[1:0];
 
      DRAM_Read_Requested <= 1'b0;
 
      Full_Address_Valid <= 1'b0;
 
    end
 
    else  // NOOP, Load Mode Register, Refresh, Unallocated
 
    begin
 
      Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_RAS_Bank_Selects[1:0] <= Captured_RAS_Bank_Selects[1:0];
 
      RAS_Address_Valid <= RAS_Address_Valid;
 
      Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0] <=
 
                Captured_CAS_Address[NUM_ADDR_BITS - 1 : 0];
 
      Captured_CAS_Bank_Selects[1:0] <= Captured_CAS_Bank_Selects[1:0];
 
      DRAM_Read_Requested <= 1'b0;
 
      Full_Address_Valid <= 1'b0;
 
    end
 
  end
 
 
 
// This debugging DRAM requires that entire 4-word bursts be done.
 
// At present, this design does not implement DM masking.
 
// This debugging DRAM captures data using the DQS signals.  It
 
//   immediately moves the data into the CLK_P positive edge clock domain.
 
 
 
  reg    [NUM_DATA_BITS - 1 : 0] DQS_Captured_Write_Data_Even;
 
  reg    [NUM_DATA_BITS - 1 : 0] DQS_Captured_Write_Data_Odd;
 
  reg     DQS_Captured_Write_DM_Even, DQS_Captured_Write_DM_Odd;
 
  reg    [NUM_DATA_BITS - 1 : 0] Delay_Write_Data_Even;
 
  reg    [NUM_DATA_BITS - 1 : 0] Sync_Write_Data_Even;
 
  reg    [NUM_DATA_BITS - 1 : 0] Sync_Write_Data_Odd;
 
  reg     Delay_Write_DM_Even, Sync_Write_DM_Even, Sync_Write_DM_Odd;
 
 
 
// Capture data on rising edge of DQS
 
  always @(posedge DQS)
 
  begin
 
    DQS_Captured_Write_Data_Even[NUM_DATA_BITS - 1 : 0] <= DQ[NUM_DATA_BITS - 1 : 0];
 
    DQS_Captured_Write_DM_Even <= DM;
 
  end
 
 
 
// Delay data captured on rising edge so that it can be captured the NEXT rising edge
 
  always @(negedge CLK_P)
 
  begin
 
    Delay_Write_Data_Even[NUM_DATA_BITS - 1 : 0] <=
 
                DQS_Captured_Write_Data_Even[NUM_DATA_BITS - 1 : 0];
 
    Delay_Write_DM_Even <= DQS_Captured_Write_DM_Even;
 
  end
 
 
 
// Capture data on falling edge of DQS
 
  always @(negedge DQS)
 
  begin
 
    DQS_Captured_Write_Data_Odd[NUM_DATA_BITS - 1 : 0] <= DQ[NUM_DATA_BITS - 1 : 0];
 
    DQS_Captured_Write_DM_Odd <= DM;
 
  end
 
 
 
// Capture a data item pair into the positive edge clock domain.
 
  always @(posedge CLK_P)
 
  begin
 
    Sync_Write_Data_Even[NUM_DATA_BITS - 1 : 0] <=
 
                Delay_Write_Data_Even[NUM_DATA_BITS - 1 : 0];
 
    Sync_Write_Data_Odd[NUM_DATA_BITS - 1 : 0] <=
 
                DQS_Captured_Write_Data_Odd[NUM_DATA_BITS - 1 : 0];
 
    Sync_Write_DM_Even <= Delay_Write_DM_Even;
 
    Sync_Write_DM_Odd <= DQS_Captured_Write_DM_Odd;
 
  end
 
 
 
// For Writes, the CAS Address comes in at time T0.
 
// Data is available on the external DQ wires at time T1 and T2;
 
// Data is available as Sync_Write_Data at times T2 and T3
 
// The SRAM can be written as soon as the last data is available,
 
//   which seems to be at T4.
 
//
 
// For Reads, the Address comes in at time T0.
 
// The DQS signal needs to start being driven to 1'b0 at T1
 
// The DQ signals need to start being driven with valid data at T2
 
// Both DQS and DQ need to be valid until the beginning of T4
 
//
 
// At first glance, it would seem that the Read Data needs to be
 
//   grabbed out of the DRAM before, or at the same time, as the
 
//   data is written into the DRAM.
 
// Fortunately, the parameter TWTR says that there must be 1 extra
 
//   clock between a Write and a Read to serve as a Write Recovery
 
//   time.  Write data is available out of the internal Sync DRAM
 
//   storage element in plenty of time to get to the bus.
 
 
 
  reg    [NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] DRAM_Address_T1;
 
  reg    [NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] DRAM_Address_T2;
 
  reg    [NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] DRAM_Address_T3;
 
  reg    [1:0] BANK_Address_T1, BANK_Address_T2, BANK_Address_T3;
 
  reg     DRAM_Read_T1, DRAM_Read_T2, DRAM_Read_T3;
 
  reg     DRAM_Full_Addr_Valid_T1, DRAM_Full_Addr_Valid_T2, DRAM_Full_Addr_Valid_T3;
 
  reg    [NUM_DATA_BITS - 1 : 0] Delayed_Sync_Write_Data_Even_T3;
 
  reg    [NUM_DATA_BITS - 1 : 0] Delayed_Sync_Write_Data_Odd_T3;
 
 
 
// Pipeline delay the Read and Write address so that it stays available
 
//   all the way up to the time the data is available and the whole
 
//   lot of it is written to storage.
 
 
 
  always @(posedge CLK_P)
 
  begin
 
    DRAM_Address_T1[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] <=
 
                {Captured_RAS_Address[NUM_ADDR_BITS - 1 : 0],
 
                 Captured_CAS_Address[NUM_COL_BITS - 1 : 11],  // skip address bit 10
 
                 Captured_CAS_Address[9 : 0]};
 
    DRAM_Address_T2[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] <=
 
                DRAM_Address_T1[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0];
 
    DRAM_Address_T3[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0] <=
 
                DRAM_Address_T2[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0];
 
    BANK_Address_T1[1:0] <= Captured_CAS_Bank_Selects[1:0];
 
    BANK_Address_T2[1:0] <= BANK_Address_T1[1:0];
 
    BANK_Address_T3[1:0] <= BANK_Address_T2[1:0];
 
    DRAM_Read_T1 <= DRAM_Read_Requested;
 
    DRAM_Read_T2 <= DRAM_Read_T1;
 
    DRAM_Read_T3 <= DRAM_Read_T2;
 
    DRAM_Full_Addr_Valid_T1 <= Full_Address_Valid;
 
    DRAM_Full_Addr_Valid_T2 <= DRAM_Full_Addr_Valid_T1;
 
    DRAM_Full_Addr_Valid_T3 <= DRAM_Full_Addr_Valid_T2;
 
    Delayed_Sync_Write_Data_Even_T3[NUM_DATA_BITS - 1 : 0] <=
 
                Sync_Write_Data_Even[NUM_DATA_BITS - 1 : 0];
 
    Delayed_Sync_Write_Data_Odd_T3[NUM_DATA_BITS - 1 : 0] <=
 
                Sync_Write_Data_Odd[NUM_DATA_BITS - 1 : 0];
 
  end
 
 
 
 
 
  assign  DQ_E_oe = 1'b0;
 
  assign  DQ_O_oe = 1'b0;
 
  assign  DQS_E_oe = 1'b0;
 
  assign  DQS_O_oe = 1'b0;
 
 
 
// Storage
 
 
 
  wire   [(4 * NUM_DATA_BITS) - 1 : 0] write_data =
 
                {Sync_Write_Data_Odd[NUM_DATA_BITS - 1 : 0],
 
                 Sync_Write_Data_Even[NUM_DATA_BITS - 1 : 0],
 
                 Delayed_Sync_Write_Data_Odd_T3[NUM_DATA_BITS - 1 : 0],
 
                 Delayed_Sync_Write_Data_Even_T3[NUM_DATA_BITS - 1 : 0]};
 
  wire   [(4 * NUM_DATA_BITS) - 1 : 0] read_data;
 
 
 
sram_for_debugging_sync
 
# ( NUM_ADDR_BITS + NUM_COL_BITS,
 
    4 * NUM_DATA_BITS  // NUM_DATA_BITS
 
  ) storage (
 
  .data_out                   (read_data[(4 * NUM_DATA_BITS) - 1 : 0]),
 
  .data_in                    (write_data[(4 * NUM_DATA_BITS) - 1 : 0]),
 
  .address                    (DRAM_Address_T3[NUM_ADDR_BITS + NUM_COL_BITS - 1 : 0]),
 
  .read_enable                (DRAM_Full_Addr_Valid_T3 &  DRAM_Read_T3),
 
  .write_enable               (DRAM_Full_Addr_Valid_T3 & ~DRAM_Read_T3),
 
  .clk                        (CLK_P)
 
);
 
 
 
// These are the important DDR DRAM timing specs in nanoseconds:
 
parameter LOAD_MODE_REGISTER_PERIOD_TMRD   = 15.0;  // stay idle after load mode
 
parameter ACT_A_TO_ACT_B_TRRD              = 15.0;  // Activate-to-activate minimum time
 
parameter ACT_TO_READ_OR_WRITE_TRCD        = 20.0;
 
parameter ACT_TO_PRECHARGE_TRAS            = 40.0;
 
parameter ACT_TO_REFRESH_TRC               = 65.0;
 
parameter ACT_A_TO_ACT_A_TRC               = 65.0;  // needed if failover
 
parameter WRITE_RECOVERY_TO_PRECHARGE_TWR  = 15.0;
 
parameter PRECHARGE_PERIOD_TRP             = 20.0;
 
parameter REFRESH_PERIOD_TRFC              = 75.0;
 
 
 
parameter CLOCK_PERIOD = (1.0 / FREQUENCY);
 
 
 
// These timing requirements become CYCLE requirements, depending on the
 
//   operating frequency.  Note that 133.333 MHz = 7.5 nSec;
 
// These calculations assume that 133 MHz is the fastest this circuit will run.
 
// These are calculated by doing (N * 1/period) for N big enough to result in > 85 MHz.
 
// Each 1/period gives a frequency to test for, and each N gives the cycle count.
 
// Example:  20 nSec gives N * 50 MHz.  So for N == 2, that gives 100 MHz > 85 MHz.
 
//           If FREQUENCY > 100 MHz, use N = 2, else use N = 1;
 
// The cycle count is the number of cycles to HOLD OFF doing the next command.
 
// p.s. Note I don't know how to take the integer part of something in verilog!
 
 
 
parameter LOAD_MODE_REGISTER_CYCLES          =  (FREQUENCY > 133.334) ? 3 : 2;
 
parameter ACT_A_TO_ACT_B_CYCLES              =  (FREQUENCY > 133.334) ? 3 : 2;
 
parameter ACT_TO_READ_OR_WRITE_CYCLES        =  (FREQUENCY > 100.000) ? 3 : 2;
 
parameter ACT_TO_PRECHARGE_CYCLES            =  (FREQUENCY > 125.000) ? 6
 
                                             : ((FREQUENCY > 100.000) ? 5 : 4);
 
// parameter ACK_TO_REFRESH_CYCLES              =  (FREQUENCY > 123.075) ? 9
 
//                                             : ((FREQUENCY > 107.690) ? 8
 
//                                             : ((FREQUENCY >  92.300) ? 7 : 6));
 
parameter ACT_A_TO_ACT_A_CYCLES              =  (FREQUENCY > 123.075) ? 9
 
                                             : ((FREQUENCY > 107.690) ? 8
 
                                             : ((FREQUENCY >  92.300) ? 7 : 6));
 
parameter READ_TO_WRITE_CYCLES               =  (LATENCY > 4.0) ? 5
 
                                             : ((LATENCY > 3.0) ? 4
 
                                             : ((LATENCY > 2.0) ? 3 : 2));
 
parameter WRITE_TO_READ_CYCLES               = 2;
 
parameter WRITE_RECOVERY_TO_PRECHARGE_CYCLES =  (FREQUENCY > 133.334) ? 3 : 2;
 
parameter PRECHARGE_CYCLES                   =  (FREQUENCY > 100.000) ? 3 : 2;
 
parameter REFRESH_CYCLES                     =  (FREQUENCY > 133.334) ? 11
 
                                             : ((FREQUENCY > 120.000) ? 10
 
                                             : ((FREQUENCY > 106.667) ? 9
 
                                             : ((FREQUENCY >  93.330) ? 8 : 7)));
 
 
 
// The DDR-II DRAM has 4 banks.  Each bank can operate independently, with
 
//   only a few exceptions.
 
//
 
// Each bank needs counters to
 
// 1) prevent refresh too soon after activate
 
// 2) prevent activate to same bank too soon after activate
 
// 3) prevent activate to alternate bank too soon after activate
 
// 4) prevent (or notice) precharge too soon after activate
 
// 5) count out autorefresh delay
 
 
 
  reg    [3:0] load_mode_delay_counter;
 
  reg    [3:0] act_a_to_act_b_counter;
 
  reg    [3:0] act_to_read_or_write_counter;
 
  reg    [3:0] act_to_precharge_counter;
 
  reg    [3:0] act_a_to_act_a_counter;  // double use for act_to_refresh and act_a_to_act_a
 
  reg    [3:0] burst_counter;
 
  reg    [3:0] read_to_write_counter;
 
  reg    [3:0] write_to_read_counter;
 
  reg    [3:0] write_recovery_counter;
 
  reg    [3:0] precharge_counter;
 
  reg    [3:0] refresh_counter;
 
 
 
parameter POWER_ON                          = 0;
 
parameter WRITING_REG                       = 1;
 
parameter BANK_IDLE                         = 2;
 
parameter ACTIVATING                        = 3;
 
parameter WRITING                           = 4;
 
parameter WRITING_PRECHARGE                 = 5;
 
parameter READING                           = 6;
 
parameter READING_PRECHARGE                 = 7;
 
parameter PRECHARGING                       = 8;
 
parameter REFRESHING                        = 9;
 
parameter WAITING_FOR_AUTO_PRECHARGE       = 10;
 
 
 
parameter BANK_STATE_WIDTH = 4;
 
 
 
  reg    [BANK_STATE_WIDTH - 1 : 0] bank_state;
 
  reg     Timing_Error;
 
 
 
  initial
 
  begin  // nail state to known at the start of simulation
 
    bank_state[BANK_STATE_WIDTH - 1 : 0] = POWER_ON;  // nail it to known at the start of simulation
 
  end
 
 
 
  always @(posedge CLK_P)
 
  begin
 
    if (ENABLE_TIMING_CHECKS != 0)
 
    begin  // if out the entire case statement!
 
    case (bank_state[BANK_STATE_WIDTH - 1 : 0])
 
      POWER_ON:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= POWER_ON;
 
            Timing_Error <= 1'b0;
 
          end
 
          else if (control_wires[4:0] == LOAD_MODE)  // no bank involved
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_REG;
 
            Timing_Error <= 1'b0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM needs to have a LOAD MODE REGISTER before any other command %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= POWER_ON;
 
            Timing_Error <= 1'b1;
 
          end
 
          load_mode_delay_counter[3:0]      <= LOAD_MODE_REGISTER_CYCLES;
 
          act_a_to_act_b_counter[3:0]       <= 4'h0;
 
          act_to_read_or_write_counter[3:0] <= 4'h0;
 
          act_to_precharge_counter[3:0]     <= 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= 4'h0;
 
          burst_counter[3:0]                <= 4'h0;
 
          read_to_write_counter [3:0]       <= 4'h0;
 
          write_to_read_counter [3:0]       <= 4'h0;
 
          write_recovery_counter[3:0]       <= 4'h0;
 
          precharge_counter[3:0]            <= 4'h0;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      WRITING_REG:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (load_mode_delay_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_REG;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else  // nothing else legal until load mode finished
 
          begin
 
            if (load_mode_delay_counter[3:0] > 4'h2)  // looping
 
            begin
 
              $display ("*** %m DDR DRAM cannot accept any other command while doing a LOAD MODE REGISTER command %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_REG;
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              $display ("*** %m DDR DRAM cannot accept any other command while doing a LOAD MODE REGISTER command %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b1;
 
            end
 
          end
 
          load_mode_delay_counter[3:0]      <= (load_mode_delay_counter[3:0] != 4'h0)
 
                                             ? (load_mode_delay_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= 4'h0;
 
          act_to_read_or_write_counter[3:0] <= 4'h0;
 
          act_to_precharge_counter[3:0]     <= 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= 4'h0;
 
          burst_counter[3:0]                <= 4'h0;
 
          read_to_write_counter [3:0]       <= 4'h0;
 
          write_to_read_counter [3:0]       <= 4'h0;
 
          write_recovery_counter[3:0]       <= 4'h0;
 
          precharge_counter[3:0]            <= 4'h0;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
// All interesting work starts here, except for read, write followed by read, write, precharge
 
      BANK_IDLE:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            Timing_Error <= 1'b0;
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == LOAD_MODE)  // no bank involved
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_REG;
 
            Timing_Error <= 1'b0;
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              if (act_a_to_act_a_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an ACT too soon after another ACT to the same bank %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
                Timing_Error <= 1'b1;
 
                act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                                   ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
                act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                                   ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
                act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                                   ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
                act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                                   ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b0;
 
                act_a_to_act_b_counter[3:0]       <= ACT_A_TO_ACT_B_CYCLES;
 
                act_to_read_or_write_counter[3:0] <= ACT_TO_READ_OR_WRITE_CYCLES;
 
                act_to_precharge_counter[3:0]     <= ACT_TO_PRECHARGE_CYCLES;
 
                act_a_to_act_a_counter[3:0]       <= ACT_A_TO_ACT_A_CYCLES;
 
              end
 
            end
 
            else  // some other bank
 
            begin
 
              if (act_a_to_act_b_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an ACT too soon after another ACT to the same bank %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
                Timing_Error <= 1'b0;
 
              end
 
              act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                                 ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
              act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                                 ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
              act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                                 ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
              act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                                 ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
          end
 
          else if ((control_wires[4:0] == READ_BANK) & (BA[1:0] != bank_num[1:0]))
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            Timing_Error <= 1'b0;
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if ((control_wires[4:0] == WRITE_BANK) & (BA[1:0] != bank_num[1:0]))
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            Timing_Error <= 1'b0;
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              if (act_to_precharge_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an PRECHARGE too soon after ACTIVATE %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
                Timing_Error <= 1'b1;
 
              end
 
              else  // ignore precharges when in idle state
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b0;
 
            end
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == REFRESH_BANK)  // all already precharged
 
          begin
 
            if (act_a_to_act_a_counter[3:0] > 4'h1)
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an REFRESH too soon after ACTIVATE %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
              Timing_Error <= 1'b0;
 
            end
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only do Activate, Refresh, Precharge, or Load Mode Register from Idle %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            Timing_Error <= 1'b1;
 
            act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                               ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
            act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                               ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
            act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                               ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          load_mode_delay_counter[3:0]      <= LOAD_MODE_REGISTER_CYCLES;
 
          burst_counter[3:0]                <= 4'h0;
 
          read_to_write_counter [3:0]       <= 4'h0;
 
          write_to_read_counter [3:0]       <= 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= (precharge_counter[3:0] != 4'h0)
 
                                             ? (precharge_counter[3:0] - 4'h1) : 4'h0;
 
          refresh_counter[3:0]              <= REFRESH_CYCLES;
 
        end
 
 
 
      ACTIVATING:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            Timing_Error <= 1'b0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is already Activated %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              if (act_a_to_act_b_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an Activate to a different bank too soon after this bank is Activated %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
          end
 
          else if (control_wires[4:0] == READ_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              if (act_to_read_or_write_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from Activate to Read %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else if (write_to_read_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from Write to Read %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                if (A[10] == 1'b1)
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
                else
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              if (act_to_read_or_write_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from Activate to Write %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else if (read_to_write_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from Read to Write %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                if (A[10] == 1'b1)
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
                else
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // only do precharge if this bank is addressed
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              if (act_to_precharge_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from Activate to Precharge %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else if (write_recovery_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM has to wait from end of Write to Precharge %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only do Read, Write, or Precharge from Activated %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            Timing_Error <= 1'b1;
 
          end
 
          load_mode_delay_counter[3:0]      <= 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          burst_counter[3:0]                <= 4'h2;
 
          read_to_write_counter [3:0]       <= (read_to_write_counter[3:0] != 4'h0)
 
                                             ? (read_to_write_counter[3:0] - 4'h1) : 4'h0;
 
          write_to_read_counter [3:0]       <= (write_to_read_counter[3:0] != 4'h0)
 
                                             ? (write_to_read_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      WRITING:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b0;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Written %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              if (act_a_to_act_b_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an Activate to a different bank too soon after this bank is Activated %t", $time);
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == READ_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Read until Write completes plus recovery %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do a Write to a bank until the previous Write completes %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;  // might want to go to activate!
 
                Timing_Error <= 1'b1;
 
                burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                   ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
              end
 
              else
 
              begin
 
                if (A[10] == 1'b1)
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
                else
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
                Timing_Error <= 1'b0;
 
                burst_counter[3:0]                <= 4'h2;
 
              end
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              end
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // do idles when it is safe to do so
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Precharge until Write completes plus recovery %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only do Read, Write, or Precharge from Write %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING;
 
            Timing_Error <= 1'b1;
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                              ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          load_mode_delay_counter[3:0]      <= 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= (read_to_write_counter[3:0] != 4'h0)
 
                                             ? (read_to_write_counter[3:0] - 4'h1) : 4'h0;
 
          write_to_read_counter [3:0]       <= WRITE_TO_READ_CYCLES;
 
          write_recovery_counter[3:0]       <= WRITE_RECOVERY_TO_PRECHARGE_CYCLES + 1;  // to let write finish!
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      WRITING_PRECHARGE:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Written %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              if (act_a_to_act_b_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an Activate to a different bank too soon after this bank is Activated %t", $time);
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == READ_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Read until Write_precharge completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Write until Write_precharge completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // do idles when it is safe to do so
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Precharge until Write_precharge completes plus recovery %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              end
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only wait from Write_precharge %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= WRITING_PRECHARGE;
 
            Timing_Error <= 1'b1;
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                              ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          load_mode_delay_counter[3:0]      <= 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= (read_to_write_counter[3:0] != 4'h0)
 
                                             ? (read_to_write_counter[3:0] - 4'h1) : 4'h0;
 
          write_to_read_counter [3:0]       <= WRITE_TO_READ_CYCLES;
 
          write_recovery_counter[3:0]       <= WRITE_RECOVERY_TO_PRECHARGE_CYCLES + 1;  // to let write finish!
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      READING:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              Timing_Error <= 1'b0;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Read %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              if (act_a_to_act_b_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do an Activate to a different bank too soon after this bank is Activated %t", $time);
 
                Timing_Error <= 1'b1;
 
              end
 
              else
 
              begin
 
                Timing_Error <= 1'b0;
 
              end
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == READ_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do a Read to a bank until the previous Read completes %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
                Timing_Error <= 1'b1;
 
                burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                   ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
              end
 
              else
 
              begin
 
                if (A[10] == 1'b1)
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
                else
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
                Timing_Error <= 1'b0;
 
                burst_counter[3:0]                <= 4'h2;
 
              end
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              end
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Read until Write completes plus recovery %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              end
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // do idles when it is safe to do so
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                $display ("*** %m DDR DRAM cannot do a Precharge to a bank until the previous Read completes %t", $time);
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
                Timing_Error <= 1'b1;
 
                burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                   ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
              end
 
              else
 
              begin
 
                if (act_to_precharge_counter[3:0] > 4'h1)
 
                begin
 
                  $display ("*** %m DDR DRAM has to wait during READ from Activate to Precharge %t", $time);
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
                  Timing_Error <= 1'b1;
 
                end
 
                else
 
                begin
 
                  bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
                  Timing_Error <= 1'b0;
 
                end
 
              end
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= ACTIVATING;
 
              end
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only do Read, Write, or Precharge from Read %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING;
 
            Timing_Error <= 1'b1;
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          load_mode_delay_counter[3:0]      <= (load_mode_delay_counter[3:0] != 4'h0)
 
                                             ? (load_mode_delay_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= READ_TO_WRITE_CYCLES;
 
          write_to_read_counter [3:0]       <= (write_to_read_counter[3:0] != 4'h0)
 
                                             ? (write_to_read_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      READING_PRECHARGE:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Read %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == READ_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Read until Read_precharge completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Write until Read_precharge completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (burst_counter[3:0] > 4'h1)
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // do idles when it is safe to do so
 
          begin
 
            if ((BA[1:0] == bank_num[1:0]) | (A[10] == 1'b1))
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Precharge until Read_precharge completes plus recovery %t", $time);
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            else  // was to a different bank.  We are done
 
            begin
 
              if (burst_counter[3:0] > 4'h1)
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
              end
 
              else
 
              begin
 
                bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              end
 
            end
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only do Read, Write, or Precharge from Read %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= READING_PRECHARGE;
 
            Timing_Error <= 1'b1;
 
            burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                               ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          end
 
          load_mode_delay_counter[3:0]      <= (load_mode_delay_counter[3:0] != 4'h0)
 
                                             ? (load_mode_delay_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                             ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= READ_TO_WRITE_CYCLES;
 
          write_to_read_counter [3:0]       <= (write_to_read_counter[3:0] != 4'h0)
 
                                             ? (write_to_read_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      WAITING_FOR_AUTO_PRECHARGE:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (   (write_recovery_counter[3:0] > 4'h1)
 
                 | (act_to_precharge_counter[3:0] > 4'h1) )
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being auto_precharging %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            if (   (write_recovery_counter[3:0] > 4'h1)
 
                 | (act_to_precharge_counter[3:0] > 4'h1) )
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == READ_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Read until bank completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (   (write_recovery_counter[3:0] > 4'h1)
 
                 | (act_to_precharge_counter[3:0] > 4'h1) )
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do a Write until bank completes precharge %t", $time);
 
              Timing_Error <= 1'b1;
 
              burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                                 ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
            end
 
            if (   (write_recovery_counter[3:0] > 4'h1)
 
                 | (act_to_precharge_counter[3:0] > 4'h1) )
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // do idles when it is safe to do so
 
          begin
 
             if (   (write_recovery_counter[3:0] > 4'h1)
 
                 | (act_to_precharge_counter[3:0] > 4'h1) )
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can only wait from Write_precharge %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= WAITING_FOR_AUTO_PRECHARGE;
 
            Timing_Error <= 1'b1;
 
          end
 
          load_mode_delay_counter[3:0]      <= 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                             ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= (read_to_write_counter[3:0] != 4'h0)
 
                                             ? (read_to_write_counter[3:0] - 4'h1) : 4'h0;
 
          write_to_read_counter [3:0]       <= (write_to_read_counter[3:0] != 4'h0)
 
                                             ? (write_to_read_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= PRECHARGE_CYCLES;
 
          refresh_counter[3:0]              <= 4'h0;
 
        end
 
 
 
      PRECHARGING:
 
        begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (precharge_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Precharged %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (precharge_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == READ_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Read to a bank which is being Precharged %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (precharge_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Write to a bank which is being Precharged %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (precharge_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // ignore extra precharges
 
          begin
 
            Timing_Error <= 1'b0;
 
            if (precharge_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can't do anything from Precharge %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= PRECHARGING;
 
            Timing_Error <= 1'b1;
 
          end
 
          load_mode_delay_counter[3:0]      <= (load_mode_delay_counter[3:0] != 4'h0)
 
                                             ? (load_mode_delay_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                             ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          read_to_write_counter [3:0]       <= (read_to_write_counter[3:0] != 4'h0)
 
                                             ? (read_to_write_counter[3:0] - 4'h1) : 4'h0;
 
          write_to_read_counter [3:0]       <= (write_to_read_counter[3:0] != 4'h0)
 
                                             ? (write_to_read_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= (precharge_counter[3:0] != 4'h0)
 
                                             ? (precharge_counter[3:0] - 4'h1) : 4'h0;
 
          refresh_counter[3:0]              <= (refresh_counter[3:0] != 4'h0)
 
                                             ? (refresh_counter[3:0] - 4'h1) : 4'h0;
 
        end
 
 
 
      REFRESHING:
 
         begin
 
          if (   (control_wires[4] == 1'b0)      // powered off
 
               | (control_wires[3] == 1'b1)      // not selected
 
               | (control_wires[4:0] == NOOP) )  // noop
 
          begin
 
            if (refresh_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
              Timing_Error <= 1'b0;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
              Timing_Error <= 1'b0;
 
            end
 
          end
 
          else if (control_wires[4:0] == ACTIVATE_BANK)  // activate only if this bank is addressed
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Activate to a bank which is being Refreshed %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (refresh_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == READ_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Read to a bank which is being Refreshed %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (refresh_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == WRITE_BANK)  // no bank involved
 
          begin
 
            if (BA[1:0] == bank_num[1:0])
 
            begin
 
              $display ("*** %m DDR DRAM cannot do an Write to a bank which is being Refreshed %t", $time);
 
              Timing_Error <= 1'b1;
 
            end
 
            else
 
            begin
 
              Timing_Error <= 1'b0;
 
            end
 
            if (refresh_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else if (control_wires[4:0] == PRECHARGE_BANK)  // ignore extra precharges
 
          begin
 
            Timing_Error <= 1'b0;
 
            if (refresh_counter[3:0] > 4'h2)  // looping
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
            end
 
            else
 
            begin
 
              bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
            end
 
          end
 
          else
 
          begin
 
            $display ("*** %m DDR DRAM can't do anything from Refresh %t", $time);
 
            bank_state[BANK_STATE_WIDTH - 1 : 0] <= REFRESHING;
 
            Timing_Error <= 1'b1;
 
          end
 
          load_mode_delay_counter[3:0]      <= (load_mode_delay_counter[3:0] != 4'h0)
 
                                             ? (load_mode_delay_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_b_counter[3:0]       <= (act_a_to_act_b_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_b_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_read_or_write_counter[3:0] <= (act_to_read_or_write_counter[3:0] != 4'h0)
 
                                             ? (act_to_read_or_write_counter[3:0] - 4'h1) : 4'h0;
 
          act_to_precharge_counter[3:0]     <= (act_to_precharge_counter[3:0] != 4'h0)
 
                                             ? (act_to_precharge_counter[3:0] - 4'h1) : 4'h0;
 
          act_a_to_act_a_counter[3:0]       <= (act_a_to_act_a_counter[3:0] != 4'h0)
 
                                             ? (act_a_to_act_a_counter[3:0] - 4'h1) : 4'h0;
 
          burst_counter[3:0]                <= (burst_counter[3:0] != 4'h0)
 
                                             ? (burst_counter[3:0] - 4'h1) : 4'h0;
 
          write_recovery_counter[3:0]       <= (write_recovery_counter[3:0] != 4'h0)
 
                                             ? (write_recovery_counter[3:0] - 4'h1) : 4'h0;
 
          precharge_counter[3:0]            <= (precharge_counter[3:0] != 4'h0)
 
                                             ? (precharge_counter[3:0] - 4'h1) : 4'h0;
 
          refresh_counter[3:0]              <= (refresh_counter[3:0] != 4'h0)
 
                                             ? (refresh_counter[3:0] - 4'h1) : 4'h0;
 
        end
 
 
 
      default:
 
        begin
 
          $display ("*** %m DDR DRAM default jump should be impossible %t", $time);
 
          bank_state[BANK_STATE_WIDTH - 1 : 0] <= BANK_IDLE;
 
          Timing_Error <= 1'b1;
 
        end
 
    endcase
 
    end  // if out the entire case statement!
 
  end
 
endmodule
 
 
 
`define TEST_DDR_2_DRAM
 
`ifdef TEST_DDR_2_DRAM
 
module test_ddr_2_dram;
 
  reg  CLK_P, CLK_N;
 
 
 
  initial
 
  begin
 
    CLK_P <= 1'b0;
 
    CLK_N <= 1'b1;
 
    # 10_000 ;  // make times be even
 
    while (1'b1)
 
    begin
 
      #10_000 ;  // 10 nSec
 
      CLK_P <= ~CLK_P;
 
      CLK_N <= ~CLK_N;
 
    end
 
  end
 
 
 
  initial
 
  begin
 
    #2000_000 $finish;
 
  end
 
 
 
// hook up sequential test bench to instantiation of DDR DRAM for test
 
parameter DATA_BUS_WIDTH = 4;
 
 
 
  wire   [DATA_BUS_WIDTH - 1 : 0] DQ;
 
  wire    DQS;
 
 
 
  reg     DM;
 
  reg    [12:0] A;
 
  reg    [1:0] BA;
 
  reg     RAS_L, CAS_L, WE_L, CS_L, CKE;
 
  reg    [DATA_BUS_WIDTH - 1 : 0] DQ_out_0;
 
  reg    [DATA_BUS_WIDTH - 1 : 0] DQ_out_1;
 
  reg     DQ_oe_0, DQ_oe_1;
 
  reg     DQS_out;
 
  reg     DQS_oe;
 
 
 
// MUX the two data items together based on clock phase
 
  wire   [DATA_BUS_WIDTH - 1 : 0] DQ_out = CLK_P
 
                ? DQ_out_1[DATA_BUS_WIDTH - 1 : 0]
 
                : DQ_out_0[DATA_BUS_WIDTH - 1 : 0];
 
 
 
// Either send data or tristate the bus
 
  assign  DQ[DATA_BUS_WIDTH - 1 : 0] = DQ_oe
 
                ? DQ_out[DATA_BUS_WIDTH - 1 : 0]
 
                : {DATA_BUS_WIDTH{1'bZ}};
 
 
 
// The DQS signal is OE'd BEFORE the Data.  Called the preamble.
 
  assign DQS = DQS_oe ? DQS_out : 1'bZ;
 
 
 
// {CKE, CS_L, RAS_L, CAS_L, WE_L}
 
parameter NOOP      = 5'h17;
 
parameter ACTIVATE  = 5'h13;
 
parameter READ      = 5'h15;
 
parameter WRITE     = 5'h14;
 
parameter PRECHARGE = 5'h12;
 
parameter REFRESH   = 5'h11;
 
parameter LOAD_MODE = 5'h10;
 
 
 
  initial
 
  begin
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
DQ_oe_0 <= 1'b0;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
DQ_oe_1 <= 1'b0;
 
 
 
    CKE <= 1'b1;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    DQ_oe <= 1'b0;  DQS_oe <= 1'b0;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
A[12:0] <= 13'h1555;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= LOAD_MODE;
 
    @ (posedge CLK_P) ;  // write reg
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= ACTIVATE;
 
    @ (posedge CLK_P) ;  // activate
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= WRITE;
 
    @ (posedge CLK_P) ;  // write DRAM
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'h1;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'h2;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hE;
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= WRITE;
 
    @ (posedge CLK_P) ;  // write DRAM
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'h3;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hD;
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'h4;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hC;
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hB;
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_1[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= READ;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= READ;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= PRECHARGE;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= ACTIVATE;
 
    @ (posedge CLK_P) ;  // activate
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= READ;
 
    @ (posedge CLK_P) ;  // read
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data  //
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= WRITE;
 
    @ (posedge CLK_P) ;  // write
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hE;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hD;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= PRECHARGE;
 
    @ (posedge CLK_P) ;  // noop
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= REFRESH;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= ACTIVATE;
 
    @ (posedge CLK_P) ;  // activate
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h400;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= WRITE;
 
    @ (posedge CLK_P) ;  // write
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hB;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'h7;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
DQ_out_0[DATA_BUS_WIDTH - 1 : 0] <= 4'hZ;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= ACTIVATE;
 
    @ (posedge CLK_P) ;  // activate
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h400;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= READ;
 
    @ (posedge CLK_P) ;  // write
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
A[12:0] <= 13'h0;  BA[1:0] <= 2'h0;
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= ACTIVATE;
 
    @ (posedge CLK_P) ;  // activate
 
 
 
    {CKE, CS_L, RAS_L, CAS_L, WE_L} <= NOOP;
 
    @ (posedge CLK_P) ;  // noop + data
 
 
 
  end
 
 
 
 
 
 
 
 
 
  assign  DQ[DATA_BUS_WIDTH - 1 : 0] =
 
                  (   (DQ_out_0[DATA_BUS_WIDTH - 1 : 0] !== {DATA_BUS_WIDTH{1'bZ}})
 
                    & (CLK_N == 1'b1) )
 
                ? DQ_out_0[DATA_BUS_WIDTH - 1 : 0]
 
                : ( (   (DQ_out_1[DATA_BUS_WIDTH - 1 : 0] !== {DATA_BUS_WIDTH{1'bZ}})
 
                      & (CLK_P == 1'b1) )
 
                  ? DQ_out_1[DATA_BUS_WIDTH - 1 : 0]
 
                  : {DATA_BUS_WIDTH{1'bZ}});
 
 
 
ddr_2_dram
 
# ( 100.0,  // frequency
 
    2.0,  // latency
 
    13,  // num_addr_bits
 
    12,  // num_col_bits
 
     4 * DATA_BUS_WIDTH,  // num_data_bits
 
    32,  // num_words_in_test_memory
 
     1
 
  ) ddr_2_dram (
 
  .DQ                         ({DQ[DATA_BUS_WIDTH - 1 : 0], DQ[DATA_BUS_WIDTH - 1 : 0],
 
                                DQ[DATA_BUS_WIDTH - 1 : 0], DQ[DATA_BUS_WIDTH - 1 : 0]}),
 
  .DQS                        (DQS),
 
  .DM                         (DM),
 
  .A                          (A[12:0]),
 
  .BA                         (BA[1:0]),
 
  .RAS_L                      (RAS_L),
 
  .CAS_L                      (CAS_L),
 
  .WE_L                       (WE_L),
 
  .CS_L                       (CS_L),
 
  .CKE                        (CKE),
 
  .CLK_P                      (CLK_P),
 
  .CLK_N                      (CLK_N)
 
);
 
 
 
  wire   [3:0] BANK_STATE_0 = ddr_2_dram.ddr_2_dram_single_bank_0.bank_state[3:0];
 
  wire   [3:0] BANK_STATE_1 = ddr_2_dram.ddr_2_dram_single_bank_1.bank_state[3:0];
 
  wire   [3:0] BANK_STATE_2 = ddr_2_dram.ddr_2_dram_single_bank_2.bank_state[3:0];
 
  wire   [3:0] BANK_STATE_3 = ddr_2_dram.ddr_2_dram_single_bank_3.bank_state[3:0];
 
 
 
endmodule
 
`endif  // TEST_DDR_2_DRAM
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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