MNIST handwritten digits recognition

Written by Yujun Lin

Preparation

Follow the instructions on notebook for training a binary single-layer perception and saving weights and images to local file.

change image_id for other pictures. There are 10 pictures in total, numbered from 0 to 9.

change filename to the name of file containing weights and images.


In [1]:
image_id = 9
filename = 'nn_train/BNN.pkl'

Preview the image of digit

To have a look at the image to be recognized on icestick


In [2]:
import pickle
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

with open(filename, 'rb') as input_file:
    checkpoint = pickle.load(input_file)
imgs = checkpoint['imgs']

def display_img(index):
    img = imgs[index, :]
    img = np.reshape(img, [16, 16])
    plt.imshow(img, cmap='gray')
    plt.show()

display_img(image_id)


Rewrite script for new image_id and filename


In [3]:
with open('modules.py', 'r') as m, open('pipeline.py', 'w') as p:
    for line in m:
        if line.startswith('image_id = '):
            p.write('image_id = {}\n'.format(image_id))
        elif line.startswith('filename = '):
            p.write('filename = \'{}\'\n'.format(filename))
        else:
            p.write(line)

Compile

we can use the magma binary to compile nn.py for the icestick


In [4]:
!../../bin/magma -b icestick main.py


import mantle lattice ice40
import mantle lattice mantle40
compiling FullAdder
compiling Add4Cout
compiling Register4
compiling Counter4
compiling Add4
compiling Register4R
compiling Register4CE
compiling Cascade4x2_2
compiling Controller
compiling ReadROM
compiling Register24
compiling NXOr2x16
compiling BitCounter4
compiling HalfAdder
compiling BitCounter8
compiling BitCounter16
compiling Add9
compiling Mux2
compiling Mux2x9
compiling Register9
compiling Register8
compiling Invert9
compiling Add9CinCout
compiling Sub9Cout
compiling Register9CE
compiling Classifier
compiling Pipeline
compiling main

To inspect the generated verilog


In [5]:
with open("build/main.v", "r") as main_verilog:
    print(main_verilog.read())


module FullAdder (input  I0, input  I1, input  CIN, output  O, output  COUT);
wire  inst0_O;
wire  inst1_CO;
SB_LUT4 #(.LUT_INIT(16'h9696)) inst0 (.I0(I0), .I1(I1), .I2(CIN), .I3(1'b0), .O(inst0_O));
SB_CARRY inst1 (.I0(I0), .I1(I1), .CI(CIN), .CO(inst1_CO));
assign O = inst0_O;
assign COUT = inst1_CO;
endmodule

module Add4Cout (input [3:0] I0, input [3:0] I1, output [3:0] O, output  COUT);
wire  inst0_O;
wire  inst0_COUT;
wire  inst1_O;
wire  inst1_COUT;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
FullAdder inst0 (.I0(I0[0]), .I1(I1[0]), .CIN(1'b0), .O(inst0_O), .COUT(inst0_COUT));
FullAdder inst1 (.I0(I0[1]), .I1(I1[1]), .CIN(inst0_COUT), .O(inst1_O), .COUT(inst1_COUT));
FullAdder inst2 (.I0(I0[2]), .I1(I1[2]), .CIN(inst1_COUT), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(I0[3]), .I1(I1[3]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
assign O = {inst3_O,inst2_O,inst1_O,inst0_O};
assign COUT = inst3_COUT;
endmodule

module Register4 (input [3:0] I, output [3:0] O, input  CLK);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
SB_DFF inst0 (.C(CLK), .D(I[0]), .Q(inst0_Q));
SB_DFF inst1 (.C(CLK), .D(I[1]), .Q(inst1_Q));
SB_DFF inst2 (.C(CLK), .D(I[2]), .Q(inst2_Q));
SB_DFF inst3 (.C(CLK), .D(I[3]), .Q(inst3_Q));
assign O = {inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Counter4 (output [3:0] O, output  COUT, input  CLK);
wire [3:0] inst0_O;
wire  inst0_COUT;
wire [3:0] inst1_O;
Add4Cout inst0 (.I0(inst1_O), .I1({1'b0,1'b0,1'b0,1'b1}), .O(inst0_O), .COUT(inst0_COUT));
Register4 inst1 (.I(inst0_O), .O(inst1_O), .CLK(CLK));
assign O = inst1_O;
assign COUT = inst0_COUT;
endmodule

module Add4 (input [3:0] I0, input [3:0] I1, output [3:0] O);
wire  inst0_O;
wire  inst0_COUT;
wire  inst1_O;
wire  inst1_COUT;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
FullAdder inst0 (.I0(I0[0]), .I1(I1[0]), .CIN(1'b0), .O(inst0_O), .COUT(inst0_COUT));
FullAdder inst1 (.I0(I0[1]), .I1(I1[1]), .CIN(inst0_COUT), .O(inst1_O), .COUT(inst1_COUT));
FullAdder inst2 (.I0(I0[2]), .I1(I1[2]), .CIN(inst1_COUT), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(I0[3]), .I1(I1[3]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
assign O = {inst3_O,inst2_O,inst1_O,inst0_O};
endmodule

module Register4R (input [3:0] I, output [3:0] O, input  CLK, input  RESET);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
SB_DFFSR inst0 (.C(CLK), .R(RESET), .D(I[0]), .Q(inst0_Q));
SB_DFFSR inst1 (.C(CLK), .R(RESET), .D(I[1]), .Q(inst1_Q));
SB_DFFSR inst2 (.C(CLK), .R(RESET), .D(I[2]), .Q(inst2_Q));
SB_DFFSR inst3 (.C(CLK), .R(RESET), .D(I[3]), .Q(inst3_Q));
assign O = {inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Register4CE (input [3:0] I, output [3:0] O, input  CLK, input  CE);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
SB_DFFE inst0 (.C(CLK), .E(CE), .D(I[0]), .Q(inst0_Q));
SB_DFFE inst1 (.C(CLK), .E(CE), .D(I[1]), .Q(inst1_Q));
SB_DFFE inst2 (.C(CLK), .E(CE), .D(I[2]), .Q(inst2_Q));
SB_DFFE inst3 (.C(CLK), .E(CE), .D(I[3]), .Q(inst3_Q));
assign O = {inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Cascade4x2_2 (input [3:0] I0, input [3:0] I1, output  O);
wire  inst0_O;
wire  inst1_O;
wire  inst2_O;
wire  inst3_O;
SB_LUT4 #(.LUT_INIT(16'h8282)) inst0 (.I0(1'b1), .I1(I0[0]), .I2(I1[0]), .I3(1'b0), .O(inst0_O));
SB_LUT4 #(.LUT_INIT(16'h8282)) inst1 (.I0(inst0_O), .I1(I0[1]), .I2(I1[1]), .I3(1'b0), .O(inst1_O));
SB_LUT4 #(.LUT_INIT(16'h8282)) inst2 (.I0(inst1_O), .I1(I0[2]), .I2(I1[2]), .I3(1'b0), .O(inst2_O));
SB_LUT4 #(.LUT_INIT(16'h8282)) inst3 (.I0(inst2_O), .I1(I0[3]), .I2(I1[3]), .I3(1'b0), .O(inst3_O));
assign O = inst3_O;
endmodule

module Controller (input  CLK, output [3:0] IDX, output [3:0] CYCLE);
wire [3:0] inst0_O;
wire [3:0] inst1_O;
wire [3:0] inst2_O;
wire [3:0] inst3_O;
wire  inst4_O;
wire  inst5_O;
wire  inst6_O;
Add4 inst0 (.I0(inst1_O), .I1({1'b0,1'b0,1'b0,1'b1}), .O(inst0_O));
Register4R inst1 (.I(inst0_O), .O(inst1_O), .CLK(CLK), .RESET(inst4_O));
Add4 inst2 (.I0(inst3_O), .I1({1'b0,1'b0,1'b0,inst6_O}), .O(inst2_O));
Register4CE inst3 (.I(inst2_O), .O(inst3_O), .CLK(CLK), .CE(inst4_O));
Cascade4x2_2 inst4 (.I0(inst1_O), .I1({1'b1,1'b1,1'b1,1'b1}), .O(inst4_O));
Cascade4x2_2 inst5 (.I0(inst3_O), .I1({1'b1,1'b0,1'b0,1'b1}), .O(inst5_O));
SB_LUT4 #(.LUT_INIT(16'h7777)) inst6 (.I0(inst4_O), .I1(inst5_O), .I2(1'b0), .I3(1'b0), .O(inst6_O));
assign IDX = inst3_O;
assign CYCLE = inst0_O;
endmodule

module ReadROM (input [3:0] IDX, input [3:0] CYCLE, input  CLK, output [15:0] WEIGHT, output [15:0] IMAGE);
wire [15:0] inst0_RDATA;
wire  inst1_O;
wire  inst2_O;
wire  inst3_O;
wire  inst4_O;
wire  inst5_O;
wire  inst6_O;
wire  inst7_O;
wire  inst8_O;
wire  inst9_O;
wire  inst10_O;
wire  inst11_O;
wire  inst12_O;
wire  inst13_O;
wire  inst14_O;
wire  inst15_O;
wire  inst16_O;
SB_RAM40_4K #(.INIT_0(256'h770FEA140D861B00EE5A1436641B341CDE0A1E1941DD26F2D0F019CD2C8162CB),
.INIT_1(256'h7F6E3828E003D002C304E101C1800103410340C04081C0004033714FD394F3A1),
.INIT_2(256'hA1A4EA02782F2E375F2EB7FF3D0041A060020020C030DD5A9B405FE65882981C),
.INIT_3(256'h23221E648C89FD715050F05A0015C162A3D7A0D3C0F6D1284FE28C06BFA43405),
.INIT_4(256'h8BBFD00A5037C016C001694624621E642E7ACE614415302D5009E815E31101CE),
.INIT_5(256'h082B0C7E49815B6D5113A03D8001A61389838E00030F023A4C0FBC5CD2A3B423),
.INIT_6(256'h5DFAA00E8007418247F80F7E4438C0A7CD7DAA0081018001900601DAECFE0BF1),
.INIT_7(256'h83B27EB7B81B6003010340C1A06280013073ED6947FA0C4220035001CB7321BE),
.INIT_8(256'h78187831E7B511D60E0065414280C3C603D895734D1D871DA371428936D951CD),
.INIT_9(256'h781DA8F9A0348009800380C12441AEE39EF3DE704503814390430806318B2A66),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000),
.READ_MODE(0),
.WRITE_MODE(0)) inst0 (.RDATA(inst0_RDATA), .RADDR({1'b0,1'b0,1'b0,IDX[3],IDX[2],IDX[1],IDX[0],CYCLE[3],CYCLE[2],CYCLE[1],CYCLE[0]}), .RCLK(CLK), .RCLKE(1'b1), .RE(1'b1), .WCLK(CLK), .WCLKE(1'b0), .WE(1'b0), .WADDR({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), .MASK({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), .WDATA({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}));
SB_LUT4 #(.LUT_INIT(0)) inst1 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst1_O));
SB_LUT4 #(.LUT_INIT(0)) inst2 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst2_O));
SB_LUT4 #(.LUT_INIT(0)) inst3 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst3_O));
SB_LUT4 #(.LUT_INIT(0)) inst4 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst4_O));
SB_LUT4 #(.LUT_INIT(0)) inst5 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst5_O));
SB_LUT4 #(.LUT_INIT(15840)) inst6 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst6_O));
SB_LUT4 #(.LUT_INIT(32752)) inst7 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst7_O));
SB_LUT4 #(.LUT_INIT(16176)) inst8 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst8_O));
SB_LUT4 #(.LUT_INIT(816)) inst9 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst9_O));
SB_LUT4 #(.LUT_INIT(1008)) inst10 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst10_O));
SB_LUT4 #(.LUT_INIT(480)) inst11 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst11_O));
SB_LUT4 #(.LUT_INIT(0)) inst12 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst12_O));
SB_LUT4 #(.LUT_INIT(0)) inst13 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst13_O));
SB_LUT4 #(.LUT_INIT(0)) inst14 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst14_O));
SB_LUT4 #(.LUT_INIT(0)) inst15 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst15_O));
SB_LUT4 #(.LUT_INIT(0)) inst16 (.I0(CYCLE[0]), .I1(CYCLE[1]), .I2(CYCLE[2]), .I3(CYCLE[3]), .O(inst16_O));
assign WEIGHT = inst0_RDATA;
assign IMAGE = {inst16_O,inst15_O,inst14_O,inst13_O,inst12_O,inst11_O,inst10_O,inst9_O,inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O};
endmodule

module Register24 (input [23:0] I, output [23:0] O, input  CLK);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
wire  inst4_Q;
wire  inst5_Q;
wire  inst6_Q;
wire  inst7_Q;
wire  inst8_Q;
wire  inst9_Q;
wire  inst10_Q;
wire  inst11_Q;
wire  inst12_Q;
wire  inst13_Q;
wire  inst14_Q;
wire  inst15_Q;
wire  inst16_Q;
wire  inst17_Q;
wire  inst18_Q;
wire  inst19_Q;
wire  inst20_Q;
wire  inst21_Q;
wire  inst22_Q;
wire  inst23_Q;
SB_DFF inst0 (.C(CLK), .D(I[0]), .Q(inst0_Q));
SB_DFF inst1 (.C(CLK), .D(I[1]), .Q(inst1_Q));
SB_DFF inst2 (.C(CLK), .D(I[2]), .Q(inst2_Q));
SB_DFF inst3 (.C(CLK), .D(I[3]), .Q(inst3_Q));
SB_DFF inst4 (.C(CLK), .D(I[4]), .Q(inst4_Q));
SB_DFF inst5 (.C(CLK), .D(I[5]), .Q(inst5_Q));
SB_DFF inst6 (.C(CLK), .D(I[6]), .Q(inst6_Q));
SB_DFF inst7 (.C(CLK), .D(I[7]), .Q(inst7_Q));
SB_DFF inst8 (.C(CLK), .D(I[8]), .Q(inst8_Q));
SB_DFF inst9 (.C(CLK), .D(I[9]), .Q(inst9_Q));
SB_DFF inst10 (.C(CLK), .D(I[10]), .Q(inst10_Q));
SB_DFF inst11 (.C(CLK), .D(I[11]), .Q(inst11_Q));
SB_DFF inst12 (.C(CLK), .D(I[12]), .Q(inst12_Q));
SB_DFF inst13 (.C(CLK), .D(I[13]), .Q(inst13_Q));
SB_DFF inst14 (.C(CLK), .D(I[14]), .Q(inst14_Q));
SB_DFF inst15 (.C(CLK), .D(I[15]), .Q(inst15_Q));
SB_DFF inst16 (.C(CLK), .D(I[16]), .Q(inst16_Q));
SB_DFF inst17 (.C(CLK), .D(I[17]), .Q(inst17_Q));
SB_DFF inst18 (.C(CLK), .D(I[18]), .Q(inst18_Q));
SB_DFF inst19 (.C(CLK), .D(I[19]), .Q(inst19_Q));
SB_DFF inst20 (.C(CLK), .D(I[20]), .Q(inst20_Q));
SB_DFF inst21 (.C(CLK), .D(I[21]), .Q(inst21_Q));
SB_DFF inst22 (.C(CLK), .D(I[22]), .Q(inst22_Q));
SB_DFF inst23 (.C(CLK), .D(I[23]), .Q(inst23_Q));
assign O = {inst23_Q,inst22_Q,inst21_Q,inst20_Q,inst19_Q,inst18_Q,inst17_Q,inst16_Q,inst15_Q,inst14_Q,inst13_Q,inst12_Q,inst11_Q,inst10_Q,inst9_Q,inst8_Q,inst7_Q,inst6_Q,inst5_Q,inst4_Q,inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module NXOr2x16 (input [15:0] I0, input [15:0] I1, output [15:0] O);
wire  inst0_O;
wire  inst1_O;
wire  inst2_O;
wire  inst3_O;
wire  inst4_O;
wire  inst5_O;
wire  inst6_O;
wire  inst7_O;
wire  inst8_O;
wire  inst9_O;
wire  inst10_O;
wire  inst11_O;
wire  inst12_O;
wire  inst13_O;
wire  inst14_O;
wire  inst15_O;
SB_LUT4 #(.LUT_INIT(16'h9999)) inst0 (.I0(I0[0]), .I1(I1[0]), .I2(1'b0), .I3(1'b0), .O(inst0_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst1 (.I0(I0[1]), .I1(I1[1]), .I2(1'b0), .I3(1'b0), .O(inst1_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst2 (.I0(I0[2]), .I1(I1[2]), .I2(1'b0), .I3(1'b0), .O(inst2_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst3 (.I0(I0[3]), .I1(I1[3]), .I2(1'b0), .I3(1'b0), .O(inst3_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst4 (.I0(I0[4]), .I1(I1[4]), .I2(1'b0), .I3(1'b0), .O(inst4_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst5 (.I0(I0[5]), .I1(I1[5]), .I2(1'b0), .I3(1'b0), .O(inst5_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst6 (.I0(I0[6]), .I1(I1[6]), .I2(1'b0), .I3(1'b0), .O(inst6_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst7 (.I0(I0[7]), .I1(I1[7]), .I2(1'b0), .I3(1'b0), .O(inst7_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst8 (.I0(I0[8]), .I1(I1[8]), .I2(1'b0), .I3(1'b0), .O(inst8_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst9 (.I0(I0[9]), .I1(I1[9]), .I2(1'b0), .I3(1'b0), .O(inst9_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst10 (.I0(I0[10]), .I1(I1[10]), .I2(1'b0), .I3(1'b0), .O(inst10_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst11 (.I0(I0[11]), .I1(I1[11]), .I2(1'b0), .I3(1'b0), .O(inst11_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst12 (.I0(I0[12]), .I1(I1[12]), .I2(1'b0), .I3(1'b0), .O(inst12_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst13 (.I0(I0[13]), .I1(I1[13]), .I2(1'b0), .I3(1'b0), .O(inst13_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst14 (.I0(I0[14]), .I1(I1[14]), .I2(1'b0), .I3(1'b0), .O(inst14_O));
SB_LUT4 #(.LUT_INIT(16'h9999)) inst15 (.I0(I0[15]), .I1(I1[15]), .I2(1'b0), .I3(1'b0), .O(inst15_O));
assign O = {inst15_O,inst14_O,inst13_O,inst12_O,inst11_O,inst10_O,inst9_O,inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O,inst0_O};
endmodule

module BitCounter4 (input [3:0] I, output [2:0] O);
wire  inst0_O;
wire  inst1_O;
wire  inst2_O;
SB_LUT4 #(.LUT_INIT(27030)) inst0 (.I0(I[0]), .I1(I[1]), .I2(I[2]), .I3(I[3]), .O(inst0_O));
SB_LUT4 #(.LUT_INIT(32488)) inst1 (.I0(I[0]), .I1(I[1]), .I2(I[2]), .I3(I[3]), .O(inst1_O));
SB_LUT4 #(.LUT_INIT(32768)) inst2 (.I0(I[0]), .I1(I[1]), .I2(I[2]), .I3(I[3]), .O(inst2_O));
assign O = {inst2_O,inst1_O,inst0_O};
endmodule

module HalfAdder (input  I0, input  I1, output  O, output  COUT);
wire  inst0_O;
wire  inst1_CO;
SB_LUT4 #(.LUT_INIT(16'h6666)) inst0 (.I0(I0), .I1(I1), .I2(1'b0), .I3(1'b0), .O(inst0_O));
SB_CARRY inst1 (.I0(I0), .I1(I1), .CI(1'b0), .CO(inst1_CO));
assign O = inst0_O;
assign COUT = inst1_CO;
endmodule

module BitCounter8 (input [7:0] I, output [3:0] O);
wire [2:0] inst0_O;
wire [2:0] inst1_O;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
wire  inst4_O;
wire  inst4_COUT;
BitCounter4 inst0 (.I({I[3],I[2],I[1],I[0]}), .O(inst0_O));
BitCounter4 inst1 (.I({I[7],I[6],I[5],I[4]}), .O(inst1_O));
HalfAdder inst2 (.I0(inst0_O[0]), .I1(inst1_O[0]), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(inst0_O[1]), .I1(inst1_O[1]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
FullAdder inst4 (.I0(inst0_O[2]), .I1(inst1_O[2]), .CIN(inst3_COUT), .O(inst4_O), .COUT(inst4_COUT));
assign O = {inst4_COUT,inst4_O,inst3_O,inst2_O};
endmodule

module BitCounter16 (input [15:0] I, output [4:0] O);
wire [3:0] inst0_O;
wire [3:0] inst1_O;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
wire  inst4_O;
wire  inst4_COUT;
wire  inst5_O;
wire  inst5_COUT;
BitCounter8 inst0 (.I({I[7],I[6],I[5],I[4],I[3],I[2],I[1],I[0]}), .O(inst0_O));
BitCounter8 inst1 (.I({I[15],I[14],I[13],I[12],I[11],I[10],I[9],I[8]}), .O(inst1_O));
HalfAdder inst2 (.I0(inst0_O[0]), .I1(inst1_O[0]), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(inst0_O[1]), .I1(inst1_O[1]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
FullAdder inst4 (.I0(inst0_O[2]), .I1(inst1_O[2]), .CIN(inst3_COUT), .O(inst4_O), .COUT(inst4_COUT));
FullAdder inst5 (.I0(inst0_O[3]), .I1(inst1_O[3]), .CIN(inst4_COUT), .O(inst5_O), .COUT(inst5_COUT));
assign O = {inst5_COUT,inst5_O,inst4_O,inst3_O,inst2_O};
endmodule

module Add9 (input [8:0] I0, input [8:0] I1, output [8:0] O);
wire  inst0_O;
wire  inst0_COUT;
wire  inst1_O;
wire  inst1_COUT;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
wire  inst4_O;
wire  inst4_COUT;
wire  inst5_O;
wire  inst5_COUT;
wire  inst6_O;
wire  inst6_COUT;
wire  inst7_O;
wire  inst7_COUT;
wire  inst8_O;
wire  inst8_COUT;
FullAdder inst0 (.I0(I0[0]), .I1(I1[0]), .CIN(1'b0), .O(inst0_O), .COUT(inst0_COUT));
FullAdder inst1 (.I0(I0[1]), .I1(I1[1]), .CIN(inst0_COUT), .O(inst1_O), .COUT(inst1_COUT));
FullAdder inst2 (.I0(I0[2]), .I1(I1[2]), .CIN(inst1_COUT), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(I0[3]), .I1(I1[3]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
FullAdder inst4 (.I0(I0[4]), .I1(I1[4]), .CIN(inst3_COUT), .O(inst4_O), .COUT(inst4_COUT));
FullAdder inst5 (.I0(I0[5]), .I1(I1[5]), .CIN(inst4_COUT), .O(inst5_O), .COUT(inst5_COUT));
FullAdder inst6 (.I0(I0[6]), .I1(I1[6]), .CIN(inst5_COUT), .O(inst6_O), .COUT(inst6_COUT));
FullAdder inst7 (.I0(I0[7]), .I1(I1[7]), .CIN(inst6_COUT), .O(inst7_O), .COUT(inst7_COUT));
FullAdder inst8 (.I0(I0[8]), .I1(I1[8]), .CIN(inst7_COUT), .O(inst8_O), .COUT(inst8_COUT));
assign O = {inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O,inst0_O};
endmodule

module Mux2 (input [1:0] I, input  S, output  O);
wire  inst0_O;
SB_LUT4 #(.LUT_INIT(16'hCACA)) inst0 (.I0(I[0]), .I1(I[1]), .I2(S), .I3(1'b0), .O(inst0_O));
assign O = inst0_O;
endmodule

module Mux2x9 (input [8:0] I0, input [8:0] I1, input  S, output [8:0] O);
wire  inst0_O;
wire  inst1_O;
wire  inst2_O;
wire  inst3_O;
wire  inst4_O;
wire  inst5_O;
wire  inst6_O;
wire  inst7_O;
wire  inst8_O;
Mux2 inst0 (.I({I1[0],I0[0]}), .S(S), .O(inst0_O));
Mux2 inst1 (.I({I1[1],I0[1]}), .S(S), .O(inst1_O));
Mux2 inst2 (.I({I1[2],I0[2]}), .S(S), .O(inst2_O));
Mux2 inst3 (.I({I1[3],I0[3]}), .S(S), .O(inst3_O));
Mux2 inst4 (.I({I1[4],I0[4]}), .S(S), .O(inst4_O));
Mux2 inst5 (.I({I1[5],I0[5]}), .S(S), .O(inst5_O));
Mux2 inst6 (.I({I1[6],I0[6]}), .S(S), .O(inst6_O));
Mux2 inst7 (.I({I1[7],I0[7]}), .S(S), .O(inst7_O));
Mux2 inst8 (.I({I1[8],I0[8]}), .S(S), .O(inst8_O));
assign O = {inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O,inst0_O};
endmodule

module Register9 (input [8:0] I, output [8:0] O, input  CLK);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
wire  inst4_Q;
wire  inst5_Q;
wire  inst6_Q;
wire  inst7_Q;
wire  inst8_Q;
SB_DFF inst0 (.C(CLK), .D(I[0]), .Q(inst0_Q));
SB_DFF inst1 (.C(CLK), .D(I[1]), .Q(inst1_Q));
SB_DFF inst2 (.C(CLK), .D(I[2]), .Q(inst2_Q));
SB_DFF inst3 (.C(CLK), .D(I[3]), .Q(inst3_Q));
SB_DFF inst4 (.C(CLK), .D(I[4]), .Q(inst4_Q));
SB_DFF inst5 (.C(CLK), .D(I[5]), .Q(inst5_Q));
SB_DFF inst6 (.C(CLK), .D(I[6]), .Q(inst6_Q));
SB_DFF inst7 (.C(CLK), .D(I[7]), .Q(inst7_Q));
SB_DFF inst8 (.C(CLK), .D(I[8]), .Q(inst8_Q));
assign O = {inst8_Q,inst7_Q,inst6_Q,inst5_Q,inst4_Q,inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Register8 (input [7:0] I, output [7:0] O, input  CLK);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
wire  inst4_Q;
wire  inst5_Q;
wire  inst6_Q;
wire  inst7_Q;
SB_DFF inst0 (.C(CLK), .D(I[0]), .Q(inst0_Q));
SB_DFF inst1 (.C(CLK), .D(I[1]), .Q(inst1_Q));
SB_DFF inst2 (.C(CLK), .D(I[2]), .Q(inst2_Q));
SB_DFF inst3 (.C(CLK), .D(I[3]), .Q(inst3_Q));
SB_DFF inst4 (.C(CLK), .D(I[4]), .Q(inst4_Q));
SB_DFF inst5 (.C(CLK), .D(I[5]), .Q(inst5_Q));
SB_DFF inst6 (.C(CLK), .D(I[6]), .Q(inst6_Q));
SB_DFF inst7 (.C(CLK), .D(I[7]), .Q(inst7_Q));
assign O = {inst7_Q,inst6_Q,inst5_Q,inst4_Q,inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Invert9 (input [8:0] I, output [8:0] O);
wire  inst0_O;
wire  inst1_O;
wire  inst2_O;
wire  inst3_O;
wire  inst4_O;
wire  inst5_O;
wire  inst6_O;
wire  inst7_O;
wire  inst8_O;
SB_LUT4 #(.LUT_INIT(16'h5555)) inst0 (.I0(I[0]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst0_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst1 (.I0(I[1]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst1_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst2 (.I0(I[2]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst2_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst3 (.I0(I[3]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst3_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst4 (.I0(I[4]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst4_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst5 (.I0(I[5]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst5_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst6 (.I0(I[6]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst6_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst7 (.I0(I[7]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst7_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst8 (.I0(I[8]), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst8_O));
assign O = {inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O,inst0_O};
endmodule

module Add9CinCout (input [8:0] I0, input [8:0] I1, input  CIN, output [8:0] O, output  COUT);
wire  inst0_O;
wire  inst0_COUT;
wire  inst1_O;
wire  inst1_COUT;
wire  inst2_O;
wire  inst2_COUT;
wire  inst3_O;
wire  inst3_COUT;
wire  inst4_O;
wire  inst4_COUT;
wire  inst5_O;
wire  inst5_COUT;
wire  inst6_O;
wire  inst6_COUT;
wire  inst7_O;
wire  inst7_COUT;
wire  inst8_O;
wire  inst8_COUT;
FullAdder inst0 (.I0(I0[0]), .I1(I1[0]), .CIN(CIN), .O(inst0_O), .COUT(inst0_COUT));
FullAdder inst1 (.I0(I0[1]), .I1(I1[1]), .CIN(inst0_COUT), .O(inst1_O), .COUT(inst1_COUT));
FullAdder inst2 (.I0(I0[2]), .I1(I1[2]), .CIN(inst1_COUT), .O(inst2_O), .COUT(inst2_COUT));
FullAdder inst3 (.I0(I0[3]), .I1(I1[3]), .CIN(inst2_COUT), .O(inst3_O), .COUT(inst3_COUT));
FullAdder inst4 (.I0(I0[4]), .I1(I1[4]), .CIN(inst3_COUT), .O(inst4_O), .COUT(inst4_COUT));
FullAdder inst5 (.I0(I0[5]), .I1(I1[5]), .CIN(inst4_COUT), .O(inst5_O), .COUT(inst5_COUT));
FullAdder inst6 (.I0(I0[6]), .I1(I1[6]), .CIN(inst5_COUT), .O(inst6_O), .COUT(inst6_COUT));
FullAdder inst7 (.I0(I0[7]), .I1(I1[7]), .CIN(inst6_COUT), .O(inst7_O), .COUT(inst7_COUT));
FullAdder inst8 (.I0(I0[8]), .I1(I1[8]), .CIN(inst7_COUT), .O(inst8_O), .COUT(inst8_COUT));
assign O = {inst8_O,inst7_O,inst6_O,inst5_O,inst4_O,inst3_O,inst2_O,inst1_O,inst0_O};
assign COUT = inst8_COUT;
endmodule

module Sub9Cout (input [8:0] I0, input [8:0] I1, output [8:0] O, output  COUT);
wire [8:0] inst0_O;
wire [8:0] inst1_O;
wire  inst1_COUT;
Invert9 inst0 (.I(I1), .O(inst0_O));
Add9CinCout inst1 (.I0(I0), .I1(inst0_O), .CIN(1'b1), .O(inst1_O), .COUT(inst1_COUT));
assign O = inst1_O;
assign COUT = inst1_COUT;
endmodule

module Register9CE (input [8:0] I, output [8:0] O, input  CLK, input  CE);
wire  inst0_Q;
wire  inst1_Q;
wire  inst2_Q;
wire  inst3_Q;
wire  inst4_Q;
wire  inst5_Q;
wire  inst6_Q;
wire  inst7_Q;
wire  inst8_Q;
SB_DFFE inst0 (.C(CLK), .E(CE), .D(I[0]), .Q(inst0_Q));
SB_DFFE inst1 (.C(CLK), .E(CE), .D(I[1]), .Q(inst1_Q));
SB_DFFE inst2 (.C(CLK), .E(CE), .D(I[2]), .Q(inst2_Q));
SB_DFFE inst3 (.C(CLK), .E(CE), .D(I[3]), .Q(inst3_Q));
SB_DFFE inst4 (.C(CLK), .E(CE), .D(I[4]), .Q(inst4_Q));
SB_DFFE inst5 (.C(CLK), .E(CE), .D(I[5]), .Q(inst5_Q));
SB_DFFE inst6 (.C(CLK), .E(CE), .D(I[6]), .Q(inst6_Q));
SB_DFFE inst7 (.C(CLK), .E(CE), .D(I[7]), .Q(inst7_Q));
SB_DFFE inst8 (.C(CLK), .E(CE), .D(I[8]), .Q(inst8_Q));
assign O = {inst8_Q,inst7_Q,inst6_Q,inst5_Q,inst4_Q,inst3_Q,inst2_Q,inst1_Q,inst0_Q};
endmodule

module Classifier (input [8:0] I, input [3:0] IDX, input  CLK, output [3:0] O);
wire  inst0_O;
wire [8:0] inst1_O;
wire  inst1_COUT;
wire [8:0] inst2_O;
wire [3:0] inst3_O;
SB_LUT4 #(.LUT_INIT(16'h5555)) inst0 (.I0(inst1_COUT), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst0_O));
Sub9Cout inst1 (.I0(inst2_O), .I1(I), .O(inst1_O), .COUT(inst1_COUT));
Register9CE inst2 (.I(I), .O(inst2_O), .CLK(CLK), .CE(inst0_O));
Register4CE inst3 (.I(IDX), .O(inst3_O), .CLK(CLK), .CE(inst0_O));
assign O = inst3_O;
endmodule

module Pipeline (input  CLK, output [3:0] O, output  D);
wire [3:0] inst0_IDX;
wire [3:0] inst0_CYCLE;
wire [3:0] inst1_O;
wire  inst2_Q;
wire  inst3_O;
wire  inst4_O;
wire [15:0] inst5_WEIGHT;
wire [15:0] inst5_IMAGE;
wire [23:0] inst6_O;
wire  inst7_Q;
wire [15:0] inst8_O;
wire [4:0] inst9_O;
wire [8:0] inst10_O;
wire [8:0] inst11_O;
wire [8:0] inst12_O;
wire [8:0] inst13_O;
wire [7:0] inst14_O;
wire  inst15_O;
wire [3:0] inst16_O;
wire [7:0] inst17_O;
wire [3:0] inst18_O;
wire  inst19_O;
wire  inst20_O;
wire  inst21_O;
wire  inst22_Q;
wire  inst23_O;
Controller inst0 (.CLK(CLK), .IDX(inst0_IDX), .CYCLE(inst0_CYCLE));
Register4 inst1 (.I(inst0_CYCLE), .O(inst1_O), .CLK(CLK));
SB_DFF inst2 (.C(CLK), .D(inst3_O), .Q(inst2_Q));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst3 (.I0(1'b1), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst3_O));
SB_LUT4 #(.LUT_INIT(16'h5555)) inst4 (.I0(inst2_Q), .I1(1'b0), .I2(1'b0), .I3(1'b0), .O(inst4_O));
ReadROM inst5 (.IDX(inst0_IDX), .CYCLE(inst1_O), .CLK(CLK), .WEIGHT(inst5_WEIGHT), .IMAGE(inst5_IMAGE));
Register24 inst6 (.I({inst1_O[3],inst1_O[2],inst1_O[1],inst1_O[0],inst0_IDX[3],inst0_IDX[2],inst0_IDX[1],inst0_IDX[0],inst5_IMAGE[15],inst5_IMAGE[14],inst5_IMAGE[13],inst5_IMAGE[12],inst5_IMAGE[11],inst5_IMAGE[10],inst5_IMAGE[9],inst5_IMAGE[8],inst5_IMAGE[7],inst5_IMAGE[6],inst5_IMAGE[5],inst5_IMAGE[4],inst5_IMAGE[3],inst5_IMAGE[2],inst5_IMAGE[1],inst5_IMAGE[0]}), .O(inst6_O), .CLK(CLK));
SB_DFF inst7 (.C(CLK), .D(inst4_O), .Q(inst7_Q));
NXOr2x16 inst8 (.I0(inst5_WEIGHT), .I1({inst6_O[15],inst6_O[14],inst6_O[13],inst6_O[12],inst6_O[11],inst6_O[10],inst6_O[9],inst6_O[8],inst6_O[7],inst6_O[6],inst6_O[5],inst6_O[4],inst6_O[3],inst6_O[2],inst6_O[1],inst6_O[0]}), .O(inst8_O));
BitCounter16 inst9 (.I(inst8_O), .O(inst9_O));
Add9 inst10 (.I0(inst11_O), .I1(inst12_O), .O(inst10_O));
Mux2x9 inst11 (.I0({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), .I1({1'b0,1'b0,1'b0,1'b0,inst9_O[4],inst9_O[3],inst9_O[2],inst9_O[1],inst9_O[0]}), .S(inst7_Q), .O(inst11_O));
Mux2x9 inst12 (.I0(inst13_O), .I1({1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0,1'b0}), .S(inst15_O), .O(inst12_O));
Register9 inst13 (.I(inst10_O), .O(inst13_O), .CLK(CLK));
Register8 inst14 (.I({inst6_O[23],inst6_O[22],inst6_O[21],inst6_O[20],inst6_O[19],inst6_O[18],inst6_O[17],inst6_O[16]}), .O(inst14_O), .CLK(CLK));
SB_LUT4 #(.LUT_INIT(1)) inst15 (.I0(inst6_O[20]), .I1(inst6_O[21]), .I2(inst6_O[22]), .I3(inst6_O[23]), .O(inst15_O));
Classifier inst16 (.I(inst13_O), .IDX({inst14_O[3],inst14_O[2],inst14_O[1],inst14_O[0]}), .CLK(CLK), .O(inst16_O));
Register8 inst17 (.I(inst14_O), .O(inst17_O), .CLK(CLK));
Register4CE inst18 (.I(inst16_O), .O(inst18_O), .CLK(CLK), .CE(inst21_O));
Cascade4x2_2 inst19 (.I0({inst17_O[3],inst17_O[2],inst17_O[1],inst17_O[0]}), .I1({1'b1,1'b0,1'b0,1'b1}), .O(inst19_O));
Cascade4x2_2 inst20 (.I0({inst17_O[7],inst17_O[6],inst17_O[5],inst17_O[4]}), .I1({1'b1,1'b1,1'b1,1'b1}), .O(inst20_O));
SB_LUT4 #(.LUT_INIT(16'h8888)) inst21 (.I0(inst19_O), .I1(inst20_O), .I2(1'b0), .I3(1'b0), .O(inst21_O));
SB_DFF inst22 (.C(CLK), .D(inst23_O), .Q(inst22_Q));
SB_LUT4 #(.LUT_INIT(16'hEEEE)) inst23 (.I0(inst21_O), .I1(inst22_Q), .I2(1'b0), .I3(1'b0), .O(inst23_O));
assign O = inst18_O;
assign D = inst22_Q;
endmodule

module main (output  D5, output  D4, output  D3, output  D2, output  D1, input  CLKIN);
wire [3:0] inst0_O;
wire  inst0_COUT;
wire [3:0] inst1_O;
wire  inst1_D;
Counter4 inst0 (.O(inst0_O), .COUT(inst0_COUT), .CLK(CLKIN));
Pipeline inst1 (.CLK(inst0_O[3]), .O(inst1_O), .D(inst1_D));
assign D5 = inst1_D;
assign D4 = inst1_O[3];
assign D3 = inst1_O[2];
assign D2 = inst1_O[1];
assign D1 = inst1_O[0];
endmodule


To inspect the genterated pcf


In [6]:
with open("build/main.pcf", "r") as main_pcf:
    print(main_pcf.read())


set_io D5 95
set_io D4 96
set_io D3 97
set_io D2 98
set_io D1 99
set_io CLKIN 21

To flash the nn circuit onto the icestick using yosys, arachne-pnr and the icestorm tools.

To see the results of synthesis, delete choice -q in arachne-pnr command.


In [7]:
%%bash
yosys -q -p 'synth_ice40 -top main -blif build/main.blif' build/main.v
arachne-pnr -d 1k -o build/main.txt -p build/main.pcf build/main.blif 
icepack build/main.txt build/main.bin
#iceprog build/main.bin


seed: 1
device: 1k
read_chipdb +/share/arachne-pnr/chipdb-1k.bin...
  supported packages: cb121, cb132, cb81, cm121, cm36, cm49, cm81, qn84, swg16tr, tq144, vq100
read_blif build/main.blif...
prune...
read_pcf build/main.pcf...
instantiate_io...
pack...

After packing:
IOs          6 / 96
GBs          0 / 8
  GB_IOs     0 / 8
LCs          218 / 1280
  DFF        85
  CARRY      36
  CARRY, DFF 0
  DFF PASS   50
  CARRY PASS 28
BRAMs        1 / 16
WARMBOOTs    0 / 1
PLLs         0 / 1

place_constraints...
promote_globals...
  promoted inst0.inst0.inst3.I0, 84 / 84
  promoted inst1.inst16.inst0_O, 13 / 13
  promoted 2 nets
    1 cen/wclke
    1 clk
  2 globals
    1 cen/wclke
    1 clk
realize_constants...
  realized 0, 1
place...
  initial wire length = 2563
  at iteration #50: temp = 6.36153, wire length = 1903
  at iteration #100: temp = 3.43752, wire length = 1197
  at iteration #150: temp = 1.51294, wire length = 680
  at iteration #200: temp = 0.281989, wire length = 398
  final wire length = 335

After placement:
PIOs       6 / 96
PLBs       53 / 160
BRAMs      1 / 16

  place time 0.48s
route...
  pass 1, 0 shared.

After routing:
span_4     129 / 6944
span_12    28 / 1440

  route time 0.12s
write_txt build/main.txt...

To view the timing analysis


In [8]:
!icetime -tmd hx1k build/main.txt


// Reading input .asc file..
// Reading 1k chipdb file..
// Creating timing netlist..

icetime topological timing analysis report
==========================================

Info: max_span_hack is enabled: estimate is conservative.

Report for critical path:
-------------------------

        ram_3_7 (SB_RAM40_4K) [clk] -> RDATA[14]: 2.246 ns
     2.246 ns net_5145 (inst1.inst5.inst0_RDATA[14])
        odrv_3_8_5145_5275 (Odrv4) I -> O: 0.372 ns
        t208 (LocalMux) I -> O: 0.330 ns
        inmux_5_8_11197_11220 (InMux) I -> O: 0.260 ns
        lc40_5_8_3 (LogicCell40) in0 -> lcout: 0.449 ns
     3.656 ns net_9023 (inst1.inst8.inst14_O)
        odrv_5_8_9023_10248 (Odrv12) I -> O: 0.540 ns
        t329 (LocalMux) I -> O: 0.330 ns
        inmux_5_7_11063_11099 (InMux) I -> O: 0.260 ns
        t47 (CascadeMux) I -> O: 0.000 ns
        lc40_5_7_3 (LogicCell40) in2 -> lcout: 0.379 ns
     5.164 ns net_8900 (inst1.inst9.inst1.inst1.inst1_O)
        odrv_5_7_8900_10789 (Odrv4) I -> O: 0.372 ns
        t318 (LocalMux) I -> O: 0.330 ns
        inmux_6_7_13162_13196 (InMux) I -> O: 0.260 ns
        t67 (CascadeMux) I -> O: 0.000 ns
        lc40_6_7_1 (LogicCell40) in2 -> carryout: 0.231 ns
     6.356 ns net_13193 (inst1.inst9.inst1.inst3.inst1_CO$2)
        inmux_6_7_13193_13203 (InMux) I -> O: 0.260 ns
        lc40_6_7_2 (LogicCell40) in3 -> lcout: 0.316 ns
     6.931 ns net_11007 (inst1.inst9.inst1.inst3.inst1_CO)
        t367 (LocalMux) I -> O: 0.330 ns
        inmux_6_7_13173_13214 (InMux) I -> O: 0.260 ns
        t69 (CascadeMux) I -> O: 0.000 ns
        lc40_6_7_4 (LogicCell40) in2 -> lcout: 0.379 ns
     7.899 ns net_11009 (inst1.inst9.inst1.inst4.inst0_O)
        odrv_6_7_11009_11156 (Odrv4) I -> O: 0.372 ns
        t390 (LocalMux) I -> O: 0.330 ns
        inmux_6_10_13537_13571 (InMux) I -> O: 0.260 ns
        t74 (CascadeMux) I -> O: 0.000 ns
        lc40_6_10_2 (LogicCell40) in2 -> carryout: 0.231 ns
     9.091 ns net_13568 (inst1.inst9.inst4.inst1_CO$2)
        inmux_6_10_13568_13578 (InMux) I -> O: 0.260 ns
        lc40_6_10_3 (LogicCell40) in3 -> lcout: 0.316 ns
     9.666 ns net_11377 (inst1.inst9.inst4.inst1_CO)
        t419 (LocalMux) I -> O: 0.330 ns
        inmux_6_10_13543_13589 (InMux) I -> O: 0.260 ns
        t76 (CascadeMux) I -> O: 0.000 ns
        lc40_6_10_5 (LogicCell40) in2 -> lcout: 0.379 ns
    10.634 ns net_11379 (inst1.inst9.inst5.inst0_O)
        odrv_6_10_11379_11401 (Odrv4) I -> O: 0.372 ns
        t421 (LocalMux) I -> O: 0.330 ns
        inmux_6_12_13772_13822 (InMux) I -> O: 0.260 ns
        lc40_6_12_3 (LogicCell40) in1 -> lcout: 0.400 ns
    11.995 ns net_11623 (inst1.inst10.inst3.I0)
        t428 (LocalMux) I -> O: 0.330 ns
        inmux_7_13_16029_16054 (InMux) I -> O: 0.260 ns
        lc40_7_13_3 (LogicCell40) in1 -> carryout: 0.260 ns
    12.843 ns net_16052 (inst1.inst10.inst3.inst1_CO$2)
        lc40_7_13_4 (LogicCell40) carryin -> carryout: 0.126 ns
    12.970 ns net_16058 (inst1.inst10.inst4.inst1_CO$2)
        lc40_7_13_5 (LogicCell40) carryin -> carryout: 0.126 ns
    13.096 ns net_16064 (inst1.inst10.inst5.inst1_CO$2)
        lc40_7_13_6 (LogicCell40) carryin -> carryout: 0.126 ns
    13.222 ns net_16070 (inst1.inst10.inst6.inst1_CO$2)
        inmux_7_13_16070_16080 (InMux) I -> O: 0.260 ns
        lc40_7_13_7 (LogicCell40) in3 -> lcout: 0.316 ns
    13.797 ns net_13859 (inst1.inst10.inst6.inst1_CO)
        t541 (LocalMux) I -> O: 0.330 ns
        inmux_7_12_15894_15950 (InMux) I -> O: 0.260 ns
        t107 (CascadeMux) I -> O: 0.000 ns
    14.386 ns net_15950_cascademuxed
        lc40_7_12_6 (LogicCell40) in2 [setup]: 0.323 ns
    14.709 ns net_13735 (inst1.inst13.inst7_Q)

Resolvable net names on path:
     2.246 ns ..  3.207 ns inst1.inst5.inst0_RDATA[14]
     3.656 ns ..  4.785 ns inst1.inst8.inst14_O
     5.164 ns ..  6.125 ns inst1.inst9.inst1.inst1.inst1_O
     6.356 ns ..  6.615 ns inst1.inst9.inst1.inst3.inst1_CO$2
     6.931 ns ..  7.520 ns inst1.inst9.inst1.inst3.inst1_CO
     7.899 ns ..  8.860 ns inst1.inst9.inst1.inst4.inst0_O
     9.091 ns ..  9.351 ns inst1.inst9.inst4.inst1_CO$2
     9.666 ns .. 10.255 ns inst1.inst9.inst4.inst1_CO
    10.634 ns .. 11.595 ns inst1.inst9.inst5.inst0_O
    11.995 ns .. 12.584 ns inst1.inst10.inst3.I0
    12.843 ns .. 12.843 ns inst1.inst10.inst3.inst1_CO$2
    12.970 ns .. 12.970 ns inst1.inst10.inst4.inst1_CO$2
    13.096 ns .. 13.096 ns inst1.inst10.inst5.inst1_CO$2
    13.222 ns .. 13.482 ns inst1.inst10.inst6.inst1_CO$2
    13.797 ns .. 14.386 ns inst1.inst10.inst6.inst1_CO
                  lcout -> inst1.inst13.inst7_Q

Total number of logic levels: 15
Total path delay: 14.71 ns (67.99 MHz)