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

Subversion Repositories common

[/] [common/] [trunk/] [ddr_2_dram_for_debugging.v] - Rev 48

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
//// 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
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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