From 39178ce4602200e0ae776a86353093d45547fb74 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 2 Oct 2020 12:30:19 +0200 Subject: [PATCH] test: add minimal OSERDESE2/OSERDESE3 simulations to check Data/Tristate latencies. --- test/primitives/glbl.v | 70 ++++++++++++++++++ test/primitives/test_oserdese2.py | 113 ++++++++++++++++++++++++++++++ test/primitives/test_oserdese3.py | 112 +++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 test/primitives/glbl.v create mode 100644 test/primitives/test_oserdese2.py create mode 100644 test/primitives/test_oserdese3.py diff --git a/test/primitives/glbl.v b/test/primitives/glbl.v new file mode 100644 index 0000000..04e0341 --- /dev/null +++ b/test/primitives/glbl.v @@ -0,0 +1,70 @@ +`ifndef GLBL +`define GLBL +`timescale 1 ps / 1 ps + +module glbl (); + + parameter ROC_WIDTH = 100000; + parameter TOC_WIDTH = 0; + +//-------- STARTUP Globals -------------- + wire GSR; + wire GTS; + wire GWE; + wire PRLD; + tri1 p_up_tmp; + tri (weak1, strong0) PLL_LOCKG = p_up_tmp; + + wire PROGB_GLBL; + wire CCLKO_GLBL; + wire FCSBO_GLBL; + wire [3:0] DO_GLBL; + wire [3:0] DI_GLBL; + + reg GSR_int; + reg GTS_int; + reg PRLD_int; + +//-------- JTAG Globals -------------- + wire JTAG_TDO_GLBL; + wire JTAG_TCK_GLBL; + wire JTAG_TDI_GLBL; + wire JTAG_TMS_GLBL; + wire JTAG_TRST_GLBL; + + reg JTAG_CAPTURE_GLBL; + reg JTAG_RESET_GLBL; + reg JTAG_SHIFT_GLBL; + reg JTAG_UPDATE_GLBL; + reg JTAG_RUNTEST_GLBL; + + reg JTAG_SEL1_GLBL = 0; + reg JTAG_SEL2_GLBL = 0 ; + reg JTAG_SEL3_GLBL = 0; + reg JTAG_SEL4_GLBL = 0; + + reg JTAG_USER_TDO1_GLBL = 1'bz; + reg JTAG_USER_TDO2_GLBL = 1'bz; + reg JTAG_USER_TDO3_GLBL = 1'bz; + reg JTAG_USER_TDO4_GLBL = 1'bz; + + assign (weak1, weak0) GSR = GSR_int; + assign (weak1, weak0) GTS = GTS_int; + assign (weak1, weak0) PRLD = PRLD_int; + + initial begin + GSR_int = 1'b1; + PRLD_int = 1'b1; + #(ROC_WIDTH) + GSR_int = 1'b0; + PRLD_int = 1'b0; + end + + initial begin + GTS_int = 1'b1; + #(TOC_WIDTH) + GTS_int = 1'b0; + end + +endmodule +`endif diff --git a/test/primitives/test_oserdese2.py b/test/primitives/test_oserdese2.py new file mode 100644 index 0000000..d5546e7 --- /dev/null +++ b/test/primitives/test_oserdese2.py @@ -0,0 +1,113 @@ +# +# This file is part of LiteDRAM. +# +# Copyright (c) 2020 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import sys + +from migen import * + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform + +from litex.soc.integration.builder import * +from litex.soc.cores.clock import * + + +class Platform(XilinxPlatform): + def __init__(self): + XilinxPlatform.__init__(self, "", [("clk", 0, Pins("X"))]) + + +class OSERDESE2Sim(Module): + def __init__(self, platform): + + # Clocking + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain() + self.submodules.pll = pll = S7PLL(speedgrade=-1) + pll.register_clkin(platform.request("clk"), 100e6) + pll.create_clkout(self.cd_sys, 100e6) + pll.create_clkout(self.cd_sys4x, 400e6) + + # OSERDESE2 + i_d = Signal(8) + i_t1 = Signal() + o_tq = Signal() + o_oq = Signal() + self.specials += Instance("OSERDESE2", + p_SERDES_MODE = "MASTER", + p_DATA_WIDTH = 8, + p_TRISTATE_WIDTH = 1, + p_DATA_RATE_OQ = "DDR", + p_DATA_RATE_TQ = "BUF", + i_RST = ResetSignal(), + i_CLK = ClockSignal("sys4x"), + i_CLKDIV = ClockSignal(), + **{f"i_D{n+1}": i_d[n] for n in range(8)}, + i_TCE = 1, + i_T1 = ~i_t1, + o_TQ = o_tq, + i_OCE = 1, + o_OQ = o_oq, + ) + + # Stimulation + counter = Signal(16) + self.sync += [ + counter.eq(counter + 1), + If(counter == (16 - 1), + counter.eq(0) + ), + If(counter == 0, + i_d.eq(0xff), + i_t1.eq(0b0), + ).Else( + i_d.eq(0x00), + i_t1.eq(0b1), + ) + ] + +def generate_top(): + platform = Platform() + sim = OSERDESE2Sim(platform) + platform.build(sim, build_dir="./", run=False) + + +def generate_top_tb(): + f = open("top_tb.v", "w") + f.write(""" +`timescale 1ns/1ps + +module top_tb(); + +reg clk; +initial clk = 1'b1; +always #5 clk = ~clk; + +top dut ( + .clk(clk) +); + +endmodule""") + f.close() + +def run_sim(gui=False): + os.system("xvlog glbl.v") + os.system("xvlog top.v -sv") + os.system("xvlog top_tb.v -sv") + os.system("xelab -debug typical top_tb glbl -s top_tb_sim -L unisims_ver -L unimacro_ver -L SIMPRIM_VER -L secureip -L $xsimdir/xil_defaultlib -timescale 1ns/1ps") + if gui: + os.system("xsim top_tb_sim -gui") + else: + os.system("xsim top_tb_sim -runall") + +def main(): + generate_top() + generate_top_tb() + run_sim(gui="gui" in sys.argv[1:]) + + +if __name__ == "__main__": + main() diff --git a/test/primitives/test_oserdese3.py b/test/primitives/test_oserdese3.py new file mode 100644 index 0000000..880e400 --- /dev/null +++ b/test/primitives/test_oserdese3.py @@ -0,0 +1,112 @@ +# +# This file is part of LiteDRAM. +# +# Copyright (c) 2020 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import sys + +from migen import * + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform + +from litex.soc.integration.builder import * +from litex.soc.cores.clock import * + + +class Platform(XilinxPlatform): + def __init__(self): + XilinxPlatform.__init__(self, "", [("clk", 0, Pins("X"))]) + + +class OSERDESE3Sim(Module): + def __init__(self, platform): + + # Clocking + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain() + self.submodules.pll = pll = USPLL(speedgrade=-1) + pll.register_clkin(platform.request("clk"), 100e6) + pll.create_clkout(self.cd_sys, 100e6) + pll.create_clkout(self.cd_sys4x, 400e6) + + # OSERDESE3 + i_d = Signal(8) + i_t = Signal() + o_t_out = Signal() + o_oq = Signal() + self.specials += Instance("OSERDESE3", + p_SIM_DEVICE = "ULTRASCALE", + p_DATA_WIDTH = 8, + p_INIT = 0, + p_IS_RST_INVERTED = 0, + p_IS_CLK_INVERTED = 0, + p_IS_CLKDIV_INVERTED = 0, + i_RST = ResetSignal(), + i_CLK = ClockSignal("sys4x"), + i_CLKDIV = ClockSignal(), + i_T = ~i_t, + i_D = i_d, + o_OQ = o_oq, + o_T_OUT = o_t_out, + ), + + # Stimulation + counter = Signal(16) + self.sync += [ + counter.eq(counter + 1), + If(counter == (16 - 1), + counter.eq(0) + ), + If(counter == 0, + i_d.eq(0xff), + i_t.eq(0b0), + ).Else( + i_d.eq(0x00), + i_t.eq(0b1), + ) + ] + +def generate_top(): + platform = Platform() + sim = OSERDESE3Sim(platform) + platform.build(sim, build_dir="./", run=False) + + +def generate_top_tb(): + f = open("top_tb.v", "w") + f.write(""" +`timescale 1ns/1ps + +module top_tb(); + +reg clk; +initial clk = 1'b1; +always #5 clk = ~clk; + +top dut ( + .clk(clk) +); + +endmodule""") + f.close() + +def run_sim(gui=False): + os.system("xvlog glbl.v") + os.system("xvlog top.v -sv") + os.system("xvlog top_tb.v -sv") + os.system("xelab -debug typical top_tb glbl -s top_tb_sim -L unisims_ver -L unimacro_ver -L SIMPRIM_VER -L secureip -L $xsimdir/xil_defaultlib -timescale 1ns/1ps") + if gui: + os.system("xsim top_tb_sim -gui") + else: + os.system("xsim top_tb_sim -runall") + +def main(): + generate_top() + generate_top_tb() + run_sim(gui="gui" in sys.argv[1:]) + + +if __name__ == "__main__": + main()