change rst to high-active
[fleet.git] / ships / DDR2.ship
index b594c87..1092f73 100644 (file)
@@ -7,6 +7,27 @@ data  in:    inDataWrite
 
 data  out:   out
 
+percolate up:    DDR2_CAS_B   1
+percolate up:    DDR2_CKE     2
+percolate up:    DDR2_RAS_B   1
+percolate up:    DDR2_WE_B    1
+percolate up:    DDR2_ODT     2
+percolate up:    DDR2_CS0_B   2
+percolate up:    DDR2_CLK_N   2
+percolate up:    DDR2_CLK_P   2
+percolate up:    DDR2_A       14
+percolate up:    DDR2_BA      3
+percolate inout: DDR2_DQ      64
+percolate up:    DDR2_DM      8
+percolate inout: DDR2_DQS_N   8
+percolate inout: DDR2_DQS_P   8
+
+percolate inout: I2C_DDR2_SCL 1
+percolate inout: I2C_DDR2_SDA 1
+
+percolate down:  CLKBUF_Q1_N  1
+percolate down:  CLKBUF_Q1_P  1
+
 == TeX ==============================================================
 
 == Fleeterpreter ====================================================
@@ -15,63 +36,266 @@ data  out:   out
 
 == FPGA ==============================================================
 
-  reg         ddr2_addr_r;
-  reg         ddr2_isread;
-  reg         ddr2_write_data_push;
-  reg         ddr2_read_data_pop;
-  reg  [`DATAWIDTH:0]  out_d;
-
-  assign ddr2_addr_r_ = ddr2_addr_r;
-  assign ddr2_isread_ = ddr2_isread;
-  assign ddr2_addr_ = !ddr2_isread ? inAddrWrite_d[31:0] : inAddrRead_d[31:0];
-  assign ddr2_write_data_push_ = ddr2_write_data_push;
-  assign ddr2_read_data_pop_ = ddr2_read_data_pop;
-  assign ddr2_write_data_ = { inDataWrite_d[31:5], inDataWrite_d[4], inDataWrite_d[35:0] };
-//  assign ddr2_write_data_ = inDataWrite_d[(`DATAWIDTH-1):0];
-  assign out_d_ = out_d;
+// Nearly all of this was copied from Greg Gibeling's work; copyright shown below:
+
+// Everything here was copied from
+// GateLib/Firmware/DRAM/Hardware/DDR2SDRAM/Test/FPGA_TOP_ML505_DDR2SDRAMTest.v
+
+//==============================================================================
+//      Section:        License
+//==============================================================================
+//      Copyright (c) 2005-2008, Regents of the University of California
+//      All rights reserved.
+//
+//      Redistribution and use in source and binary forms, with or without modification,
+//      are permitted provided that the following conditions are met:
+//
+//              - Redistributions of source code must retain the above copyright notice,
+//                      this list of conditions and the following disclaimer.
+//              - Redistributions in binary form must reproduce the above copyright
+//                      notice, this list of conditions and the following disclaimer
+//                      in the documentation and/or other materials provided with the
+//                      distribution.
+//              - Neither the name of the University of California, Berkeley nor the
+//                      names of its contributors may be used to endorse or promote
+//                      products derived from this software without specific prior
+//                      written permission.
+//
+//      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+//      ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+//      WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+//      DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+//      ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+//      (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+//      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+//      ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+//      SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//==============================================================================
+
+parameter
+    ClockFreq  = 200000000,
+    BAWidth    = 2,
+    RAWidth    = 13,
+    CAWidth    = 10,                                                     
+    DWidth     = 128,       // 128b SDR internal transfers
+    UWidth     = 8,         // This will almost ALWAYS be 8
+    BurstLen   = 2,         // 256b total burst, 2 words DWidth words at SDR, or 4 external words at DDR
+    EnableMask = 1,
+    EnableECC  = 0,
+    Board      = 0;
+
+localparam
+    UCount   =  DWidth / UWidth,
+    // 128b/8 = 16b per mask means per-byte masking
+    MWidth   =  (EnableECC || (EnableMask == 0)) ? 0 : UCount,
+    // Unused lower address bits, the -1 is to get a proper log2
+    UAWidth  =  `log2(UCount-1),
+    TAWidth  =  CAWidth + RAWidth + BAWidth,
+    // Note that the components are in order according to where in the
+    // address they appear, the -1 is to account for DDR
+    AWidth   =  TAWidth + UAWidth - 1,
+    ECheck   =  EnableECC ? 2 : 0,
+    ECorrect =  EnableECC ? 1 : 0,
+    CWidth   =  3,
+    EHWidth  =  `max(`log2(ECheck), 1),
+    ERWidth  =  `max(`log2(ECheck), 1);
+
+wire   Reset;
+assign Reset = !rst;
+
+reg     [AWidth-1:0]    CommandAddress;
+reg     [CWidth-1:0]    Command; 
+wire                    CommandReady;
+reg                     CommandValid;
+
+wire    [DWidth-1:0]    DataIn;
+wire    [MWidth-1:0]    DataInMask;
+reg                     DataInValid;
+wire                    DataInReady;
+        
+wire    [DWidth-1:0]    DataOut;
+wire    [EHWidth-1:0]   DataOutErrorChecked;
+wire    [ERWidth-1:0]   DataOutErrorCorrected;
+wire                    DataOutValid;
+reg                     DataOutReady;
+
+wire                    Clock_IBUFG;
+wire                    Clock, ClockD2, ClockP90;
+wire                    Clock_DCM, ClockD2_DCM, ClockP90_DCM;
+wire                    Locked;
+
+reg  [`WORDWIDTH:0] out_d;
+assign out_d_ = out_d;
+
+assign  DDR2_BA[2]    = 1'b0;
+assign  DDR2_CS0_B[1] = 1'b1;
+assign  DDR2_ODT[1]   = 1'b0;
+assign  DDR2_CKE[1]   = 1'b0;
+
+IBUFGDS ClockIBufG(.I(CLKBUF_Q1_P), .IB(CLKBUF_Q1_N), .O(Clock_IBUFG));
+DCM_BASE
+  #( 
+     .CLKIN_PERIOD(5.0),
+     .CLKDV_DIVIDE(2.0),
+     .DLL_FREQUENCY_MODE("HIGH"),
+     .DUTY_CYCLE_CORRECTION("TRUE"),
+     .FACTORY_JF(16'hF0F0)
+   )
+  DCMBase(
+     .CLK0(Clock_DCM),
+     .CLK180( ),
+     .CLK270( ),
+     .CLK2X( ),
+     .CLK2X180( ),
+     .CLK90(ClockP90_DCM),
+     .CLKDV(ClockD2_DCM),
+     .CLKFX( ),
+     .CLKFX180( ),
+     .LOCKED(Locked),
+     .CLKFB(Clock),
+     .CLKIN(Clock_IBUFG),
+     .RST(Reset));
+  // synthesis attribute CLKIN_PERIOD          of DCMBase is "5.0"
+  // synthesis attribute CLKDV_DIVIDE          of DCMBase is "2.0"
+  // synthesis attribute DLL_FREQUENCY_MODE    of DCMBase is "HIGH"
+  // synthesis attribute DUTY_CYCLE_CORRECTION of DCMBase is "TRUE"
+  // synthesis attribute FACTORY_JF            of DCMBase is "16'hF0F0"
+  BUFG    ClockBufG(.I(Clock_DCM), .O(Clock));
+  BUFG    ClockP90BufG(.I(ClockP90_DCM), .O(ClockP90));
+  BUFG    ClockD2BufG(.I(ClockD2_DCM), .O(ClockD2));
+
+DDR2SDRAM DDR2SDRAM(
+      .Clock(Clock),
+      .ClockD2(ClockD2),
+      .ClockP90(ClockP90),
+      .Reset(Reset),
+      .Locked(Locked),
+      .ClockF200(Clock),
+      .Initialized( ),
+      .PoweredUp( ),
+
+      .CommandClock(clk),
+      .DataInClock(clk),
+      .DataOutClock(clk),
+      .CommandReset(Reset),
+      .DataInReset(Reset),
+      .DataOutReset(Reset),
+
+      .CommandAddress(CommandAddress),
+      .Command(Command),
+      .CommandValid(CommandValid),
+      .CommandReady(CommandReady),
+      .DataIn(DataIn),
+      .DataInMask(DataInMask),
+      .DataInValid(DataInValid),
+      .DataInReady(DataInReady),
+      .DataOut(DataOut),
+      .DataOutErrorChecked(DataOutErrorChecked),
+      .DataOutErrorCorrected(DataOutErrorCorrected),
+      .DataOutValid(DataOutValid),
+      .DataOutReady(DataOutReady),
+      .DDR2_DQ(DDR2_DQ),
+      .DDR2_A(DDR2_A),
+      .DDR2_BA(DDR2_BA[1:0]),
+      .DDR2_RAS_B(DDR2_RAS_B),
+      .DDR2_CAS_B(DDR2_CAS_B),
+      .DDR2_WE_B(DDR2_WE_B),
+      .DDR2_CS0_B(DDR2_CS0_B[0]),
+      .DDR2_ODT(DDR2_ODT[0]),
+      .DDR2_CKE(DDR2_CKE[0]),
+      .DDR2_DM(DDR2_DM),
+      .DDR2_DQS_P(DDR2_DQS_P),
+      .DDR2_DQS_N(DDR2_DQS_N),
+      .DDR2_CLK_P(DDR2_CLK_P),
+      .DDR2_CLK_N(DDR2_CLK_N));
+      defparam DDR2SDRAM.UWidth     = UWidth;
+      defparam DDR2SDRAM.BAWidth    = BAWidth;
+      defparam DDR2SDRAM.RAWidth    = RAWidth;
+      defparam DDR2SDRAM.CAWidth    = CAWidth;
+      defparam DDR2SDRAM.DWidth     = DWidth;
+      defparam DDR2SDRAM.BurstLen   = BurstLen;
+      defparam DDR2SDRAM.EnableMask = EnableMask;
+      defparam DDR2SDRAM.EnableECC  = EnableECC;
+      defparam DDR2SDRAM.Board      = Board;
+      defparam DDR2SDRAM.MultiClock = 1;
+
+  assign DataIn     = inDataWrite_d;
+  assign DataInMask = 16'b1111111111111111;
 
   always @(posedge clk) begin
 
-    if (!rst) begin
+    if (rst) begin
       `reset
-      ddr2_isread <= 0;
-      ddr2_addr_r <= 0;
-      ddr2_read_data_pop <= 0;
-
+      CommandValid <= 0;
+      DataOutReady <= 0;
     end else begin
-      `flush
-
-      if (!inAddrRead_r_  && inAddrRead_a)  inAddrRead_a  <= 0;
-      if (!inDataWrite_r_ && inDataWrite_a) inDataWrite_a <= 0;
-      if (!inAddrWrite_r_ && inAddrWrite_a) inAddrWrite_a <= 0;
-      if ( out_r          && out_a)         out_r <= 0;
-
-      if (ddr2_addr_r && !ddr2_addr_a) begin
-         // busy
-      end else if (ddr2_addr_r &&  ddr2_addr_a && !ddr2_isread) begin
-          ddr2_addr_r <= 0;
-          inAddrWrite_a <= 1;
-          inDataWrite_a <= 1;
-          out_d <= { 1'b1, 37'b0 };
-          out_r <= 1;
-      end else if (ddr2_addr_r &&  ddr2_addr_a && ddr2_isread) begin
-          ddr2_addr_r <= 0;
-          inAddrRead_a <= 1;
-          out_d <= { 1'b0, ddr2_read_data[36:0] };
-          out_r <= 1;
-      end else if (!out_r && !out_a && inAddrWrite_r && !inAddrWrite_a && inDataWrite_r && !inDataWrite_a && !ddr2_addr_r && !ddr2_addr_a) begin
-          ddr2_addr_r <= 1;
-          ddr2_isread <= 0;
-      end else if (!out_r && !out_a && inAddrRead_r && !inAddrRead_a && !ddr2_addr_r && !ddr2_addr_a) begin
-          ddr2_addr_r <= 1;
-          ddr2_isread <= 1;
+      `cleanup
+
+      CommandValid <= 0;
+      DataInValid  <= 0;
+
+      if (`out_empty) begin
+          DataOutReady <= 1;      
+      end
+
+      if (DataOutReady && DataOutValid && `out_empty) begin
+          out_d <= { 1'b0, DataOut[`WORDWIDTH-1:0] };
+          `fill_out
+          DataOutReady <= 0;
+
+      end else if (DataOutReady && CommandReady && DataInReady && `out_empty) begin
+          if (`inAddrWrite_full && `inDataWrite_full) begin
+            `drain_inDataWrite
+            `drain_inAddrWrite
+            CommandAddress <= inAddrWrite_d;
+            Command        <= 3'b000;
+            CommandValid   <= 1;
+            DataInValid    <= 1;
+            out_d <= { 1'b1, 37'b0 };
+            `fill_out
+            DataOutReady <= 0;
+          end else if (`inAddrRead_full) begin
+            `drain_inAddrRead
+            CommandAddress <= inAddrRead_d;
+            CommandValid   <= 1;
+            Command        <= 3'b001;
+            DataInValid    <= 0;
+            DataOutReady   <= 1;
+          end
       end
     end
   end
 
+== Test ==============================================================
 
-== Test ========================================================
 #skip
+#expect 0
+
+#ship debug : Debug
+#ship ddr   : DDR2
+
+debug.in:
+  recv, deliver;
+
+ddr.out:
+  collect;
+  set flags a=!c,b=b;
+  send to debug.in;
+  collect;
+  set flags a=!c,b=b;
+  send to debug.in;
+ddr.inAddrWrite:
+  set word=0;
+  deliver;
+  deliver;
+ddr.inDataWrite:
+  set word=1;
+  deliver;
+  deliver;
+
+
+
 
 == Constants ========================================================