diff --git a/rapidsilicon/ip/axi_async_fifo/v1_0/axi_async_fifo_gen.py b/rapidsilicon/ip/axi_async_fifo/v1_0/axi_async_fifo_gen.py index 4d0ae0b2..4897f930 100755 --- a/rapidsilicon/ip/axi_async_fifo/v1_0/axi_async_fifo_gen.py +++ b/rapidsilicon/ip/axi_async_fifo/v1_0/axi_async_fifo_gen.py @@ -132,14 +132,10 @@ def main(): "AXI ID width programmed": args.id_width, "Memory Type selected": "Single Dual Port", } - - - # Import JSON (Optional) ----------------------------------------------------------------------- if args.json: args = rs_builder.import_args_from_json(parser=parser, json_filename=args.json) - rs_builder.import_ip_details_json(build_dir=args.build_dir ,details=details , build_name = args.build_name, version = "v1_0") - + rs_builder.import_ip_details_json(build_dir=args.build_dir ,details=details , build_name = args.build_name, version = "v1_0") # Export JSON Template (Optional) -------------------------------------------------------------- if args.json_template: rs_builder.export_json_template(parser=parser, dep_dict=dep_dict) diff --git a/rapidsilicon/ip/boot_clock/v1_0/src/BOOT_CLOCK.v b/rapidsilicon/ip/boot_clock/v1_0/src/BOOT_CLOCK.v index de276cbe..1df1c975 100644 --- a/rapidsilicon/ip/boot_clock/v1_0/src/BOOT_CLOCK.v +++ b/rapidsilicon/ip/boot_clock/v1_0/src/BOOT_CLOCK.v @@ -7,7 +7,7 @@ // Copyright (c) 2023 Rapid Silicon, Inc. All rights reserved. // -module BOOT_CLOCK #( +module BOOT_CLOCK #( parameter PERIOD = 25.0 // Clock period for simulation purposes (nS) ) ( output reg O = 1'b0 // Clock output diff --git a/rapidsilicon/ip/pll/v1_0/litex_wrapper/pll_litex_wrapper.py b/rapidsilicon/ip/pll/v1_0/litex_wrapper/pll_litex_wrapper.py index c4984a63..c2d1eda9 100644 --- a/rapidsilicon/ip/pll/v1_0/litex_wrapper/pll_litex_wrapper.py +++ b/rapidsilicon/ip/pll/v1_0/litex_wrapper/pll_litex_wrapper.py @@ -22,6 +22,32 @@ logging.info(f'Log started at {timestamp}') # Helpers ------------------------------------------------------------------------------------------ + +def freq_calc(self, fast_clk_freq, ref_clk_freq, c_range, d_range): + self.product = Signal() + self.ready = Signal() + a = fast_clk_freq + b = ref_clk_freq + c_range = 1000 + d_range = 63 + # Nested loop for iterating over c and d + for c in range(c_range): + for d in range(d_range): + # Calculate 2 * (a / b) + product_candidate = 2 * (a/ b) + print("product_candidate",product_candidate) + print(f" values found - C: {c}, D: {d}") + # Check if the candidate product matches the formula with c and d + print("candidate match", ((c+1) / (d+1))) + if product_candidate == ((c+1) / (d+1)): + # If a match is found, assign c, d, and the product to the respective signals + print(f"Matching values found - C: {c}, D: {d}") + pll_mult = c + 1 + pll_div = d + 1 + return pll_mult, pll_div + #break + + class Open(Signal): pass def colorer(s, color="bright"): @@ -73,34 +99,110 @@ def __init__(self, platform, divided_clks, divide_clk_in_by_2, fast_clk_freq, re self.GEARBOX_FAST_CLK = Signal() self.LOCK = Signal() - if divided_clks == 3: + pll_mult, pll_div = freq_calc(self, fast_clk_freq, ref_clk_freq, c_range=63, d_range=1000) + print("pll_mult", pll_mult , "pll_div", pll_div) + + if divided_clks == 4: self.specials += Instance("PLL", - **kwargs, - - p_DIVIDED_CLKS = Instance.PreformattedParam(divided_clks), - P_DIVIDE_CLK_IN_BY_2 = Instance.PreformattedParam(divide_clk_in_by_2), - p_FAST_CLK_FREQ = Instance.PreformattedParam(fast_clk_freq), - p_REF_CLK_FREQ = Instance.PreformattedParam(ref_clk_freq), - p_CLK_OUT0_DIV = Instance.PreformattedParam(clk_out0_div), - p_CLK_OUT1_DIV = Instance.PreformattedParam(clk_out1_div), - p_CLK_OUT2_DIV = Instance.PreformattedParam(clk_out2_div), - p_CLK_OUT3_DIV = Instance.PreformattedParam(clk_out3_div), - - i_PLL_EN = 1, - i_CLK_IN = self.CLK_IN, - i_CLK_OUT0_EN = self.CLK_OUT0_EN, - i_CLK_OUT1_EN = 0, - i_CLK_OUT2_EN = 0, - i_CLK_OUT3_EN = 0, - o_CLK_OUT0 = self.CLK_OUT0, - o_CLK_OUT1 = self.CLK_OUT1, - o_CLK_OUT2 = self.CLK_OUT2, - o_CLK_OUT3 = self.CLK_OUT3, - o_GEARBOX_FAST_CLK = self.GEARBOX_FAST_CLK, - o_LOCK = self.LOCK - ) - - self.add_sources(platform) + **kwargs, + p_DIVIDE_CLK_IN_BY_2 = Instance.PreformattedParam(divide_clk_in_by_2), + p_PLL_MULT = Instance.PreformattedParam(pll_mult), + p_PLL_DIV = Instance.PreformattedParam(pll_div), + p_CLK_OUT0_DIV = Instance.PreformattedParam(clk_out0_div), + p_CLK_OUT1_DIV = Instance.PreformattedParam(clk_out1_div), + p_CLK_OUT2_DIV = Instance.PreformattedParam(clk_out2_div), + p_CLK_OUT3_DIV = Instance.PreformattedParam(clk_out3_div), + + i_PLL_EN = 1, + i_CLK_IN = self.CLK_IN, + i_CLK_OUT0_EN = 1, + i_CLK_OUT1_EN = 1, + i_CLK_OUT2_EN = 1, + i_CLK_OUT3_EN = 1, + o_CLK_OUT0 = self.CLK_OUT0, + o_CLK_OUT1 = self.CLK_OUT1, + o_CLK_OUT2 = self.CLK_OUT2, + o_CLK_OUT3 = self.CLK_OUT3, + o_GEARBOX_FAST_CLK = self.GEARBOX_FAST_CLK, + o_LOCK = self.LOCK + ) + elif divided_clks == 3: + self.specials += Instance("PLL", + **kwargs, + p_DIVIDE_CLK_IN_BY_2 = Instance.PreformattedParam(divide_clk_in_by_2), + p_PLL_MULT = Instance.PreformattedParam(pll_mult), + p_PLL_DIV = Instance.PreformattedParam(pll_div), + p_CLK_OUT0_DIV = Instance.PreformattedParam(clk_out0_div), + p_CLK_OUT1_DIV = Instance.PreformattedParam(clk_out1_div), + p_CLK_OUT2_DIV = Instance.PreformattedParam(clk_out2_div), + p_CLK_OUT3_DIV = Instance.PreformattedParam(clk_out3_div), + + i_PLL_EN = 1, + i_CLK_IN = self.CLK_IN, + i_CLK_OUT0_EN = 1, + i_CLK_OUT1_EN = 1, + i_CLK_OUT2_EN = 1, + i_CLK_OUT3_EN = 0, + o_CLK_OUT0 = self.CLK_OUT0, + o_CLK_OUT1 = self.CLK_OUT1, + o_CLK_OUT2 = self.CLK_OUT2, +# o_CLK_OUT3 = self.CLK_OUT3, + o_GEARBOX_FAST_CLK = self.GEARBOX_FAST_CLK, + o_LOCK = self.LOCK + ) + + elif divided_clks == 2: + self.specials += Instance("PLL", + **kwargs, + p_DIVIDE_CLK_IN_BY_2 = Instance.PreformattedParam(divide_clk_in_by_2), + p_PLL_MULT = Instance.PreformattedParam(pll_mult), + p_PLL_DIV = Instance.PreformattedParam(pll_div), + p_CLK_OUT0_DIV = Instance.PreformattedParam(clk_out0_div), + p_CLK_OUT1_DIV = Instance.PreformattedParam(clk_out1_div), + p_CLK_OUT2_DIV = Instance.PreformattedParam(clk_out2_div), + p_CLK_OUT3_DIV = Instance.PreformattedParam(clk_out3_div), + + i_PLL_EN = 1, + i_CLK_IN = self.CLK_IN, + i_CLK_OUT0_EN = 1, + i_CLK_OUT1_EN = 1, + i_CLK_OUT2_EN = 0, + i_CLK_OUT3_EN = 0, + o_CLK_OUT0 = self.CLK_OUT0, + o_CLK_OUT1 = self.CLK_OUT1, +# o_CLK_OUT2 = self.CLK_OUT2, +# o_CLK_OUT3 = self.CLK_OUT3, + o_GEARBOX_FAST_CLK = self.GEARBOX_FAST_CLK, + o_LOCK = self.LOCK + ) + + elif divided_clks == 1: + self.specials += Instance("PLL", + **kwargs, + p_DIVIDE_CLK_IN_BY_2 = Instance.PreformattedParam(divide_clk_in_by_2), + p_PLL_MULT = Instance.PreformattedParam(pll_mult), + p_PLL_DIV = Instance.PreformattedParam(pll_div), + p_CLK_OUT0_DIV = Instance.PreformattedParam(clk_out0_div), + p_CLK_OUT1_DIV = Instance.PreformattedParam(clk_out1_div), + p_CLK_OUT2_DIV = Instance.PreformattedParam(clk_out2_div), + p_CLK_OUT3_DIV = Instance.PreformattedParam(clk_out3_div), + + i_PLL_EN = 1, + i_CLK_IN = self.CLK_IN, + i_CLK_OUT0_EN = 1, + i_CLK_OUT1_EN = 0, + i_CLK_OUT2_EN = 0, + i_CLK_OUT3_EN = 0, + o_CLK_OUT0 = self.CLK_OUT0, +# o_CLK_OUT1 = self.CLK_OUT1, +# o_CLK_OUT2 = self.CLK_OUT2, +# o_CLK_OUT3 = self.CLK_OUT3, + o_GEARBOX_FAST_CLK = self.GEARBOX_FAST_CLK, + o_LOCK = self.LOCK + ) + + + self.add_sources(platform) @staticmethod def add_sources(platform): diff --git a/rapidsilicon/ip/pll/v1_0/pll_gen.py b/rapidsilicon/ip/pll/v1_0/pll_gen.py index aa1b99b3..a97b1dbe 100755 --- a/rapidsilicon/ip/pll/v1_0/pll_gen.py +++ b/rapidsilicon/ip/pll/v1_0/pll_gen.py @@ -39,15 +39,16 @@ def get_clkin_ios(): # AXI RAM Wrapper ---------------------------------------------------------------------------------- class PLLWrapper(Module): - def __init__(self, platform, divide_clk_in_by_2, pll_mult, pll_div, clk_out0_div, clk_out1_div, clk_out2_div, clk_out3_div): + def __init__(self, platform, divided_clks, divide_clk_in_by_2, fast_clk_freq, ref_clk_freq, clk_out0_div, clk_out1_div, clk_out2_div, clk_out3_div): self.clock_domains.cd_sys = ClockDomain() # AXI-RAM ---------------------------------------------------------------------------------- self.submodules.pll = pll = PLL(platform, + divided_clks = divided_clks, divide_clk_in_by_2 = divide_clk_in_by_2, - pll_mult = pll_mult, - pll_div = pll_div, + fast_clk_freq = fast_clk_freq, + ref_clk_freq = ref_clk_freq, clk_out0_div = clk_out0_div, clk_out1_div = clk_out1_div, clk_out2_div = clk_out2_div, @@ -94,6 +95,7 @@ def main(): # Core fix value parameters. core_fix_param_group = parser.add_argument_group(title="Core fix parameters") + core_fix_param_group.add_argument("--divided_clks", type=int, default=4, choices=[1,2,3,4], help="Divided clocks to be generated from fast clock") core_fix_param_group.add_argument("--clk_out0_div", type=int, default=2, choices=[2,3,4,5,6,7,8,10,12,16,20.24,32,40,48,64], help="CLK_OUT0 divider value") core_fix_param_group.add_argument("--clk_out1_div", type=int, default=2, choices=[2,3,4,5,6,7,8,10,12,16,20.24,32,40,48,64], help="CLK_OUT1 divider value") core_fix_param_group.add_argument("--clk_out2_div", type=int, default=2, choices=[2,3,4,5,6,7,8,10,12,16,20.24,32,40,48,64], help="CLK_OUT2 divider value") @@ -101,22 +103,19 @@ def main(): # Core range value parameters. core_range_param_group = parser.add_argument_group(title="Core range parameters") - core_range_param_group.add_argument("--pll_mult", type=int, default=16, choices=range(16,1000), help="RAM Address Width") - core_range_param_group.add_argument("--pll_div", type=int, default=1, choices=range(1, 63), help="RAM ID Width") + core_range_param_group.add_argument("--fast_clk_freq", type=int, default=1600, choices=range(800,3201), help="Freq in MHz") + core_range_param_group.add_argument("--ref_clk_freq", type=int, default=5, choices=range(5, 1201), help="Freq in MHz") # Core bool value parameters. core_bool_param_group = parser.add_argument_group(title="Core bool parameters") - core_bool_param_group.add_argument("--divide_clk_in_by_2", type=bool, default=False, help="RAM Pipelined Output") + core_bool_param_group.add_argument("--divide_clk_in_by_2", type=bool, default=False, help="Divide input clock by 2") - # Core file path parameters. - # core_file_path_group = parser.add_argument_group(title="Core file path parameters") - # core_file_path_group.add_argument("--file_path", type=argparse.FileType('r'), help="File Path for memory initialization file") # Build Parameters. build_group = parser.add_argument_group(title="Build parameters") build_group.add_argument("--build", action="store_true", help="Build Core") build_group.add_argument("--build-dir", default="./", help="Build Directory") - build_group.add_argument("--build-name", default="pll_wrapper", help="Build Folder Name, Build RTL File Name and Module Name") + build_group.add_argument("--build-name", default="pll_wrapper", help="Build Folder Name, Build RTL File Name and Module Name") # JSON Import/Template json_group = parser.add_argument_group(title="JSON Parameters") @@ -125,20 +124,49 @@ def main(): args = parser.parse_args() + if (args.divided_clks == 1): + option_strings_to_remove = ['--clk_out1_div', '--clk_out2_div' , '--clk_out3_div'] + parser._actions = [action for action in parser._actions if action.option_strings and action.option_strings[0] not in option_strings_to_remove] + +# parser._actions = [action for argument_name in option_strings_to_remove: +# for action in parser._actions: +# if action.option_strings and argument_name in action.option_strings: +# parser._remove_action(action)] + elif(args.divided_clks == 2): + option_strings_to_remove = ['--clk_out2_div' , '--clk_out3_div'] + parser._actions = [action for action in parser._actions if action.option_strings and action.option_strings[0] not in option_strings_to_remove] + elif(args.divided_clks == 3): + option_strings_to_remove = ['--clk_out3_div'] + parser._actions = [action for action in parser._actions if action.option_strings and action.option_strings[0] not in option_strings_to_remove] + + details = {"IP details": { + 'Name' : 'PLL', + 'Version' : 'V1_0', + 'Interface' : 'Native', + 'Description' : "PLL IP core is a key component in chip design, used to generate stable clock signals from an input reference clock. Its essential for precise synchronization and clock management in modern integrated circuits, ensuring reliable performance across various applications."}} + + summary = { + "Number of divided clocks ": args.divided_clks, + "Fast clock frequency selected": args.fast_clk_freq, + "Input reference clock frequency": args.ref_clk_freq, + } # Import JSON (Optional) ----------------------------------------------------------------------- if args.json: args = rs_builder.import_args_from_json(parser=parser, json_filename=args.json) + rs_builder.import_ip_details_json(build_dir=args.build_dir ,details=details , build_name = args.build_name, version = "v1_0") # Export JSON Template (Optional) -------------------------------------------------------------- if args.json_template: - rs_builder.export_json_template(parser=parser, dep_dict=dep_dict) + rs_builder.export_json_template(parser=parser, dep_dict=dep_dict , summary=summary) + # Create Wrapper ------------------------------------------------------------------------------- platform = OSFPGAPlatform(io=[], toolchain="raptor", device="gemini") module = PLLWrapper(platform, divide_clk_in_by_2=args.divide_clk_in_by_2, - pll_mult=args.pll_mult, - pll_div=args.pll_div, + divided_clks=args.divided_clks, + fast_clk_freq=args.fast_clk_freq, + ref_clk_freq=args.ref_clk_freq, clk_out0_div=args.clk_out0_div, clk_out1_div=args.clk_out1_div, clk_out2_div=args.clk_out2_div, diff --git a/rapidsilicon/ip/pll/v1_0/src/PLL.v b/rapidsilicon/ip/pll/v1_0/src/PLL.v index 27ec23ed..36e2d6e7 100644 --- a/rapidsilicon/ip/pll/v1_0/src/PLL.v +++ b/rapidsilicon/ip/pll/v1_0/src/PLL.v @@ -81,7 +81,7 @@ module PLL #( parameter DIVIDE_CLK_IN_BY_2 = "FALSE", // Enable input divider (TRUE/FALSE) parameter PLL_MULT = 16, // Clock multiplier value (16-1000) parameter PLL_DIV = 1, // Clock divider value (1-63) - parameter CLK_OUT0_DIV = 2, // CLK_OUT0 divider value (2,3,4,5,6,7,8,10,12,16,20.24.32.40,48,64) + parameter CLK_OUT0_DIV = 2, // CLK_OUT0 divider value (2,3,4,5,6,7,8,10,12,16,20.24.32.40,48,64) parameter CLK_OUT1_DIV = 2, // CLK_OUT1 divider value (2,3,4,5,6,7,8,10,12,16,20.24.32.40,48,64) parameter CLK_OUT2_DIV = 2, // CLK_OUT2 divider value (2,3,4,5,6,7,8,10,12,16,20.24.32.40,48,64) parameter CLK_OUT3_DIV = 2 // CLK_OUT3 divider value (2,3,4,5,6,7,8,10,12,16,20.24.32.40,48,64)