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_DFF
s.
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 [ ]: