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