<jupyter_start><jupyter_text>DFFs and RegistersThis example demonstrates the use of d-flip-flops and registers.<jupyter_code>import magma as m
m.set_mantle_target("ice40")<jupyter_output><empty_output><jupyter_text>DFFTo 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 similarto 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.<jupyter_code>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()<jupyter_output>import lattice ice40
import lattice mantle40<jupyter_text>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.<jupyter_code>m.compile("build/dff", main)
%%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<jupyter_output>/Users/hanrahan/git/magmathon/notebooks/tutorial/icestick/build<jupyter_text>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`.<jupyter_code>%cat build/dff.v<jupyter_output>module main (input  J1, output  J3, input  CLKIN);
wire  SB_DFF_inst0_Q;
SB_DFF SB_DFF_inst0 (.C(CLKIN), .D(J1), .Q(SB_DFF_inst0_Q));
assign J3 = SB_DFF_inst0_Q;
endmodule<jupyter_text>RegisterA register is simply an array of flip-flops.To create an instance of a register, call `Register`with the number of bits `n` in the register.<jupyter_code>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()<jupyter_output><empty_output><jupyter_text>Registers and DFFs are very similar to each other.The only difference is that the input and output to a DFFare `Bit` values,whereas the inputs and the outputs to registers are `Bits(n)`.<jupyter_code>m.compile("build/register4", main)
%%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<jupyter_output>/Users/hanrahan/git/magmathon/notebooks/tutorial/icestick/build<jupyter_text>If we inspect the compiled verilog, we see that our register is a module that instances a set of `SB_DFF`s.<jupyter_code>%cat build/register4.v<jupyter_output>module Register4 (input [3:0] I, output [3:0] O, input  CLK);
wire  SB_DFF_inst0_Q;
wire  SB_DFF_inst1_Q;
wire  SB_DFF_inst2_Q;
wire  SB_DFF_inst3_Q;
SB_DFF SB_DFF_inst0 (.C(CLK), .D(I[0]), .Q(SB_DFF_inst0_Q));
SB_DFF SB_DFF_inst1 (.C(CLK), .D(I[1]), .Q(SB_DFF_inst1_Q));
SB_DFF SB_DFF_inst2 (.C(CLK), .D(I[2]), .Q(SB_DFF_inst2_Q));
SB_DFF SB_DFF_inst3 (.C(CLK), .D(I[3]), .Q(SB_DFF_inst3_Q));
assign O = {SB_DFF_inst3_Q,SB_DFF_inst2_Q,SB_DFF_inst1_Q,SB_DFF_inst0_Q};
endmodule

module main (input [3:0] J1, output [3:0] J3, input  CLKIN);
wire [3:0] Register4_inst0_O;
Register4 Register4_inst0 (.I(J1), .O(Register4_inst0_O), .CLK(CLKIN));
assign J3 = Register4_inst0_O;
endmodule<jupyter_text>Enables and ResetsFlip-flops and registers can have with clock enables and resets.The flip-flop has a clock enable, its state will only be updatedif 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.<jupyter_code>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()<jupyter_output><empty_output><jupyter_text>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.<jupyter_code>m.compile("build/register4ce", main)
%%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<jupyter_output>/Users/hanrahan/git/magmathon/notebooks/tutorial/icestick/build<jupyter_text>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.<jupyter_code>%cat build/register4ce.v<jupyter_output>module Register4CER_0005 (input [3:0] I, output [3:0] O, input  CLK, input  CE, input  RESET);
wire  SB_DFFESR_inst0_Q;
wire  SB_LUT4_inst0_O;
wire  SB_LUT4_inst1_O;
wire  SB_DFFESR_inst1_Q;
wire  SB_DFFESR_inst2_Q;
wire  SB_LUT4_inst2_O;
wire  SB_LUT4_inst3_O;
wire  SB_DFFESR_inst3_Q;
SB_DFFESR SB_DFFESR_inst0 (.C(CLK), .R(RESET), .E(CE), .D(SB_LUT4_inst0_O), .Q(SB_DFFESR_inst0_Q));
SB_LUT4 #(.LUT_INIT(16'h5555)) SB_LUT4_inst0 (.I0(I[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(SB_LUT4_inst0_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) SB_LUT4_inst1 (.I0(SB_DFFESR_inst0_Q), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(SB_LUT4_inst1_O));
SB_DFFESR SB_DFFESR_inst1 (.C(CLK), .R(RESET), .E(CE), .D(I[1]), .Q(SB_DFFESR_inst1_Q));
SB_DFFESR SB_DFFESR_inst2 (.C(CLK), .R(RESET), .E(CE), .D(SB_LUT4_inst2_O), .Q(SB_DFFESR_inst2_Q));
SB_LUT4 #(.LUT_INIT(16'h5555)) SB_LUT4_inst2 (.I0(I[2]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(SB_LUT4_inst2_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) SB_LUT4_inst3 (.I0(SB_DFFESR_[...]
{'fraction_non_alphanumeric': 0.12016794556247286, 'fraction_numerical': 0.0338786738091791, 'mean_word_length': 5.510838831291235, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '347756', 'license': 'MIT', 'n_tokens_mistral': 2874, 'n_tokens_neox': 2807, 'n_words': 726, 'path': 'notebooks/tutorial/icestick/Register.ipynb', 'repo_name': 'phanrahan/magmathon', 'size': '6907'}