Params plugin: Add PLL test Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/Makefile b/Makefile index aff09e8..fe3f92d 100644 --- a/Makefile +++ b/Makefile
@@ -1,4 +1,4 @@ -PLUGIN_LIST := fasm xdc +PLUGIN_LIST := fasm xdc params PLUGINS := $(foreach plugin,$(PLUGIN_LIST),$(plugin).so) PLUGINS_INSTALL := $(foreach plugin,$(PLUGIN_LIST),install_$(plugin)) PLUGINS_CLEAN := $(foreach plugin,$(PLUGIN_LIST),clean_$(plugin))
diff --git a/params-plugin/tests/Makefile b/params-plugin/tests/Makefile new file mode 100644 index 0000000..2ab247e --- /dev/null +++ b/params-plugin/tests/Makefile
@@ -0,0 +1,39 @@ +TESTS = pll + +pll_verify = $(call compare_json,pll) + +all: $(TESTS) + +compare_json = python compare_output_json.py --json $(1)/$(1).json --golden $(1)/$(1).golden.json + +define test_tpl = +$(1): $(1)/$(1).json + $$($(1)_verify) + RETVAL=$$$$? ; \ + if [ $$$$RETVAL -eq 0 ]; then \ + echo "$(1) PASS"; \ + true; \ + else \ + echo "$(1) FAIL"; \ + false; \ + fi + +$(1)/$(1).json: $(1)/$(1).v + cd $(1); \ + PART_JSON=../xc7a35tcsg324-1.json \ + OUT_JSON=$(1).json \ + INPUT_XDC_FILE=$(1).xdc \ + yosys -p "tcl $(1).tcl" $(1).v -l yosys.log + +update_$(1): $(1)/$(1).json + @python compare_output_json.py --json $$< --golden $(1)/$(1).golden.json --update + +endef + +$(foreach test,$(TESTS),$(eval $(call test_tpl,$(test)))) + +update: $(foreach test,$(TESTS),update_$(test)) + + +clean: + rm -rf $(foreach test,$(TESTS),$(test)/$(test).json $(test)/$(test).eblif $(test)/$(test).txt $(test)/yosys.log)
diff --git a/params-plugin/tests/compare_output_json.py b/params-plugin/tests/compare_output_json.py new file mode 100644 index 0000000..3b437e8 --- /dev/null +++ b/params-plugin/tests/compare_output_json.py
@@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +""" + +This script extracts the top module cells and their corresponding parameters +from json files produced by Yosys. +The return code of this script is used to check if the output is equivalent. +""" + +import sys +import json +import argparse + +parameters = ["CLKFBOUT_CLKOUT1_HIGH_TIME"] + +def read_cells(json_file): + with open(json_file) as f: + data = json.load(f) + f.close() + cells = data['modules']['top']['cells'] + cells_parameters = dict() + for cell, opts in cells.items(): + attributes = opts['parameters'] + if len(attributes.keys()): + if any([x in parameters for x in attributes.keys()]): + cells_parameters[cell] = attributes + return cells_parameters + + +def main(args): + cells = read_cells(args.json) + if args.update: + with open(args.golden, 'w') as f: + json.dump(cells, f, indent=2) + else: + with open(args.golden) as f: + cells_golden = json.load(f) + if cells == cells_golden: + exit(0) + else: + print(json.dumps(cells, indent=4)) + json.dump(cells, open(args.json + ".fail", 'w'), indent=2) + print("VS") + print(json.dumps(cells_golden, indent=4)) + exit(1) + f.close() + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--json', help = 'JSON to compare', required = True) + parser.add_argument('--golden', help = 'Golden JSON file', required = True) + parser.add_argument('--update', action = 'store_true', help = 'Update golden reference') + args = parser.parse_args() + main(args)
diff --git a/params-plugin/tests/pll/pll.golden.json b/params-plugin/tests/pll/pll.golden.json new file mode 100644 index 0000000..e3bf97d --- /dev/null +++ b/params-plugin/tests/pll/pll.golden.json
@@ -0,0 +1,65 @@ +{ + "PLLE2_ADV": { + "CLKFBOUT_CLKOUT1_HIGH_TIME": "000110", + "CLKFBOUT_CLKOUT1_LOW_TIME": "000110", + "CLKFBOUT_CLKOUT1_OUTPUT_ENABLE": "1", + "CLKFBOUT_CLKOUT1_PHASE_MUX": "000", + "CLKFBOUT_CLKOUT2_DELAY_TIME": "000000", + "CLKFBOUT_CLKOUT2_EDGE": "0", + "CLKFBOUT_CLKOUT2_NO_COUNT": "0", + "CLKOUT0_CLKOUT1_HIGH_TIME": "001010", + "CLKOUT0_CLKOUT1_LOW_TIME": "001010", + "CLKOUT0_CLKOUT1_OUTPUT_ENABLE": "1", + "CLKOUT0_CLKOUT1_PHASE_MUX": "000", + "CLKOUT0_CLKOUT2_DELAY_TIME": "000000", + "CLKOUT0_CLKOUT2_EDGE": "0", + "CLKOUT0_CLKOUT2_NO_COUNT": "0", + "CLKOUT1_CLKOUT1_HIGH_TIME": "000010", + "CLKOUT1_CLKOUT1_LOW_TIME": "000011", + "CLKOUT1_CLKOUT1_OUTPUT_ENABLE": "1", + "CLKOUT1_CLKOUT1_PHASE_MUX": "000", + "CLKOUT1_CLKOUT2_DELAY_TIME": "000000", + "CLKOUT1_CLKOUT2_EDGE": "1", + "CLKOUT1_CLKOUT2_NO_COUNT": "0", + "CLKOUT2_CLKOUT1_HIGH_TIME": "000010", + "CLKOUT2_CLKOUT1_LOW_TIME": "000011", + "CLKOUT2_CLKOUT1_OUTPUT_ENABLE": "0", + "CLKOUT2_CLKOUT1_PHASE_MUX": "010", + "CLKOUT2_CLKOUT2_DELAY_TIME": "000001", + "CLKOUT2_CLKOUT2_EDGE": "1", + "CLKOUT2_CLKOUT2_NO_COUNT": "0", + "CLKOUT3_CLKOUT1_HIGH_TIME": "000011", + "CLKOUT3_CLKOUT1_LOW_TIME": "000011", + "CLKOUT3_CLKOUT1_OUTPUT_ENABLE": "0", + "CLKOUT3_CLKOUT1_PHASE_MUX": "000", + "CLKOUT3_CLKOUT2_DELAY_TIME": "000000", + "CLKOUT3_CLKOUT2_EDGE": "0", + "CLKOUT3_CLKOUT2_NO_COUNT": "0", + "CLKOUT4_CLKOUT1_HIGH_TIME": "000001", + "CLKOUT4_CLKOUT1_LOW_TIME": "000001", + "CLKOUT4_CLKOUT1_OUTPUT_ENABLE": "0", + "CLKOUT4_CLKOUT1_PHASE_MUX": "000", + "CLKOUT4_CLKOUT2_DELAY_TIME": "000000", + "CLKOUT4_CLKOUT2_EDGE": "0", + "CLKOUT4_CLKOUT2_NO_COUNT": "1", + "CLKOUT5_CLKOUT1_HIGH_TIME": "000001", + "CLKOUT5_CLKOUT1_LOW_TIME": "000001", + "CLKOUT5_CLKOUT1_OUTPUT_ENABLE": "0", + "CLKOUT5_CLKOUT1_PHASE_MUX": "000", + "CLKOUT5_CLKOUT2_DELAY_TIME": "000000", + "CLKOUT5_CLKOUT2_EDGE": "0", + "CLKOUT5_CLKOUT2_NO_COUNT": "1", + "DIVCLK_DIVCLK_EDGE": "0", + "DIVCLK_DIVCLK_HIGH_TIME": "000001", + "DIVCLK_DIVCLK_LOW_TIME": "000001", + "DIVCLK_DIVCLK_NO_COUNT": "1", + "FILTREG1_RESERVED": "000000001000", + "INV_CLKINSEL": "0", + "LKTABLE": "1111111111110011100111111010010000000001", + "LOCKREG3_RESERVED": "1", + "STARTUP_WAIT": "0", + "TABLE": "1111110100", + "ZINV_PWRDWN": "1", + "ZINV_RST": "0" + } +} \ No newline at end of file
diff --git a/params-plugin/tests/pll/pll.tcl b/params-plugin/tests/pll/pll.tcl new file mode 100644 index 0000000..c2238d1 --- /dev/null +++ b/params-plugin/tests/pll/pll.tcl
@@ -0,0 +1,31 @@ +yosys -import +plugin -i xdc +plugin -i params +#Import the commands from the plugins to the tcl interpreter +yosys -import + +read_verilog -specify -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v +read_verilog -lib +/xilinx/cells_xtra.v +hierarchy -check -auto-top +set phase [get_param CLKOUT2_PHASE top/PLLE2_ADV] +puts "Phase before: $phase" +setparam -set CLKOUT2_PHASE [expr $phase * 1000] top/PLLE2_ADV +puts "Phase after: [get_param CLKOUT2_PHASE top/PLLE2_ADV]" +# Start flow after library reading +synth_xilinx -vpr -flatten -abc9 -nosrl -noclkbuf -nodsp -iopad -run prepare:check + +# Map Xilinx tech library to 7-series VPR tech library. +read_verilog -lib ../techmaps/cells_sim.v +techmap -map ../techmaps/cells_map.v + +# opt_expr -undriven makes sure all nets are driven, if only by the $undef +# net. +opt_expr -undriven +opt_clean + +setundef -zero -params +stat + +# Write the design in JSON format. +write_json $::env(OUT_JSON) +write_blif -attr -param -cname -conn pll.eblif
diff --git a/params-plugin/tests/pll/pll.v b/params-plugin/tests/pll/pll.v new file mode 100644 index 0000000..a1eeb38 --- /dev/null +++ b/params-plugin/tests/pll/pll.v
@@ -0,0 +1,38 @@ +module top( + (* dont_touch = "true" *) input clk100, + input cpu_reset, + output [2:0] led +); + +wire [2:0] led; +wire builder_pll_fb; + +assign led[0] = main_locked; +assign led[1] = main_clkout0; +assign led[2] = main_clkout1; + +PLLE2_ADV #( + .CLKFBOUT_MULT(4'd12), + .CLKIN1_PERIOD(10.0), + .CLKOUT0_DIVIDE(5'd20), + .CLKOUT0_PHASE(1'd0), + .CLKOUT1_DIVIDE(3'd5), + .CLKOUT1_PHASE(1'd0), + .CLKOUT2_DIVIDE(3'd5), + .CLKOUT2_PHASE(7'd90), + .CLKOUT3_DIVIDE(3'd6), + .CLKOUT3_PHASE(1'd0), + .DIVCLK_DIVIDE(1'd1), + .REF_JITTER1(0.01), + .STARTUP_WAIT("FALSE") +) PLLE2_ADV ( + .CLKFBIN(builder_pll_fb), + .CLKIN1(clk100), + .RST(cpu_reset), + .CLKFBOUT(builder_pll_fb), + .CLKOUT0(main_clkout0), + .CLKOUT1(main_clkout1), + .LOCKED(main_locked) +); + +endmodule
diff --git a/params-plugin/tests/pll/pll.xdc b/params-plugin/tests/pll/pll.xdc new file mode 100644 index 0000000..2f4eba3 --- /dev/null +++ b/params-plugin/tests/pll/pll.xdc
@@ -0,0 +1,9 @@ +# ## clk100:0 +set_property LOC E3 [get_ports clk100] +set_property IOSTANDARD LVCMOS33 [get_ports clk100] +# ## cpu_reset:0 +set_property LOC C2 [get_ports cpu_reset] +set_property IOSTANDARD LVCMOS33 [get_ports cpu_reset] +set_property LOC H5 [get_ports {led[0]}] +set_property LOC J5 [get_ports {led[1]}] +set_property LOC T9 [get_ports {led[2]}]
diff --git a/params-plugin/tests/techmaps/cells_map.v b/params-plugin/tests/techmaps/cells_map.v new file mode 100644 index 0000000..772f588 --- /dev/null +++ b/params-plugin/tests/techmaps/cells_map.v
@@ -0,0 +1,866 @@ +// ============================================================================ +// 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 + generate if (_TECHMAP_CONSTMSK_CLKINSEL_ == 1) begin + localparam INV_CLKINSEL = !_TECHMAP_CONSTVAL_CLKINSEL_; + wire clkinsel = 1'b1; + end else if (_TECHMAP_CONSTVAL_CLKINSEL_ == 0) begin + localparam INV_CLKINSEL = IS_CLKINSEL_INVERTED; + wire clkinsel = 1'b1; + end else begin + localparam INV_CLKINSEL = IS_CLKINSEL_INVERTED; + wire clkinsel = CLKINSEL; + end endgenerate + + generate if (_TECHMAP_CONSTMSK_PWRDWN_ == 1) begin + localparam INV_PWRDWN = !_TECHMAP_CONSTVAL_PWRDWN_; + wire pwrdwn = 1'b1; + end else if (_TECHMAP_CONSTVAL_PWRDWN_ == 0) begin + localparam INV_PWRDWN = ~IS_PWRDWN_INVERTED; + wire pwrdwn = 1'b1; + end else begin + localparam INV_PWRDWN = IS_PWRDWN_INVERTED; + wire pwrdwn = PWRDWN; + end endgenerate + + generate if (_TECHMAP_CONSTMSK_RST_ == 1) begin + localparam INV_RST = !_TECHMAP_CONSTVAL_PWRDWN_; + wire rst = 1'b1; + end else if (_TECHMAP_CONSTVAL_RST_ == 0) begin + localparam INV_RST = ~IS_RST_INVERTED; + wire rst = 1'b1; + end else begin + localparam INV_RST = IS_RST_INVERTED; + 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
diff --git a/params-plugin/tests/techmaps/cells_sim.v b/params-plugin/tests/techmaps/cells_sim.v new file mode 100644 index 0000000..607f98b --- /dev/null +++ b/params-plugin/tests/techmaps/cells_sim.v
@@ -0,0 +1,145 @@ +// ============================================================================ +// CMT + +// PLLE2_ADV_VPR +(* blackbox *) +module PLLE2_ADV_VPR +( +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 [0:0] INV_CLKINSEL = 1'd0; + parameter [0:0] ZINV_PWRDWN = 1'd0; + parameter [0:0] ZINV_RST = 1'd1; + + parameter [0:0] STARTUP_WAIT = 1'd0; + + // Tables + parameter [9:0] TABLE = 10'd0; + parameter [39:0] LKTABLE = 40'd0; + parameter [15:0] POWER_REG = 16'd0; + parameter [11:0] FILTREG1_RESERVED = 12'd0; + parameter [9:0] FILTREG2_RESERVED = 10'd0; + parameter [5:0] LOCKREG1_RESERVED = 6'd0; + parameter [0:0] LOCKREG2_RESERVED = 1'b0; + parameter [0:0] LOCKREG3_RESERVED = 1'b0; + + // DIVCLK + parameter [5:0] DIVCLK_DIVCLK_HIGH_TIME = 6'd0; + parameter [5:0] DIVCLK_DIVCLK_LOW_TIME = 6'd0; + parameter [0:0] DIVCLK_DIVCLK_NO_COUNT = 1'b1; + parameter [0:0] DIVCLK_DIVCLK_EDGE = 1'b0; + + // CLKFBOUT + parameter [5:0] CLKFBOUT_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKFBOUT_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKFBOUT_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKFBOUT_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKFBOUT_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKFBOUT_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKFBOUT_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKFBOUT_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKFBOUT_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKFBOUT_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT0 + parameter [5:0] CLKOUT0_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT0_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT0_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT0_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT0_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT0_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT0_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT0_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT0_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT0_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT1 + parameter [5:0] CLKOUT1_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT1_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT1_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT1_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT1_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT1_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT1_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT1_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT1_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT1_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT2 + parameter [5:0] CLKOUT2_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT2_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT2_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT2_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT2_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT2_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT2_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT2_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT2_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT2_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT3 + parameter [5:0] CLKOUT3_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT3_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT3_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT3_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT3_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT3_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT3_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT3_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT3_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT3_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT4 + parameter [5:0] CLKOUT4_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT4_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT4_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT4_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT4_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT4_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT4_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT4_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT4_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT4_CLKOUT2_NO_COUNT = 1'b1; + + // CLKOUT5 + parameter [5:0] CLKOUT5_CLKOUT1_HIGH_TIME = 6'd0; + parameter [5:0] CLKOUT5_CLKOUT1_LOW_TIME = 6'd0; + parameter [0:0] CLKOUT5_CLKOUT1_OUTPUT_ENABLE = 1'b0; + parameter [2:0] CLKOUT5_CLKOUT1_PHASE_MUX = 3'd0; + parameter [5:0] CLKOUT5_CLKOUT2_DELAY_TIME = 6'd0; + parameter [0:0] CLKOUT5_CLKOUT2_EDGE = 1'b0; + parameter [2:0] CLKOUT5_CLKOUT2_FRAC = 3'd0; + parameter [0:0] CLKOUT5_CLKOUT2_FRAC_EN = 1'b0; + parameter [0:0] CLKOUT5_CLKOUT2_FRAC_WF_R = 1'b0; + parameter [0:0] CLKOUT5_CLKOUT2_NO_COUNT = 1'b1; + + + // TODO: Compensation parameters + + // TODO: How to simulate a PLL in verilog (i.e. the VCO) ??? + +endmodule
diff --git a/params-plugin/tests/xc7a35tcsg324-1.json b/params-plugin/tests/xc7a35tcsg324-1.json new file mode 100644 index 0000000..602b949 --- /dev/null +++ b/params-plugin/tests/xc7a35tcsg324-1.json
@@ -0,0 +1,10 @@ +{ + "iobanks": { + "0": "X1Y78", + "14": "X1Y26", + "15": "X1Y78", + "16": "X1Y130", + "34": "X113Y26", + "35": "X113Y78" + } +}