gateware: Initial import of all common parts

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
diff --git a/gateware/common/rtl/soc_base.v b/gateware/common/rtl/soc_base.v
new file mode 100644
index 0000000..7c5c407
--- /dev/null
+++ b/gateware/common/rtl/soc_base.v
@@ -0,0 +1,544 @@
+/*
+ * soc_base.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * Minimal common base for the E1 project SoC
+ *
+ * Copyright (C) 2019-2020  Sylvain Munaut <tnt@246tNt.com>
+ * SPDX-License-Identifier: CERN-OHL-S-2.0
+ */
+
+`default_nettype none
+
+module soc_base #(
+	parameter integer WB_N = 1,
+	parameter integer E1_N = 1,
+	parameter         E1_UNIT_HAS_RX = 1'b1,
+	parameter         E1_UNIT_HAS_TX = 1'b1,
+	parameter integer E1_LIU = 0
+)(
+	// E1 pads
+		// Raw PHY
+	input  wire [E1_N-1:0] e1_rx_hi_p,
+	input  wire [E1_N-1:0] e1_rx_hi_n,
+	input  wire [E1_N-1:0] e1_rx_lo_p,
+	input  wire [E1_N-1:0] e1_rx_lo_n,
+
+	output wire [E1_N-1:0] e1_tx_hi,
+	output wire [E1_N-1:0] e1_tx_lo,
+
+		// LIU
+	input  wire [E1_N-1:0] e1_rx_data,
+	input  wire [E1_N-1:0] e1_rx_clk,
+
+	output wire [E1_N-1:0] e1_tx_data,
+	output wire [E1_N-1:0] e1_tx_clk,
+
+	// USB
+	inout  wire usb_dp,
+	inout  wire usb_dn,
+	output wire usb_pu,
+
+	// Flash SPI (raw)
+	input  wire flash_mosi_i,
+	output wire flash_mosi_o,
+	output wire flash_mosi_oe,
+
+	input  wire flash_miso_i,
+	output wire flash_miso_o,
+	output wire flash_miso_oe,
+
+	input  wire flash_clk_i,
+	output wire flash_clk_o,
+	output wire flash_clk_oe,
+
+	output wire flash_csn_o,
+
+	// Debug UART
+	input  wire dbg_rx,
+	output wire dbg_tx,
+
+	// RGB LEDs
+	output wire [2:0] rgb,
+
+	// External Master Wishbone bus (CPU -> Peripheral)
+	output wire          [15:0] wb_m_addr,
+	input  wire [(WB_N*32)-1:0] wb_m_rdata,
+	output wire          [31:0] wb_m_wdata,
+	output wire          [ 3:0] wb_m_wmsk,
+	output wire                 wb_m_we,
+	output wire [ WB_N    -1:0] wb_m_cyc,
+	input  wire [ WB_N    -1:0] wb_m_ack,
+
+	// Ticks
+	output wire [E1_N-1:0] tick_e1_rx,
+	output wire [E1_N-1:0] tick_e1_tx,
+	output wire            tick_usb_sof,
+
+	// Clock / Reset
+	input  wire clk_sys,
+	input  wire rst_sys,
+	input  wire clk_48m,
+	input  wire rst_48m
+);
+
+	genvar i;
+
+	localparam integer WB_LN = 8;
+	localparam integer WB_TN = WB_N + WB_LN;
+	localparam integer WB_DW = 32;
+	localparam integer WB_MW = WB_DW / 8;
+	localparam integer WB_AW = 16;
+	localparam integer WB_AI =  2;
+
+
+	// Signals
+	// -------
+
+	// Picorv32 native bus
+	wire        pb_valid;
+	wire        pb_instr;
+	wire        pb_ready;
+	wire [31:0] pb_addr;
+	wire [31:0] pb_rdata;
+	wire [31:0] pb_wdata;
+	wire [ 3:0] pb_wstrb;
+
+	// SoC RAM
+		// BRAM
+	wire [ 7:0] bram_addr;
+	wire [31:0] bram_rdata;
+	wire [31:0] bram_wdata;
+	wire [ 3:0] bram_wmsk;
+	wire        bram_we;
+
+		// SPRAM
+	wire [14:0] spram_addr;
+	wire [31:0] spram_rdata;
+	wire [31:0] spram_wdata;
+	wire [ 3:0] spram_wmsk;
+	wire        spram_we;
+
+	// Peripheral wishbone
+	wire [WB_AW-1:0] wb_addr;
+	wire [WB_DW-1:0] wb_rdata [0:WB_LN-1];
+	wire [WB_DW-1:0] wb_wdata;
+	wire [WB_MW-1:0] wb_wmsk;
+	wire             wb_we;
+	wire [WB_TN-1:0] wb_cyc;
+	wire [WB_TN-1:0] wb_ack;
+
+	wire [(WB_DW*WB_TN)-1:0] wb_rdata_flat;
+
+	// USB
+		// Wishbone ( @ 48 MHz )
+	wire [11:0] ub_addr;
+	wire [15:0] ub_rdata;
+	wire [15:0] ub_wdata;
+	wire        ub_we;
+	wire        ub_cyc;
+	wire        ub_ack;
+
+		// EP interface
+	wire [ 8:0] ep_tx_addr_0;
+	wire [31:0] ep_tx_data_0;
+	wire        ep_tx_we_0;
+
+	wire [ 8:0] ep_rx_addr_0;
+	wire [31:0] ep_rx_data_1;
+	wire        ep_rx_re_0;
+
+		// SoF
+	wire usb_sof;
+
+	// Wishbone bus E1 to IO buffers
+	wire [13:0] wb_e1_addr;
+	wire [31:0] wb_e1_rdata;
+	wire [31:0] wb_e1_wdata;
+	wire [ 3:0] wb_e1_wmsk;
+	wire        wb_e1_we;
+	wire        wb_e1_cyc;
+	wire        wb_e1_ack;
+
+	// E1 buffer interface
+	wire [(E1_N*8)-1:0] e1_buf_rx_data;
+	wire [(E1_N*5)-1:0] e1_buf_rx_ts;
+	wire [(E1_N*4)-1:0] e1_buf_rx_frame;
+	wire [(E1_N*7)-1:0] e1_buf_rx_mf;
+	wire [ E1_N   -1:0] e1_buf_rx_we;
+	wire [ E1_N   -1:0] e1_buf_rx_rdy;
+	wire [(E1_N*8)-1:0] e1_buf_tx_data;
+	wire [(E1_N*5)-1:0] e1_buf_tx_ts;
+	wire [(E1_N*4)-1:0] e1_buf_tx_frame;
+	wire [(E1_N*7)-1:0] e1_buf_tx_mf;
+	wire [ E1_N   -1:0] e1_buf_tx_re;
+	wire [ E1_N   -1:0] e1_buf_tx_rdy;
+
+
+	// SoC core
+	// --------
+
+	// Local CPU reset
+	reg pb_rst_n;
+
+	always @(posedge clk_sys or posedge rst_sys)
+		if (rst_sys)
+			pb_rst_n <= 1'b0;
+		else
+			pb_rst_n <= 1'b1;
+
+	// CPU
+	picorv32 #(
+		.PROGADDR_RESET(32'h 0000_0000),
+		.STACKADDR(32'h 0000_0400),
+		.BARREL_SHIFTER(0),
+`ifdef BOARD_E1_TRACER
+		.TWO_CYCLE_COMPARE(0),
+		.TWO_CYCLE_ALU(0),
+`else
+		.TWO_CYCLE_COMPARE(0),
+		.TWO_CYCLE_ALU(1),
+`endif
+		.COMPRESSED_ISA(0),
+		.ENABLE_COUNTERS(0),
+		.ENABLE_MUL(0),
+		.ENABLE_DIV(0),
+		.ENABLE_IRQ(0),
+		.ENABLE_IRQ_QREGS(0),
+		.CATCH_MISALIGN(0),
+		.CATCH_ILLINSN(0)
+	) cpu_I (
+		.clk       (clk_sys),
+		.resetn    (pb_rst_n),
+		.mem_valid (pb_valid),
+		.mem_instr (pb_instr),
+		.mem_ready (pb_ready),
+		.mem_addr  (pb_addr),
+		.mem_wdata (pb_wdata),
+		.mem_wstrb (pb_wstrb),
+		.mem_rdata (pb_rdata)
+	);
+
+	// CPU bridge
+	soc_picorv32_bridge #(
+		.WB_N  (WB_TN),
+		.WB_DW (32),
+		.WB_AW (16),
+		.WB_AI ( 2),
+		.WB_REG( 0)
+	) bridge_I (
+		.pb_addr    (pb_addr),
+		.pb_rdata   (pb_rdata),
+		.pb_wdata   (pb_wdata),
+		.pb_wstrb   (pb_wstrb),
+		.pb_valid   (pb_valid),
+		.pb_ready   (pb_ready),
+		.bram_addr  (bram_addr),
+		.bram_rdata (bram_rdata),
+		.bram_wdata (bram_wdata),
+		.bram_wmsk  (bram_wmsk),
+		.bram_we    (bram_we),
+		.spram_addr (spram_addr),
+		.spram_rdata(spram_rdata),
+		.spram_wdata(spram_wdata),
+		.spram_wmsk (spram_wmsk),
+		.spram_we   (spram_we),
+		.wb_addr    (wb_addr),
+		.wb_rdata   (wb_rdata_flat),
+		.wb_wdata   (wb_wdata),
+		.wb_wmsk    (wb_wmsk),
+		.wb_we      (wb_we),
+		.wb_cyc     (wb_cyc),
+		.wb_ack     (wb_ack),
+		.clk        (clk_sys),
+		.rst        (rst_sys)
+	);
+
+	for (i=0; i<WB_LN; i=i+1)
+		assign wb_rdata_flat[i*WB_DW+:WB_DW] = wb_rdata[i];
+
+	// Boot memory - 1k
+	soc_bram #(
+		.AW(8),
+		.INIT_FILE("boot.hex"),
+	) bram_I (
+		.addr (bram_addr),
+		.rdata(bram_rdata),
+		.wdata(bram_wdata),
+		.wmsk (bram_wmsk),
+		.we   (bram_we),
+		.clk  (clk_sys)
+	);
+
+	// Main SoC memory - 64k
+	soc_spram #(
+		.AW(14)
+	) spram_I (
+		.addr (spram_addr[13:0]),
+		.rdata(spram_rdata),
+		.wdata(spram_wdata),
+		.wmsk (spram_wmsk),
+		.we   (spram_we),
+		.clk  (clk_sys)
+	);
+
+	// Peripheral wishbone export
+	assign wb_m_addr  = wb_addr;
+	assign wb_m_wdata = wb_wdata;
+	assign wb_m_wmsk  = wb_wmsk;
+	assign wb_m_we    = wb_we;
+	assign wb_m_cyc   = wb_cyc[WB_TN-1:WB_LN];
+
+	assign wb_rdata_flat[(WB_TN*WB_DW)-1:(WB_LN*WB_DW)] = wb_m_rdata;
+	assign wb_ack[WB_TN-1:WB_LN] = wb_m_ack;
+
+
+	// SPI [0]
+	// ---
+
+	ice40_spi_wb #(
+		.N_CS(1),
+		.WITH_IOB(0),
+		.UNIT(0)
+	) spi_I (
+		.sio_mosi_i (flash_mosi_i),
+		.sio_mosi_o (flash_mosi_o),
+		.sio_mosi_oe(flash_mosi_oe),
+		.sio_miso_i (flash_miso_i),
+		.sio_miso_o (flash_miso_o),
+		.sio_miso_oe(flash_miso_oe),
+		.sio_clk_i  (flash_clk_i),
+		.sio_clk_o  (flash_clk_o),
+		.sio_clk_oe (flash_clk_oe),
+		.sio_csn_o  (flash_csn_o),
+		.sio_csn_oe (),
+		.wb_addr    (wb_addr[3: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)
+	);
+
+
+	// Debug UART [1]
+	// ----------
+
+	uart_wb #(
+		.DIV_WIDTH(12),
+		.DW(WB_DW)
+	) uart_I (
+		.uart_tx  (dbg_tx),
+		.uart_rx  (dbg_rx),
+		.wb_addr  (wb_addr[1: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)
+	);
+
+
+	// RGB LEDs [2]
+	// --------
+
+	ice40_rgb_wb #(
+		.CURRENT_MODE("0b1"),
+		.RGB0_CURRENT("0b000001"),
+		.RGB1_CURRENT("0b000001"),
+		.RGB2_CURRENT("0b000001")
+	) rgb_I (
+		.pad_rgb    (rgb),
+		.wb_addr    (wb_addr[4:0]),
+		.wb_rdata   (wb_rdata[2]),
+		.wb_wdata   (wb_wdata),
+		.wb_we      (wb_we),
+		.wb_cyc     (wb_cyc[2]),
+		.wb_ack     (wb_ack[2]),
+		.clk        (clk_sys),
+		.rst        (rst_sys)
+	);
+
+
+	// USB [3]
+	// ---
+
+	// Core instance ( @ 48 MHz )
+	usb #(
+		.EPDW(32)
+	) usb_I (
+		.pad_dp      (usb_dp),
+		.pad_dn      (usb_dn),
+		.pad_pu      (usb_pu),
+		.ep_tx_addr_0(ep_tx_addr_0),
+		.ep_tx_data_0(ep_tx_data_0),
+		.ep_tx_we_0  (ep_tx_we_0),
+		.ep_rx_addr_0(ep_rx_addr_0),
+		.ep_rx_data_1(ep_rx_data_1),
+		.ep_rx_re_0  (ep_rx_re_0),
+		.ep_clk      (clk_sys),
+		.wb_addr     (ub_addr),
+		.wb_rdata    (ub_rdata),
+		.wb_wdata    (ub_wdata),
+		.wb_we       (ub_we),
+		.wb_cyc      (ub_cyc),
+		.wb_ack      (ub_ack),
+		.sof         (usb_sof),
+		.clk         (clk_48m),
+		.rst         (rst_48m)
+	);
+
+    // Cross clock bridge
+	xclk_wb #(
+		.DW(16),
+		.AW(12)
+	) wb_48m_xclk_I (
+		.s_addr (wb_addr[11:0]),
+		.s_rdata(wb_rdata[3][15:0]),
+		.s_wdata(wb_wdata[15:0]),
+		.s_we   (wb_we),
+		.s_cyc  (wb_cyc[3]),
+		.s_ack  (wb_ack[3]),
+		.s_clk  (clk_sys),
+		.m_addr (ub_addr),
+		.m_rdata(ub_rdata),
+		.m_wdata(ub_wdata),
+		.m_we   (ub_we),
+		.m_cyc  (ub_cyc),
+		.m_ack  (ub_ack),
+		.m_clk  (clk_48m),
+		.rst    (rst_sys)
+	);
+
+	assign wb_rdata[3][31:16] = 16'h0000;
+
+	// Cross clock SoF
+	xclk_strobe sof_xclk_I (
+		.in_stb (usb_sof),
+		.in_clk (clk_48m),
+		.out_stb(tick_usb_sof),
+		.out_clk(clk_sys),
+		.rst    (rst_sys)
+	);
+
+
+	// IO buffers & DMA
+	// ----------------
+	// [4] USB EP buffer
+	// [5] E1 SPRAM buffer
+	// [6] DMA
+
+	soc_iobuf iobuf_I (
+		.wb_cpu_addr (wb_addr),
+		.wb_cpu_rdata(wb_rdata[4]),
+		.wb_cpu_wdata(wb_wdata),
+		.wb_cpu_wmsk (wb_wmsk),
+		.wb_cpu_we   (wb_we),
+		.wb_cpu_cyc  (wb_cyc[6:4]),
+		.wb_cpu_ack  (wb_ack[6:4]),
+		.wb_e1_addr  (wb_e1_addr),
+		.wb_e1_rdata (wb_e1_rdata),
+		.wb_e1_wdata (wb_e1_wdata),
+		.wb_e1_wmsk  (wb_e1_wmsk),
+		.wb_e1_we    (wb_e1_we),
+		.wb_e1_cyc   (wb_e1_cyc),
+		.wb_e1_ack   (wb_e1_ack),
+		.ep_tx_addr_0(ep_tx_addr_0),
+		.ep_tx_data_0(ep_tx_data_0),
+		.ep_tx_we_0  (ep_tx_we_0),
+		.ep_rx_addr_0(ep_rx_addr_0),
+		.ep_rx_data_1(ep_rx_data_1),
+		.ep_rx_re_0  (ep_rx_re_0),
+		.clk         (clk_sys),
+		.rst         (rst_sys)
+	);
+
+	assign wb_rdata[5] = 32'h00000000;
+	assign wb_rdata[6] = 32'h00000000;
+
+
+	// E1 [7]
+	// --
+
+	// E1 wishbone module
+	e1_wb #(
+		.N(E1_N),
+		.UNIT_HAS_RX(E1_UNIT_HAS_RX),
+		.UNIT_HAS_TX(E1_UNIT_HAS_TX),
+		.LIU(E1_LIU),
+		.MFW(7)
+	) e1_I (
+		.pad_rx_hi_p (e1_rx_hi_p),
+		.pad_rx_hi_n (e1_rx_hi_n),
+		.pad_rx_lo_p (e1_rx_lo_p),
+		.pad_rx_lo_n (e1_rx_lo_n),
+		.pad_tx_hi   (e1_tx_hi),
+		.pad_tx_lo   (e1_tx_lo),
+		.pad_rx_data (e1_rx_data),
+		.pad_rx_clk  (e1_rx_clk),
+		.pad_tx_data (e1_tx_data),
+		.pad_tx_clk  (e1_tx_clk),
+		.buf_rx_data (e1_buf_rx_data),
+		.buf_rx_ts   (e1_buf_rx_ts),
+		.buf_rx_frame(e1_buf_rx_frame),
+		.buf_rx_mf   (e1_buf_rx_mf),
+		.buf_rx_we   (e1_buf_rx_we),
+		.buf_rx_rdy  (e1_buf_rx_rdy),
+		.buf_tx_data (e1_buf_tx_data),
+		.buf_tx_ts   (e1_buf_tx_ts),
+		.buf_tx_frame(e1_buf_tx_frame),
+		.buf_tx_mf   (e1_buf_tx_mf),
+		.buf_tx_re   (e1_buf_tx_re),
+		.buf_tx_rdy  (e1_buf_tx_rdy),
+		.wb_addr     (wb_addr[7:0]),
+		.wb_rdata    (wb_rdata[7][15:0]),
+		.wb_wdata    (wb_wdata[15:0]),
+		.wb_we       (wb_we),
+		.wb_cyc      (wb_cyc[7]),
+		.wb_ack      (wb_ack[7]),
+		.irq         (),
+		.tick_rx     (tick_e1_rx),
+		.tick_tx     (tick_e1_tx),
+		.clk         (clk_sys),
+		.rst         (rst_sys)
+	);
+
+	assign wb_rdata[7][31:16] = 16'h0000;
+
+	// E1 buffer interface to Wishbone
+	e1_buf_if_wb #(
+		.N(E1_N),
+		.UNIT_HAS_RX(E1_UNIT_HAS_RX),
+		.UNIT_HAS_TX(E1_UNIT_HAS_TX),
+		.MFW(7),
+		.DW(32)
+	) e1_buf_I (
+		.wb_addr     (wb_e1_addr),
+		.wb_rdata    (wb_e1_rdata),
+		.wb_wdata    (wb_e1_wdata),
+		.wb_wmsk     (wb_e1_wmsk),
+		.wb_we       (wb_e1_we),
+		.wb_cyc      (wb_e1_cyc),
+		.wb_ack      (wb_e1_ack),
+		.buf_rx_data (e1_buf_rx_data),
+		.buf_rx_ts   (e1_buf_rx_ts),
+		.buf_rx_frame(e1_buf_rx_frame),
+		.buf_rx_mf   (e1_buf_rx_mf),
+		.buf_rx_we   (e1_buf_rx_we),
+		.buf_rx_rdy  (e1_buf_rx_rdy),
+		.buf_tx_data (e1_buf_tx_data),
+		.buf_tx_ts   (e1_buf_tx_ts),
+		.buf_tx_frame(e1_buf_tx_frame),
+		.buf_tx_mf   (e1_buf_tx_mf),
+		.buf_tx_re   (e1_buf_tx_re),
+		.buf_tx_rdy  (e1_buf_tx_rdy),
+		.clk         (clk_sys),
+		.rst         (rst_sys)
+	);
+
+endmodule // soc_base