import magma as m
m.set_mantle_target("ice40")

"""
Explanation: Toggle Flip-Flop
In this example we create a toggle flip-flop (TFF) from a d-flip-flop (DFF) and an xor gate. In Magma, finite state machines can be constructed by composing combinational logic with register primitives, such as a DFF or Register.
End of explanation
"""


from mantle import DFF

class TFF(m.Circuit):
    IO = ['O', m.Out(m.Bit)] + m.ClockInterface()
    @classmethod
    def definition(io):
        # instance a dff to hold the state of the toggle flip-flop - this needs to be done first
        dff = DFF()
        # compute the next state as the not of the old state ff.O
        io.O <= dff(~dff.O)
        
def tff():
    return TFF()()

"""
Explanation: As before, we can use a native Python function to organize the definition of our TFF into a reusable component.
End of explanation
"""


from loam.boards.icestick import IceStick

icestick = IceStick()
icestick.Clock.on()
icestick.J3[0].rename('J3').output().on()

main = icestick.DefineMain()
main.J3 <= tff()
m.EndDefine()

"""
Explanation: Then we simply call this function inside our definition of the IceStick main.
End of explanation
"""


m.compile("build/tff", main)

%%bash
cd build
yosys -q -p 'synth_ice40 -top main -blif tff.blif' tff.v
arachne-pnr -q -d 1k -o tff.txt -p tff.pcf tff.blif 
icepack tff.txt tff.bin
#iceprog tff.bin

"""
Explanation: We'll compile and build our program using the standard flow.
End of explanation
"""


%cat build/tff.v

"""
Explanation: Let's inspect the generated verilog.
End of explanation
"""


%cat build/tff.pcf

"""
Explanation: We can verify our implementation is function correctly by using a logic analyzer.
End of explanation
"""


