Rework CRG simulation
authorJean THOMAS <git0@pub.jeanthomas.me>
Fri, 3 Jul 2020 12:25:45 +0000 (14:25 +0200)
committerJean THOMAS <git0@pub.jeanthomas.me>
Fri, 3 Jul 2020 12:25:45 +0000 (14:25 +0200)
gram/simulation/runsimcrg.sh
gram/simulation/simcrg.py
gram/simulation/simcrg.ys [new file with mode: 0644]
gram/simulation/simcrgtb.sv [new file with mode: 0644]
gram/simulation/simcrgtb.v [deleted file]

index d34f3de6f1018f99b6ceda34941010c8966c3845..d2eb2db24d50849ff3cd19e665f2e46a3773ab68 100755 (executable)
@@ -3,6 +3,12 @@ set -e
 
 LIB_DIR=/usr/local/diamond/3.11_x64/ispfpga/verilog/data/ecp5u
 
-python simcrg.py generate simcrg.v
-iverilog -Wall -o simcrg simcrgtb.v simcrg.v ${LIB_DIR}/ECLKSYNCB.v ${LIB_DIR}/CLKDIVF.v ${LIB_DIR}/EHXPLLL.v ${LIB_DIR}/PUR.v ${LIB_DIR}/GSR.v
-vvp -n simcrg -vcd
+python simcrg.py
+yosys simcrg.ys
+cp ${LIB_DIR}/DDRDLLA.v DDRDLLA.v
+patch DDRDLLA.v < DDRDLLA.patch
+iverilog -Wall -g2012 -s simcrgtb -o simcrg simcrgtb.sv build_simcrg/top.v dram_model/ddr3.v ${LIB_DIR}/ECLKSYNCB.v ${LIB_DIR}/EHXPLLL.v ${LIB_DIR}/PUR.v ${LIB_DIR}/GSR.v \
+       ${LIB_DIR}/FD1S3AX.v ${LIB_DIR}/SGSR.v ${LIB_DIR}/ODDRX2F.v ${LIB_DIR}/ODDRX2DQA.v ${LIB_DIR}/DELAYF.v ${LIB_DIR}/BB.v ${LIB_DIR}/OB.v ${LIB_DIR}/IB.v \
+       ${LIB_DIR}/DQSBUFM.v ${LIB_DIR}/UDFDL5_UDP_X.v ${LIB_DIR}/TSHX2DQSA.v ${LIB_DIR}/TSHX2DQA.v ${LIB_DIR}/ODDRX2DQSB.v ${LIB_DIR}/IDDRX2DQA.v DDRDLLA.v \
+       ${LIB_DIR}/CLKDIVF.v
+vvp -n simcrg -fst-speed
index dd076152b9f01dd85160a6cbd3d4fd93e0b1b039..94382b55d5586205e532b2d190d51e50122539ae 100644 (file)
 # This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
 
 from nmigen import *
-from nmigen.cli import main
-from nmigen.lib.cdc import ResetSynchronizer
+from icarusecpix5platform import IcarusECPIX5Platform
+from crg import *
+from nmigen.build import *
 
-class PLL(Elaboratable):
-    def __init__(self, clkin, clksel=Signal(shape=2, reset=2), clkout1=Signal(), clkout2=Signal(), clkout3=Signal(), clkout4=Signal(), lock=Signal(), CLKI_DIV=1, CLKFB_DIV=1, CLK1_DIV=3, CLK2_DIV=4, CLK3_DIV=5, CLK4_DIV=6):
-        self.clkin = clkin
-        self.clkout1 = clkout1
-        self.clkout2 = clkout2
-        self.clkout3 = clkout3
-        self.clkout4 = clkout4
-        self.clksel = clksel
-        self.lock = lock
-        self.CLKI_DIV = CLKI_DIV
-        self.CLKFB_DIV = CLKFB_DIV
-        self.CLKOP_DIV = CLK1_DIV
-        self.CLKOS_DIV = CLK2_DIV
-        self.CLKOS2_DIV = CLK3_DIV
-        self.CLKOS3_DIV = CLK4_DIV
-        self.ports = [
-            self.clkin,
-            self.clkout1,
-            self.clkout2,
-            self.clkout3,
-            self.clkout4,
-            self.clksel,
-            self.lock,
-        ]
-
-    def elaborate(self, platform):
-        clkfb = Signal()
-        pll = Instance("EHXPLLL",
-                       p_CLKOP_FPHASE=0,
-                       p_CLKOP_CPHASE=1,
-                       p_OUTDIVIDER_MUXA='DIVA',
-                       p_CLKOP_ENABLE='ENABLED',
-                       p_CLKOP_DIV=self.CLKOP_DIV,
-                       p_CLKOS_DIV=self.CLKOS_DIV,
-                       p_CLKOS2_DIV=self.CLKOS2_DIV,
-                       p_CLKOS3_DIV=self.CLKOS3_DIV,
-                       p_CLKFB_DIV=self.CLKFB_DIV,
-                       p_CLKI_DIV=self.CLKI_DIV,
-                       p_FEEDBK_PATH='INT_OP',
-                       #p_FREQUENCY_PIN_CLKOP='200',
-                       i_CLKI=self.clkin,
-                       i_CLKFB=clkfb,
-                       i_RST=0,
-                       i_STDBY=0,
-                       i_PHASESEL0=1,
-                       i_PHASESEL1=1,
-                       i_PHASEDIR=0,
-                       i_PHASESTEP=0,
-                       i_PLLWAKESYNC=0,
-                       i_ENCLKOP=1,
-                       i_ENCLKOS=1,
-                       i_ENCLKOS2=0,
-                       i_ENCLKOS3=0,
-                       o_CLKOP=self.clkout1,
-                       o_CLKOS=self.clkout2,
-                       o_CLKOS2=self.clkout3,
-                       o_CLKOS3=self.clkout4,
-                       o_LOCK=self.lock,
-                       )
-        m = Module()
-        m.submodules += pll
-        with m.If(self.clksel == 0):
-            m.d.comb += clkfb.eq(self.clkout1)
-        with m.Elif(self.clksel == 1):
-            m.d.comb += clkfb.eq(self.clkout2)
-        with m.Elif(self.clksel == 2):
-            m.d.comb += clkfb.eq(self.clkout3)
-        with m.Else():
-            m.d.comb += clkfb.eq(self.clkout4)
-        return m
-
-
-class ECPIX5CRG(Elaboratable):
-    def __init__(self):
-        self.clkin = Signal()
-
-    def elaborate(self, platform):
-        m = Module()
-
-        # Get 100Mhz from oscillator
-        cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
-        m.d.comb += cd_rawclk.clk.eq(self.clkin)
-        m.domains += cd_rawclk
-
-        # Power-on delay (655us)
-        podcnt = Signal(16, reset=2**16-1)
-        pod_done = Signal()
-        with m.If(podcnt != 0):
-            m.d.rawclk += podcnt.eq(podcnt-1)
-        m.d.comb += pod_done.eq(podcnt == 0)
-
-        # Generating sync2x (200Mhz) and init (25Mhz) from clk100
-        cd_sync2x = ClockDomain("sync2x", local=False)
-        cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=True, reset_less=True)
-        cd_init = ClockDomain("init", local=False)
-        cd_sync = ClockDomain("sync", local=False, reset_less=True)
-        cd_dramsync = ClockDomain("dramsync", local=False)
-        m.submodules.pll = pll = PLL(ClockSignal("rawclk"), CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=2, CLK2_DIV=16, CLK3_DIV=4,
-            clkout1=ClockSignal("sync2x_unbuf"), clkout2=ClockSignal("init"))
-        m.submodules += Instance("ECLKSYNCB",
-                i_ECLKI = ClockSignal("sync2x_unbuf"),
-                i_STOP  = 0,
-                o_ECLKO = ClockSignal("sync2x"))
-        m.domains += cd_sync2x_unbuf
-        m.domains += cd_sync2x
-        m.domains += cd_init
-        m.domains += cd_sync
-        m.domains += cd_dramsync
-        m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
-        m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
-
-        # Generating sync (100Mhz) from sync2x
-        
-        m.submodules += Instance("CLKDIVF",
-            p_DIV="2.0",
-            i_ALIGNWD=0,
-            i_CLKI=ClockSignal("sync2x"),
-            i_RST=0,
-            o_CDIVX=ClockSignal("sync"))
-        m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
-
-        return m
-
-class SimCRGTop(Elaboratable):
+class Top(Elaboratable):
     def __init__(self):
-        self.clkin = Signal()
-
-        self.sync2x = Signal()
-        self.sync = Signal()
         self.dramsync = Signal()
-        self.init = Signal()
+        self.dramsync_reset = Signal()
+        self.sync = Signal()
+        self.sync2x = Signal()
 
     def elaborate(self, platform):
         m = Module()
 
         m.submodules.crg = crg = ECPIX5CRG()
+
+        resources = [
+            Resource("clock_conn", 0, Pins("1 2 3 4", conn=("pmod", 5,), dir="o"), Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP")),
+        ]
+        platform.add_resources(resources)
+
+        clock_conn = platform.request("clock_conn", 0)
         m.d.comb += [
-            crg.clkin.eq(self.clkin),
-            self.sync2x.eq(ClockSignal("sync2x")),
-            self.sync.eq(ClockSignal("sync")),
             self.dramsync.eq(ClockSignal("dramsync")),
-            self.init.eq(ClockSignal("init")),
+            self.dramsync_reset.eq(ResetSignal("dramsync")),
+            self.sync.eq(ClockSignal("sync")),
+            self.sync2x.eq(ClockSignal("sync2x")),
+
+            clock_conn[0].eq(ClockSignal("dramsync")),
+            clock_conn[1].eq(ResetSignal("dramsync")),
+            clock_conn[2].eq(ClockSignal("sync")),
+            clock_conn[3].eq(ClockSignal("sync2x")),
         ]
 
         return m
 
-
 if __name__ == "__main__":
-    top = SimCRGTop()
-    main(top, name="simcrgtop", ports=[top.clkin, top.sync, top.sync2x, top.dramsync, top.init])
+    top = Top()
+    IcarusECPIX5Platform().build(top, build_dir="build_simcrg")
diff --git a/gram/simulation/simcrg.ys b/gram/simulation/simcrg.ys
new file mode 100644 (file)
index 0000000..3dea68c
--- /dev/null
@@ -0,0 +1,17 @@
+read_ilang build_simcrg/top.il
+delete w:$verilog_initial_trigger
+proc_prune
+proc_clean
+proc_init
+proc_arst
+proc_dff
+proc_rmdead
+proc_mux
+proc_clean
+pmuxtree
+memory_collect
+extract_fa -v
+clean
+opt
+clean
+write_verilog -norename build_simcrg/top.v
diff --git a/gram/simulation/simcrgtb.sv b/gram/simulation/simcrgtb.sv
new file mode 100644 (file)
index 0000000..d753a84
--- /dev/null
@@ -0,0 +1,47 @@
+// This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
+
+`timescale 1 ns / 1 ns
+
+module simcrgtb;
+  // GSR & PUR init requires for Lattice models
+  GSR GSR_INST (
+    .GSR(1'b1)
+  );
+  PUR PUR_INST (
+    .PUR (1'b1)
+  );
+
+  reg clkin;
+
+  // Generate 100 Mhz clock
+  always 
+    begin
+      clkin = 1'b1; 
+      #5;
+      clkin = 1'b0;
+      #5;
+    end
+  
+  top top (
+    .clk100_0__io(clkin),
+    .rst_0__io(1'b0)
+  );
+
+  initial
+    begin
+      $dumpfile("simcrg.fst");
+      $dumpvars(0, top);
+      #1000000 $finish;
+    end
+
+  initial
+    begin
+      assert (top.crg_dramsync_rst == 1'b1) else $error("DRAM clock domain is not reset at t=0");
+    end
+
+  always @ (negedge top.crg_dramsync_rst)
+    begin
+      assert($time > 600000) else $error("DRAM sync got out of reset before 600us (too early)");
+      assert($time < 700000) else $error("DRAM sync got out of reset after 700us (too late)");
+    end
+endmodule
diff --git a/gram/simulation/simcrgtb.v b/gram/simulation/simcrgtb.v
deleted file mode 100644 (file)
index 6814343..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
-
-`timescale 1 ns / 1 ns
-
-module top;
-  // GSR & PUR init requires for Lattice models
-  GSR GSR_INST (
-    .GSR(1'b0)
-  );
-  PUR PUR_INST (
-    .PUR (1'b0)
-  );
-
-  reg clkin;
-  wire sync;
-  wire sync2x;
-  wire dramsync;
-  wire init;
-
-  // Generate 100 Mhz clock
-  always 
-  begin
-    clkin = 1'b1; 
-    #5;
-    clkin = 1'b0;
-    #5;
-  end
-  
-  simcrgtop simcrgtop (
-    .clkin(clkin),
-    .sync(sync),
-    .sync2x(sync2x),
-    .dramsync(dramsync),
-    .init(init)
-  );
-
-  initial
-  begin
-    $dumpfile("simcrg.vcd");
-    $dumpvars(0, clkin);
-    $dumpvars(0, sync);
-    $dumpvars(0, sync2x);
-    $dumpvars(0, dramsync);
-    $dumpvars(0, init);
-    $dumpvars(0, simcrgtop);
-
-    #10000 $finish;
-  end
-endmodule