gateware/icE1usb-proto: Initial import
This is the project specific to the PMOD based early prototype.
It was used either with the icebreaker or the icebreaker-bitsy
board as host. Set BOARD variable appropriately during build.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
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 <tnt@246tNt.com>
+ * 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 <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_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 <tnt@246tNt.com>
+ * 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<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 (
+ .e1_vref_ct_pdm(e1_vref_ct_pdm),
+ .e1_vref_p_pdm (e1_vref_p_pdm),
+ .e1_vref_n_pdm (e1_vref_n_pdm),
+ .clk_tune_hi (clk_tune_hi),
+ .clk_tune_lo (clk_tune_lo),
+ .btn (btn),
+ .tick_e1_rx (tick_e1_rx),
+ .tick_e1_tx (tick_e1_tx),
+ .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)
+ );
+
+
+ // 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