/******************************************************************************* * This file is part of logisim-evolution. * * logisim-evolution is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * logisim-evolution is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>. * * Original code by Carl Burch (http://www.cburch.com), 2011. * Subsequent modifications by : * + Haute École Spécialisée Bernoise * http://www.bfh.ch * + Haute École du paysage, d'ingénierie et d'architecture de Genève * http://hepia.hesge.ch/ * + Haute École d'Ingénierie et de Gestion du Canton de Vaud * http://www.heig-vd.ch/ * The project is currently maintained by : * + REDS Institute - HEIG-VD * Yverdon-les-Bains, Switzerland * http://reds.heig-vd.ch *******************************************************************************/ package com.bfh.logisim.hdlgenerator; import java.util.ArrayList; import java.util.SortedMap; import java.util.TreeMap; import com.bfh.logisim.designrulecheck.Netlist; import com.bfh.logisim.designrulecheck.NetlistComponent; import com.bfh.logisim.fpgagui.FPGAReport; import com.bfh.logisim.settings.Settings; import com.cburch.logisim.data.AttributeSet; public class TickComponentHDLGeneratorFactory extends AbstractHDLGeneratorFactory { private long FpgaClockFrequency; private double TickFrequency; // private boolean useFPGAClock; private static final String ReloadValueStr = "ReloadValue"; private static final Integer ReloadValueId = -1; private static final String NrOfCounterBitsStr = "NrOfBits"; private static final Integer NrOfCounterBitsId = -2; public static final String FPGAClock = "FPGA_GlobalClock"; public static final String FPGATick = "s_FPGA_Tick"; public TickComponentHDLGeneratorFactory(long fpga_clock_frequency, double tick_frequency/* * , boolean useFPGAClock */) { FpgaClockFrequency = fpga_clock_frequency; TickFrequency = tick_frequency; // this.useFPGAClock = useFPGAClock; } @Override public String getComponentStringIdentifier() { return "LogisimTickGenerator"; } @Override public SortedMap<String, Integer> GetInputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> Inputs = new TreeMap<String, Integer>(); Inputs.put("FPGAClock", 1); return Inputs; } @Override public ArrayList<String> GetModuleFunctionality(Netlist TheNetlist, AttributeSet attrs, FPGAReport Reporter, String HDLType) { ArrayList<String> Contents = new ArrayList<String>(); String Preamble = (HDLType.equals(Settings.VHDL)) ? "" : "assign "; String AssignOperator = (HDLType.equals(Settings.VHDL)) ? "<=" : "="; Contents.add(""); Contents.addAll(MakeRemarkBlock("Here the Output is defined", 3, HDLType)); if (TheNetlist.RequiresGlobalClockConnection()) { Contents.add(" " + Preamble + "FPGATick " + AssignOperator + " '1';"); } else { Contents.add(" " + Preamble + "FPGATick " + AssignOperator + " s_tick_reg;"); } Contents.add(""); Contents.addAll(MakeRemarkBlock("Here the update logic is defined", 3, HDLType)); if (HDLType.equals(Settings.VHDL)) { Contents.add(" s_tick_next <= '1' WHEN s_count_reg = std_logic_vector(to_unsigned(0," + NrOfCounterBitsStr + ")) ELSE '0';"); Contents.add(" s_count_next <= (OTHERS => '0') WHEN s_tick_reg /= '0' AND s_tick_reg /= '1' ELSE -- For simulation only!"); Contents.add(" std_logic_vector(to_unsigned((ReloadValue-1)," + NrOfCounterBitsStr + ")) WHEN s_tick_next = '1' ELSE"); Contents.add(" std_logic_vector(unsigned(s_count_reg)-1);"); Contents.add(""); } else { Contents.add(" assign s_tick_next = (s_count_reg == 0) ? 1'b1 : 1'b0;"); Contents.add(" assign s_count_next = (s_count_reg == 0) ? ReloadValue-1 : s_count_reg-1;"); Contents.add(""); Contents.addAll(MakeRemarkBlock( "Here the simulation only initial is defined", 3, HDLType)); Contents.add(" initial"); Contents.add(" begin"); Contents.add(" s_count_reg = 0;"); Contents.add(" s_tick_reg = 1'b0;"); Contents.add(" end"); Contents.add(""); } Contents.addAll(MakeRemarkBlock("Here the flipflops are defined", 3, HDLType)); if (HDLType.equals(Settings.VHDL)) { Contents.add(" make_tick : PROCESS( FPGAClock , s_tick_next )"); Contents.add(" BEGIN"); Contents.add(" IF (FPGAClock'event AND (FPGAClock = '1')) THEN"); Contents.add(" s_tick_reg <= s_tick_next;"); Contents.add(" END IF;"); Contents.add(" END PROCESS make_tick;"); Contents.add(""); Contents.add(" make_counter : PROCESS( FPGAClock , s_count_next )"); Contents.add(" BEGIN"); Contents.add(" IF (FPGAClock'event AND (FPGAClock = '1')) THEN"); Contents.add(" s_count_reg <= s_count_next;"); Contents.add(" END IF;"); Contents.add(" END PROCESS make_counter;"); } else { Contents.add(" always @(posedge FPGAClock)"); Contents.add(" begin"); Contents.add(" s_count_reg <= s_count_next;"); Contents.add(" s_tick_reg <= s_tick_next;"); Contents.add(" end"); } return Contents; } @Override public SortedMap<String, Integer> GetOutputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> Outputs = new TreeMap<String, Integer>(); Outputs.put("FPGATick", 1); return Outputs; } @Override public SortedMap<Integer, String> GetParameterList(AttributeSet attrs) { SortedMap<Integer, String> Parameters = new TreeMap<Integer, String>(); Parameters.put(ReloadValueId, ReloadValueStr); Parameters.put(NrOfCounterBitsId, NrOfCounterBitsStr); return Parameters; } @Override public SortedMap<String, Integer> GetParameterMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter) { SortedMap<String, Integer> ParameterMap = new TreeMap<String, Integer>(); double ReloadValueAcc = ((double) FpgaClockFrequency) / TickFrequency; long ReloadValue = (long) ReloadValueAcc; int nr_of_bits = 0; if ((ReloadValue > (long) 0x7FFFFFFF) | (ReloadValue < 0)) ReloadValue = (long) 0x7FFFFFFF; ParameterMap.put(ReloadValueStr, (int) ReloadValue); while (ReloadValue != 0) { nr_of_bits++; ReloadValue /= 2; } ParameterMap.put(NrOfCounterBitsStr, nr_of_bits); return ParameterMap; } @Override public SortedMap<String, String> GetPortMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter, String HDLType) { SortedMap<String, String> PortMap = new TreeMap<String, String>(); PortMap.put("FPGAClock", TickComponentHDLGeneratorFactory.FPGAClock); PortMap.put("FPGATick", TickComponentHDLGeneratorFactory.FPGATick); return PortMap; } @Override public SortedMap<String, Integer> GetRegList(AttributeSet attrs, String HDLType) { SortedMap<String, Integer> Regs = new TreeMap<String, Integer>(); Regs.put("s_tick_reg", 1); Regs.put("s_count_reg", NrOfCounterBitsId); return Regs; } @Override public String GetSubDir() { return "base"; } @Override public SortedMap<String, Integer> GetWireList(AttributeSet attrs, Netlist Nets) { SortedMap<String, Integer> Wires = new TreeMap<String, Integer>(); Wires.put("s_tick_next", 1); Wires.put("s_count_next", NrOfCounterBitsId); return Wires; } @Override public boolean HDLTargetSupported(String HDLType, AttributeSet attrs) { return true; } }