Преглед на файлове

cores/e1: Add option to use an external LIU instead of the iCE40 as PHY

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Sylvain Munaut преди 5 години
родител
ревизия
c138c61984
променени са 5 файла, в които са добавени 320 реда и са изтрити 81 реда
  1. 2 0
      cores/e1/core.mk
  2. 69 45
      cores/e1/rtl/e1_rx.v
  3. 83 0
      cores/e1/rtl/e1_rx_liu.v
  4. 60 36
      cores/e1/rtl/e1_tx.v
  5. 106 0
      cores/e1/rtl/e1_tx_liu.v

+ 2 - 0
cores/e1/core.mk

@@ -6,9 +6,11 @@ RTL_SRCS_e1 = $(addprefix rtl/, \
 	e1_rx_deframer.v \
 	e1_rx_filter.v \
 	e1_rx_phy.v \
+	e1_rx_liu.v \
 	e1_rx.v \
 	e1_tx_framer.v \
 	e1_tx_phy.v \
+	e1_tx_liu.v \
 	e1_tx.v \
 	e1_wb.v \
 	hdb3_dec.v \

+ 69 - 45
cores/e1/rtl/e1_rx.v

@@ -29,14 +29,20 @@
 `default_nettype none
 
 module e1_rx #(
+	parameter integer LIU = 0,
 	parameter integer MFW = 7
 )(
 	// IO pads
+		// Raw PHY
 	input  wire pad_rx_hi_p,
 	input  wire pad_rx_hi_n,
 	input  wire pad_rx_lo_p,
 	input  wire pad_rx_lo_n,
 
+		// LIU
+	input  wire pad_rx_data,
+	input  wire pad_rx_clk,
+
 	// Buffer interface
 	output wire [7:0] buf_data,
 	output wire [4:0] buf_ts,
@@ -98,51 +104,69 @@ module e1_rx #(
 	// Low-level bit recovery
 	// ----------------------
 
-	// PHY
-	e1_rx_phy phy_I (
-		.pad_rx_hi_p(pad_rx_hi_p),
-		.pad_rx_hi_n(pad_rx_hi_n),
-		.pad_rx_lo_p(pad_rx_lo_p),
-		.pad_rx_lo_n(pad_rx_lo_n),
-		.rx_hi(ll_raw_hi),
-		.rx_lo(ll_raw_lo),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	// Glitch filtering
-	e1_rx_filter filter_I (
-		.in_hi(ll_raw_hi),
-		.in_lo(ll_raw_lo),
-		.out_hi(ll_flt_hi),
-		.out_lo(ll_flt_lo),
-		.out_stb(ll_flt_stb),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	// Clock recovery
-	e1_rx_clock_recovery clock_I (
-		.in_hi(ll_flt_hi),
-		.in_lo(ll_flt_lo),
-		.in_stb(ll_flt_stb),
-		.out_hi(ll_cdr_hi),
-		.out_lo(ll_cdr_lo),
-		.out_stb(ll_cdr_stb),
-		.clk(clk),
-		.rst(rst)
-	);
-
-	// HDB3 decoding
-	hdb3_dec hdb3_I (
-		.in_pos(ll_cdr_hi),
-		.in_neg(ll_cdr_lo),
-		.in_valid(ll_cdr_stb),
-		.out_data(ll_bit),
-		.out_valid(ll_valid),
-		.clk(clk),
-		.rst(rst)
-	);
+	generate
+		if (LIU == 0) begin
+
+			// PHY
+			e1_rx_phy phy_I (
+				.pad_rx_hi_p(pad_rx_hi_p),
+				.pad_rx_hi_n(pad_rx_hi_n),
+				.pad_rx_lo_p(pad_rx_lo_p),
+				.pad_rx_lo_n(pad_rx_lo_n),
+				.rx_hi(ll_raw_hi),
+				.rx_lo(ll_raw_lo),
+				.clk(clk),
+				.rst(rst)
+			);
+
+			// Glitch filtering
+			e1_rx_filter filter_I (
+				.in_hi(ll_raw_hi),
+				.in_lo(ll_raw_lo),
+				.out_hi(ll_flt_hi),
+				.out_lo(ll_flt_lo),
+				.out_stb(ll_flt_stb),
+				.clk(clk),
+				.rst(rst)
+			);
+
+			// Clock recovery
+			e1_rx_clock_recovery clock_I (
+				.in_hi(ll_flt_hi),
+				.in_lo(ll_flt_lo),
+				.in_stb(ll_flt_stb),
+				.out_hi(ll_cdr_hi),
+				.out_lo(ll_cdr_lo),
+				.out_stb(ll_cdr_stb),
+				.clk(clk),
+				.rst(rst)
+			);
+
+			// HDB3 decoding
+			hdb3_dec hdb3_I (
+				.in_pos(ll_cdr_hi),
+				.in_neg(ll_cdr_lo),
+				.in_valid(ll_cdr_stb),
+				.out_data(ll_bit),
+				.out_valid(ll_valid),
+				.clk(clk),
+				.rst(rst)
+			);
+
+		end else begin
+
+			// LIU interface
+			e1_rx_liu liuif_I (
+				.pad_rx_data(pad_rx_data),
+				.pad_rx_clk(pad_rx_clk),
+				.out_data(ll_bit),
+				.out_valid(ll_valid),
+				.clk(clk),
+				.rst(rst)
+			);
+
+		end
+	endgenerate
 
 	// Loopback output
 	assign lb_bit = ll_bit;

+ 83 - 0
cores/e1/rtl/e1_rx_liu.v

@@ -0,0 +1,83 @@
+/*
+ * e1_rx_liu.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * E1 RX interface to external LIU
+ *
+ *
+ * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
+ * All rights reserved.
+ *
+ * LGPL v3+, see LICENSE.lgpl3
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+`default_nettype none
+
+module e1_rx_liu (
+	// Pads
+	input  wire pad_rx_data,
+	input  wire pad_rx_clk,
+
+	// Output
+	output reg  out_data,
+	output reg  out_valid,
+
+	// Common
+	input  wire clk,
+	input  wire rst
+);
+
+	wire rx_data;
+	wire rx_clk;
+
+	reg  rx_data_r;
+	reg  rx_clk_r;
+
+	// IOBs (registered)
+	SB_IO #(
+		.PIN_TYPE(6'b0000_00),
+		.PULLUP(1'b0),
+		.NEG_TRIGGER(1'b0)
+	) rx_iobs_I[1:0] (
+		.PACKAGE_PIN({pad_rx_data, pad_rx_clk}),
+		.LATCH_INPUT_VALUE(1'b0),
+		.CLOCK_ENABLE(1'b1),
+		.INPUT_CLK(clk),
+		.OUTPUT_CLK(1'b0),
+		.OUTPUT_ENABLE(1'b0),
+		.D_OUT_0(1'b0),
+		.D_OUT_1(1'b0),
+		.D_IN_0({rx_data, rx_clk}),
+		.D_IN_1()
+	);
+
+	// First internal register
+	always @(posedge clk)
+	begin
+		rx_data_r <= rx_data;
+		rx_clk_r  <= rx_clk;
+	end
+
+	// Second internal register + clk falling edge detect
+	always @(posedge clk)
+	begin
+		out_data  <= rx_data_r;
+		out_valid <= rx_clk_r & ~rx_clk;
+	end
+
+endmodule // e1_rx_liu

+ 60 - 36
cores/e1/rtl/e1_tx.v

@@ -29,12 +29,18 @@
 `default_nettype none
 
 module e1_tx #(
+	parameter integer LIU = 0,
 	parameter integer MFW = 7
 )(
 	// IO pads
+		// Raw PHY
 	output wire pad_tx_hi,
 	output wire pad_tx_lo,
 
+		// LIU
+	output wire pad_tx_data,
+	output wire pad_tx_clk,
+
 	// Buffer interface
 	input  wire [7:0] buf_data,
 	output wire [4:0] buf_ts,
@@ -153,45 +159,63 @@ module e1_tx #(
 	// Low-level
 	// ---------
 
-	// HDB3 encoding
-	hdb3_enc hdb3_I (
-		.out_pos(ll_pg_hi),
-		.out_neg(ll_pg_lo),
-		.out_valid(ll_pg_stb),
-		.in_data(ll_bit),
-		.in_valid(ll_valid),
-		.clk(clk),
-		.rst(rst)
-	);
+	generate
+		if (LIU == 0) begin
+
+			// HDB3 encoding
+			hdb3_enc hdb3_I (
+				.out_pos(ll_pg_hi),
+				.out_neg(ll_pg_lo),
+				.out_valid(ll_pg_stb),
+				.in_data(ll_bit),
+				.in_valid(ll_valid),
+				.clk(clk),
+				.rst(rst)
+			);
+
+			// Pulse generation
+			always @(posedge clk)
+			begin
+				if (rst) begin
+					pg_hi <= 0;
+					pg_lo <= 0;
+				end else begin
+					if (ll_pg_stb) begin
+						pg_hi <= ll_pg_hi ? 5'h19 : 5'h00;
+						pg_lo <= ll_pg_lo ? 5'h19 : 5'h00;
+					end else begin
+						pg_hi <= pg_hi - pg_hi[4];
+						pg_lo <= pg_lo - pg_lo[4];
+					end
+				end
+			end
+
+			assign ll_raw_hi = pg_hi[4];
+			assign ll_raw_lo = pg_lo[4];
+
+			// PHY
+			e1_tx_phy phy_I (
+				.pad_tx_hi(pad_tx_hi),
+				.pad_tx_lo(pad_tx_lo),
+				.tx_hi(ll_raw_hi),
+				.tx_lo(ll_raw_lo),
+				.clk(clk),
+				.rst(rst)
+			);
 
-	// Pulse generation
-	always @(posedge clk)
-	begin
-		if (rst) begin
-			pg_hi <= 0;
-			pg_lo <= 0;
 		end else begin
-			if (ll_pg_stb) begin
-				pg_hi <= ll_pg_hi ? 5'h19 : 5'h00;
-				pg_lo <= ll_pg_lo ? 5'h19 : 5'h00;
-			end else begin
-				pg_hi <= pg_hi - pg_hi[4];
-				pg_lo <= pg_lo - pg_lo[4];
-			end
-		end
-	end
 
-	assign ll_raw_hi = pg_hi[4];
-	assign ll_raw_lo = pg_lo[4];
+			// LIU interface
+			e1_tx_liu liuif_I (
+				.pad_tx_data(pad_tx_data),
+				.pad_tx_clk(pad_tx_clk),
+				.in_data(ll_bit),
+				.in_valid(ll_valid),
+				.clk(clk),
+				.rst(rst)
+			);
 
-	// PHY
-	e1_tx_phy phy_I (
-		.pad_tx_hi(pad_tx_hi),
-		.pad_tx_lo(pad_tx_lo),
-		.tx_hi(ll_raw_hi),
-		.tx_lo(ll_raw_lo),
-		.clk(clk),
-		.rst(rst)
-	);
+		end
+	endgenerate
 
 endmodule // e1_tx

+ 106 - 0
cores/e1/rtl/e1_tx_liu.v

@@ -0,0 +1,106 @@
+/*
+ * e1_tx_liu.v
+ *
+ * vim: ts=4 sw=4
+ *
+ * E1 RX interface to external LIU
+ *
+ *
+ * Copyright (C) 2019  Sylvain Munaut <tnt@246tNt.com>
+ * All rights reserved.
+ *
+ * LGPL v3+, see LICENSE.lgpl3
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+`default_nettype none
+
+module e1_tx_liu (
+	// Pads
+	input  wire pad_tx_data,
+	input  wire pad_tx_clk,
+
+	// Intput
+	input  wire in_data,
+	input  wire in_valid,
+
+	// Common
+	input  wire clk,
+	input  wire rst
+);
+	// Signals
+	reg [5:0] cnt_cur;
+	reg [5:0] cnt_nxt;
+
+	reg  tx_data;
+	wire tx_clk;
+
+	// Counters
+	always @(posedge clk)
+		if (in_valid)
+			cnt_nxt <= 0;
+		else
+			cnt_nxt <= cnt_nxt + 1;
+
+	always @(posedge clk)
+		if (in_valid)
+			cnt_cur <= { 1'b1, cnt_nxt[5:1] };
+		else
+			cnt_cur <= cnt_cur - 1;
+
+	// TX
+	always @(posedge clk)
+		if (in_valid)
+			tx_data <= in_data;
+
+	assign tx_clk = cnt_cur[5];
+
+	// IOBs (registered)
+	SB_IO #(
+		.PIN_TYPE(6'b0101_00),
+		.PULLUP(1'b0),
+		.NEG_TRIGGER(1'b0)
+	) tx_data_iob_I (
+		.PACKAGE_PIN(pad_tx_data),
+		.LATCH_INPUT_VALUE(1'b0),
+		.CLOCK_ENABLE(1'b1),
+		.INPUT_CLK(1'b0),
+		.OUTPUT_CLK(clk),
+		.OUTPUT_ENABLE(1'b1),
+		.D_OUT_0(tx_data),
+		.D_OUT_1(1'b0),
+		.D_IN_0(),
+		.D_IN_1()
+	);
+
+	SB_IO #(
+		.PIN_TYPE(6'b0101_00),
+		.PULLUP(1'b0),
+		.NEG_TRIGGER(1'b0)
+	) tx_clk_iob_I (
+		.PACKAGE_PIN(pad_tx_clk),
+		.LATCH_INPUT_VALUE(1'b0),
+		.CLOCK_ENABLE(1'b1),
+		.INPUT_CLK(1'b0),
+		.OUTPUT_CLK(clk),
+		.OUTPUT_ENABLE(1'b1),
+		.D_OUT_0(tx_clk),
+		.D_OUT_1(1'b0),
+		.D_IN_0(),
+		.D_IN_1()
+	);
+
+endmodule // e1_tx_liu