2014-12-14 17:18:53 -05:00
|
|
|
module erx_io (/*AUTOARG*/
|
|
|
|
// Outputs
|
2015-04-13 23:35:21 -04:00
|
|
|
rxo_wr_wait_p, rxo_wr_wait_n, rxo_rd_wait_p, rxo_rd_wait_n,
|
2015-04-11 00:04:18 -04:00
|
|
|
rx_lclk_div4, rx_frame_par, rx_data_par, ecfg_rx_datain,
|
2014-12-14 17:18:53 -05:00
|
|
|
// Inputs
|
2015-04-13 23:35:21 -04:00
|
|
|
reset, rxi_lclk_p, rxi_lclk_n, rxi_frame_p, rxi_frame_n,
|
2015-04-23 18:01:19 -04:00
|
|
|
rxi_data_p, rxi_data_n, rx_wr_wait, rx_rd_wait
|
2014-12-14 17:18:53 -05:00
|
|
|
);
|
|
|
|
|
2015-04-23 18:01:19 -04:00
|
|
|
parameter IOSTANDARD = "LVDS_25";
|
2015-04-08 13:20:25 -04:00
|
|
|
|
2014-12-14 17:18:53 -05:00
|
|
|
//###########
|
2015-04-23 18:01:19 -04:00
|
|
|
//# reset
|
2014-12-14 17:18:53 -05:00
|
|
|
//###########
|
2015-04-23 18:01:19 -04:00
|
|
|
input reset; // Reset (from ecfg)
|
2014-12-14 17:18:53 -05:00
|
|
|
|
2015-04-08 13:20:25 -04:00
|
|
|
//###########
|
|
|
|
//# eLink pins
|
|
|
|
//###########
|
2015-04-23 18:01:19 -04:00
|
|
|
input rxi_lclk_p, rxi_lclk_n; //link rx clock input
|
2015-04-13 23:35:21 -04:00
|
|
|
input rxi_frame_p, rxi_frame_n; //link rx frame signal
|
|
|
|
input [7:0] rxi_data_p, rxi_data_n; //link rx data
|
|
|
|
output rxo_wr_wait_p,rxo_wr_wait_n; //link rx write pushback output
|
|
|
|
output rxo_rd_wait_p,rxo_rd_wait_n; //link rx read pushback output
|
|
|
|
|
2014-12-14 17:18:53 -05:00
|
|
|
//#############
|
|
|
|
//# Fabric interface, 1/8 bit rate of eLink
|
|
|
|
//#############
|
2015-04-23 18:01:19 -04:00
|
|
|
output rx_lclk_div4; // Parallel clock output (slow)
|
2015-03-24 20:44:03 -04:00
|
|
|
output [7:0] rx_frame_par;
|
|
|
|
output [63:0] rx_data_par;
|
2014-12-14 17:18:53 -05:00
|
|
|
input rx_wr_wait;
|
|
|
|
input rx_rd_wait;
|
|
|
|
|
|
|
|
//#############
|
2015-04-23 18:01:19 -04:00
|
|
|
//# Direct sampling mode
|
|
|
|
//##############
|
2015-04-11 00:04:18 -04:00
|
|
|
output [8:0] ecfg_rx_datain; //gpio data in (data in and frame)
|
2014-12-14 17:18:53 -05:00
|
|
|
|
|
|
|
//############
|
|
|
|
//# WIRES
|
|
|
|
//############
|
2015-04-23 18:01:19 -04:00
|
|
|
wire [7:0] rx_data; // High-speed serial data
|
|
|
|
wire rx_frame; // serial frame
|
|
|
|
wire rx_lclk; // Single-ended clock
|
|
|
|
wire rx_lclk_s; // Serial clock after BUFIO
|
2014-12-14 17:18:53 -05:00
|
|
|
|
|
|
|
//################################
|
|
|
|
//# Input Buffers Instantiation
|
|
|
|
//################################
|
|
|
|
IBUFDS
|
2015-04-23 18:01:19 -04:00
|
|
|
#(.DIFF_TERM ("TRUE"),
|
|
|
|
.IOSTANDARD (IOSTANDARD))
|
2015-04-14 14:00:23 -04:00
|
|
|
ibufds_rxdata[7:0]
|
|
|
|
(.I (rxi_data_p[7:0]),
|
|
|
|
.IB (rxi_data_n[7:0]),
|
|
|
|
.O (rx_data[7:0]));
|
2014-12-14 17:18:53 -05:00
|
|
|
|
|
|
|
IBUFDS
|
2015-04-23 18:01:19 -04:00
|
|
|
#(.DIFF_TERM ("TRUE"),
|
|
|
|
.IOSTANDARD (IOSTANDARD))
|
2015-03-24 20:44:03 -04:00
|
|
|
ibufds_rx_frame
|
2015-04-13 23:35:21 -04:00
|
|
|
(.I (rxi_frame_p),
|
|
|
|
.IB (rxi_frame_n),
|
2014-12-14 17:18:53 -05:00
|
|
|
.O (rx_frame));
|
|
|
|
|
|
|
|
//#####################
|
|
|
|
//# Clock Buffers
|
|
|
|
//#####################
|
|
|
|
|
|
|
|
IBUFGDS
|
2015-04-23 18:01:19 -04:00
|
|
|
#(.DIFF_TERM ("TRUE"),
|
|
|
|
.IOSTANDARD (IOSTANDARD))
|
2014-12-14 17:18:53 -05:00
|
|
|
ibufds_rxlclk
|
2015-04-13 23:35:21 -04:00
|
|
|
(.I (rxi_lclk_p),
|
|
|
|
.IB (rxi_lclk_n),
|
2014-12-14 17:18:53 -05:00
|
|
|
.O (rx_lclk));
|
|
|
|
|
|
|
|
BUFIO bufio_rxlclk
|
|
|
|
(.I (rx_lclk),
|
|
|
|
.O (rx_lclk_s));
|
|
|
|
|
|
|
|
// BUFR generates the slow clock
|
|
|
|
BUFR
|
|
|
|
#(.SIM_DEVICE("7SERIES"),
|
|
|
|
.BUFR_DIVIDE("4"))
|
|
|
|
clkout_bufr
|
2015-03-24 20:44:03 -04:00
|
|
|
(.O (rx_lclk_div4),
|
2014-12-14 17:18:53 -05:00
|
|
|
.CE(1'b1),
|
2015-04-16 22:31:36 -04:00
|
|
|
.CLR(reset),
|
2014-12-14 17:18:53 -05:00
|
|
|
.I (rx_lclk));
|
|
|
|
|
|
|
|
//#############################
|
|
|
|
//# Deserializer instantiations
|
2015-04-23 18:01:19 -04:00
|
|
|
//#############################
|
2014-12-14 17:18:53 -05:00
|
|
|
genvar i;
|
|
|
|
generate for(i=0; i<8; i=i+1)
|
|
|
|
begin : gen_serdes
|
|
|
|
ISERDESE2
|
|
|
|
#(
|
|
|
|
.DATA_RATE("DDR"), // DDR, SDR
|
|
|
|
.DATA_WIDTH(8), // Parallel data width (2-8,10,14)
|
|
|
|
.DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
|
|
|
|
.DYN_CLK_INV_EN("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
|
|
|
|
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
|
|
|
|
.INIT_Q1(1'b0),
|
|
|
|
.INIT_Q2(1'b0),
|
|
|
|
.INIT_Q3(1'b0),
|
|
|
|
.INIT_Q4(1'b0),
|
|
|
|
.INTERFACE_TYPE("NETWORKING"),
|
|
|
|
// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
|
|
|
|
.IOBDELAY("NONE"), // NONE, BOTH, IBUF, IFD
|
|
|
|
.NUM_CE(2), // Number of clock enables (1,2)
|
|
|
|
.OFB_USED("FALSE"), // Select OFB path (FALSE, TRUE)
|
|
|
|
.SERDES_MODE("MASTER"), // MASTER, SLAVE
|
|
|
|
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
|
|
|
|
.SRVAL_Q1(1'b0),
|
|
|
|
.SRVAL_Q2(1'b0),
|
|
|
|
.SRVAL_Q3(1'b0),
|
|
|
|
.SRVAL_Q4(1'b0)
|
|
|
|
)
|
|
|
|
ISERDESE2_rxdata
|
|
|
|
(
|
|
|
|
.O(), // 1-bit output: Combinatorial output
|
|
|
|
// Q1 - Q8: 1-bit (each) output: Registered data outputs
|
2015-04-23 18:01:19 -04:00
|
|
|
.Q1(rx_data_par[i]), // Last data in?
|
|
|
|
.Q2(rx_data_par[i+8]),
|
|
|
|
.Q3(rx_data_par[i+16]),
|
|
|
|
.Q4(rx_data_par[i+24]),
|
|
|
|
.Q5(rx_data_par[i+32]),
|
|
|
|
.Q6(rx_data_par[i+40]),
|
|
|
|
.Q7(rx_data_par[i+48]),
|
|
|
|
.Q8(rx_data_par[i+56]), // First data in?
|
2014-12-14 17:18:53 -05:00
|
|
|
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
|
|
|
|
.SHIFTOUT1(),
|
|
|
|
.SHIFTOUT2(),
|
|
|
|
.BITSLIP(1'b0), // 1-bit input: The BITSLIP pin performs a Bitslip operation
|
|
|
|
// synchronous to CLKDIV when asserted (active High). Subsequently, the data
|
|
|
|
// seen on the Q1 to Q8 output ports will shift, as in a barrel-shifter
|
|
|
|
// operation, one position every time Bitslip is invoked. DDR operation is
|
|
|
|
// different from SDR.
|
|
|
|
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
|
|
|
|
.CE1(1'b1),
|
|
|
|
.CE2(1'b1),
|
|
|
|
.CLKDIVP(1'b0), // 1-bit input: TBD
|
|
|
|
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
|
|
|
|
.CLK(rx_lclk_s), // 1-bit input: High-speed clock
|
2015-04-23 18:01:19 -04:00
|
|
|
.CLKB(~rx_lclk_s), // 1-bit input: High-speed secondary clock
|
2015-03-24 20:44:03 -04:00
|
|
|
.CLKDIV(rx_lclk_div4), // 1-bit input: Divided clock
|
2014-12-14 17:18:53 -05:00
|
|
|
.OCLK(1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
|
|
|
|
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
|
|
|
|
.DYNCLKDIVSEL(1'b0), // 1-bit input: Dynamic CLKDIV inversion
|
|
|
|
.DYNCLKSEL(1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
|
|
|
|
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
|
|
|
|
.D(rx_data[i]), // 1-bit input: Data input
|
|
|
|
.DDLY(1'b0), // 1-bit input: Serial data from IDELAYE2
|
|
|
|
.OFB(1'b0), // 1-bit input: Data feedback from OSERDESE2
|
2015-04-23 18:01:19 -04:00
|
|
|
.OCLKB(1'b0), // 1-bit input: High speed negative edge output clock
|
|
|
|
.RST(reset), // 1-bit input: Active high asynchronous reset
|
2014-12-14 17:18:53 -05:00
|
|
|
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
|
|
|
|
.SHIFTIN1(1'b0),
|
|
|
|
.SHIFTIN2(1'b0)
|
|
|
|
);
|
|
|
|
end // block: gen_serdes
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
ISERDESE2
|
|
|
|
#(
|
|
|
|
.DATA_RATE("DDR"), // DDR, SDR
|
|
|
|
.DATA_WIDTH(8), // Parallel data width (2-8,10,14)
|
|
|
|
.DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
|
|
|
|
.DYN_CLK_INV_EN("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
|
|
|
|
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
|
|
|
|
.INIT_Q1(1'b0),
|
|
|
|
.INIT_Q2(1'b0),
|
|
|
|
.INIT_Q3(1'b0),
|
|
|
|
.INIT_Q4(1'b0),
|
|
|
|
.INTERFACE_TYPE("NETWORKING"),
|
|
|
|
// MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
|
|
|
|
.IOBDELAY("NONE"), // NONE, BOTH, IBUF, IFD
|
|
|
|
.NUM_CE(2), // Number of clock enables (1,2)
|
|
|
|
.OFB_USED("FALSE"), // Select OFB path (FALSE, TRUE)
|
|
|
|
.SERDES_MODE("MASTER"), // MASTER, SLAVE
|
|
|
|
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
|
|
|
|
.SRVAL_Q1(1'b0),
|
|
|
|
.SRVAL_Q2(1'b0),
|
|
|
|
.SRVAL_Q3(1'b0),
|
|
|
|
.SRVAL_Q4(1'b0)
|
|
|
|
)
|
2015-03-24 20:44:03 -04:00
|
|
|
ISERDESE2_rx_frame
|
2014-12-14 17:18:53 -05:00
|
|
|
(
|
|
|
|
.O(), // 1-bit output: Combinatorial output
|
|
|
|
// Q1 - Q8: 1-bit (each) output: Registered data outputs
|
2015-04-23 18:01:19 -04:00
|
|
|
.Q1(rx_frame_par[0]),
|
|
|
|
.Q2(rx_frame_par[1]),
|
|
|
|
.Q3(rx_frame_par[2]),
|
|
|
|
.Q4(rx_frame_par[3]),
|
|
|
|
.Q5(rx_frame_par[4]),
|
|
|
|
.Q6(rx_frame_par[5]),
|
|
|
|
.Q7(rx_frame_par[6]),
|
|
|
|
.Q8(rx_frame_par[7]),
|
2014-12-14 17:18:53 -05:00
|
|
|
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
|
|
|
|
.SHIFTOUT1(),
|
|
|
|
.SHIFTOUT2(),
|
|
|
|
.BITSLIP(1'b0), // 1-bit input: The BITSLIP pin performs a Bitslip operation
|
|
|
|
// synchronous to CLKDIV when asserted (active High). Subsequently, the data
|
|
|
|
// seen on the Q1 to Q8 output ports will shift, as in a barrel-shifter
|
|
|
|
// operation, one position every time Bitslip is invoked. DDR operation is
|
|
|
|
// different from SDR.
|
|
|
|
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
|
|
|
|
.CE1(1'b1),
|
|
|
|
.CE2(1'b1),
|
|
|
|
.CLKDIVP(1'b0), // 1-bit input: TBD
|
|
|
|
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
|
|
|
|
.CLK(rx_lclk_s), // 1-bit input: High-speed clock
|
2015-04-23 18:57:55 -04:00
|
|
|
.CLKB(~rx_lclk_s), // 1-bit input: High-speed secondary clock
|
2015-03-24 20:44:03 -04:00
|
|
|
.CLKDIV(rx_lclk_div4), // 1-bit input: Divided clock
|
2014-12-14 17:18:53 -05:00
|
|
|
.OCLK(1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
|
|
|
|
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
|
|
|
|
.DYNCLKDIVSEL(1'b0), // 1-bit input: Dynamic CLKDIV inversion
|
|
|
|
.DYNCLKSEL(1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
|
|
|
|
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
|
|
|
|
.D(rx_frame), // 1-bit input: Data input
|
|
|
|
.DDLY(1'b0), // 1-bit input: Serial data from IDELAYE2
|
|
|
|
.OFB(1'b0), // 1-bit input: Data feedback from OSERDESE2
|
|
|
|
.OCLKB(1'b0), // 1-bit input: High speed negative edge output clock
|
2015-04-23 18:01:19 -04:00
|
|
|
.RST(reset), // 1-bit input: Active high asynchronous reset
|
2014-12-14 17:18:53 -05:00
|
|
|
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
|
|
|
|
.SHIFTIN1(1'b0),
|
|
|
|
.SHIFTIN2(1'b0)
|
|
|
|
);
|
|
|
|
|
|
|
|
//#############
|
|
|
|
//# Wait signals (asynchronous)
|
|
|
|
//#############
|
|
|
|
|
|
|
|
OBUFDS
|
|
|
|
#(
|
2015-04-23 18:01:19 -04:00
|
|
|
.IOSTANDARD(IOSTANDARD),
|
2014-12-14 17:18:53 -05:00
|
|
|
.SLEW("SLOW")
|
|
|
|
) OBUFDS_RXWRWAIT
|
|
|
|
(
|
2015-04-13 23:35:21 -04:00
|
|
|
.O(rxo_wr_wait_p),
|
|
|
|
.OB(rxo_wr_wait_n),
|
2015-04-23 18:01:19 -04:00
|
|
|
.I(rx_wr_wait)
|
2014-12-14 17:18:53 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
OBUFDS
|
|
|
|
#(
|
2015-04-23 18:01:19 -04:00
|
|
|
.IOSTANDARD(IOSTANDARD),
|
2014-12-14 17:18:53 -05:00
|
|
|
.SLEW("SLOW")
|
|
|
|
) OBUFDS_RXRDWAIT
|
|
|
|
(
|
2015-04-13 23:35:21 -04:00
|
|
|
.O(rxo_rd_wait_p),
|
|
|
|
.OB(rxo_rd_wait_n),
|
2015-04-23 18:01:19 -04:00
|
|
|
.I(rx_rd_wait)
|
2014-12-14 17:18:53 -05:00
|
|
|
);
|
|
|
|
|
2015-04-14 14:00:23 -04:00
|
|
|
endmodule // erx_io
|
|
|
|
|
|
|
|
/*
|
|
|
|
File: e_rx_io.v
|
|
|
|
|
|
|
|
This file is part of the Parallella Project .
|
|
|
|
|
|
|
|
Copyright (C) 2014 Adapteva, Inc.
|
|
|
|
Contributed by Fred Huettig <fred@adapteva.com>
|
|
|
|
Contributed by Andreas Olofsson <fred@adapteva.com>
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU 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 General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program (see the file COPYING). If not, see
|
|
|
|
<http://www.gnu.org/licenses/>.
|
|
|
|
*/
|