| // Copyright (C) 2020-2021 The SymbiFlow Authors. | |
| // | |
| // Use of this source code is governed by a ISC-style | |
| // license that can be found in the LICENSE file or at | |
| // https://opensource.org/licenses/ISC | |
| // | |
| // SPDX-License-Identifier:ISC | |
| // ============================================================================ | |
| // CMT | |
| `define PLL_FRAC_PRECISION 10 | |
| `define PLL_FIXED_WIDTH 32 | |
| // Rounds a fixed point number to a given precision | |
| function [`PLL_FIXED_WIDTH:1] pll_round_frac(input [`PLL_FIXED_WIDTH:1] decimal, | |
| input [`PLL_FIXED_WIDTH:1] precision); | |
| if (decimal[(`PLL_FRAC_PRECISION-precision)] == 1'b1) begin | |
| pll_round_frac = decimal + (1'b1 << (`PLL_FRAC_PRECISION - precision)); | |
| end else begin | |
| pll_round_frac = decimal; | |
| end | |
| endfunction | |
| // Computes content of the PLLs divider registers | |
| function [13:0] pll_divider_regs(input [7:0] divide, // Max divide is 128 | |
| input [31:0] duty_cycle // Duty cycle is multiplied by 100,000 | |
| ); | |
| reg [`PLL_FIXED_WIDTH:1] duty_cycle_fix; | |
| reg [`PLL_FIXED_WIDTH:1] duty_cycle_min; | |
| reg [`PLL_FIXED_WIDTH:1] duty_cycle_max; | |
| reg [ 6:0] high_time; | |
| reg [ 6:0] low_time; | |
| reg w_edge; | |
| reg no_count; | |
| reg [`PLL_FIXED_WIDTH:1] temp; | |
| if (divide >= 64) begin | |
| duty_cycle_min = ((divide - 64) * 100_000) / divide; | |
| duty_cycle_max = (645 / divide) * 100_00; | |
| if (duty_cycle > duty_cycle_max) duty_cycle = duty_cycle_max; | |
| if (duty_cycle < duty_cycle_min) duty_cycle = duty_cycle_min; | |
| end | |
| duty_cycle_fix = (duty_cycle << `PLL_FRAC_PRECISION) / 100_000; | |
| if (divide == 7'h01) begin | |
| high_time = 7'h01; | |
| w_edge = 1'b0; | |
| low_time = 7'h01; | |
| no_count = 1'b1; | |
| end else begin | |
| temp = pll_round_frac(duty_cycle_fix*divide, 1); | |
| high_time = temp[`PLL_FRAC_PRECISION+7:`PLL_FRAC_PRECISION+1]; | |
| w_edge = temp[`PLL_FRAC_PRECISION]; | |
| if (high_time == 7'h00) begin | |
| high_time = 7'h01; | |
| w_edge = 1'b0; | |
| end | |
| if (high_time == divide) begin | |
| high_time = divide - 1; | |
| w_edge = 1'b1; | |
| end | |
| low_time = divide - high_time; | |
| no_count = 1'b0; | |
| end | |
| pll_divider_regs = {w_edge, no_count, high_time[5:0], low_time[5:0]}; | |
| endfunction | |
| // Computes the PLLs phase shift registers | |
| function [10:0] pll_phase_regs(input [7:0] divide, input signed [31:0] phase); | |
| reg [`PLL_FIXED_WIDTH:1] phase_in_cycles; | |
| reg [`PLL_FIXED_WIDTH:1] phase_fixed; | |
| reg [1:0] mx; | |
| reg [5:0] delay_time; | |
| reg [2:0] phase_mux; | |
| reg [`PLL_FIXED_WIDTH:1] temp; | |
| if (phase < 0) begin | |
| phase_fixed = ((phase + 360000) << `PLL_FRAC_PRECISION) / 1000; | |
| end else begin | |
| phase_fixed = (phase << `PLL_FRAC_PRECISION) / 1000; | |
| end | |
| phase_in_cycles = (phase_fixed * divide) / 360; | |
| temp = pll_round_frac(phase_in_cycles, 3); | |
| mx = 2'b00; | |
| phase_mux = temp[`PLL_FRAC_PRECISION:`PLL_FRAC_PRECISION-2]; | |
| delay_time = temp[`PLL_FRAC_PRECISION+6:`PLL_FRAC_PRECISION+1]; | |
| pll_phase_regs = {mx, phase_mux, delay_time}; | |
| endfunction | |
| // Given PLL/MMCM divide, duty_cycle and phase calculates content of the | |
| // CLKREG1 and CLKREG2. | |
| function [37:0] pll_clkregs(input [7:0] divide, // Max divide is 128 | |
| input [31:0] duty_cycle, // Multiplied by 100,000 | |
| input signed [31:0] phase // Phase is given in degrees (-360,000 to 360,000) | |
| ); | |
| reg [13:0] pll_div; // EDGE, NO_COUNT, HIGH_TIME[5:0], LOW_TIME[5:0] | |
| reg [10:0] pll_phase; // MX, PHASE_MUX[2:0], DELAY_TIME[5:0] | |
| pll_div = pll_divider_regs(divide, duty_cycle); | |
| pll_phase = pll_phase_regs(divide, phase); | |
| pll_clkregs = { | |
| // CLKREG2: RESERVED[6:0], MX[1:0], EDGE, NO_COUNT, DELAY_TIME[5:0] | |
| 6'h00, | |
| pll_phase[10:9], | |
| pll_div[13:12], | |
| pll_phase[5:0], | |
| // CLKREG1: PHASE_MUX[3:0], RESERVED, HIGH_TIME[5:0], LOW_TIME[5:0] | |
| pll_phase[8:6], | |
| 1'b0, | |
| pll_div[11:0] | |
| }; | |
| endfunction | |
| // This function takes the divide value and outputs the necessary lock values | |
| function [39:0] pll_lktable_lookup(input [6:0] divide // Max divide is 64 | |
| ); | |
| reg [2559:0] lookup; | |
| lookup = { | |
| // This table is composed of: | |
| // LockRefDly_LockFBDly_LockCnt_LockSatHigh_UnlockCnt | |
| 40'b00110_00110_1111101000_1111101001_0000000001, | |
| 40'b00110_00110_1111101000_1111101001_0000000001, | |
| 40'b01000_01000_1111101000_1111101001_0000000001, | |
| 40'b01011_01011_1111101000_1111101001_0000000001, | |
| 40'b01110_01110_1111101000_1111101001_0000000001, | |
| 40'b10001_10001_1111101000_1111101001_0000000001, | |
| 40'b10011_10011_1111101000_1111101001_0000000001, | |
| 40'b10110_10110_1111101000_1111101001_0000000001, | |
| 40'b11001_11001_1111101000_1111101001_0000000001, | |
| 40'b11100_11100_1111101000_1111101001_0000000001, | |
| 40'b11111_11111_1110000100_1111101001_0000000001, | |
| 40'b11111_11111_1100111001_1111101001_0000000001, | |
| 40'b11111_11111_1011101110_1111101001_0000000001, | |
| 40'b11111_11111_1010111100_1111101001_0000000001, | |
| 40'b11111_11111_1010001010_1111101001_0000000001, | |
| 40'b11111_11111_1001110001_1111101001_0000000001, | |
| 40'b11111_11111_1000111111_1111101001_0000000001, | |
| 40'b11111_11111_1000100110_1111101001_0000000001, | |
| 40'b11111_11111_1000001101_1111101001_0000000001, | |
| 40'b11111_11111_0111110100_1111101001_0000000001, | |
| 40'b11111_11111_0111011011_1111101001_0000000001, | |
| 40'b11111_11111_0111000010_1111101001_0000000001, | |
| 40'b11111_11111_0110101001_1111101001_0000000001, | |
| 40'b11111_11111_0110010000_1111101001_0000000001, | |
| 40'b11111_11111_0110010000_1111101001_0000000001, | |
| 40'b11111_11111_0101110111_1111101001_0000000001, | |
| 40'b11111_11111_0101011110_1111101001_0000000001, | |
| 40'b11111_11111_0101011110_1111101001_0000000001, | |
| 40'b11111_11111_0101000101_1111101001_0000000001, | |
| 40'b11111_11111_0101000101_1111101001_0000000001, | |
| 40'b11111_11111_0100101100_1111101001_0000000001, | |
| 40'b11111_11111_0100101100_1111101001_0000000001, | |
| 40'b11111_11111_0100101100_1111101001_0000000001, | |
| 40'b11111_11111_0100010011_1111101001_0000000001, | |
| 40'b11111_11111_0100010011_1111101001_0000000001, | |
| 40'b11111_11111_0100010011_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001, | |
| 40'b11111_11111_0011111010_1111101001_0000000001 | |
| }; | |
| pll_lktable_lookup = lookup[((64-divide)*40)+:40]; | |
| endfunction | |
| // This function takes the divide value and the bandwidth setting of the PLL | |
| // and outputs the digital filter settings necessary. | |
| function [9:0] pll_table_lookup(input [6:0] divide, // Max divide is 64 | |
| input [8*9:0] BANDWIDTH); | |
| reg [639:0] lookup_low; | |
| reg [639:0] lookup_high; | |
| reg [639:0] lookup_optimized; | |
| reg [ 9:0] lookup_entry; | |
| lookup_low = { | |
| // CP_RES_LFHF | |
| 10'b0010_1111_00, | |
| 10'b0010_1111_00, | |
| 10'b0010_0111_00, | |
| 10'b0010_1101_00, | |
| 10'b0010_0101_00, | |
| 10'b0010_0101_00, | |
| 10'b0010_1001_00, | |
| 10'b0010_1110_00, | |
| 10'b0010_1110_00, | |
| 10'b0010_0001_00, | |
| 10'b0010_0001_00, | |
| 10'b0010_0110_00, | |
| 10'b0010_0110_00, | |
| 10'b0010_0110_00, | |
| 10'b0010_0110_00, | |
| 10'b0010_1010_00, | |
| 10'b0010_1010_00, | |
| 10'b0010_1010_00, | |
| 10'b0010_1010_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_1100_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0010_0010_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0011_1100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00 | |
| }; | |
| lookup_high = { | |
| // CP_RES_LFHF | |
| 10'b0011_0111_00, | |
| 10'b0011_0111_00, | |
| 10'b0101_1111_00, | |
| 10'b0111_1111_00, | |
| 10'b0111_1011_00, | |
| 10'b1101_0111_00, | |
| 10'b1110_1011_00, | |
| 10'b1110_1101_00, | |
| 10'b1111_1101_00, | |
| 10'b1111_0111_00, | |
| 10'b1111_1011_00, | |
| 10'b1111_1101_00, | |
| 10'b1111_0011_00, | |
| 10'b1110_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0101_1100_00, | |
| 10'b0101_1100_00, | |
| 10'b0101_1100_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b0100_0010_00, | |
| 10'b0100_0010_00, | |
| 10'b0100_0010_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0011_0100_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00 | |
| }; | |
| lookup_optimized = { | |
| // CP_RES_LFHF | |
| 10'b0011_0111_00, | |
| 10'b0011_0111_00, | |
| 10'b0101_1111_00, | |
| 10'b0111_1111_00, | |
| 10'b0111_1011_00, | |
| 10'b1101_0111_00, | |
| 10'b1110_1011_00, | |
| 10'b1110_1101_00, | |
| 10'b1111_1101_00, | |
| 10'b1111_0111_00, | |
| 10'b1111_1011_00, | |
| 10'b1111_1101_00, | |
| 10'b1111_0011_00, | |
| 10'b1110_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b1111_0101_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0111_0110_00, | |
| 10'b0101_1100_00, | |
| 10'b0101_1100_00, | |
| 10'b0101_1100_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b1100_0001_00, | |
| 10'b0100_0010_00, | |
| 10'b0100_0010_00, | |
| 10'b0100_0010_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0011_0100_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0010_1000_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0100_1100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00, | |
| 10'b0010_0100_00 | |
| }; | |
| if (BANDWIDTH == "LOW") begin | |
| pll_table_lookup = lookup_low[((64-divide)*10)+:10]; | |
| end else if (BANDWIDTH == "HIGH") begin | |
| pll_table_lookup = lookup_high[((64-divide)*10)+:10]; | |
| end else if (BANDWIDTH == "OPTIMIZED") begin | |
| pll_table_lookup = lookup_optimized[((64-divide)*10)+:10]; | |
| end | |
| endfunction | |
| // ............................................................................ | |
| // IMPORTANT NOTE: Due to lack of support for real type parameters in Yosys | |
| // the PLL parameters that define duty cycles and phase shifts have to be | |
| // provided as integers! The DUTY_CYCLE is expressed as % of high time times | |
| // 1000 whereas the PHASE is expressed in degrees times 1000. | |
| // PLLE2_ADV | |
| module PLLE2_ADV ( | |
| input CLKFBIN, | |
| input CLKIN1, | |
| input CLKIN2, | |
| input CLKINSEL, | |
| output CLKFBOUT, | |
| output CLKOUT0, | |
| output CLKOUT1, | |
| output CLKOUT2, | |
| output CLKOUT3, | |
| output CLKOUT4, | |
| output CLKOUT5, | |
| input PWRDWN, | |
| input RST, | |
| output LOCKED, | |
| input DCLK, | |
| input DEN, | |
| input DWE, | |
| output DRDY, | |
| input [ 6:0] DADDR, | |
| input [15:0] DI, | |
| output [15:0] DO | |
| ); | |
| parameter _TECHMAP_CONSTMSK_CLKINSEL_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKINSEL_ = 0; | |
| parameter _TECHMAP_CONSTMSK_RST_ = 0; | |
| parameter _TECHMAP_CONSTVAL_RST_ = 0; | |
| parameter _TECHMAP_CONSTMSK_PWRDWN_ = 0; | |
| parameter _TECHMAP_CONSTVAL_PWRDWN_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKFBOUT_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKFBOUT_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT0_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT0_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT1_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT1_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT2_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT2_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT3_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT3_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT4_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT4_ = 0; | |
| parameter _TECHMAP_CONSTMSK_CLKOUT5_ = 0; | |
| parameter _TECHMAP_CONSTVAL_CLKOUT5_ = 0; | |
| parameter _TECHMAP_CONSTMSK_DCLK_ = 0; | |
| parameter _TECHMAP_CONSTVAL_DCLK_ = 0; | |
| parameter _TECHMAP_CONSTMSK_DEN_ = 0; | |
| parameter _TECHMAP_CONSTVAL_DEN_ = 0; | |
| parameter _TECHMAP_CONSTMSK_DWE_ = 0; | |
| parameter _TECHMAP_CONSTVAL_DWE_ = 0; | |
| parameter IS_CLKINSEL_INVERTED = 1'b0; | |
| parameter IS_RST_INVERTED = 1'b0; | |
| parameter IS_PWRDWN_INVERTED = 1'b0; | |
| parameter BANDWIDTH = "OPTIMIZED"; | |
| parameter STARTUP_WAIT = "FALSE"; | |
| parameter COMPENSATION = "ZHOLD"; | |
| parameter CLKIN1_PERIOD = 0.0; | |
| parameter REF_JITTER1 = 0.01; | |
| parameter CLKIN2_PERIOD = 0.0; | |
| parameter REF_JITTER2 = 0.01; | |
| parameter [5:0] DIVCLK_DIVIDE = 1; | |
| parameter [5:0] CLKFBOUT_MULT = 1; | |
| parameter CLKFBOUT_PHASE = 0; | |
| parameter [6:0] CLKOUT0_DIVIDE = 1; | |
| parameter CLKOUT0_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT0_PHASE = 0; | |
| parameter [6:0] CLKOUT1_DIVIDE = 1; | |
| parameter CLKOUT1_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT1_PHASE = 0; | |
| parameter [6:0] CLKOUT2_DIVIDE = 1; | |
| parameter CLKOUT2_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT2_PHASE = 0; | |
| parameter [6:0] CLKOUT3_DIVIDE = 1; | |
| parameter CLKOUT3_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT3_PHASE = 0; | |
| parameter [6:0] CLKOUT4_DIVIDE = 1; | |
| parameter CLKOUT4_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT4_PHASE = 0; | |
| parameter [6:0] CLKOUT5_DIVIDE = 1; | |
| parameter CLKOUT5_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT5_PHASE = 0; | |
| // Compute PLL's registers content | |
| localparam CLKFBOUT_REGS = pll_clkregs(CLKFBOUT_MULT, 50000, CLKFBOUT_PHASE); | |
| localparam DIVCLK_REGS = pll_clkregs(DIVCLK_DIVIDE, 50000, 0); | |
| localparam CLKOUT0_REGS = pll_clkregs(CLKOUT0_DIVIDE, CLKOUT0_DUTY_CYCLE, CLKOUT0_PHASE); | |
| localparam CLKOUT1_REGS = pll_clkregs(CLKOUT1_DIVIDE, CLKOUT1_DUTY_CYCLE, CLKOUT1_PHASE); | |
| localparam CLKOUT2_REGS = pll_clkregs(CLKOUT2_DIVIDE, CLKOUT2_DUTY_CYCLE, CLKOUT2_PHASE); | |
| localparam CLKOUT3_REGS = pll_clkregs(CLKOUT3_DIVIDE, CLKOUT3_DUTY_CYCLE, CLKOUT3_PHASE); | |
| localparam CLKOUT4_REGS = pll_clkregs(CLKOUT4_DIVIDE, CLKOUT4_DUTY_CYCLE, CLKOUT4_PHASE); | |
| localparam CLKOUT5_REGS = pll_clkregs(CLKOUT5_DIVIDE, CLKOUT5_DUTY_CYCLE, CLKOUT5_PHASE); | |
| // Handle inputs that should have certain logic levels when left unconnected | |
| localparam INV_CLKINSEL = (_TECHMAP_CONSTMSK_CLKINSEL_ == 1) ? !_TECHMAP_CONSTVAL_CLKINSEL_ : | |
| (_TECHMAP_CONSTVAL_CLKINSEL_ == 0) ? IS_CLKINSEL_INVERTED : | |
| IS_CLKINSEL_INVERTED; | |
| generate | |
| if (_TECHMAP_CONSTMSK_CLKINSEL_ == 1) begin | |
| wire clkinsel = 1'b1; | |
| end else if (_TECHMAP_CONSTVAL_CLKINSEL_ == 0) begin | |
| wire clkinsel = 1'b1; | |
| end else begin | |
| wire clkinsel = CLKINSEL; | |
| end | |
| endgenerate | |
| localparam INV_PWRDWN = (_TECHMAP_CONSTMSK_PWRDWN_ == 1) ? !_TECHMAP_CONSTVAL_PWRDWN_ : | |
| (_TECHMAP_CONSTVAL_PWRDWN_ == 0) ? ~IS_PWRDWN_INVERTED : | |
| IS_PWRDWN_INVERTED; | |
| generate | |
| if (_TECHMAP_CONSTMSK_PWRDWN_ == 1) begin | |
| wire pwrdwn = 1'b1; | |
| end else if (_TECHMAP_CONSTVAL_PWRDWN_ == 0) begin | |
| wire pwrdwn = 1'b1; | |
| end else begin | |
| wire pwrdwn = PWRDWN; | |
| end | |
| endgenerate | |
| localparam INV_RST = (_TECHMAP_CONSTMSK_RST_ == 1) ? !_TECHMAP_CONSTVAL_PWRDWN_ : | |
| (_TECHMAP_CONSTVAL_RST_ == 0) ? ~IS_RST_INVERTED : IS_RST_INVERTED; | |
| generate | |
| if (_TECHMAP_CONSTMSK_RST_ == 1) begin | |
| wire rst = 1'b1; | |
| end else if (_TECHMAP_CONSTVAL_RST_ == 0) begin | |
| wire rst = 1'b1; | |
| end else begin | |
| wire rst = RST; | |
| end | |
| endgenerate | |
| generate | |
| if (_TECHMAP_CONSTMSK_DCLK_ == 1) wire dclk = _TECHMAP_CONSTVAL_DCLK_; | |
| else if (_TECHMAP_CONSTVAL_DCLK_ == 0) wire dclk = 1'b0; | |
| else wire dclk = DCLK; | |
| endgenerate | |
| generate | |
| if (_TECHMAP_CONSTMSK_DEN_ == 1) wire den = _TECHMAP_CONSTVAL_DEN_; | |
| else if (_TECHMAP_CONSTVAL_DEN_ == 0) wire den = 1'b0; | |
| else wire den = DEN; | |
| endgenerate | |
| generate | |
| if (_TECHMAP_CONSTMSK_DWE_ == 1) wire dwe = _TECHMAP_CONSTVAL_DWE_; | |
| else if (_TECHMAP_CONSTVAL_DWE_ == 0) wire dwe = 1'b0; | |
| else wire dwe = DWE; | |
| endgenerate | |
| // The substituted cell | |
| PLLE2_ADV_VPR #( | |
| // Inverters | |
| .INV_CLKINSEL(INV_CLKINSEL), | |
| .ZINV_PWRDWN (INV_PWRDWN), | |
| .ZINV_RST (INV_RST), | |
| // Straight mapped parameters | |
| .STARTUP_WAIT(STARTUP_WAIT == "TRUE"), | |
| // Lookup tables | |
| .LKTABLE(pll_lktable_lookup(CLKFBOUT_MULT)), | |
| .TABLE (pll_table_lookup(CLKFBOUT_MULT, BANDWIDTH)), | |
| // FIXME: How to compute values the two below ? | |
| .FILTREG1_RESERVED(12'b0000_00001000), | |
| .LOCKREG3_RESERVED(1'b1), | |
| // Clock feedback settings | |
| .CLKFBOUT_CLKOUT1_HIGH_TIME (CLKFBOUT_REGS[11:6]), | |
| .CLKFBOUT_CLKOUT1_LOW_TIME (CLKFBOUT_REGS[5:0]), | |
| .CLKFBOUT_CLKOUT1_PHASE_MUX (CLKFBOUT_REGS[15:13]), | |
| .CLKFBOUT_CLKOUT2_DELAY_TIME(CLKFBOUT_REGS[21:16]), | |
| .CLKFBOUT_CLKOUT2_EDGE (CLKFBOUT_REGS[23]), | |
| .CLKFBOUT_CLKOUT2_NO_COUNT (CLKFBOUT_REGS[22]), | |
| // Internal VCO divider settings | |
| .DIVCLK_DIVCLK_HIGH_TIME(DIVCLK_REGS[11:6]), | |
| .DIVCLK_DIVCLK_LOW_TIME (DIVCLK_REGS[5:0]), | |
| .DIVCLK_DIVCLK_NO_COUNT (DIVCLK_REGS[22]), | |
| .DIVCLK_DIVCLK_EDGE (DIVCLK_REGS[23]), | |
| // CLKOUT0 | |
| .CLKOUT0_CLKOUT1_HIGH_TIME (CLKOUT0_REGS[11:6]), | |
| .CLKOUT0_CLKOUT1_LOW_TIME (CLKOUT0_REGS[5:0]), | |
| .CLKOUT0_CLKOUT1_PHASE_MUX (CLKOUT0_REGS[15:13]), | |
| .CLKOUT0_CLKOUT2_DELAY_TIME(CLKOUT0_REGS[21:16]), | |
| .CLKOUT0_CLKOUT2_EDGE (CLKOUT0_REGS[23]), | |
| .CLKOUT0_CLKOUT2_NO_COUNT (CLKOUT0_REGS[22]), | |
| // CLKOUT1 | |
| .CLKOUT1_CLKOUT1_HIGH_TIME (CLKOUT1_REGS[11:6]), | |
| .CLKOUT1_CLKOUT1_LOW_TIME (CLKOUT1_REGS[5:0]), | |
| .CLKOUT1_CLKOUT1_PHASE_MUX (CLKOUT1_REGS[15:13]), | |
| .CLKOUT1_CLKOUT2_DELAY_TIME(CLKOUT1_REGS[21:16]), | |
| .CLKOUT1_CLKOUT2_EDGE (CLKOUT1_REGS[23]), | |
| .CLKOUT1_CLKOUT2_NO_COUNT (CLKOUT1_REGS[22]), | |
| // CLKOUT2 | |
| .CLKOUT2_CLKOUT1_HIGH_TIME (CLKOUT2_REGS[11:6]), | |
| .CLKOUT2_CLKOUT1_LOW_TIME (CLKOUT2_REGS[5:0]), | |
| .CLKOUT2_CLKOUT1_PHASE_MUX (CLKOUT2_REGS[15:13]), | |
| .CLKOUT2_CLKOUT2_DELAY_TIME(CLKOUT2_REGS[21:16]), | |
| .CLKOUT2_CLKOUT2_EDGE (CLKOUT2_REGS[23]), | |
| .CLKOUT2_CLKOUT2_NO_COUNT (CLKOUT2_REGS[22]), | |
| // CLKOUT3 | |
| .CLKOUT3_CLKOUT1_HIGH_TIME (CLKOUT3_REGS[11:6]), | |
| .CLKOUT3_CLKOUT1_LOW_TIME (CLKOUT3_REGS[5:0]), | |
| .CLKOUT3_CLKOUT1_PHASE_MUX (CLKOUT3_REGS[15:13]), | |
| .CLKOUT3_CLKOUT2_DELAY_TIME(CLKOUT3_REGS[21:16]), | |
| .CLKOUT3_CLKOUT2_EDGE (CLKOUT3_REGS[23]), | |
| .CLKOUT3_CLKOUT2_NO_COUNT (CLKOUT3_REGS[22]), | |
| // CLKOUT4 | |
| .CLKOUT4_CLKOUT1_HIGH_TIME (CLKOUT4_REGS[11:6]), | |
| .CLKOUT4_CLKOUT1_LOW_TIME (CLKOUT4_REGS[5:0]), | |
| .CLKOUT4_CLKOUT1_PHASE_MUX (CLKOUT4_REGS[15:13]), | |
| .CLKOUT4_CLKOUT2_DELAY_TIME(CLKOUT4_REGS[21:16]), | |
| .CLKOUT4_CLKOUT2_EDGE (CLKOUT4_REGS[23]), | |
| .CLKOUT4_CLKOUT2_NO_COUNT (CLKOUT4_REGS[22]), | |
| // CLKOUT5 | |
| .CLKOUT5_CLKOUT1_HIGH_TIME (CLKOUT5_REGS[11:6]), | |
| .CLKOUT5_CLKOUT1_LOW_TIME (CLKOUT5_REGS[5:0]), | |
| .CLKOUT5_CLKOUT1_PHASE_MUX (CLKOUT5_REGS[15:13]), | |
| .CLKOUT5_CLKOUT2_DELAY_TIME(CLKOUT5_REGS[21:16]), | |
| .CLKOUT5_CLKOUT2_EDGE (CLKOUT5_REGS[23]), | |
| .CLKOUT5_CLKOUT2_NO_COUNT (CLKOUT5_REGS[22]), | |
| // Clock output enable controls | |
| .CLKFBOUT_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKFBOUT_ === 1'bX), | |
| .CLKOUT0_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT0_ === 1'bX), | |
| .CLKOUT1_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT1_ === 1'bX), | |
| .CLKOUT2_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT2_ === 1'bX), | |
| .CLKOUT3_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT3_ === 1'bX), | |
| .CLKOUT4_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT4_ === 1'bX), | |
| .CLKOUT5_CLKOUT1_OUTPUT_ENABLE(_TECHMAP_CONSTVAL_CLKOUT5_ === 1'bX) | |
| ) _TECHMAP_REPLACE_ ( | |
| .CLKFBIN (CLKFBIN), | |
| .CLKIN1 (CLKIN1), | |
| .CLKIN2 (CLKIN2), | |
| .CLKFBOUT(CLKFBOUT), | |
| .CLKOUT0 (CLKOUT0), | |
| .CLKOUT1 (CLKOUT1), | |
| .CLKOUT2 (CLKOUT2), | |
| .CLKOUT3 (CLKOUT3), | |
| .CLKOUT4 (CLKOUT4), | |
| .CLKOUT5 (CLKOUT5), | |
| .CLKINSEL(clkinsel), | |
| .PWRDWN(pwrdwn), | |
| .RST (rst), | |
| .LOCKED(LOCKED), | |
| .DCLK (dclk), | |
| .DEN (den), | |
| .DWE (dwe), | |
| .DRDY (DRDY), | |
| .DADDR(DADDR), | |
| .DI (DI), | |
| .DO (DO) | |
| ); | |
| endmodule | |
| // PLLE2_BASE | |
| module PLLE2_BASE ( | |
| input CLKFBIN, | |
| input CLKIN, | |
| output CLKFBOUT, | |
| output CLKOUT0, | |
| output CLKOUT1, | |
| output CLKOUT2, | |
| output CLKOUT3, | |
| output CLKOUT4, | |
| output CLKOUT5, | |
| input RST, | |
| output LOCKED | |
| ); | |
| parameter IS_CLKINSEL_INVERTED = 1'b0; | |
| parameter IS_RST_INVERTED = 1'b0; | |
| parameter BANDWIDTH = "OPTIMIZED"; | |
| parameter STARTUP_WAIT = "FALSE"; | |
| parameter CLKIN1_PERIOD = 0.0; | |
| parameter REF_JITTER1 = 0.1; | |
| parameter [5:0] DIVCLK_DIVIDE = 1; | |
| parameter [5:0] CLKFBOUT_MULT = 1; | |
| parameter signed CLKFBOUT_PHASE = 0; | |
| parameter [6:0] CLKOUT0_DIVIDE = 1; | |
| parameter CLKOUT0_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT0_PHASE = 0; | |
| parameter [6:0] CLKOUT1_DIVIDE = 1; | |
| parameter CLKOUT1_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT1_PHASE = 0; | |
| parameter [6:0] CLKOUT2_DIVIDE = 1; | |
| parameter CLKOUT2_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT2_PHASE = 0; | |
| parameter [6:0] CLKOUT3_DIVIDE = 1; | |
| parameter CLKOUT3_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT3_PHASE = 0; | |
| parameter [6:0] CLKOUT4_DIVIDE = 1; | |
| parameter CLKOUT4_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT4_PHASE = 0; | |
| parameter [6:0] CLKOUT5_DIVIDE = 1; | |
| parameter CLKOUT5_DUTY_CYCLE = 50000; | |
| parameter signed CLKOUT5_PHASE = 0; | |
| // The substituted cell | |
| PLLE2_ADV #( | |
| .IS_CLKINSEL_INVERTED(IS_CLKINSEL_INVERTED), | |
| .IS_RST_INVERTED(IS_RST_INVERTED), | |
| .IS_PWRDWN_INVERTED(1'b0), | |
| .BANDWIDTH(BANDWIDTH), | |
| .STARTUP_WAIT(STARTUP_WAIT), | |
| .CLKIN1_PERIOD(CLKIN1_PERIOD), | |
| .REF_JITTER1 (REF_JITTER1), | |
| .DIVCLK_DIVIDE(DIVCLK_DIVIDE), | |
| .CLKFBOUT_MULT (CLKFBOUT_MULT), | |
| .CLKFBOUT_PHASE(CLKFBOUT_PHASE), | |
| .CLKOUT0_DIVIDE(CLKOUT0_DIVIDE), | |
| .CLKOUT0_DUTY_CYCLE(CLKOUT0_DUTY_CYCLE), | |
| .CLKOUT0_PHASE(CLKOUT0_PHASE), | |
| .CLKOUT1_DIVIDE(CLKOUT1_DIVIDE), | |
| .CLKOUT1_DUTY_CYCLE(CLKOUT1_DUTY_CYCLE), | |
| .CLKOUT1_PHASE(CLKOUT1_PHASE), | |
| .CLKOUT2_DIVIDE(CLKOUT2_DIVIDE), | |
| .CLKOUT2_DUTY_CYCLE(CLKOUT2_DUTY_CYCLE), | |
| .CLKOUT2_PHASE(CLKOUT2_PHASE), | |
| .CLKOUT3_DIVIDE(CLKOUT3_DIVIDE), | |
| .CLKOUT3_DUTY_CYCLE(CLKOUT3_DUTY_CYCLE), | |
| .CLKOUT3_PHASE(CLKOUT3_PHASE), | |
| .CLKOUT4_DIVIDE(CLKOUT4_DIVIDE), | |
| .CLKOUT4_DUTY_CYCLE(CLKOUT4_DUTY_CYCLE), | |
| .CLKOUT4_PHASE(CLKOUT4_PHASE), | |
| .CLKOUT5_DIVIDE(CLKOUT5_DIVIDE), | |
| .CLKOUT5_DUTY_CYCLE(CLKOUT5_DUTY_CYCLE), | |
| .CLKOUT5_PHASE(CLKOUT5_PHASE) | |
| ) _TECHMAP_REPLACE_ ( | |
| .CLKFBIN (CLKFBIN), | |
| .CLKIN1 (CLKIN), | |
| .CLKINSEL(1'b1), | |
| .CLKFBOUT(CLKFBOUT), | |
| .CLKOUT0 (CLKOUT0), | |
| .CLKOUT1 (CLKOUT1), | |
| .CLKOUT2 (CLKOUT2), | |
| .CLKOUT3 (CLKOUT3), | |
| .CLKOUT4 (CLKOUT4), | |
| .CLKOUT5 (CLKOUT5), | |
| .PWRDWN(1'b0), | |
| .RST(RST), | |
| .LOCKED(LOCKED), | |
| .DCLK(1'b0), | |
| .DEN(1'b0), | |
| .DWE(1'b0), | |
| .DRDY(), | |
| .DADDR(7'd0), | |
| .DI(16'd0), | |
| .DO() | |
| ); | |
| endmodule |