gateware/e1-tracer: Initial import
This is the project specific to the e1-tracer board that was
initially based on the iCEpick with a couple dev boards attached
but eventually consolidated to a proper board, which still retaining
100% electrical compatibility (and thus same gateware and firmware)
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
diff --git a/gateware/e1-tracer/.gitignore b/gateware/e1-tracer/.gitignore
new file mode 100644
index 0000000..24d1c97
--- /dev/null
+++ b/gateware/e1-tracer/.gitignore
@@ -0,0 +1,4 @@
+build-tmp
+__pycache__
+*.vcd
+.*.swp
diff --git a/gateware/e1-tracer/Makefile b/gateware/e1-tracer/Makefile
new file mode 100644
index 0000000..cda5efc
--- /dev/null
+++ b/gateware/e1-tracer/Makefile
@@ -0,0 +1,43 @@
+# Project config
+PROJ=e1-tracer
+
+PROJ_DEPS := no2e1 no2ice40 no2misc no2usb
+PROJ_RTL_SRCS := $(addprefix rtl/, \
+ misc.v \
+ sysmgr.v \
+)
+PROJ_RTL_SRCS += $(addprefix ../common/rtl/, \
+ dfu_helper.v \
+ picorv32.v \
+ soc_base.v \
+ soc_bram.v \
+ soc_iobuf.v \
+ soc_picorv32_bridge.v \
+ soc_spram.v \
+ wb_arbiter.v \
+ wb_dma.v \
+ wb_epbuf.v \
+)
+PROJ_PREREQ = \
+ $(BUILD_TMP)/boot.hex \
+ $(NULL)
+PROJ_TOP_SRC := rtl/top.v
+PROJ_TOP_MOD := top
+
+# Target config
+BOARD ?= e1-tracer
+DEVICE = up5k
+PACKAGE = sg48
+
+NEXTPNR_ARGS = --pre-pack data/clocks.py --seed 19
+
+# Include default rules
+NO2BUILD_DIR := ../build
+include $(NO2BUILD_DIR)/project-rules.mk
+
+# Custom rules
+../common/fw/boot.hex:
+ make -C ../common/fw boot.hex
+
+$(BUILD_TMP)/boot.hex: ../common/fw/boot.hex
+ cp $< $@
diff --git a/gateware/e1-tracer/data/clocks.py b/gateware/e1-tracer/data/clocks.py
new file mode 100644
index 0000000..c39f9b2
--- /dev/null
+++ b/gateware/e1-tracer/data/clocks.py
@@ -0,0 +1,2 @@
+ctx.addClock("clk_sys", 24)
+ctx.addClock("clk_48m", 48)
diff --git a/gateware/e1-tracer/data/top-e1-tracer.pcf b/gateware/e1-tracer/data/top-e1-tracer.pcf
new file mode 100644
index 0000000..eebd02e
--- /dev/null
+++ b/gateware/e1-tracer/data/top-e1-tracer.pcf
@@ -0,0 +1,40 @@
+# LIU data
+set_io -pullup yes e1A_rx_data 45 # B1
+set_io -pullup yes e1A_rx_clk 44 # B0
+set_io -pullup yes e1B_rx_data 47 # B3
+set_io -pullup yes e1B_rx_clk 46 # B2
+
+# LIU control
+set_io -pullup yes liu_mosi 31 # A0
+set_io -pullup yes liu_miso 32 # A1
+set_io -pullup yes liu_clk 34 # A2
+set_io -pullup yes liu_cs_n[0] 42 # A4
+set_io -pullup yes liu_cs_n[1] 43 # A5
+
+# USB
+set_io usb_dp 10
+set_io usb_dn 9
+set_io usb_pu 6
+
+# Flash
+set_io -pullup yes flash_mosi 14
+set_io -pullup yes flash_miso 17
+set_io -pullup yes flash_clk 15
+set_io -pullup yes flash_cs_n 16
+
+# Vio
+set_io -pullup yes vio_pdm 19
+
+# Button
+set_io -pullup yes btn 25
+
+# Clock
+set_io clk_in 20
+
+# Debug UART
+set_io -pullup yes dbg_tx 38
+
+# Leds
+set_io rgb[0] 39
+set_io rgb[1] 40
+set_io rgb[2] 41
diff --git a/gateware/e1-tracer/doc/mem-map.md b/gateware/e1-tracer/doc/mem-map.md
new file mode 100644
index 0000000..06cfad0
--- /dev/null
+++ b/gateware/e1-tracer/doc/mem-map.md
@@ -0,0 +1,187 @@
+e1-tracer SoC Memory Map
+========================
+
+Overview
+--------
+
+| Base | Size | Description | IP Core doc
+|-------------|------------------|-----------------|-------------
+|`0x00000000` | `0x00400` (1k) | Boot ROM |
+|`0x00020000` | `0x10000` (64k) | Main SRAM |
+|`0x80000000` | | Flash SPI | [`no2ice40/ice40_spi_wb`](../../cores/no2ice40/doc/ice40_spi_wb.md)
+|`0x81000000` | | Debug UART | [`no2misc/uart_wb`](../../cores/no2misc/doc/uart_wb.md)
+|`0x82000000` | | RGB LED | [`no2ice40/ice40_rgb_wb`](../../cores/no2ice40/doc/ice40_rgb_wb.md)
+|`0x83000000` | | USB core | [`no2usb`](../../cores/no2usb/doc/mem-map.md)
+|`0x84000000` | `0x01000` (4k) | USB data buffer |
+|`0x85000000` | `0x10000` (64k) | E1 data buffer |
+|`0x86000000` | | DMA | See below
+|`0x87000000` | | E1 core | [`no2e1`](../../cores/no2e1/doc/mem-map.md). See notes below.
+|`0x88000000` | | Misc | See below
+|`0x89000000` | | LIU SPI | [`no2ice40/ice40_spi_wb`](../../cores/no2ice40/doc/ice40_spi_wb.md)
+
+
+Memory
+------
+
+### `0x00000000`: Boot ROM
+
+This memory zone is initialized directly in the FPGA bitstream itself.
+It contains the bootstrap program that will load the main firmware from
+flash into the main SRAM and jump to it.
+
+
+### `0x00020000`: Main SRAM
+
+The main SoC SRAM, implemented using the UP5k SPRAMs. It can't be initialized
+in the FPGA bitstream directly, hence the need for the Boot ROM zone.
+
+
+### `0x84000000`: USB data buffer
+
+This 4k zone actually correspond to 8k of SRAM inside the USB core.
+The RX and TX buffer for the USB are distinct and are accessed independently
+depending if read or write access are made to this zone. (RX buffer can only
+be read, TX buffer can only be written). All accesses must also be 32 bit
+wide !
+
+
+### `0x85000000`: E1 data buffer
+
+This 64k buffer is reserved for E1 data and is what is used by the E1 core.
+
+Address mapping is :
+
+```text
+,---------------------------------------------------------------,
+| f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+|---------------------------------------------------------------|
+| multi-frame | frame | timeslot |
+'---------------------------------------------------------------'
+```
+
+and the `multi-frame` number is what is exchanged in the E1 core buffer
+descriptors.
+
+
+Custom Peripherals
+------------------
+
+### `0x86000000`: DMA
+
+Very simple DMA core allowing direct copy of data between the USB and E1 data
+buffers.
+
+#### Status (Read Only, addr `0x00`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | b| d| /| len |
+'-----------------------------------------------------------------------------------------------'
+
+ * [ 15] - b : Busy flag
+ * [ 14] - d : Direction ( 0=E1 to USB, 1=USB to E1 )
+ * [12: 0] - len : Remaining length of the in-progress transfer ( -1 = done )
+```
+
+#### Transfer start/direction/length (Write Only, addr `0x00`)
+
+Write to this register initiate the transfer.
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | d| / | len |
+'-----------------------------------------------------------------------------------------------'
+
+ * [ 14] - d : Direction ( 0=E1 to USB, 1=USB to E1 )
+ * [11: 0] - len : Transfer length ( Number of Words - 2 )
+```
+
+#### E1 buffer offset (Write Only, addr `0x08`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | e1_ofs |
+'-----------------------------------------------------------------------------------------------'
+
+ * [13:0] - e1_ofs
+```
+
+Word offset inside the E1 data buffer where the next transfer will start
+
+#### USB buffer offset (Write Only, addr `0x0C`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | usb_ofs |
+'-----------------------------------------------------------------------------------------------'
+
+ * [9:0] - usb_ofs
+```
+
+Word offset inside the USB End Point buffer where the next transfer will start
+
+
+### `0x87000000`: E1 core
+
+Refer to the [`no2e1` core documentation](../../cores/no2e1/doc/mem-map.md)
+for register description.
+
+The core instanciated here has a 2 channels with only RX units present.
+
+
+### `0x88000000`: Misc
+
+Collection of small auxiliary peripherals.
+
+#### Boot (Write Only, addr `0x00`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | x| sel |
+'-----------------------------------------------------------------------------------------------'
+
+ * [ 2] - d : boot eXecute
+ * [11:0] - sel : boot select
+```
+
+Write to this register with bit 2 set will trigger a FPGA reload of the selected image.
+
+#### E1 tick channel 0/1 (Read Only, addr `0x04` / `0x05`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| / | rx_tick |
+'-----------------------------------------------------------------------------------------------'
+
+ * [15:0] - rx_tick
+```
+
+An internal counter is incremented at every bit received by the corresponding E1 channel. That
+counter value is then captured at every USB Start-of-Frame packet and the last captured value
+made available here.
+
+#### Time (Read Only, addr `0x07`)
+
+```text
+,-----------------------------------------------------------------------------------------------,
+|31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+|-----------------------------------------------------------------------------------------------|
+| time |
+'-----------------------------------------------------------------------------------------------'
+
+ * [31:0] - time
+```
+
+32 bit counter incremented at the system clock rate ( 24 MHz )
diff --git a/gateware/e1-tracer/rtl/misc.v b/gateware/e1-tracer/rtl/misc.v
new file mode 100644
index 0000000..99ae0b8
--- /dev/null
+++ b/gateware/e1-tracer/rtl/misc.v
@@ -0,0 +1,138 @@
+/*
+ * misc.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * Misc peripheral functions
+ *
+ * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
+ * SPDX-License-Identifier: CERN-OHL-S-2.0
+ */
+
+`default_nettype none
+
+module misc (
+ // Button
+ input wire btn,
+
+ // Ticks
+ input wire [1:0] tick_e1_rx,
+ input wire tick_usb_sof,
+
+ // Reset request
+ output wire rst_req,
+
+ // Wishbone
+ input wire [ 7:0] wb_addr,
+ output reg [31:0] wb_rdata,
+ input wire [31:0] wb_wdata,
+ input wire wb_we,
+ input wire wb_cyc,
+ output reg wb_ack,
+
+ // Clock / Reset
+ input wire clk,
+ input wire rst
+);
+
+ // Signals
+ // -------
+
+ genvar i;
+
+ // Bus
+ wire bus_clr;
+ reg bus_we_boot;
+
+ // Counters
+ reg [15:0] cnt_e1_rx[0:1];
+ reg [15:0] cap_e1_rx[0:1];
+ reg [31:0] cnt_time;
+
+ // Boot
+ reg [1:0] boot_sel;
+ reg boot_now;
+
+
+ // Bus interface
+ // -------------
+
+ // Ack
+ always @(posedge clk)
+ wb_ack <= wb_cyc & ~wb_ack;
+
+ assign bus_clr = ~wb_cyc | wb_ack;
+
+ // Write enables
+ always @(posedge clk)
+ if (bus_clr | ~wb_we)
+ bus_we_boot <= 1'b0;
+ else
+ bus_we_boot <= wb_addr == 4'h0;
+
+ // Read mux
+ always @(posedge clk)
+ if (bus_clr)
+ wb_rdata <= 32'h00000000;
+ else
+ case (wb_addr[3:0])
+ 4'h4: wb_rdata <= { cap_e1_rx[0], 16'h0000 };
+ 4'h5: wb_rdata <= { cap_e1_rx[1], 16'h0000 };
+ 4'h7: wb_rdata <= cnt_time;
+ default: wb_rdata <= 32'hxxxxxxxx;
+ endcase
+
+
+ // Counters
+ // --------
+
+ // E1 ticks
+ for (i=0; i<2; i=i+1) begin
+
+ always @(posedge clk or posedge rst)
+ if (rst)
+ cnt_e1_rx[i] <= 16'h0000;
+ else if (tick_e1_rx[i])
+ cnt_e1_rx[i] <= cnt_e1_rx[i] + 1;
+
+ always @(posedge clk)
+ if (tick_usb_sof)
+ cap_e1_rx[i] <= cnt_e1_rx[i];
+
+ end
+
+ // Time counter
+ always @(posedge clk)
+ if (rst)
+ cnt_time <= 32'h00000000;
+ else
+ cnt_time <= cnt_time + 1;
+
+
+ // DFU / Reboot
+ // ------------
+
+ always @(posedge clk or posedge rst)
+ if (rst) begin
+ boot_now <= 1'b0;
+ boot_sel <= 2'b00;
+ end else if (bus_we_boot) begin
+ boot_now <= wb_wdata[2];
+ boot_sel <= wb_wdata[1:0];
+ end
+
+ dfu_helper #(
+ .TIMER_WIDTH(26),
+ .BTN_MODE(3),
+ .DFU_MODE(0)
+ ) dfu_I (
+ .boot_sel(boot_sel),
+ .boot_now(boot_now),
+ .btn_pad (btn),
+ .btn_val (),
+ .rst_req (rst_req),
+ .clk (clk),
+ .rst (rst)
+ );
+
+endmodule // misc
diff --git a/gateware/e1-tracer/rtl/sysmgr.v b/gateware/e1-tracer/rtl/sysmgr.v
new file mode 100644
index 0000000..b5dbb3c
--- /dev/null
+++ b/gateware/e1-tracer/rtl/sysmgr.v
@@ -0,0 +1,97 @@
+/*
+ * sysmgr.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * System Clock / Reset generation
+ *
+ * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
+ * SPDX-License-Identifier: CERN-OHL-S-2.0
+ */
+
+`default_nettype none
+
+module sysmgr (
+ input wire clk_in,
+ input wire rst_in,
+ output wire clk_sys,
+ output wire rst_sys,
+ output wire clk_48m,
+ output wire rst_48m
+);
+
+ // Signals
+ wire pll_lock;
+ wire pll_reset_n;
+
+ wire clk_12m_i;
+ wire clk_24m_i;
+ wire clk_48m_i;
+
+ wire rst_i;
+ wire rst_out;
+ reg [3:0] rst_cnt;
+
+ // Global input buffer for 12 MHz clock
+ SB_GB_IO #(
+ .PIN_TYPE(6'b000001)
+ ) gb_in (
+ .PACKAGE_PIN(clk_in),
+ .GLOBAL_BUFFER_OUTPUT(clk_12m_i),
+ );
+
+ // PLL instance
+ SB_PLL40_2F_CORE #(
+ .DIVR(4'b0000),
+ .DIVF(7'b0111111),
+ .DIVQ(3'b100),
+ .FILTER_RANGE(3'b001),
+ .FEEDBACK_PATH("SIMPLE"),
+ .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"),
+ .FDA_FEEDBACK(4'b0000),
+ .SHIFTREG_DIV_MODE(2'b00),
+ .PLLOUT_SELECT_PORTA("GENCLK"),
+ .PLLOUT_SELECT_PORTB("GENCLK_HALF"),
+ .ENABLE_ICEGATE_PORTA(1'b0),
+ .ENABLE_ICEGATE_PORTB(1'b0)
+ ) pll_I (
+ .REFERENCECLK(clk_12m_i),
+ .PLLOUTCOREA(),
+ .PLLOUTGLOBALA(clk_48m_i),
+ .PLLOUTCOREB(),
+ .PLLOUTGLOBALB(clk_24m_i),
+ .EXTFEEDBACK(1'b0),
+ .DYNAMICDELAY(8'h00),
+ .RESETB(pll_reset_n),
+ .BYPASS(1'b0),
+ .LATCHINPUTVALUE(1'b0),
+ .LOCK(pll_lock),
+ .SDI(1'b0),
+ .SDO(),
+ .SCLK(1'b0)
+ );
+
+ assign clk_sys = clk_24m_i;
+ assign clk_48m = clk_48m_i;
+
+ // PLL reset generation
+ assign pll_reset_n = ~rst_in;
+
+ // Logic reset generation
+ always @(posedge clk_24m_i or negedge pll_lock)
+ if (!pll_lock)
+ rst_cnt <= 4'h0;
+ else if (~rst_cnt[3])
+ rst_cnt <= rst_cnt + 1;
+
+ assign rst_i = ~rst_cnt[3];
+
+ SB_GB rst_gbuf_I (
+ .USER_SIGNAL_TO_GLOBAL_BUFFER(rst_i),
+ .GLOBAL_BUFFER_OUTPUT(rst_out)
+ );
+
+ assign rst_sys = rst_out;
+ assign rst_48m = rst_out;
+
+endmodule // sysmgr
diff --git a/gateware/e1-tracer/rtl/top.v b/gateware/e1-tracer/rtl/top.v
new file mode 100644
index 0000000..0e76c5a
--- /dev/null
+++ b/gateware/e1-tracer/rtl/top.v
@@ -0,0 +1,226 @@
+/*
+ * top.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * Top-level for the e1-tracer boards.
+ *
+ * Note that some things here are only to maintain bitstream compatibility
+ * with the icepick based proto setup.
+ *
+ * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
+ * SPDX-License-Identifier: CERN-OHL-S-2.0
+ */
+
+`default_nettype none
+
+module top (
+ // LIU data
+ input wire e1A_rx_data,
+ input wire e1A_rx_clk,
+ input wire e1B_rx_data,
+ input wire e1B_rx_clk,
+
+ // LIU control
+ inout wire liu_mosi,
+ inout wire liu_miso,
+ inout wire liu_clk,
+ inout wire [1:0] liu_cs_n,
+
+ // USB
+ inout wire usb_dp,
+ inout wire usb_dn,
+ output wire usb_pu,
+
+ // Flash
+ inout wire flash_mosi,
+ inout wire flash_miso,
+ inout wire flash_clk,
+ inout wire flash_cs_n,
+
+ // VIO PDM
+ output wire vio_pdm,
+
+ // Button
+ input wire btn,
+
+ // Clock (12 MHz)
+ input wire clk_in,
+
+ // Debug UART
+ output wire dbg_tx,
+
+ // RGB LEDs
+ output wire [2:0] rgb
+);
+
+ localparam integer WB_N = 2;
+
+ genvar i;
+
+
+ // Signals
+ // -------
+
+ // Flash SPI internal signals
+ wire flash_mosi_i, flash_miso_i, flash_clk_i;
+ wire flash_mosi_o, flash_miso_o, flash_clk_o;
+ wire flash_mosi_oe, flash_miso_oe, flash_clk_oe;
+ wire flash_csn_o;
+
+ // Peripheral wishbone
+ wire [15:0] wb_addr;
+ wire [31:0] wb_rdata [0:WB_N-1];
+ wire [31:0] wb_wdata;
+ wire [ 3:0] wb_wmsk;
+ wire wb_we;
+ wire [WB_N-1:0] wb_cyc;
+ wire [WB_N-1:0] wb_ack;
+
+ wire [(WB_N*32)-1:0] wb_rdata_flat;
+
+ // Ticks
+ wire [1:0] tick_e1_rx;
+ wire tick_usb_sof;
+
+ // Clocks / Reset
+ wire rst_req;
+
+ wire clk_sys;
+ wire rst_sys;
+ wire clk_48m;
+ wire rst_48m;
+
+
+ // SoC base
+ // --------
+
+ // Instance
+ soc_base #(
+ .WB_N(WB_N),
+ .E1_N(2),
+ .E1_UNIT_HAS_RX(2'b11),
+ .E1_UNIT_HAS_TX(2'b00),
+ .E1_LIU(1)
+ ) soc_I (
+ .e1_rx_hi_p (),
+ .e1_rx_hi_n (),
+ .e1_rx_lo_p (),
+ .e1_rx_lo_n (),
+ .e1_tx_hi (),
+ .e1_tx_lo (),
+ .e1_rx_data ({e1B_rx_data, e1A_rx_data}),
+ .e1_rx_clk ({e1B_rx_clk, e1A_rx_clk }),
+ .e1_tx_data (),
+ .e1_tx_clk (),
+ .usb_dp (usb_dp),
+ .usb_dn (usb_dn),
+ .usb_pu (usb_pu),
+ .flash_mosi_i (flash_mosi_i),
+ .flash_mosi_o (flash_mosi_o),
+ .flash_mosi_oe(flash_mosi_oe),
+ .flash_miso_i (flash_miso_i),
+ .flash_miso_o (flash_miso_o),
+ .flash_miso_oe(flash_miso_oe),
+ .flash_clk_i (flash_clk_i),
+ .flash_clk_o (flash_clk_o),
+ .flash_clk_oe (flash_clk_oe),
+ .flash_csn_o (flash_csn_o),
+ .dbg_rx (1'b1),
+ .dbg_tx (dbg_tx),
+ .rgb (rgb),
+ .wb_m_addr (wb_addr),
+ .wb_m_rdata (wb_rdata_flat),
+ .wb_m_wdata (wb_wdata),
+ .wb_m_wmsk (wb_wmsk),
+ .wb_m_we (wb_we),
+ .wb_m_cyc (wb_cyc),
+ .wb_m_ack (wb_ack),
+ .tick_e1_rx (tick_e1_rx),
+ .tick_usb_sof (tick_usb_sof),
+ .clk_sys (clk_sys),
+ .rst_sys (rst_sys),
+ .clk_48m (clk_48m),
+ .rst_48m (rst_48m)
+ );
+
+ // WB read data flattening
+ for (i=0; i<WB_N; i=i+1)
+ assign wb_rdata_flat[i*32+:32] = wb_rdata[i];
+
+ // SPI IO
+ SB_IO #(
+ .PIN_TYPE(6'b101001),
+ .PULLUP(1'b1)
+ ) spi_io_I[2:0] (
+ .PACKAGE_PIN ({flash_mosi, flash_miso, flash_clk }),
+ .OUTPUT_ENABLE({flash_mosi_oe, flash_miso_oe, flash_clk_oe}),
+ .D_OUT_0 ({flash_mosi_o, flash_miso_o, flash_clk_o }),
+ .D_IN_0 ({flash_mosi_i, flash_miso_i, flash_clk_i })
+ );
+
+ assign flash_cs_n = flash_csn_o;
+
+
+ // Misc [0]
+ // ----
+
+ misc misc_I (
+ .btn (btn),
+ .tick_e1_rx (tick_e1_rx),
+ .tick_usb_sof (tick_usb_sof),
+ .rst_req (rst_req),
+ .wb_addr (wb_addr[7:0]),
+ .wb_rdata (wb_rdata[0]),
+ .wb_wdata (wb_wdata),
+ .wb_we (wb_we),
+ .wb_cyc (wb_cyc[0]),
+ .wb_ack (wb_ack[0]),
+ .clk (clk_sys),
+ .rst (rst_sys)
+ );
+
+
+ // LIU SPI [1]
+ // -------
+
+ ice40_spi_wb #(
+ .N_CS(2),
+ .WITH_IOB(1),
+ .UNIT(1)
+ ) spi_I (
+ .pad_mosi (liu_mosi),
+ .pad_miso (liu_miso),
+ .pad_clk (liu_clk),
+ .pad_csn (liu_cs_n),
+ .wb_addr (wb_addr[3:0]),
+ .wb_rdata (wb_rdata[1]),
+ .wb_wdata (wb_wdata),
+ .wb_we (wb_we),
+ .wb_cyc (wb_cyc[1]),
+ .wb_ack (wb_ack[1]),
+ .clk (clk_sys),
+ .rst (rst_sys)
+ );
+
+
+ // Vio PDM
+ // -------
+
+ // Compat with iCEpick
+ assign vio_pdm = 1'b1;
+
+
+ // Clock / Reset
+ // -------------
+
+ sysmgr sys_mgr_I (
+ .clk_in (clk_in),
+ .rst_in (rst_req),
+ .clk_sys(clk_sys),
+ .rst_sys(rst_sys),
+ .clk_48m(clk_48m),
+ .rst_48m(rst_48m)
+ );
+
+endmodule // top