diff --git a/gateware/icE1usb-proto/.gitignore b/gateware/icE1usb-proto/.gitignore new file mode 100644 index 0000000..24d1c97 --- /dev/null +++ b/gateware/icE1usb-proto/.gitignore @@ -0,0 +1,4 @@ +build-tmp +__pycache__ +*.vcd +.*.swp diff --git a/gateware/icE1usb-proto/Makefile b/gateware/icE1usb-proto/Makefile new file mode 100644 index 0000000..52f4b5a --- /dev/null +++ b/gateware/icE1usb-proto/Makefile @@ -0,0 +1,43 @@ +# Project config +PROJ=icE1usb-proto + +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 ?= icebreaker +DEVICE = up5k +PACKAGE = sg48 + +NEXTPNR_ARGS = --pre-pack data/clocks.py --seed 4 + +# 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/icE1usb-proto/data/clocks.py b/gateware/icE1usb-proto/data/clocks.py new file mode 100644 index 0000000..3a6a288 --- /dev/null +++ b/gateware/icE1usb-proto/data/clocks.py @@ -0,0 +1,2 @@ +ctx.addClock("clk_sys", 30.72) +ctx.addClock("clk_48m", 48) diff --git a/gateware/icE1usb-proto/data/top-bitsy-v0.pcf b/gateware/icE1usb-proto/data/top-bitsy-v0.pcf new file mode 100644 index 0000000..2f13dbb --- /dev/null +++ b/gateware/icE1usb-proto/data/top-bitsy-v0.pcf @@ -0,0 +1,40 @@ +# E1 PHY +set_io e1_rx_hi_p 48 +set_io e1_rx_hi_n 45 +set_io e1_rx_lo_p 4 +set_io e1_rx_lo_n 3 +set_io e1_tx_hi 46 +set_io e1_tx_lo 47 + +set_io e1_vref_ct_pdm 32 +set_io e1_vref_p_pdm 27 +set_io e1_vref_n_pdm 34 + +# USB +set_io usb_dp 43 +set_io usb_dn 42 +set_io usb_pu 38 + +# 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 + +# Button +set_io -pullup yes btn 10 + +# Clock +set_io clk_in 44 + +set_io clk_tune_hi 28 +set_io clk_tune_lo 31 + +# Debug UART +set_io -pullup yes dbg_rx 18 +set_io -pullup yes dbg_tx 19 + +# RGB LEDs +set_io rgb[0] 39 +set_io rgb[1] 40 +set_io rgb[2] 41 diff --git a/gateware/icE1usb-proto/data/top-icebreaker.pcf b/gateware/icE1usb-proto/data/top-icebreaker.pcf new file mode 100644 index 0000000..1a745a7 --- /dev/null +++ b/gateware/icE1usb-proto/data/top-icebreaker.pcf @@ -0,0 +1,41 @@ +# E1 PHY +set_io e1_rx_hi_p 43 +set_io e1_rx_hi_n 36 +set_io e1_rx_lo_p 42 +set_io e1_rx_lo_n 38 +set_io e1_tx_hi 32 +set_io e1_tx_lo 31 + +set_io e1_vref_ct_pdm 46 +set_io e1_vref_p_pdm 34 +set_io e1_vref_n_pdm 28 + +# USB +set_io usb_dp 4 +set_io usb_dn 3 +set_io usb_pu 2 +set_io -nowarn usb_vsense 48 + +# 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 + +# Button +set_io -pullup yes btn 10 + +# Clock +set_io clk_in 44 + +set_io clk_tune_hi 47 +set_io clk_tune_lo 45 + +# Debug UART +set_io -pullup yes dbg_rx 6 +set_io -pullup yes dbg_tx 9 + +# RGB LEDs +set_io rgb[0] 39 +set_io rgb[1] 40 +set_io rgb[2] 41 diff --git a/gateware/icE1usb-proto/doc/mem-map.md b/gateware/icE1usb-proto/doc/mem-map.md new file mode 100644 index 0000000..87407a6 --- /dev/null +++ b/gateware/icE1usb-proto/doc/mem-map.md @@ -0,0 +1,226 @@ +icE1usb-proto 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 + + +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 1 single channel containing both +RX and TX units. + + +### `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 (Read Only, addr `0x04`) + +```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| +|-----------------------------------------------------------------------------------------------| +| tx_tick | rx_tick | +'-----------------------------------------------------------------------------------------------' + + * [31:16] - tx_tick + * [15: 0] - rx_tick +``` + +An internal counter is incremented at every bit received/transmitted 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 ( 30.72 MHz ) + + +#### PDM (Read/Write, addr `0x08-0x0f`) + +This exposes configurable voltages ( DACs ). Some channels are 12 bits, some are 8 bits. + +```text +12 bits: + +,-----------------------------------------------------------------------------------------------, +|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| +|-----------------------------------------------------------------------------------------------| +|en| / | value | +'-----------------------------------------------------------------------------------------------' + + * [31 ] - enable (output tristated if 0) + * [11:0] - value + + + 8 bits: + +,-----------------------------------------------------------------------------------------------, +|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| +|-----------------------------------------------------------------------------------------------| +|en| / | value | +'-----------------------------------------------------------------------------------------------' + + * [31 ] - enable (output tristated if 0) + * [11:0] - value +``` + +Channels : + + * `0`: Clock tune ( low ) [ 12 bits ] + * `1`: Clock tune ( high ) [ 12 bits ] + * `2`: E1 RX Negative bias [ 8 bits ] + * `3`: E1 RX Positive bias [ 8 bits ] + * `4`: E1 RX Center Tap bias [ 8 bits ] diff --git a/gateware/icE1usb-proto/rtl/misc.v b/gateware/icE1usb-proto/rtl/misc.v new file mode 100644 index 0000000..e7a2854 --- /dev/null +++ b/gateware/icE1usb-proto/rtl/misc.v @@ -0,0 +1,217 @@ +/* + * misc.v + * + * vim: ts=4 sw=4 + * + * Misc peripheral functions + * + * Copyright (C) 2019-2020 Sylvain Munaut + * SPDX-License-Identifier: CERN-OHL-S-2.0 + */ + +`default_nettype none + +module misc ( + // PDM outputs + output wire e1_vref_ct_pdm, + output wire e1_vref_p_pdm, + output wire e1_vref_n_pdm, + + output wire clk_tune_hi, + output wire clk_tune_lo, + + // Button + input wire btn, + + // Ticks + input wire tick_e1_rx, + input wire tick_e1_tx, + 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 + // ------- + + // Bus + wire bus_clr; + reg bus_we_boot; + reg [ 1:0] bus_we_pdm_clk; + reg [ 2:0] bus_we_pdm_e1; + + // Counters + reg [15:0] cnt_e1_rx; + reg [15:0] cap_e1_rx; + reg [15:0] cnt_e1_tx; + reg [15:0] cap_e1_tx; + reg [31:0] cnt_time; + + // PDM + reg [12:0] pdm_clk[0:1]; + reg [ 8:0] pdm_e1[0:2]; + + // 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) begin + bus_we_boot <= 1'b0; + bus_we_pdm_clk[0] <= 1'b0; + bus_we_pdm_clk[1] <= 1'b0; + bus_we_pdm_e1[0] <= 1'b0; + bus_we_pdm_e1[1] <= 1'b0; + bus_we_pdm_e1[2] <= 1'b0; + end else begin + bus_we_boot <= wb_addr == 4'h0; + bus_we_pdm_clk[0] <= wb_addr == 4'h8; + bus_we_pdm_clk[1] <= wb_addr == 4'h9; + bus_we_pdm_e1[0] <= wb_addr == 4'ha; + bus_we_pdm_e1[1] <= wb_addr == 4'hb; + bus_we_pdm_e1[2] <= wb_addr == 4'hc; + end + + // 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, cap_e1_tx }; + 4'h7: wb_rdata <= cnt_time; + 4'h8: wb_rdata <= { pdm_clk[0][12], 19'h00000, pdm_clk[0][11:0] }; + 4'h9: wb_rdata <= { pdm_clk[1][12], 19'h00000, pdm_clk[1][11:0] }; + 4'ha: wb_rdata <= { pdm_e1[0][8], 23'h000000, pdm_e1[0][ 7:0] }; + 4'hb: wb_rdata <= { pdm_e1[1][8], 23'h000000, pdm_e1[1][ 7:0] }; + 4'hc: wb_rdata <= { pdm_e1[2][8], 23'h000000, pdm_e1[2][ 7:0] }; + default: wb_rdata <= 32'hxxxxxxxx; + endcase + + + // Counters + // -------- + + // E1 ticks + always @(posedge clk or posedge rst) + if (rst) + cnt_e1_rx <= 16'h0000; + else if (tick_e1_rx) + cnt_e1_rx <= cnt_e1_rx + 1; + + always @(posedge clk or posedge rst) + if (rst) + cnt_e1_tx <= 16'h0000; + else if (tick_e1_tx) + cnt_e1_tx <= cnt_e1_tx + 1; + + always @(posedge clk) + if (tick_usb_sof) begin + cap_e1_rx <= cnt_e1_rx; + cap_e1_tx <= cnt_e1_tx; + end + + // Time counter + always @(posedge clk) + if (rst) + cnt_time <= 32'h00000000; + else + cnt_time <= cnt_time + 1; + + + // PDM outputs + // ----------- + + // Registers + always @(posedge clk or posedge rst) + if (rst) begin + pdm_clk[0] <= 0; // 13'h1800; + pdm_clk[1] <= 0; // 13'h1800; + pdm_e1[0] <= 0; // 9'h190; + pdm_e1[1] <= 0; // 9'h190; + pdm_e1[2] <= 0; // 9'h190; + end else begin + if (bus_we_pdm_clk[0]) pdm_clk[0] <= { wb_wdata[31], wb_wdata[11:0] }; + if (bus_we_pdm_clk[1]) pdm_clk[1] <= { wb_wdata[31], wb_wdata[11:0] }; + if (bus_we_pdm_e1[0]) pdm_e1[0] <= { wb_wdata[31], wb_wdata[ 7:0] }; + if (bus_we_pdm_e1[1]) pdm_e1[1] <= { wb_wdata[31], wb_wdata[ 7:0] }; + if (bus_we_pdm_e1[2]) pdm_e1[2] <= { wb_wdata[31], wb_wdata[ 7:0] }; + end + + // PDM cores + pdm #( + .WIDTH(12), + .PHY("ICE40"), + .DITHER("YES") + ) pdm_clk_I[1:0] ( + .pdm ({ clk_tune_hi, clk_tune_lo }), + .cfg_val({ pdm_clk[1][11:0], pdm_clk[0][11:0] }), + .cfg_oe ({ pdm_clk[1][12], pdm_clk[0][12] }), + .clk (clk), + .rst (rst) + ); + + pdm #( + .WIDTH(8), + .PHY("ICE40"), + .DITHER("NO") + ) pdm_e1_I[2:0] ( + .pdm ({ e1_vref_ct_pdm, e1_vref_p_pdm, e1_vref_n_pdm }), + .cfg_val({ pdm_e1[2][7:0], pdm_e1[1][7:0], pdm_e1[0][7:0] }), + .cfg_oe ({ pdm_e1[2][8], pdm_e1[1][8], pdm_e1[0][8] }), + .clk (clk), + .rst (rst) + ); + + + // 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/icE1usb-proto/rtl/sysmgr.v b/gateware/icE1usb-proto/rtl/sysmgr.v new file mode 100644 index 0000000..6ae9721 --- /dev/null +++ b/gateware/icE1usb-proto/rtl/sysmgr.v @@ -0,0 +1,100 @@ +/* + * sysmgr.v + * + * vim: ts=4 sw=4 + * + * System Clock / Reset generation + * + * Copyright (C) 2019-2020 Sylvain Munaut + * 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_30m72_i; + wire rst_30m72_i; + wire clk_48m_i; + reg rst_48m_i; + + reg [3:0] rst_cnt; + + // Global input buffer for 30.72 MHz clock + SB_GB_IO #( + .PIN_TYPE(6'b000001), + ) gb_in ( + .PACKAGE_PIN(clk_in), + .GLOBAL_BUFFER_OUTPUT(clk_30m72_i), + ); + + // PLL instance + SB_PLL40_CORE #( + .DIVR(4'b0000), + .DIVF(7'b0011000), + .DIVQ(3'b100), + .FILTER_RANGE(3'b011), + .FEEDBACK_PATH("SIMPLE"), + .DELAY_ADJUSTMENT_MODE_FEEDBACK("FIXED"), + .FDA_FEEDBACK(4'b0000), + .SHIFTREG_DIV_MODE(2'b00), + .PLLOUT_SELECT("GENCLK"), + .ENABLE_ICEGATE(1'b0), + ) pll_I ( + .REFERENCECLK(clk_30m72_i), + .PLLOUTCORE(), + .PLLOUTGLOBAL(clk_48m_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_30m72_i; + assign clk_48m = clk_48m_i; + + // PLL reset generation + assign pll_reset_n = ~rst_in; + + // Logic reset generation + always @(posedge clk_30m72_i or negedge pll_lock) + if (!pll_lock) + rst_cnt <= 4'h0; + else if (~rst_cnt[3]) + rst_cnt <= rst_cnt + 1; + + assign rst_30m72_i = ~rst_cnt[3]; + + always @(posedge clk_48m or posedge rst_30m72_i) + if (rst_30m72_i) + rst_48m_i <= 1'b1; + else + rst_48m_i <= 1'b0; + + SB_GB rst_sys_gbuf_I ( + .USER_SIGNAL_TO_GLOBAL_BUFFER(rst_30m72_i), + .GLOBAL_BUFFER_OUTPUT(rst_sys) + ); + + SB_GB rst_48m_gbuf_I ( + .USER_SIGNAL_TO_GLOBAL_BUFFER(rst_48m_i), + .GLOBAL_BUFFER_OUTPUT(rst_48m) + ); + +endmodule // sysmgr diff --git a/gateware/icE1usb-proto/rtl/top.v b/gateware/icE1usb-proto/rtl/top.v new file mode 100644 index 0000000..7cefeac --- /dev/null +++ b/gateware/icE1usb-proto/rtl/top.v @@ -0,0 +1,202 @@ +/* + * top.v + * + * vim: ts=4 sw=4 + * + * Top-level for the icE1usb icebreaker/bitsy based prototypes + * + * Copyright (C) 2019-2020 Sylvain Munaut + * SPDX-License-Identifier: CERN-OHL-S-2.0 + */ + +`default_nettype none + +module top ( + // E1 PHY + input wire e1_rx_hi_p, +// input wire e1_rx_hi_n, + input wire e1_rx_lo_p, +// input wire e1_rx_lo_n, + + output wire e1_tx_hi, + output wire e1_tx_lo, + + output wire e1_vref_ct_pdm, + output wire e1_vref_p_pdm, + output wire e1_vref_n_pdm, + + // 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, + + // Button + input wire btn, + + // Clock (30.72 MHz) + input wire clk_in, + output wire clk_tune_hi, + output wire clk_tune_lo, + + // Debug UART + input wire dbg_rx, + output wire dbg_tx, + + // RGB LEDs + output wire [2:0] rgb +); + + localparam integer WB_N = 1; + + 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 tick_e1_rx; + wire tick_e1_tx; + 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(1), + .E1_UNIT_HAS_RX(1'b1), + .E1_UNIT_HAS_TX(1'b1), + .E1_LIU(0) + ) soc_I ( + .e1_rx_hi_p (e1_rx_hi_p), +// .e1_rx_hi_n (e1_rx_hi_n), + .e1_rx_lo_p (e1_rx_lo_p), +// .e1_rx_lo_n (e1_rx_lo_n), + .e1_tx_hi (e1_tx_hi), + .e1_tx_lo (e1_tx_lo), + .e1_rx_data (), + .e1_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 (dbg_rx), + .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_e1_tx (tick_e1_tx), + .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