| // Copyright 2020-2022 F4PGA Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // SPDX-License-Identifier: Apache-2.0 |
| |
| // ============================================================================ |
| // 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 |