From feb3ea43e8aea8798cbccdf0955e07d64acf924a Mon Sep 17 00:00:00 2001 From: Jean THOMAS Date: Fri, 3 Jul 2020 14:25:45 +0200 Subject: [PATCH] Rework CRG simulation --- gram/simulation/runsimcrg.sh | 12 ++- gram/simulation/simcrg.py | 162 ++++++----------------------------- gram/simulation/simcrg.ys | 17 ++++ gram/simulation/simcrgtb.sv | 47 ++++++++++ gram/simulation/simcrgtb.v | 49 ----------- 5 files changed, 97 insertions(+), 190 deletions(-) create mode 100644 gram/simulation/simcrg.ys create mode 100644 gram/simulation/simcrgtb.sv delete mode 100644 gram/simulation/simcrgtb.v diff --git a/gram/simulation/runsimcrg.sh b/gram/simulation/runsimcrg.sh index d34f3de..d2eb2db 100755 --- a/gram/simulation/runsimcrg.sh +++ b/gram/simulation/runsimcrg.sh @@ -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 diff --git a/gram/simulation/simcrg.py b/gram/simulation/simcrg.py index dd07615..94382b5 100644 --- a/gram/simulation/simcrg.py +++ b/gram/simulation/simcrg.py @@ -1,156 +1,42 @@ # This file is Copyright (c) 2020 LambdaConcept 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 index 0000000..3dea68c --- /dev/null +++ b/gram/simulation/simcrg.ys @@ -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 index 0000000..d753a84 --- /dev/null +++ b/gram/simulation/simcrgtb.sv @@ -0,0 +1,47 @@ +// This file is Copyright (c) 2020 LambdaConcept + +`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 index 6814343..0000000 --- a/gram/simulation/simcrgtb.v +++ /dev/null @@ -1,49 +0,0 @@ -// This file is Copyright (c) 2020 LambdaConcept - -`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 -- 2.30.2