In [1]:
import magma as m
m.set_mantle_target("ice40")
To use a DFF we import the mantle circuit DFF.
Calling DFF() creates an instance of a DFF.
Although a sequential logic element like a DFF has internal state, in Magma it is treated very similar to a combinational logic element like a full adder. Both combinational and sequential circuits have inputs and outputs. The inputs and outputs are wired up in the same way in both cases.
In [2]:
from loam.boards.icestick import IceStick
from mantle import DFF
icestick = IceStick()
icestick.Clock.on() # Need to turn on the clock for sequential logic
icestick.J1[0].input().on()
icestick.J3[0].output().on()
main = icestick.DefineMain()
dff = DFF()
main.J3 <= dff(main.J1)
m.EndDefine()
Since a flip-flop is a sequential logic element, it has a clock. The clock generator is a peripheral on the FPGA. We need to turn it on if we want to use the clock. Turning it on creates a global clock signal on the FPGA.
Note that we did not need to wire the clock to the DFF;
magma automatically wires the global clock to the flip-flop's clock input.
Let's compile and build.
In [3]:
m.compile("build/dff", main)
In [4]:
%%bash
cd build
yosys -q -p 'synth_ice40 -top main -blif dff.blif' dff.v
arachne-pnr -q -d 1k -o dff.txt -p dff.pcf dff.blif
icepack dff.txt dff.bin
#iceprog dff.bin
If we inspect the compiled verilog, we see that our mantle DFF uses the SB_DFF ice40 primitive. Notice also that the top-level main module has a CLKIN signal,
and that that signal has been wired to the clock of the SB_DFF.
In [5]:
%cat build/dff.v
In [6]:
import magma as m
m.set_mantle_target("ice40")
from loam.boards.icestick import IceStick
from mantle import Register
icestick = IceStick()
icestick.Clock.on() # Need to turn on the clock for sequential logic
for i in range(4):
icestick.J1[i].input().on()
icestick.J3[i].output().on()
main = icestick.DefineMain()
register4 = Register(4)
main.J3 <= register4(main.J1)
m.EndDefine()
Registers and DFFs are very similar to each other.
The only difference is that the input and output to a DFF
are Bit values,
whereas the inputs and the outputs to registers are Bits(n).
In [7]:
m.compile("build/register4", main)
In [8]:
%%bash
cd build
yosys -q -p 'synth_ice40 -top main -blif register4.blif' register4.v
arachne-pnr -q -d 1k -o register4.txt -p register4.pcf register4.blif
icepack register4.txt register4.bin
#iceprog register4.bin
If we inspect the compiled verilog, we see that our register is a module that instances a set of SB_DFFs.
In [9]:
%cat build/register4.v
Flip-flops and registers can have with clock enables and resets. The flip-flop has a clock enable, its state will only be updated if the clock enable is true. Similarly, if a flip-flop has a reset signal, it will be reset to its initial value if reset is true.
To create registers with these additional inputs,
set the optional arguments has_ce and/or has_reset
when instancing the register.
In [10]:
import magma as m
m.set_mantle_target("ice40")
from loam.boards.icestick import IceStick
from mantle import Register
icestick = IceStick()
icestick.Clock.on()
for i in range(4):
icestick.J1[i].input().on()
icestick.J3[i].output().on()
icestick.J1[4].input().on() # ce signal
icestick.J1[5].input().on() # reset signal
main = icestick.DefineMain()
register4 = Register(4, init=5, has_ce=True, has_reset=True )
main.J3 <= register4(main.J1[0:4], ce=main.J1[4], reset=main.J1[5])
m.EndDefine()
To wire the optional clock inputs, clock enable and reset,
use named arguments (ce and reset) when you call the register with its inputs.
In Magma, clock signals are handled differently than signals.
Compile, build, and upload.
In [11]:
m.compile("build/register4ce", main)
In [12]:
%%bash
cd build
yosys -q -p 'synth_ice40 -top main -blif register4ce.blif' register4ce.v
arachne-pnr -q -d 1k -o register4ce.txt -p register4ce.pcf register4ce.blif
icepack register4ce.txt register4ce.bin
#iceprog register4ce.bin
Notice in the generated verilog the code uses the SB_DFFESR primitive and that the CE port is wired up to the E (enable) input of the flip flop.
In [13]:
%cat build/register4ce.v
In [ ]: