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/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