<!-- if a clockGenerator is given, this config needs to create the required source code -->
<toolchain name="BASYS3" clockGenerator="clockGenerator">
    <commands>
        <command name="Export VHDL" requires="vhdl" />
        <command name="Export VHDL &amp; Start Vivado" requires="vhdl" filter="true" timeout="0">
            <arg>vivado</arg>
            <arg>vivado/{?=shortname?}.xpr</arg>
        </command>
        <command name="Export Verilog" requires="verilog" />
        <command name="Export Verilog &amp; Start Vivado" requires="verilog" filter="true" timeout="0">
            <arg>vivado</arg>
            <arg>vivado/{?=shortname?}.xpr</arg>
        </command>
    </commands>
    <params>
        <!-- used by the clock generator -->
        <param name="F_IN">100.0</param> <!-- in MHz -->
        <!-- used by the Vivado project template -->
        <param name="chip">xc7a35ticpg236-1L</param>
    </params>
    <files>
        <!-- Creates the VHDL/Verilog file which is imported by the created hdl code. -->
        <file name="clockGenerator{?=extension?}" overwrite="true" filter="true" id="MMCME2_BASE">
            <content><![CDATA[<?
   if (model.frequency<4687500) {
     maxCounter:=round(F_IN*500000.0 / model.frequency);
     log("counter: "+maxCounter);
     bits := bitsNeededFor(maxCounter);

     if (hdl="vhdl") {
?>LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_unsigned.all;

entity clockGenerator is
  port (
    cout: out std_logic;
    cin: in std_logic );
end clockGenerator;

architecture Behavioral of clockGenerator is
  -- Don't use a logic signal as clock source in a real world application!
  -- Use the on chip clock resources instead!
  signal counter: integer range 0 to <?=maxCounter?> := 0;
  signal state: std_logic;
begin
  process (cin)
  begin
    if rising_edge(cin) then
       if counter = <?=maxCounter?> then
          counter <= 0;
          state <= NOT (state);
       else
          counter <= counter+1;
       end if;
    end if;
  end process;
  cout <= state;
end Behavioral;
<? } else {
?>module clockGenerator
(
    input cin,
    output cout
);
 /*
  * Don't use a logic signal as clock source in a real world application!
  * Use the on chip clock resources instead!
  */
  reg [<?=bits-1?>:0] counter;
  reg state;

  assign cout = state;

  always @ (posedge cin) begin
       if (counter == <?=maxCounter?>) begin
            counter <= 0;
            state <= ~state;
       end
       else begin
          counter <= counter + 1;
       end
  end

endmodule
<?  }
} else {

  PDF_MIN := 10;
  PDF_MAX := 450;

  VCO_MIN := 600;
  VCO_MAX := 1200;

  D_MIN := min(106,max(1,ceil( F_IN/PDF_MAX )));
  D_MAX := min(106,max(1,floor( F_IN/PDF_MIN )));

  M_MIN := min(64,max(2,ceil( VCO_MIN/F_IN*D_MIN )));
  M_MAX := min(64,max(2,floor( VCO_MAX/F_IN*D_MAX )));

  PERIOD := 1000/F_IN;

  log(format("D_min=%d",D_MIN));
  log(format("D_max=%d",D_MAX));

  log(format("M_min=%d",M_MIN));
  log(format("M_max=%d",M_MAX));

  M_IDEAL := D_MIN*VCO_MAX/F_IN;

  F_DES := model.frequency/1000000.0;

  bestError:=F_DES;
  bestErrorM:=float(M_MAX);
  M:=0.0;
  D:=0;
  DIV:=0.0;
  for (d:=D_MIN;d<=D_MAX;d++) {
      m_min_d := min(64,max(2,ceil( VCO_MIN/F_IN*d )));
      m_max_d := min(64,max(2,floor( VCO_MAX/F_IN*d )));

      divMin:=max(1,round(VCO_MIN/F_DES*8));
      divMax:=min(128*8,round(VCO_MAX/F_DES*8));
      for (divInt := divMin; divInt<=divMax; divInt++) {
          div:= divInt/8.0;

          m:=max(m_min_d,min(m_max_d,round((F_DES*d*div*1000)/F_IN)/1000.0));

          F_OUT := (F_IN*m)/d/div;

          error:=abs(F_DES-F_OUT);
          errorM:=abs(m-M_IDEAL);

          if ((error<bestError) | ((error=bestError) & (errorM<bestErrorM))) {
              bestError=error;
              bestErrorM=errorM;
              M=m;
              DIV=div;
              D=d;
          }

      }
  }

  export F_VCO := (F_IN*M)/D; // export value for test case usage

  log(format("M_ideal=%.2f",M_IDEAL));
  log(format("M=%.3f",M));
  log(format("D=%d",D));
  log(format("DIV=%f",DIV));

  export F_OUT := F_VCO/DIV;  // export value for test case usage

  log(format("F_VCO=%.2f",F_VCO));
  log(format("F_OUT    =%f",F_OUT));
  log(format("F_Desired=%f",F_DES));

  if (hdl="vhdl") {
?>LIBRARY ieee;
USE ieee.std_logic_1164.all;

Library UNISIM;
use UNISIM.vcomponents.all;

-- MMCME2_BASE: Base Mixed Mode Clock Manager
-- 7 Series
-- Xilinx HDL Libraries Guide, version 2012.2

entity clockGenerator is
  port (
    cout: out std_logic;
    cin: in std_logic );
end clockGenerator;

architecture Behavioral of clockGenerator is
    signal DEV_NULL: std_logic;
    signal feedback: std_logic;
begin
  DEV_NULL <= '0';

  -- code taken from the "Vivado Design Suite 7 Series FPGA Libraries Guide" (UG953)

  MMCME2_BASE_inst : MMCME2_BASE
    generic map (
      BANDWIDTH => "OPTIMIZED",    -- Jitter programming (OPTIMIZED, HIGH, LOW)
      CLKFBOUT_MULT_F => <?=format("%.3f",M)?>,   -- Multiply value for all CLKOUT (2.000-64.000).
      CLKFBOUT_PHASE => 0.0,       -- Phase offset in degrees of CLKFB (-360.000-360.000).
      CLKIN1_PERIOD => <?=format("%.3f",PERIOD)?>,       --* Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
      -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
      CLKOUT1_DIVIDE => 1,
      CLKOUT2_DIVIDE => 1,
      CLKOUT3_DIVIDE => 1,
      CLKOUT4_DIVIDE => 1,
      CLKOUT5_DIVIDE => 1,
      CLKOUT6_DIVIDE => 1,
      CLKOUT0_DIVIDE_F => <?=format("%.3f",DIV)?>, -- Divide amount for CLKOUT0 (1.000-128.000).
      -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
      CLKOUT0_DUTY_CYCLE => 0.5,
      CLKOUT1_DUTY_CYCLE => 0.5,
      CLKOUT2_DUTY_CYCLE => 0.5,
      CLKOUT3_DUTY_CYCLE => 0.5,
      CLKOUT4_DUTY_CYCLE => 0.5,
      CLKOUT5_DUTY_CYCLE => 0.5,
      CLKOUT6_DUTY_CYCLE => 0.5,
      -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
      CLKOUT0_PHASE => 0.0,
      CLKOUT1_PHASE => 0.0,
      CLKOUT2_PHASE => 0.0,
      CLKOUT3_PHASE => 0.0,
      CLKOUT4_PHASE => 0.0,
      CLKOUT5_PHASE => 0.0,
      CLKOUT6_PHASE => 0.0,
      CLKOUT4_CASCADE => FALSE,  -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
      DIVCLK_DIVIDE => <?=D?>,   -- Master division value (1-106)
      REF_JITTER1 => 0.0,        -- Reference input jitter in UI (0.000-0.999).
      STARTUP_WAIT => FALSE      -- Delays DONE until MMCM is locked (FALSE, TRUE)
    )
    port map (
      -- Clock Outputs: 1-bit (each) output: User configurable clock outputs
      CLKOUT0 => cout,           --* 1-bit output: CLKOUT0
      --CLKOUT0B => CLKOUT0B,      -- 1-bit output: Inverted CLKOUT0
      --CLKOUT1 => CLKOUT1,        -- 1-bit output: CLKOUT1
      --CLKOUT1B => CLKOUT1B,      -- 1-bit output: Inverted CLKOUT1
      --CLKOUT2 => CLKOUT2,        -- 1-bit output: CLKOUT2
      --CLKOUT2B => CLKOUT2B,      -- 1-bit output: Inverted CLKOUT2
      --CLKOUT3 => CLKOUT3,        -- 1-bit output: CLKOUT3
      --CLKOUT3B => CLKOUT3B,      -- 1-bit output: Inverted CLKOUT3
      --CLKOUT4 => CLKOUT4,        -- 1-bit output: CLKOUT4
      --CLKOUT5 => CLKOUT5,        -- 1-bit output: CLKOUT5
      --CLKOUT6 => CLKOUT6,        -- 1-bit output: CLKOUT6
      -- Feedback Clocks: 1-bit (each) output: Clock feedback ports
      CLKFBOUT => feedback,      --* 1-bit output: Feedback clock
      --CLKFBOUTB => CLKFBOUTB,    -- 1-bit output: Inverted CLKFBOUT
      -- Status Ports: 1-bit (each) output: MMCM status ports
      --LOCKED => LOCKED,          -- 1-bit output: LOCK
      -- Clock Inputs: 1-bit (each) input: Clock input
      CLKIN1 => cin,             --* 1-bit input: Clock
      -- Control Ports: 1-bit (each) input: MMCM control ports
      PWRDWN => DEV_NULL,        --* 1-bit input: Power-down
      RST => DEV_NULL,           --* 1-bit input: Reset
      -- Feedback Clocks: 1-bit (each) input: Clock feedback ports
      CLKFBIN => feedback        --* 1-bit input: Feedback clock
    );
end Behavioral;
<? } else {
?>module clockGenerator
(
    input cin,
    output cout
);

  wire feedback;

MMCME2_BASE #(
  .BANDWIDTH("OPTIMIZED"),         // Jitter programming (OPTIMIZED, HIGH, LOW)
  .CLKFBOUT_MULT_F(<?=format("%.3f",M)?>),           // Multiply value for all CLKOUT (2.000-64.000).
  .CLKFBOUT_PHASE(0.0),            // Phase offset in degrees of CLKFB (-360.000-360.000).
  .CLKIN1_PERIOD(<?=format("%.3f",PERIOD)?>),             // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
  // CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
  .CLKOUT1_DIVIDE(1),
  .CLKOUT2_DIVIDE(1),
  .CLKOUT3_DIVIDE(1),
  .CLKOUT4_DIVIDE(1),
  .CLKOUT5_DIVIDE(1),
  .CLKOUT6_DIVIDE(1),
  .CLKOUT0_DIVIDE_F(<?=format("%.3f",DIV)?>),          // Divide amount for CLKOUT0 (1.000-128.000).
  // CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99).
  .CLKOUT0_DUTY_CYCLE(0.5),
  .CLKOUT1_DUTY_CYCLE(0.5),
  .CLKOUT2_DUTY_CYCLE(0.5),
  .CLKOUT3_DUTY_CYCLE(0.5),
  .CLKOUT4_DUTY_CYCLE(0.5),
  .CLKOUT5_DUTY_CYCLE(0.5),
  .CLKOUT6_DUTY_CYCLE(0.5),
  // CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
  .CLKOUT0_PHASE(0.0),
  .CLKOUT1_PHASE(0.0),
  .CLKOUT2_PHASE(0.0),
  .CLKOUT3_PHASE(0.0),
  .CLKOUT4_PHASE(0.0),
  .CLKOUT5_PHASE(0.0),
  .CLKOUT6_PHASE(0.0),
  .CLKOUT4_CASCADE("FALSE"),       // Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE)
  .DIVCLK_DIVIDE(<?=D?>),               // Master division value (1-106)
  .REF_JITTER1(0.0),               // Reference input jitter in UI (0.000-0.999).
  .STARTUP_WAIT("FALSE")           // Delays DONE until MMCM is locked (FALSE, TRUE)
)
MMCME2_BASE_inst (
  // Clock Outputs: 1-bit (each) output: User configurable clock outputs
  .CLKOUT0(cout),                  // 1-bit output: CLKOUT0
  //.CLKOUT0B(CLKOUT0B),             // 1-bit output: Inverted CLKOUT0
  //.CLKOUT1(CLKOUT1),               // 1-bit output: CLKOUT1
  //.CLKOUT1B(CLKOUT1B),             // 1-bit output: Inverted CLKOUT1
  //.CLKOUT2(CLKOUT2),               // 1-bit output: CLKOUT2
  //.CLKOUT2B(CLKOUT2B),             // 1-bit output: Inverted CLKOUT2
  //.CLKOUT3(CLKOUT3),               // 1-bit output: CLKOUT3
  //.CLKOUT3B(CLKOUT3B),             // 1-bit output: Inverted CLKOUT3
  //.CLKOUT4(CLKOUT4),               // 1-bit output: CLKOUT4
  //.CLKOUT5(CLKOUT5),               // 1-bit output: CLKOUT5
  //.CLKOUT6(CLKOUT6),               // 1-bit output: CLKOUT6
  // Feedback Clocks: 1-bit (each) output: Clock feedback ports
  .CLKFBOUT(feedback),             // 1-bit output: Feedback clock
  //.CLKFBOUTB(CLKFBOUTB),           // 1-bit output: Inverted CLKFBOUT
  // Status Ports: 1-bit (each) output: MMCM status ports
  //.LOCKED(LOCKED),                 // 1-bit output: LOCK
  // Clock Inputs: 1-bit (each) input: Clock input
  .CLKIN1(cin),                 // 1-bit input: Clock
  // Control Ports: 1-bit (each) input: MMCM control ports
  .PWRDWN( 1'b0 ),                 // 1-bit input: Power-down
  .RST( 1'b0 ),                       // 1-bit input: Reset
  // Feedback Clocks: 1-bit (each) input: Clock feedback ports
  .CLKFBIN(feedback)                // 1-bit input: Feedback clock
);

endmodule
<? }
}?>]]></content>
        </file>
        <!-- Creates the constrains file which contains the pin assignments.-->
        <file name="{?=shortname?}_constraints.xdc" overwrite="true" filter="true" id="constraints.xdc">
            <content><![CDATA[<?

for (i:=0; i<sizeOf(model.ports);i++) {
    port:=model.ports[i];
    if (port.bits=1) {
        print("set_property PACKAGE_PIN "+port.pin+" [get_ports "+port.name+"]\n");
        print("set_property IOSTANDARD LVCMOS33 [get_ports "+port.name+"]\n\n");
        if (port.clock) {
            print("create_clock -add -name sys_clk_pin -period 10 -waveform {0 5} [get_ports "+port.name+"]\n\n");
        }
    } else {
        pins := splitString(port.pin);
        for (p:=0;p<sizeOf(pins);p++) {
            print("set_property PACKAGE_PIN "+pins[p]+" [get_ports "+port.name+"["+p+"]]\n");
            print("set_property IOSTANDARD LVCMOS33 [get_ports "+port.name+"["+p+"]]\n\n");
        }
    }
}
print("set_property CFGBVS VCCO  [current_design]\n");
print("set_property CONFIG_VOLTAGE 3.3 [current_design]\n");

            ?>]]></content>
        </file>
        <!-- Creates the Vivado project file.-->
        <file name="vivado/{?=shortname?}.xpr" overwrite="false" filter="true" id="vivado">
            <content><![CDATA[<?print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");?>
<!-- Created by Digital -->

<Project Version="7" Minor="20" Path="<?=dir?>/vivado/<?=shortname?>.xpr">
  <DefaultLaunch Dir="$PRUNDIR"/>
  <Configuration>
    <Option Name="Part" Val="<?=chip?>"/>
  </Configuration>
  <FileSets Version="1" Minor="31">
    <FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1">
      <Filter Type="Srcs"/>
      <File Path="$PPRDIR/../<?=shortname?><?=extension?>">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
<? if (isPresent("clockGenerator") & (model.frequency>0)) { ?>
      <File Path="$PPRDIR/../<?=clockGenerator?><?=extension?>">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>
<? } ?>
      <Config>
        <Option Name="DesignMode" Val="RTL"/>
        <Option Name="TopModule" Val="main"/>
        <Option Name="TopAutoSet" Val="TRUE"/>
      </Config>
    </FileSet>
    <FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1">
      <Filter Type="Constrs"/>
      <File Path="$PPRDIR/../<?=shortname?>_constraints.xdc">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="implementation"/>
        </FileInfo>
      </File>
      <Config>
        <Option Name="ConstrsType" Val="XDC"/>
      </Config>
    </FileSet>
  </FileSets>
</Project>]]></content>
        </file>
    </files>
</toolchain>
