OpenCores
URL https://opencores.org/ocsvn/1000base-x/1000base-x/trunk

Subversion Repositories 1000base-x

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /1000base-x/trunk
    from Rev 2 to Rev 3
    Reverse comparison

Rev 2 → Rev 3

/rtl/verilog/encoder_8b10b.v
0,0 → 1,267
 
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "encoder_8b10b.v" ////
//// ////
//// This file is part of the : ////
//// ////
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" ////
//// ////
//// http://opencores.org/project,1000base-x ////
//// ////
//// Author(s): ////
//// - D.W.Pegler Cambridge Broadband Networks Ltd ////
//// ////
//// { peglerd@gmail.com, dwp@cambridgebroadand.com } ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 AUTHORS. All rights reserved. ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source 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 source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// This module is based on the coding method described in ////
//// IEEE Std 802.3-2008 Section 36.2.4 which is available from : ////
//// ////
//// http://standards.ieee.org/about/get/802/802.3.html ////
//// ////
//// and the 8B/10B coding scheme from the 1993 IBM publication ////
//// "DC-Balanced, Partitioned-Block, 8B/10B Transmission Code" ////
//// by A.X. Widmer and P.A. Franasze" see doc/01-581v1.pdf ////
//// ////
//// and US patent #4,486,739 "BYTE ORIENTED DC BALANCED ////
//// (0,4) 8B/10B PARTITIONED BLOCK TRANSMISSION CODE "; see : ////
//// ////
//// doc/US4486739.pdf ////
//// ////
//// http://en.wikipedia.org/wiki/8b/10b_encoding ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "timescale.v"
 
module encoder_8b10b (
// --- Resets
input reset,
 
// --- Clocks
input SBYTECLK,
// --- Control (K) input
input K,
// --- Eight Bt input bus
input [7:0] ebi,
// --- TB (Ten Bt Interface) output bus
output [9:0] tbi,
 
output reg disparity
);
 
// Figure 3 - Encoder: 5B/6B classification, L functions
wire L40, L04, L13, L31, L22, AeqB, CeqD;
 
// Figure 5 - 5B/6B Encoder: disparity classifications
wire PD_1S6, NDOS6, PDOS6, ND_1S6;
 
// Figure 5 - 3B/4B Encoder: disparity classifications
wire ND_1S4, PD_1S4, NDOS4, PDOS4;
 
// Figure 6 - Encoder: control of complementation
wire illegalk, DISPARITY6;
reg COMPLS6, COMPLS4;
 
// Figure 7 - 5B/6B encoding
wire NAO, NBO, NCO, NDO, NEO, NIO;
// Figure 8: 3B/4B encoding
wire NFO, NGO, NHO, NJO;
 
// 8B Inputs
wire A,B,C,D,E,F,G,H;
assign {H,G,F,E,D,C,B,A} = ebi[7:0];
// 10B Outputs
reg a,b,c,d,e,i,f,g,h,j;
assign tbi[9:0] = {a,b,c,d,e,i,f,g,h,j};
 
wire [9:0] tst;
assign tst[9:0] = {NAO,NBO,NCO,NDO,NEO,NIO,NFO,NGO,NHO,NJO};
// ******************************************************************************
// Figures 7 & 8 - Latched 5B/6B and 3B/4B encoder outputs
// ******************************************************************************
always @(posedge SBYTECLK, posedge reset)
if (reset)
begin
disparity <= 1'b0; {a,b,c,d,e,i,f,g,h,j} <= 10'b0;
end
else begin
disparity <= (PDOS4 | NDOS4) ^ DISPARITY6;
{a,b,c,d,e,i,f,g,h,j} <= { NAO^COMPLS6, NBO^COMPLS6, NCO^COMPLS6,
NDO^COMPLS6, NEO^COMPLS6, NIO^COMPLS6,
NFO^COMPLS4, NGO^COMPLS4,
NHO^COMPLS4, NJO^COMPLS4 };
end // else: !if(reset)
// ******************************************************************************
// Figure 3 - Encoder: 5B/6B classification, L functions
// ******************************************************************************
assign AeqB = (A & B) | (!A & !B);
assign CeqD = (C & D) | (!C & !D);
assign L40 = A & B & C & D ;
assign L04 = !A & !B & !C & !D;
assign L13 = (!AeqB & !C & !D) | (!CeqD & !A & !B);
assign L31 = (!AeqB & C & D) | (!CeqD & A & B);
assign L22 = (A & B & !C & !D) | (C & D & !A & !B) | ( !AeqB & !CeqD) ;
// ******************************************************************************
// Figure 5 - 5B/6B Encoder: disparity classifications
// ******************************************************************************
assign PD_1S6 = (E & D & !C & !B & !A) | (!E & !L22 & !L31) ;
 
//assign PD_1S6 = (L13 & D & E) | (!E & !L22 & !L31) ;
assign NDOS6 = PD_1S6 ;
assign PDOS6 = K | (E & !L22 & !L13) ;
assign ND_1S6 = K | (E & !L22 & !L13) | (!E & !D & C & B & A) ;
// ******************************************************************************
// Figure 5 - 3B/4B Encoder: disparity classifications
// ******************************************************************************
assign ND_1S4 = F & G ;
assign NDOS4 = (!F & !G) ;
assign PD_1S4 = (!F & !G) | (K & ((F & !G) | (!F & G)));
assign PDOS4 = F & G & H ;
// ******************************************************************************
// Figure 6 - Encoder: control of complementation
// ******************************************************************************
 
// not K28.0->7 & K23/27/29/30.7
assign illegalk = K & (A | B | !C | !D | !E) & (!F | !G | !H | !E | !L31);
 
assign DISPARITY6 = disparity ^ (NDOS6 | PDOS6) ;
 
always @(posedge SBYTECLK, posedge reset)
if(reset) begin
COMPLS4 <= 0;
COMPLS6 <= 0;
end
else begin
COMPLS4 <= (PD_1S4 & !DISPARITY6) | (ND_1S4 & DISPARITY6);
COMPLS6 <= (PD_1S6 & !disparity) | (ND_1S6 & disparity);
end
// ******************************************************************************
// Figure 7 - 5B/6B encoding
// ******************************************************************************
 
reg tNAO, tNBOx, tNBOy, tNCOx, tNCOy, tNDO , tNEOx, tNEOy, tNIOw, tNIOx, tNIOy, tNIOz;
 
always @(posedge SBYTECLK, posedge reset)
if(reset) begin
tNAO <= 0;
tNBOx <= 0;
tNBOy <= 0;
tNCOx <= 0;
tNCOy <= 0;
tNDO <= 0;
tNEOx <= 0;
tNEOy <= 0;
tNIOw <= 0;
tNIOx <= 0;
tNIOy <= 0;
tNIOz <= 0;
end
else begin
tNAO <= A ;
 
tNBOx <= B & !L40;
tNBOy <= L04 ;
 
tNCOx <= L04 | C ;
tNCOy <= E & D & !C & !B & !A ;
 
tNDO <= D & ! (A & B & C) ;
 
tNEOx <= E | L13;
tNEOy <= !(E & D & !C & !B & !A) ;
 
tNIOw <= (L22 & !E) | (E & L40) ;
tNIOx <= E & !D & !C & !(A & B) ;
tNIOy <= K & E & D & C & !B & !A ;
tNIOz <= E & !D & C & !B & !A ;
end
 
assign NAO = tNAO ;
assign NBO = tNBOx | tNBOy ;
assign NCO = tNCOx | tNCOy ;
assign NDO = tNDO ;
assign NEO = tNEOx & tNEOy ;
assign NIO = tNIOw | tNIOx | tNIOy | tNIOz;
// ******************************************************************************
// Figure 8: 3B/4B encoding
// ******************************************************************************
 
reg alt7, tNFO, tNGO, tNHO, tNJO;
 
always @(posedge SBYTECLK, posedge reset)
if(reset) begin
alt7 <= 0;
tNFO <= 0;
tNGO <= 0;
tNHO <= 0;
tNJO <= 0;
end
else begin
alt7 <= F & G & H & (K | (disparity ? (!E & D & L31) : (E & !D & L13))) ;
tNFO <= F;
tNGO <= G | (!F & !G & !H) ;
tNHO <= H ;
tNJO <= !H & (G ^ F) ;
end
 
assign NFO = tNFO & !alt7 ;
assign NGO = tNGO ;
assign NHO = tNHO ;
assign NJO = tNJO | alt7 ;
 
endmodule
 
/rtl/verilog/ge_1000baseX_fpga.v
0,0 → 1,350
//////////////////////////////////////////////////////////////////////
//// ////
//// File name "ge_1000baseX_core.v" ////
//// ////
//// This file is part of the : ////
//// ////
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" ////
//// ////
//// http://opencores.org/project,1000base-x ////
//// ////
//// Author(s): ////
//// - D.W.Pegler Cambridge Broadband Networks Ltd ////
//// ////
//// { peglerd@gmail.com, dwp@cambridgebroadand.com } ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2009 AUTHORS. All rights reserved. ////
//// ////
//// This source file may be used and distributed without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer. ////
//// ////
//// This source file 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 2.1 of the License, or (at your option) any ////
//// later version. ////
//// ////
//// This source 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 source; if not, download it ////
//// from http://www.opencores.org/lgpl.shtml ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// This module is based on the coding method described in ////
//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) ////
//// and Physical Medium Attachment (PMA) sublayer, type ////
//// 1000BASE-X"; see : ////
//// ////
//// http://standards.ieee.org/about/get/802/802.3.html ////
//// and ////
//// doc/802.3-2008_section3.pdf, Clause/Section 36. ////
//// ////
//////////////////////////////////////////////////////////////////////
 
`include "timescale.v"
 
module ge_1000baseX_fpga
(
// --- Resets ---
input reset_pin,
// --- Clocks --
input ckpin,
// --- GE 125MHz reference clock
input GE_125MHz_ref_ckpin,
// --- FO TBI 125MHz Rx clk
input fo_tbi_rx_ckpin,
 
// --- CU GMII 125MHz Rx and Tx clk
input cu_gmii_rx_ckpin,
input cu_gmii_tx_ckpin,
// --- Fibre-Optic (fo) GE TBI Interface
input [9:0] fo_tbi_rxd,
output [9:0] fo_tbi_txd,
 
`ifdef MODEL_TECH
// -- Route GMII from IEEE 802.3 1000BaseLX out - for testing
output [7:0] fo_gmii_rxd,
output fo_gmii_rx_dv,
output fo_gmii_rx_er,
output fo_gmii_col,
output fo_gmii_cs,
input [7:0] fo_gmii_txd,
input fo_gmii_tx_en,
input fo_gmii_tx_er,
`endif // `ifdef MODEL_TECH
// --- Fibre-Optic (fo) ctrl signals
output fo_sync_en,
output fo_loop_en,
output fo_prbs_en,
input fo_signal_detect,
input fo_sync,
// --- Copper GE GMII Interface ---
input [7:0] cu_gmii_rxd,
input cu_gmii_rx_dv,
input cu_gmii_rx_er,
output [7:0] cu_gmii_txd,
output cu_gmii_tx_en,
output cu_gmii_tx_er,
 
input cu_gmii_cs,
input cu_gmii_col,
// --- MDIO interface
output mdio,
input mdc_in,
output mdc_out
);
//----------------------------------------------------------------------------
// GE 125MHz reference clock
//----------------------------------------------------------------------------
IBUFG GE_125MHz_ref_ckpin_bufi(.I(GE_125MHz_ref_ckpin), .O(GE_125MHz_ref_ckpin_buf));
 
wire GE_125MHz_ref_fbclk, GE_125MHz_ref_ck_locked;
DCM #(
.CLKIN_PERIOD(8.0), // Specify period of input clock in ns
.CLKFX_MULTIPLY(5),
.CLKFX_DIVIDE(8)
) GE_125MHz_ref_ck_DCMi(
//.CLK0(GE_125MHz_ref_fbclk),
.CLK0(GE_125MHz_ref_ck_unbuf),
.CLK180(),
.CLK270(),
.CLK2X(),
.CLK2X180(),
.CLK90(),
//.CLKDV(GE_125MHz_ref_ck_unbuf),
.CLKDV(),
.CLKFX(core_ck_unbuf),
.CLKFX180(),
.LOCKED(GE_125MHz_ref_ck_locked),
.PSDONE(),
.STATUS(),
//.CLKFB(GE_125MHz_ref_fbclk),
.CLKFB(GE_125MHz_ref_ck),
.CLKIN(GE_125MHz_ref_ckpin_buf),
.DSSEN(1'b0),
.PSCLK(1'b0),
.PSEN(1'b0),
.PSINCDEC(1'b0),
.RST(reset_pin)
);
 
//----------------------------------------------------------------------------
// 125MHz refence clock
//----------------------------------------------------------------------------
`ifdef MODEL_TECH
BUFG GE_125MHz_ref_ck_bufi(.I(GE_125MHz_ref_ck_unbuf), .O(GE_125MHz_ref_ck));
`else
BUFGMUX GE_125MHz_ref_ck_bufi(.I1(GE_125MHz_ref_ck_unbuf), .O(GE_125MHz_ref_ck), .S(1'b1));
`endif
//----------------------------------------------------------------------------
// 25MHz Copper (CU) MII TX clock - TX clk pin when CU interface in MII mode
//----------------------------------------------------------------------------
IBUFG cu_mii_tx_ckpin_bufi(.I(cu_mii_tx_ckpin), .O(cu_mii_tx_ckpin_buf));
 
`ifdef MODEL_TECH
BUFG cu_gmii_tx_ck_bufi(.I(GE_125MHz_ref_ck_unbuf),.O(cu_gmii_tx_ck));
`else
BUFGMUX cu_gmii_tx_ck_bufi(.I0(GE_125MHz_ref_ck_unbuf), .I1(cu_mii_tx_ckpin_buf), .O(cu_gmii_tx_ck), .S(cu_125MHz_tx_clk_en));
`endif
//----------------------------------------------------------------------------
// Fibre-Optic (FO) TBI RX clock.
//----------------------------------------------------------------------------
IBUFG fo_tbi_rx_ckpin_bufi(.I(fo_tbi_rx_ckpin), .O(fo_tbi_rx_ckpin_buf));
wire cpu_mii_ref_ck_unbuf;
DCM #(
.CLKIN_PERIOD(8.0),
.CLKFX_DIVIDE(5)
) fo_tbi_rx_ck_DCMi(
//.CLK0(fo_tbi_rx_fbclk),
.CLK0(fo_tbi_rx_ck_unbuf),
.CLK180(),
.CLK270(),
.CLK2X(),
.CLK2X180(),
.CLK90(),
//.CLKDV(fo_tbi_rx_ck_unbuf),
.CLKDV(),
.CLKFX(cpu_mii_ref_ck_unbuf),
.CLKFX180(),
.LOCKED(fo_tbi_rx_ck_locked),
.PSDONE(),
.STATUS(),
//.CLKFB(fo_tbi_rx_fbclk),
.CLKFB(fo_tbi_rx_ck),
.CLKIN(fo_tbi_rx_ckpin_buf),
.DSSEN(1'b0),
.PSCLK(1'b0),
.PSEN(1'b0),
.PSINCDEC(1'b0),
.RST(reset_pin)
);
// FO TBI 125MHz rx clock
BUFG fo_tbi_rx_ck_bufi( .I(fo_tbi_rx_ck_unbuf), .O(fo_tbi_rx_ck));
//----------------------------------------------------------------------------
// 125/25MHz Copper(CU) GMII RX clock
//----------------------------------------------------------------------------
IBUFG cu_gmii_rx_ckpin_bufi(.I(cu_gmii_rx_ckpin), .O(cu_gmii_rx_ckpin_buf));
wire cu_gmii_rx_ck_locked;
DCM #(
.CLKIN_PERIOD(8.0)
) cu_gmii_rx_ck_DCMi(
//.CLK0(cu_gmii_rx_fbclk),
.CLK0(cu_gmii_rx_ck_unbuf),
.CLK180(),
.CLK270(),
.CLK2X(),
.CLK2X180(),
.CLK90(),
//.CLKDV(cu_gmii_rx_ck_unbuf),
.CLKDV(),
.CLKFX(),
.CLKFX180(),
.LOCKED(cu_gmii_rx_ck_locked),
.PSDONE(),
.STATUS(),
//.CLKFB(cu_gmii_rx_fbclk),
.CLKFB(cu_gmii_rx_ck),
.CLKIN(cu_gmii_rx_ckpin_buf),
.DSSEN(1'b0),
.PSCLK(1'b0),
.PSEN(1'b0),
.PSINCDEC(1'b0),
.RST(reset_pin)
);
BUFG cu_gmii_rx_ck_bufi(.I(cu_gmii_rx_ck_unbuf), .O(cu_gmii_rx_ck));
//----------------------------------------------------------------------------
// 78MHz BUFG core clock
//----------------------------------------------------------------------------
BUFG core_ck_bufi(.I(core_ck_unbuf), .O(core_ck));
//----------------------------------------------------------------------------
// Reset Cleaners
//----------------------------------------------------------------------------
wire cu_gmii_ctrl_reset, fo_gmii_ctrl_reset;
wire main_clocks_locked = GE_125MHz_ref_ck_locked;
wire reset_in = reset_pin | ~main_clocks_locked;
wire cu_gmii_txck_reset_in = reset_pin | ~main_clocks_locked | cu_gmii_ctrl_reset;
wire cu_gmii_rxck_reset_in = reset_pin | ~main_clocks_locked | cu_gmii_ctrl_reset;
wire fo_tbi_rxck_reset_in = reset_pin | ~main_clocks_locked | fo_gmii_ctrl_reset;
wire GE_125MHz_reset_in = reset_pin | ~main_clocks_locked | fo_gmii_ctrl_reset;
wire reset, cu_gmii_tx_reset, cu_gmii_rx_reset, GE_125MHz_reset,fo_tbi_rx_reset;
 
reset_cleaner reset_cleaneri(.ck(core_ck), .reset_in(reset_in), .reset_out(reset));
reset_cleaner GE_125MHz_reset_cleaneri(.ck(GE_125MHz_ref_ck), .reset_in(GE_125MHz_reset_in), .reset_out(GE_125MHz_reset));
reset_cleaner fo_tbi_rx_reset_cleaneri(.ck(fo_tbi_rx_ck), .reset_in(fo_tbi_rxck_reset_in), .reset_out(fo_tbi_rx_reset));
reset_cleaner cu_gmii_tx_reset_cleaneri(.ck(cu_gmii_tx_ck), .reset_in(cu_gmii_txck_reset_in), .reset_out(cu_gmii_tx_reset));
reset_cleaner cu_gmii_rx_reset_cleaneri(.ck(cu_gmii_rx_ck), .reset_in(cu_gmii_rxck_reset_in), .reset_out(cu_gmii_rx_reset));
//----------------------------------------------------------------------------
// Core
//----------------------------------------------------------------------------
genie_ge_x_test_core genie_ge_x_test_corei(
 
// --- Clocks --
.core_ck(core_ck),
// --- Resets ---
.reset(reset),
//
.fo_tbi_tx_reset(GE_125MHz_reset),
.fo_tbi_rx_reset(fo_tbi_rx_reset),
.cu_gmii_tx_reset(cu_gmii_tx_reset),
.cu_gmii_rx_reset(cu_gmii_rx_reset),
// --- FO TBI 125MHz Rx and Tx clks
.fo_tbi_rx_ck(fo_tbi_rx_ck),
.fo_tbi_tx_ck(GE_125MHz_ref_ck),
// --- CU GMII 125MHz Rx and Tx clks
.cu_gmii_rx_ck(cu_gmii_rx_ck),
.cu_gmii_tx_ck(cu_gmii_tx_ck),
// --- TLK1221 transmit TBI bus ---
.fo_tbi_rxd(fo_tbi_rxd),
.fo_tbi_txd(fo_tbi_txd),
 
`ifdef MODEL_TECH
// --- IEEE 802.3 1000BaseLX Receive GMII bus ---
.fo_gmii_rxd(fo_gmii_rxd),
.fo_gmii_rx_dv(fo_gmii_rx_dv),
.fo_gmii_rx_er(fo_gmii_rx_er),
.fo_gmii_col(fo_gmii_col),
.fo_gmii_cs(fo_gmii_cs),
// --- Transmit GMII bus ---
.fo_gmii_tx_en(fo_gmii_tx_en),
.fo_gmii_tx_er(fo_gmii_tx_er),
.fo_gmii_txd(fo_gmii_txd),
`endif
// --- Fibre-Optic (FO) ctrl signals
.fo_sync_en(fo_sync_en),
.fo_loop_en(fo_loop_en),
.fo_prbs_en(fo_prbs_en),
.fo_signal_detect(fo_signal_detect),
.fo_sync(fo_sync),
 
// --- Copper GE GMII Interface ---
.cu_gmii_rxd(cu_gmii_rxd),
.cu_gmii_rx_dv(cu_gmii_rx_dv),
.cu_gmii_rx_er(cu_gmii_rx_er),
//
.cu_gmii_txd(cu_gmii_txd),
.cu_gmii_tx_en(cu_gmii_tx_en),
.cu_gmii_tx_er(cu_gmii_tx_er),
//
.cu_gmii_cs(cu_gmii_cs),
.cu_gmii_col(cu_gmii_col),
// --- MDIO interface ---
.mdio(mdio),
.mdc_in(mdc_in),
.mdc_out(mdc_out)
);
endmodule
 
 
rtl/verilog/ge_1000baseX_fpga.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ge_1000baseX_an.v =================================================================== --- rtl/verilog/ge_1000baseX_an.v (nonexistent) +++ rtl/verilog/ge_1000baseX_an.v (revision 3) @@ -0,0 +1,487 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_an.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 37" Auto-Negotiation function, //// +//// type 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause 37. //// +//// //// +////////////////////////////////////////////////////////////////////// + + +`include "ge_1000baseX_constants.v" +`include "timescale.v" + +module ge_1000baseX_an ( + + // --- clocks and reset --- + input ck, + input reset, + + // --- Startup interface. --- + input startup_enable, + + // --- Auto-negotiation ctrl parameter --- + output reg [2:0] xmit, + output reg [15:0] tx_config, + input [15:0] rx_config, + input rx_config_set, + input ability_match, + input acknowledge_match, + input consistency_match, + input idle_match, + + // --- RX_UNITDATA.indicate messages from RX state machine --- + input [2:0] rudi, + + + // --- Synchronisation Status --- + input sync_status, + input signal_detect, + + // --- GMII Register 0 - AN Basic Control register --- + input mr_main_reset, + input mr_loopback, + input mr_restart_an, + input mr_an_enable, + + // --- GMII Register 1 - AN Basic Status register --- + output reg mr_an_complete, + + // --- GMII register 4 - AN Advertisement + input [15:0] mr_adv_ability, + + // --- GMII register 5 - AN Link Partner Ability + output reg [15:0] mr_lp_adv_ability, + + // --- GMII register 6 - AN Expansion + output reg mr_np_abl, + output reg mr_page_rx, + + // --- GMII register 7 - AN Next Page + input [15:0] mr_np_tx, + + // --- GMII register 8 - AN Link Partner Next Page + output reg [15:0] mr_lp_np_rx + ); + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg mr_np_loaded; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + +`ifdef MODEL_TECH + enum logic [3:0] { +`else + localparam +`endif + S_PCS_AN_STARTUP_RUN = 0, + S_PCS_AN_ENABLE = 1, + S_PCS_AN_RESTART = 2, + S_PCS_AN_DISABLE_LINK_OK = 3, + S_PCS_AN_ABILITY_DETECT = 4, + S_PCS_AN_ACKNOWLEDGE_DETECT = 5, + S_PCS_AN_COMPLETE_ACKNOWLEDGE = 6, + S_PCS_AN_IDLE_DETECT = 7, + S_PCS_AN_LINK_OK = 8, + S_PCS_AN_NEXT_PAGE_WAIT = 9 +`ifdef MODEL_TECH + } pcs_an_present, pcs_an_next; +`else + ; reg [3:0] pcs_an_present, pcs_an_next; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // rx configuration + ////////////////////////////////////////////////////////////////////////////// + + wire rx_config_clr = ~rx_config_set; + + ////////////////////////////////////////////////////////////////////////////// + // Link timer + ////////////////////////////////////////////////////////////////////////////// + +`ifdef MODEL_TECH +`define LINK_TIMER_DONE 1250 +`else +`define LINK_TIMER_DONE 1250000 +`endif + + reg [20:0] link_timer_cnt; + reg link_timer_m_start, link_timer_m_inc; + wire link_timer_done; + + always @(posedge ck, posedge reset) + if (reset) + begin + link_timer_cnt <= 0; + end + else + begin + if (link_timer_m_start) link_timer_cnt <= 0; + else if (link_timer_m_inc) link_timer_cnt <= link_timer_cnt + 1; + end + + assign link_timer_done = (link_timer_cnt >= `LINK_TIMER_DONE); + + ////////////////////////////////////////////////////////////////////////////// + // xmit - set to tell TX state machine state of AN + ////////////////////////////////////////////////////////////////////////////// + + reg xmit_CONFIGURATION_m_set, xmit_DATA_m_set, xmit_IDLE_m_set; + + always @(posedge ck, posedge reset) + if (reset) + xmit <= `XMIT_IDLE; + else + begin + if (~mr_an_enable & rudi != `RUDI_INVALID) xmit <= `XMIT_DATA; + else if (xmit_CONFIGURATION_m_set) xmit <= `XMIT_CONFIGURATION; + else if (xmit_DATA_m_set) xmit <= `XMIT_DATA; + else if (xmit_IDLE_m_set) xmit <= `XMIT_IDLE; + end + + ////////////////////////////////////////////////////////////////////////////// + // mr_lp_adv_ability - variable to store Link partner capabilities + ////////////////////////////////////////////////////////////////////////////// + + reg mr_lp_adv_ability_set, mr_lp_adv_ability_clr; + + always @(posedge ck, posedge reset) + if (reset) + mr_lp_adv_ability <= 16'h0; + else + begin + if (mr_lp_adv_ability_set) mr_lp_adv_ability <= rx_config; + else if (mr_lp_adv_ability_clr) mr_lp_adv_ability <= 16'h00; + end + + ////////////////////////////////////////////////////////////////////////////// + // mr_np_loaded - variable to indicate if the next page has been loaded + ////////////////////////////////////////////////////////////////////////////// + + reg mr_np_loaded_m_set, mr_np_loaded_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + mr_np_loaded <= 0; + else + begin + if (mr_np_loaded_m_set) mr_np_loaded <= 1; + else if (mr_np_loaded_m_clr) mr_np_loaded <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // mr_page_rx_m_clr + ////////////////////////////////////////////////////////////////////////////// + + reg mr_page_rx_m_set, mr_page_rx_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + mr_page_rx <= 0; + else + begin + if (mr_page_rx_m_set) mr_page_rx <= 1; + else if (mr_page_rx_m_clr) mr_page_rx <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // mr_an_complete + ////////////////////////////////////////////////////////////////////////////// + + reg mr_an_complete_m_set, mr_an_complete_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + mr_an_complete <= 0; + else + begin + if (mr_an_complete_m_set) mr_an_complete <= 1; + else if (mr_an_complete_m_clr) mr_an_complete <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // toggle_tx + ////////////////////////////////////////////////////////////////////////////// + + reg toggle_tx, toggle_tx_adv_m_set, toggle_tx_toggle_m_set; + + always @(posedge ck, posedge reset) + if (reset) + toggle_tx <= 0; + else + begin + if (toggle_tx_adv_m_set) toggle_tx <= mr_adv_ability[12]; + else if (toggle_tx_toggle_m_set) toggle_tx <= ~toggle_tx; + end + + ////////////////////////////////////////////////////////////////////////////// + // toggle_rx + ////////////////////////////////////////////////////////////////////////////// + + reg toggle_rx, toggle_rx_m_set; + + always @(posedge ck, posedge reset) + if (reset) + toggle_rx <= 0; + else + begin + if (toggle_rx_m_set) toggle_rx <= rx_config[11]; + end + + ////////////////////////////////////////////////////////////////////////////// + // tx_config register ctrl + ////////////////////////////////////////////////////////////////////////////// + + reg tx_config_m_clr, tx_config_ABILITY_m_set, tx_config_ACK_m_set, tx_config_NP_m_set; + + always @(posedge ck, posedge reset) + if (reset) + tx_config <= 0; + else + begin + if (tx_config_m_clr) tx_config <= 0; + else if (tx_config_ACK_m_set) tx_config[14] <= 1; + else if (tx_config_ABILITY_m_set) tx_config <= { mr_adv_ability[15],1'b0, mr_adv_ability[13:0] }; + else if (tx_config_NP_m_set) tx_config <= { mr_np_tx[15], 1'b0, mr_np_tx[13:12], toggle_tx,mr_np_tx[10:0] }; + end + + ////////////////////////////////////////////////////////////////////////////// + // np_rx + ////////////////////////////////////////////////////////////////////////////// + + reg np_rx, np_rx_m_set; + + always @(posedge ck, posedge reset) + if (reset) + np_rx <= 0; + else + begin + if (np_rx_m_set) np_rx <= rx_config[15]; + end + + ////////////////////////////////////////////////////////////////////////////// + // mr_lp_np_rx + ////////////////////////////////////////////////////////////////////////////// + + reg mr_lp_np_rx_m_set; + + always @(posedge ck, posedge reset) + if (reset) + mr_lp_np_rx <= 0; + else + begin + if (mr_lp_np_rx_m_set) mr_lp_np_rx <= rx_config[15]; + end + + ////////////////////////////////////////////////////////////////////////////// + // np_page_rx + ////////////////////////////////////////////////////////////////////////////// + + reg np_page_rx, np_page_rx_m_set; + + always @(posedge ck, posedge reset) + if (reset) + np_page_rx <= 0; + else + begin + if (np_page_rx_m_set) np_page_rx <= 1; + end + + ////////////////////////////////////////////////////////////////////////////// + // resolve_priority + ////////////////////////////////////////////////////////////////////////////// + + reg resolve_priority, resolve_priority_m_set; + + always @(posedge ck, posedge reset) + if (reset) + resolve_priority <= 0; + else + begin + if (resolve_priority_m_set) resolve_priority <= 1; + end + + ////////////////////////////////////////////////////////////////////////////// + // autonegotiation state machine registered part + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge ck, posedge reset) + + pcs_an_present <= (reset) ? S_PCS_AN_STARTUP_RUN : pcs_an_next; + + ////////////////////////////////////////////////////////////////////////////// + // autonegotiation state machine - IEEE 802.3-2008 Clause 36 + ////////////////////////////////////////////////////////////////////////////// + + always @* + begin + pcs_an_next = pcs_an_present; + + xmit_CONFIGURATION_m_set = 0; xmit_DATA_m_set = 0; xmit_IDLE_m_set = 0; + + mr_np_loaded_m_set = 0; mr_np_loaded_m_clr = 0; + + mr_page_rx_m_set = 0; mr_page_rx_m_clr = 0; + + mr_an_complete_m_set = 0; mr_an_complete_m_clr = 0; + + mr_lp_adv_ability_set = 0; mr_lp_adv_ability_clr = 0; + + tx_config_m_clr = 0; tx_config_ABILITY_m_set = 0;tx_config_ACK_m_set = 0;tx_config_NP_m_set = 0; + + link_timer_m_start = 0; link_timer_m_inc = 0; + + toggle_tx_adv_m_set = 0; toggle_tx_toggle_m_set = 0; + + toggle_rx_m_set = 0; mr_lp_np_rx_m_set = 0; np_rx_m_set = 0; np_page_rx_m_set = 0; + + resolve_priority_m_set = 0; + + case (pcs_an_present) + + S_PCS_AN_STARTUP_RUN: + begin + pcs_an_next = startup_enable ? S_PCS_AN_ENABLE: S_PCS_AN_STARTUP_RUN; + end + + + S_PCS_AN_ENABLE: + begin + mr_page_rx_m_clr = 1; mr_lp_adv_ability_clr = 1; mr_an_complete_m_clr = 1; + + if (mr_an_enable) + begin + xmit_CONFIGURATION_m_set = 1; tx_config_m_clr = 1; + end + else xmit_IDLE_m_set = 1; + + pcs_an_next = (mr_an_enable) ? S_PCS_AN_RESTART : S_PCS_AN_DISABLE_LINK_OK; + + link_timer_m_start = mr_an_enable; + end + + S_PCS_AN_RESTART: + begin + mr_np_loaded_m_clr = 1; tx_config_m_clr = 1; xmit_CONFIGURATION_m_set = 1; + + pcs_an_next = (link_timer_done) ? S_PCS_AN_ABILITY_DETECT : S_PCS_AN_RESTART; + + link_timer_m_inc = ~link_timer_done; + end + + S_PCS_AN_DISABLE_LINK_OK: + begin + xmit_DATA_m_set = 1; + + pcs_an_next = S_PCS_AN_DISABLE_LINK_OK; + end + + S_PCS_AN_ABILITY_DETECT: + begin + toggle_tx_adv_m_set = 1; tx_config_ABILITY_m_set = 1; + + pcs_an_next = (ability_match & rx_config_set) ? S_PCS_AN_ACKNOWLEDGE_DETECT : S_PCS_AN_ABILITY_DETECT; + + mr_lp_adv_ability_set = (ability_match & rx_config_set); + + end + + S_PCS_AN_ACKNOWLEDGE_DETECT: + begin + tx_config_ACK_m_set = 1; + + pcs_an_next = (acknowledge_match & consistency_match) ? S_PCS_AN_COMPLETE_ACKNOWLEDGE : + (acknowledge_match & ~consistency_match) ? S_PCS_AN_ENABLE : + (ability_match & rx_config_clr) ? S_PCS_AN_ENABLE : S_PCS_AN_ACKNOWLEDGE_DETECT; + + link_timer_m_start = (acknowledge_match & consistency_match); + end + + S_PCS_AN_COMPLETE_ACKNOWLEDGE: + begin + toggle_tx_toggle_m_set = 1; toggle_rx_m_set = 1; np_rx_m_set = 1; mr_page_rx_m_set = 1; + + if (ability_match & rx_config_clr) pcs_an_next = S_PCS_AN_ENABLE; + + else if (link_timer_done & (~ability_match | rx_config_set)) + begin + link_timer_m_start = 1; pcs_an_next = S_PCS_AN_IDLE_DETECT; + end + + else link_timer_m_inc = ~link_timer_done; + end + + S_PCS_AN_IDLE_DETECT: + begin + xmit_IDLE_m_set = 1; resolve_priority_m_set = 1; + + pcs_an_next = (ability_match & rx_config_clr) ? S_PCS_AN_ENABLE : + (idle_match & link_timer_done) ? S_PCS_AN_LINK_OK : S_PCS_AN_IDLE_DETECT; + + link_timer_m_inc = ~link_timer_done; + end + + S_PCS_AN_LINK_OK: + begin + xmit_DATA_m_set = 1; mr_an_complete_m_set = 1; resolve_priority_m_set = 1; + + pcs_an_next = (ability_match | mr_restart_an) ? S_PCS_AN_ENABLE : S_PCS_AN_LINK_OK; + end + endcase + + if (~sync_status) pcs_an_next = S_PCS_AN_ENABLE; + else if (mr_main_reset) pcs_an_next = S_PCS_AN_ENABLE; + else if (mr_restart_an) pcs_an_next = S_PCS_AN_ENABLE; + else if (rudi == `RUDI_INVALID) pcs_an_next = S_PCS_AN_ENABLE; + end + +endmodule Index: rtl/verilog/ge_1000baseX_test.v =================================================================== --- rtl/verilog/ge_1000baseX_test.v (nonexistent) +++ rtl/verilog/ge_1000baseX_test.v (revision 3) @@ -0,0 +1,246 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_test.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "timescale.v" + +module ge_1000baseX_test +( + // --- Resets --- + input reset_pin, + + // --- GE 125MHz reference clock --- + input GE_125MHz_ref_ckpin, + + // --- FO TBI 125MHz Rx clk --- + input tbi_rx_ckpin, + + // --- Fibre-Optic (fo) GE TBI Interface --- + input [9:0] tbi_rxd, + output [9:0] tbi_txd, + + // --- GMII interface --- + output [7:0] gmii_rxd, + output gmii_rx_dv, + output gmii_rx_er, + output gmii_col, + output gmii_cs, + + input [7:0] gmii_txd, + input gmii_tx_en, + input gmii_tx_er, + + // --- Fibre-Optic (fo) ctrl signals --- + output sync_en, + output loop_en, + output prbs_en, + + input signal_detect, + input sync, + + // --- MDIO interface + inout mdio, + input mdio_ckpin + ); + + assign sync_en = 1'b0; + assign loop_en = 1'b0; + assign prbs_en = 1'b0; + + + //---------------------------------------------------------------------------- + // MDIO/MDC clock buffering + //---------------------------------------------------------------------------- + + IBUFG mdio_ckpin_bufi(.I(mdio_ckpin), .O(mdio_ckpin_buf)); + + BUFG mdio_ck_bufi(.I(mdio_ckpin_buf), .O(mdc)); + + //---------------------------------------------------------------------------- + // GE 125MHz reference clock + //---------------------------------------------------------------------------- + + IBUFG GE_125MHz_ref_ckpin_bufi(.I(GE_125MHz_ref_ckpin), .O(GE_125MHz_ref_ckpin_buf)); + + wire GE_125MHz_ref_ck_locked; + + DCM #( + .CLKIN_PERIOD(8.0), // Specify period of input clock in ns + .CLKFX_MULTIPLY(5), + .CLKFX_DIVIDE(8) + ) GE_125MHz_ref_ck_DCMi( + .CLK0(GE_125MHz_ref_ck_unbuf), + .CLK180(), + .CLK270(), + .CLK2X(), + .CLK2X180(), + .CLK90(), + .CLKDV(), + .CLKFX(), + .CLKFX180(), + .LOCKED(GE_125MHz_ref_ck_locked), + .PSDONE(), + .STATUS(), + .CLKFB(GE_125MHz_ref_ck), + .CLKIN(GE_125MHz_ref_ckpin_buf), + .DSSEN(1'b0), + .PSCLK(1'b0), + .PSEN(1'b0), + .PSINCDEC(1'b0), + .RST(reset_pin) + ); + + //---------------------------------------------------------------------------- + // 125MHz refence clock + //---------------------------------------------------------------------------- +`ifdef MODEL_TECH + BUFG GE_125MHz_ref_ck_bufi(.I(GE_125MHz_ref_ck_unbuf), .O(GE_125MHz_ref_ck)); +`else + BUFGMUX GE_125MHz_ref_ck_bufi(.I1(GE_125MHz_ref_ck_unbuf), .O(GE_125MHz_ref_ck), .S(1'b1)); +`endif + + //---------------------------------------------------------------------------- + // Fibre-Optic (FO) TBI RX clock. + //---------------------------------------------------------------------------- + + IBUFG tbi_rx_ckpin_bufi(.I(tbi_rx_ckpin), .O(tbi_rx_ckpin_buf)); + + DCM #( + .CLKIN_PERIOD(8.0) + ) tbi_rx_ck_DCMi( + .CLK0(tbi_rx_ck_unbuf), + .CLK180(), + .CLK270(), + .CLK2X(), + .CLK2X180(), + .CLK90(), + .CLKDV(), + .CLKFX(), + .CLKFX180(), + .LOCKED(tbi_rx_ck_locked), + .PSDONE(), + .STATUS(), + .CLKFB(tbi_rx_ck), + .CLKIN(tbi_rx_ckpin_buf), + .DSSEN(1'b0), + .PSCLK(1'b0), + .PSEN(1'b0), + .PSINCDEC(1'b0), + .RST(reset_pin) + ); + + // FO TBI 125MHz rx clock + BUFG tbi_rx_ck_bufi( .I(tbi_rx_ck_unbuf), .O(tbi_rx_ck)); + + //---------------------------------------------------------------------------- + // Reset Cleaners + //---------------------------------------------------------------------------- + + wire main_clocks_locked = GE_125MHz_ref_ck_locked; + + wire tbi_rxck_reset_in = reset_pin | ~main_clocks_locked; + wire GE_125MHz_reset_in = reset_pin | ~main_clocks_locked; + wire mdc_reset_in = reset_pin | ~main_clocks_locked; + + wire GE_125MHz_reset, tbi_rx_reset; + + clean_rst GE_125MHz_reset_cleaneri(.clk(GE_125MHz_ref_ck), .rsti(GE_125MHz_reset_in), .rsto(GE_125MHz_reset)); + clean_rst tbi_rx_reset_cleaneri( .clk(tbi_rx_ck), .rsti(tbi_rxck_reset_in), .rsto(tbi_rx_reset)); + clean_rst mdc_reset_cleaneri( .clk(mdc), .rsti(mdc_reset_in), .rsto(mdc_reset)); + + //------------------------------------------------------------------------------- + // --- IEEE 802.3-2008 1000baseX PCS --- + //------------------------------------------------------------------------------- + + ge_1000baseX ge_1000baseX_i( + + // --- Clocks --- + .rx_ck(tbi_rx_ck), .tx_ck(GE_125MHz_ref_ck), + + // --- resets --- + .tx_reset(GE_125MHz_reset), .rx_reset(tbi_rx_reset), + + // --- Startup interface. --- + .startup_enable(~GE_125MHz_reset), + + // --- Signal detect from FO transceiver + .signal_detect(signal_detect), + + // --- Receive GMII bus --- + .gmii_rxd(gmii_rxd), + .gmii_rx_dv(gmii_rx_dv), + .gmii_rx_er(gmii_rx_er), + .gmii_col(gmii_col), + .gmii_cs(gmii_cs), + // --- Transmit GMII bus --- + .gmii_tx_en(gmii_tx_en), + .gmii_tx_er(gmii_tx_er), + .gmii_txd(gmii_txd), + + // --- Receive 8B10B bus --- + .tbi_rxd(tbi_rxd), + // --- Transmit 8B10B bus --- + .tbi_txd(tbi_txd), + + // --- Mode of operation --- + .repeater_mode(1'b0), + + // --- MDIO interface --- + .mdc_reset(mdc_reset), + .mdc(mdc), + .mdio(mdio)/* synthesis xc_pullup = 1 */ + ); + + +endmodule + +
rtl/verilog/ge_1000baseX_test.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ge_1000baseX.v =================================================================== --- rtl/verilog/ge_1000baseX.v (nonexistent) +++ rtl/verilog/ge_1000baseX.v (revision 3) @@ -0,0 +1,713 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "timescale.v" + +`include "ge_1000baseX_regs.v" +`include "ge_1000baseX_constants.v" + + +module ge_1000baseX #( + parameter PHY_ADDR = 5'b00000 +)( + // Clocks + input rx_ck, + input tx_ck, + + // Resets + input rx_reset, + input tx_reset, + + // Startup interface + input startup_enable, + + // Signal detect from FO transceiver + input signal_detect, + + // RLK1221 receive TBI bus + input [9:0] tbi_rxd, + + // TLK1221 transmit TBI bus + output [9:0] tbi_txd, + + // Receive GMII bus + output [7:0] gmii_rxd, + output gmii_rx_dv, + output gmii_rx_er, + output gmii_col, + output reg gmii_cs, + + + // Transmit GMII bus + input [7:0] gmii_txd, + input gmii_tx_en, + input gmii_tx_er, + + input repeater_mode, + + // MDIO interface + input mdc_reset, + inout mdio, + input mdc + + ); + + ////////////////////////////////////////////////////////////////////////////// + // IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) and + // Media Independent Interface (MII)IEEE 802.3-2005 Clause 22 + ////////////////////////////////////////////////////////////////////////////// + + wire mdio_in, mdio_out, mdio_oe; + + wire [15:0] gmii_reg_wr; + wire [15:0] gmii_reg_rd; + wire [4:0] gmii_reg_addr; + wire gmii_reg_wr_strobe; + + ge_1000baseX_mdio #( + .PHY_ADDR(PHY_ADDR) + ) gmii_mdioi( + .reset(mdc_reset), + .mdc(mdc), + .mdio(mdio_in), + .mdio_out(mdio_out), + .mdio_oe(mdio_oe), + + .data_addr(gmii_reg_addr), + .data_rd(gmii_reg_rd), + .data_wr(gmii_reg_wr), + .strobe_wr(gmii_reg_wr_strobe) + ); + + // MDIO tristate drivers. + assign mdio = (mdio_oe) ? mdio_out : 1'bz; + + assign mdio_in = mdio; + + ////////////////////////////////////////////////////////////////////////////// + // IEEE 802.3-2008 1000BASE-X PCS OUI and version Number + ////////////////////////////////////////////////////////////////////////////// + + wire [23:0] IEEE_OUI = 24'ha1b2c3; + + wire [7:0] version = { 4'b0000, 4'b0001 }; + + ////////////////////////////////////////////////////////////////////////////// + // Aneg configuration registers + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] tx_config_reg; wire [15:0] rx_config_reg; wire rx_config_reg_set; + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 0 - Basic Control - IEEE 802.3-8 1000BASE-X clause 37 page 35 + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] gmii_reg_0; + + wire mr_main_reset, mr_loopback, mr_restart_an, mr_an_enable; + + assign mr_main_reset = gmii_reg_0[15]; + assign mr_loopback = gmii_reg_0[14]; + assign mr_an_enable = gmii_reg_0[12]; + assign mr_restart_an = gmii_reg_0[9]; + +`ifdef MODEL_TECH + // Register 0 bit 11 (normally power-down) used in simulation + // to simulate fibre being inserted and removed + // + wire signal_detect_int = (gmii_reg_0[11] & signal_detect); +`else + wire signal_detect_int = signal_detect; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // Safe versions of various signals in the RX clock domain + ////////////////////////////////////////////////////////////////////////////// + + reg [1:0] mr_main_reset_rxc, mr_loopback_rxc, mr_restart_an_rxc; + reg [1:0] signal_detect_rxc, mr_an_enable_rxc, startup_enable_rxc; + + always @(posedge rx_ck, posedge rx_reset) + if (rx_reset) begin + mr_main_reset_rxc <= 2'b00; mr_loopback_rxc <= 2'b00; + mr_restart_an_rxc <= 2'b00; mr_an_enable_rxc <= 2'b00; + signal_detect_rxc <= 2'b00; startup_enable_rxc <= 2'b00; + end + else begin + mr_main_reset_rxc <= { mr_main_reset_rxc[0], mr_main_reset }; + mr_loopback_rxc <= { mr_loopback_rxc[0], mr_loopback }; + mr_restart_an_rxc <= { mr_restart_an_rxc[0], mr_restart_an }; + mr_an_enable_rxc <= { mr_an_enable_rxc[0], mr_an_enable }; + signal_detect_rxc <= { signal_detect_rxc[0], signal_detect_int }; + startup_enable_rxc <= { startup_enable_rxc[0], startup_enable }; + end + + // Speed select - when AN disabled + wire [1:0] speed_select = {gmii_reg_0[6], gmii_reg_0[13]}; + + +`ifdef MODEL_TECH + `define GMII_REG_0_RESET {8'h19, 8'h40} +`else + `define GMII_REG_0_RESET {8'h11, h40} +`endif + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 1 - Basic Status - IEEE 802.3-5 1000baseLX clause 37 page 36 + ////////////////////////////////////////////////////////////////////////////// + + wire mr_an_complete, sync_status; + +`ifdef MODEL_TECH + // For simulation - sync_status is on gmii_reg 1 bit 7 - currently unused + wire [15:0] gmii_reg_1 = { 1'b0, 1'b0, 1'b0, 1'b0, + 1'b0, 1'b0, 1'b0, 1'b0, + sync_status, 1'b1, mr_an_complete, 1'b0, + 1'b1, signal_detect_rxc[1], 1'b0, 1'b0}; +`else + wire [15:0] gmii_reg_1 = { 1'b0, 1'b0, 1'b0, 1'b0, + 1'b0, 1'b0, 1'b0, 1'b0, + 1'b0, 1'b1, mr_an_complete, 1'b0, + 1'b1, signal_detect_rxc[1], 1'b0, 1'b0}; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 2 - PHY Identifier 1 - IEEE 802.3-5 1000baseX + // clause 37 page 36 + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] gmii_reg_2 = { IEEE_OUI[15:8], IEEE_OUI[23:16]}; + + ////////////////////////////////////////////////////////////////////////////// + // --- GMII register 3 - PHY Identifier 2 - IEEE 802.3-5 1000baseX + // clause 37 page 36 + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] gmii_reg_3 = { version, IEEE_OUI[7:0] }; + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 4 - Auto-Negotiation Advertisement - IEEE 802.3-5 1000baseX + // clause 37 page 37 + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] gmii_reg_4; + + wire [15:0] mr_adv_ability; + + // See IEEE 802.3-5 1000baseLX clause 37 page 82 - Table 37-1 for these + + assign mr_adv_ability = gmii_reg_4; + +`define GMII_REG_4_RESET 16'b0000000000100000 + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 5 - Auto-Negotiation Link Partner Ability - IEEE 802.3-5 + // 1000baseX clause 37 page 37 + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] mr_lp_adv_ability; + + wire [15:0] gmii_reg_5 = mr_lp_adv_ability; + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 6 - Auto-Negotiation Expansion - IEEE 802.3-5 1000baseX + // clause 37 page 38 + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] gmii_reg_6; + + wire mr_np_abl, mr_page_rx; + + assign gmii_reg_6 = { 1'b0, 1'b0, 1'b0, 1'b0, + 1'b0, 1'b0, 1'b0, 1'b0, + 1'b0, 1'b0, 1'b0, 1'b0, + mr_np_abl, 1'b0, mr_page_rx,1'b0}; + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 7 - Auto-Negotiation Link Partner Next Page - IEEE 802.3-5 + // 1000baseX clause 37 page 38 + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] gmii_reg_7; + + wire[15:0] mr_np_tx; + + assign mr_np_tx = gmii_reg_7; + +`define GMII_REG_7_RESET 16'b0000000000000000 + + ////////////////////////////////////////////////////////////////////////////// + // GMII register 8 - Auto-Negotiation Link Partner Next Page - IEEE 802.3-5 + // 1000baseX clause 37 page 38 + ////////////////////////////////////////////////////////////////////////////// + + wire [15:0] gmii_reg_8; + + wire [15:0] mr_lp_np_rx; + + assign gmii_reg_8 = mr_lp_np_rx; + + ////////////////////////////////////////////////////////////////////////////// + // IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) and + // Media Independent Interface (MII)IEEE 802.3-2005 Clause 22 + ////////////////////////////////////////////////////////////////////////////// + + // Read operations + assign gmii_reg_rd = (gmii_reg_addr == `GMII_BASIC_CTRL) ? gmii_reg_0 : + (gmii_reg_addr == `GMII_BASIC_STATUS) ? gmii_reg_1 : + (gmii_reg_addr == `GMII_PHY_ID1) ? gmii_reg_2 : + (gmii_reg_addr == `GMII_PHY_ID2) ? gmii_reg_3 : + (gmii_reg_addr == `GMII_AN_ADV) ? gmii_reg_4 : + (gmii_reg_addr == `GMII_AN_LP_ADV) ? gmii_reg_5 : + (gmii_reg_addr == `GMII_AN_EXPANSION) ? gmii_reg_6 : + (gmii_reg_addr == `GMII_AN_NP) ? gmii_reg_7 : + (gmii_reg_addr == `GMII_AN_LP_NP) ? gmii_reg_8 : 5'b00000; + + // Write operations + always @(posedge mdc or posedge mdc_reset) + if (mdc_reset) + begin + gmii_reg_0 <= `GMII_REG_0_RESET; + gmii_reg_4 <= `GMII_REG_4_RESET; + gmii_reg_7 <= `GMII_REG_7_RESET; + end + else + if (gmii_reg_wr_strobe) + begin + case (gmii_reg_addr) + + `GMII_BASIC_CTRL : gmii_reg_0 <= gmii_reg_wr; + `GMII_AN_ADV : gmii_reg_4 <= gmii_reg_wr; + `GMII_AN_NP : gmii_reg_7 <= gmii_reg_wr; + endcase + end + else + begin + // mr_an_restart is self clearing + if (gmii_reg_0[9]) gmii_reg_0[9] <= 1'b0; + + // mr_main_reset) is self clearing + else if (gmii_reg_0[15]) gmii_reg_0[15] <= 1'b0; + end + + + ////////////////////////////////////////////////////////////////////////////// + // Status + ////////////////////////////////////////////////////////////////////////////// + + wire [2:0] xmit; + + wire carrier_detect; + + wire transmitting, receiving; + + ////////////////////////////////////////////////////////////////////////////// + // Generate GMII Carrier Sense - IEEE 802.3-2008 Clause 36 - 26.2.5.2.5 + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge rx_ck, posedge rx_reset) + if (rx_reset) + gmii_cs <= 1'b0; + else + if ((~repeater_mode & transmitting) | receiving) begin gmii_cs <= 1'b1; end + + else if ((repeater_mode | ~transmitting) & ~receiving) begin gmii_cs <= 1'b0; end + + + ////////////////////////////////////////////////////////////////////////////// + // delayed versions of 10b interface + ////////////////////////////////////////////////////////////////////////////// + + reg [9:0] tbi_rxd_d1, tbi_rxd_d2, tbi_rxd_d3, tbi_rxd_d4; + + always @(posedge rx_ck, posedge rx_reset) + begin + tbi_rxd_d1 <= (rx_reset) ? 0 : tbi_rxd; + tbi_rxd_d2 <= (rx_reset) ? 0 : tbi_rxd_d1; + tbi_rxd_d3 <= (rx_reset) ? 0 : tbi_rxd_d2; + tbi_rxd_d4 <= (rx_reset) ? 0 : tbi_rxd_d3; + end + + ////////////////////////////////////////////////////////////////////////////// + /// 8b10 decoder module + ////////////////////////////////////////////////////////////////////////////// + + wire decoder_K, decoder_disparity_err, decoder_coding_err; + + wire [7:0] decoder_8b_rxd; + + + decoder_8b10b decoder_8b10bi( + + .RBYTECLK(rx_ck), + + .reset(rx_reset), + + // 10B input + .tbi(tbi_rxd_d1), + + // Data/special code-group ctrl + .K_out(decoder_K), + + // 8B output + .ebi(decoder_8b_rxd), + + // Disparity error + .disparity_err(decoder_disparity_err), + + // Disparity output + .disparity(decoder_disparity_out), + + // Coding error + .coding_err(decoder_coding_err) + ); + +`ifdef MODEL_TECH + wire [4:0] decoder_8b_rxd_X; + wire [2:0] decoder_8b_rxd_Y; + + assign {decoder_8b_rxd_Y, decoder_8b_rxd_X} = decoder_8b_rxd; + +`endif + + ////////////////////////////////////////////////////////////////////////////// + // Instantiate 802.3-2005 PCS sync module - 802.3-2008 Clause 36 + ////////////////////////////////////////////////////////////////////////////// + + wire sync_K, sync_rx_even; + wire [7:0] sync_8b_rxd; + +`ifdef MODEL_TECH + wire [4:0] sync_8b_rxd_X = sync_8b_rxd[4:0]; + wire [2:0] sync_8b_rxd_Y = sync_8b_rxd[7:5]; +`endif + + ge_1000baseX_sync ge_1000baseX_sync_i( + + .ck(rx_ck), .reset(rx_reset), + + .startup_enable(startup_enable_rxc[1]), + + // Signal detect from FO transceiver + .signal_detect(signal_detect_rxc[1]), + + // 8B input from 8b10 decoder + .ebi_rxd(decoder_8b_rxd), + .ebi_K(decoder_K), + + // 8B output from sync + .ebi_rxd_out(sync_8b_rxd), + .ebi_K_out(sync_K), + + // Synchronisation status + .sync_status(sync_status), + + .rx_even(sync_rx_even), + + .decoder_disparity_err(decoder_disparity_err), + + .decoder_coding_err(decoder_coding_err), + + .loopback(mr_loopback_rxc[1]) + ); + + ////////////////////////////////////////////////////////////////////////////// + // Carrier Detect - IEEE 802.3-2008 Section 36.2.5.1.4 + ////////////////////////////////////////////////////////////////////////////// + + wire [5:0] sb; wire [3:0] fb; + + wire RDn_cd_fail_match1, RDn_cd_fail_match2, RDn_cd_fail_match; + + wire RDp_cd_fail_match1, RDp_cd_fail_match2, RDp_cd_fail_match; + + assign sb[5:0] = tbi_rxd_d4[9:4]; + + assign fb[3:0] = tbi_rxd_d4[3:0]; + + assign RDn_cd_fail_match1 = ((sb == 6'b110000) & ((fb == 4'b0101) | (fb == 4'b0100) | (fb == 4'b0111) | (fb == 4'b0001) | (fb==4'b1101))); + + assign RDn_cd_fail_match2 = ((fb == 4'b0101) & ((sb==6'b110001) |(sb==6'b110010) | (sb==6'b110100) | (sb==6'b111000) | (sb==6'b100000) | (sb==6'b010000))); + + assign RDn_cd_fail_match = RDn_cd_fail_match1 | RDn_cd_fail_match2; + + + assign RDp_cd_fail_match1 = ((sb == 6'b001111) & ((fb==4'b1010)|(fb==4'b1011)|(fb==4'b1000)|(fb==4'b1110)|(fb==4'b0010))); + + assign RDp_cd_fail_match2 = ((fb == 4'b1010) & ((sb==6'b001110)|(sb==6'b001101)|(sb==6'b001011)|(sb==6'b000111)|(sb==6'b011111)|(sb==6'b101111))); + + assign RDp_cd_fail_match = RDp_cd_fail_match1 | RDp_cd_fail_match2; + + assign carrier_detect = sync_rx_even & ~RDn_cd_fail_match & ~RDp_cd_fail_match; + + ////////////////////////////////////////////////////////////////////////////// + // 802.3-2008 1000baseX PCS autonegotiation (AN) module - 802.3-2008 Clause 37 + ////////////////////////////////////////////////////////////////////////////// + + wire [2:0] rudi; // RX_UNITDATA.indicate messages + + ge_1000baseX_an ge_1000baseX_an_i( + + .ck(rx_ck),.reset(rx_reset), + + .startup_enable(startup_enable_rxc[1]), + + // Auto-negotiation ctrl + .xmit(xmit), + .rx_config(rx_config_reg), + .rx_config_set(rx_config_reg_set), + .tx_config(tx_config_reg), + + // RX_UNITDATA.indicate messages + .rudi(rudi), + + // Auto-negotiation /C/ and /I/ matching + .ability_match(ability_match), + .acknowledge_match(acknowledge_match), + .consistency_match(consistency_match), + .idle_match(idle_match), + + // Synchronisation Status + .sync_status(sync_status), + .signal_detect(signal_detect_rxc[1]), + + // GMII Register 0 - AN Basic Control + .mr_main_reset(mr_main_reset_rxc[1]), + .mr_loopback(mr_loopback_rxc[1]), + .mr_restart_an(mr_restart_an_rxc[1]), + .mr_an_enable(mr_an_enable_rxc[1]), + + // GMII Register 1 - AN Basic Status + .mr_an_complete(mr_an_complete), + + // GMII register 4 - AN Advertisement + .mr_adv_ability(mr_adv_ability), + + // GMII register 5 - AN Link Partner Ability + .mr_lp_adv_ability(mr_lp_adv_ability), + + // GMII register 6 - AN Expansion + .mr_np_abl(mr_np_abl), + .mr_page_rx(mr_page_rx), + + // GMII register 7 - AN Next Page + .mr_np_tx(mr_np_tx), + + // GMII register 8 - AN Link Partner Next Page + .mr_lp_np_rx(mr_lp_np_rx) + ); + + wire tx_frame_pulse, frame_rx_pulse; + + ////////////////////////////////////////////////////////////////////////////// + // 802.3-2008 1000baseX PCS receive module - 802.3-2008 Clause 36 + ////////////////////////////////////////////////////////////////////////////// + + ge_1000baseX_rx ge_1000base_rxi( + + .ck(rx_ck), .reset(rx_reset), + + // Receive 8B bus from sync module + .ebi_rxd(sync_8b_rxd), + .ebi_K(sync_K), + + .rx_even(sync_rx_even), + .carrier_detect(carrier_detect), + .sync_status(sync_status), + + // Signal detect from FO transceiver + .signal_detect(signal_detect_rxc[1]), + + // Receive frame pulse + .rx_frame_pulse(rx_frame_pulse), + + // Receive GMII bus + .gmii_rxd(gmii_rxd), + .gmii_rx_dv(gmii_rx_dv), + .gmii_rx_er(gmii_rx_er), + + // Auto-negotiation ctrl + .xmit(xmit), + .mr_main_reset(mr_main_reset_rxc[1]), + .rx_config(rx_config_reg), + .rx_config_set(rx_config_reg_set), + .rudi(rudi), + + // Auto-negotiation /C/ and /I/ matching + .ability_match(ability_match), + .acknowledge_match(acknowledge_match), + .consistency_match(consistency_match), + .idle_match(idle_match), + + .receiving(receiving) + ); + + ////////////////////////////////////////////////////////////////////////////// + // Safe versions of various signals in the TX clock domain + ////////////////////////////////////////////////////////////////////////////// + + reg [1:0] mr_main_reset_txc, receiving_txc, signal_detect_txc, startup_enable_txc; + + always @(posedge tx_ck, posedge tx_reset) + if (tx_reset) begin + + mr_main_reset_txc <= 2'b00; receiving_txc <= 2'b00; + signal_detect_txc <= 2'b00; startup_enable_txc <= 2'b00; + end + else + begin + mr_main_reset_txc <= { mr_main_reset_txc[0], mr_main_reset }; + receiving_txc <= { receiving_txc[0], receiving }; + signal_detect_txc <= { signal_detect_txc[0], signal_detect }; + startup_enable_txc <= { startup_enable_txc[0], startup_enable }; + end + + reg [2:0] xmit_txc, xmit_txc0; + + always @(posedge tx_ck, posedge tx_reset) + begin + xmit_txc <= (tx_reset) ? `XMIT_IDLE : xmit_txc0; + + xmit_txc0 <= (tx_reset) ? `XMIT_IDLE : xmit; + end + + ////////////////////////////////////////////////////////////////////////////// + // 802.3-2008 1000baseX PCS transmit module 802.3-2008 Clause 36 + ////////////////////////////////////////////////////////////////////////////// + + ge_1000baseX_tx ge_1000baseX_txi( + + // --- TX clock and reset --- + .ck(tx_ck), + .reset(tx_reset), + + // --- RLK1221 transmit TBI bus --- + .tbi_txd(tbi_txd), + + .signal_detect(signal_detect_txc[1]), + + // Transmit frame pulse + .tx_frame_pulse(tx_frame_pulse), + + // --- Transmit GMII bus - + .gmii_tx_en_in(gmii_tx_en), + .gmii_tx_er_in(gmii_tx_er), + .gmii_txd_in(gmii_txd), + + .gmii_col(gmii_col), + + .receiving(receiving_txc[1]), + .transmitting(transmitting), + + // --- Auto-negotiation ctrl --- + .xmit(xmit_txc), + .tx_config(tx_config_reg), + .mr_main_reset(mr_main_reset_txc[1]) + ); + + ////////////////////////////////////////////////////////////////////////////// + // Frame transmit LED pulse + ////////////////////////////////////////////////////////////////////////////// + + reg [23:0] tx_led_counter; + reg tx_frame_pulse_latch, tx_frame_activity; + + always @(posedge tx_ck, posedge tx_reset) + + if (tx_reset) + begin + tx_led_counter <= 0; tx_frame_activity <= 0; tx_frame_pulse_latch <= 1; + end + else + begin + tx_led_counter <= tx_led_counter + 1; + + if (tx_frame_activity) + begin + if (~tx_led_counter[23]) begin tx_frame_pulse_latch <= 0;tx_frame_activity <= 0; end + end + else if (tx_led_counter[23] & tx_frame_pulse_latch) tx_frame_activity <= 1; + + else if (tx_frame_pulse) tx_frame_pulse_latch <= 1; + end + + ////////////////////////////////////////////////////////////////////////////// + // Frame receive LED pulse + ////////////////////////////////////////////////////////////////////////////// + + reg [23:0] rx_led_counter; + reg rx_frame_pulse_latch, rx_frame_activity; + + always @(posedge rx_ck, posedge rx_reset) + + if (rx_reset) + begin + rx_led_counter <= 0; rx_frame_activity <= 0; rx_frame_pulse_latch <= 1; + end + else + begin + rx_led_counter <= rx_led_counter + 1; + + if (rx_frame_activity) + begin + if (~rx_led_counter[23]) begin rx_frame_pulse_latch <= 0;rx_frame_activity <= 0; end + end + else if (rx_led_counter[23] & rx_frame_pulse_latch) rx_frame_activity <= 1; + + else if (rx_frame_pulse) rx_frame_pulse_latch <= 1; + end + + + wire fo_activity = rx_frame_activity | tx_frame_activity; + +endmodule Index: rtl/verilog/ge_1000baseX_regs.v =================================================================== --- rtl/verilog/ge_1000baseX_regs.v (nonexistent) +++ rtl/verilog/ge_1000baseX_regs.v (revision 3) @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_regs.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`define GMII_BASIC_CTRL 'd00 +`define GMII_BASIC_STATUS 'd02 +`define GMII_PHY_ID1 'd04 +`define GMII_PHY_ID2 'd06 +`define GMII_AN_ADV 'd08 +`define GMII_AN_LP_ADV 'd10 +`define GMII_AN_EXPANSION 'd12 +`define GMII_AN_NP 'd14 +`define GMII_AN_LP_NP 'd16 Index: rtl/verilog/decoder_8b10b.v =================================================================== --- rtl/verilog/decoder_8b10b.v (nonexistent) +++ rtl/verilog/decoder_8b10b.v (revision 3) @@ -0,0 +1,362 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "decoder_8b10b.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Section 36.2.4 which is available from : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// //// +//// and the 8B/10B coding scheme from the 1993 IBM publication //// +//// "DC-Balanced, Partitioned-Block, 8B/10B Transmission Code" //// +//// by A.X. Widmer and P.A. Franasze" see doc/01-581v1.pdf //// +//// //// +//// and US patent #4,486,739 "BYTE ORIENTED DC BALANCED //// +//// (0,4) 8B/10B PARTITIONED BLOCK TRANSMISSION CODE "; see : //// +//// //// +//// doc/US4486739.pdf //// +//// //// +//// http://en.wikipedia.org/wiki/8b/10b_encoding //// +//// //// +////////////////////////////////////////////////////////////////////// + + +`include "timescale.v" + +module decoder_8b10b ( + + // --- Resets --- + input reset, + + // --- Clocks --- + input RBYTECLK, + + // --- TBI (Ten Bit Interface) input bus + input [9:0] tbi, + + // --- Control (K) + output reg K_out, + + // -- Eight bit output bus + output reg [7:0] ebi, + + // --- 8B/10B RX coding error --- + output reg coding_err, + + // --- 8B/10B RX disparity --- + output reg disparity, + + // --- 8B/10B RX disparity error --- + output disparity_err + + ); + +`ifdef MODEL_TECH + // ModelSim debugging only + wire [4:0] decoder_8b_X; wire [2:0] decoder_8b_Y; + + assign decoder_8b_X = ebi[4:0]; + assign decoder_8b_Y = ebi[7:5]; +`endif + + wire a,b,c,d,e,i,f,g,h,j; // 10 Bit inputs + + assign {a,b,c,d,e,i,f,g,h,j} = tbi[9:0]; + + // ****************************************************************************** + // Figure 10 - Decoder: 6b - Signals + // ****************************************************************************** + wire AEQB, CEQD, P22, P13, P31; + + // ****************************************************************************** + // Figure 11 - Decoder: K - Signals + // ****************************************************************************** + + wire eeqi, c_d_e_i, cn_dn_en_in; + + wire P22_a_c_eeqi, P22_an_cn_eeqi; + + wire P22_b_c_eeqi, P22_bn_cn_eeqi, an_bn_en_in; + + wire a_b_e_i, P13_d_e_i, P13_in, P13_en, P31_i; + + // ****************************************************************************** + // Figure 12 - Decoder: 5B - Signals + // ****************************************************************************** + + wire OR12_1, OR12_2, OR12_3, OR12_4, OR12_5, OR12_6, OR12_7; + + wire A, B, C, D, E; + + // ****************************************************************************** + // Figure 13 - Decoder: 3B - Signals + // ****************************************************************************** + + wire K, F, G, H, K28p, KA, KB, KC; + + // ****************************************************************************** + // Figure 10 - Decoder: 6b Input Function + // ****************************************************************************** + + assign AEQB = (a & b) | (!a & !b) ; + assign CEQD = (c & d) | (!c & !d) ; + assign P22 = (a & b & !c & !d) | (c & d & !a & !b) | ( !AEQB & !CEQD) ; + assign P13 = ( !AEQB & !c & !d) | ( !CEQD & !a & !b) ; + assign P31 = ( !AEQB & c & d) | ( !CEQD & a & b) ; + + // ****************************************************************************** + // Figure 11 - Decoder: K + // ****************************************************************************** + + assign eeqi = (e == i); + + assign P22_a_c_eeqi = P22 & a & c & eeqi; + assign P22_an_cn_eeqi = P22 & !a & !c & eeqi; + + assign cn_dn_en_in = (!c & !d & !e & !i); + assign c_d_e_i = (c & d & e & i); + + assign KA = c_d_e_i | cn_dn_en_in; + assign KB = P13 & (!e & i & g & h & j); + assign KC = P31 & (e & !i & !g & !h & !j); + + assign K = KA | KB | KC; + + assign P22_b_c_eeqi = P22 & b & c & eeqi; + assign P22_bn_cn_eeqi = P22 & !b & !c & eeqi; + assign an_bn_en_in = !a & !b & !e & !i; + assign a_b_e_i = a & b & e & i; + assign P13_d_e_i = P13 & d & e & i; + assign P13_in = P13 & !i; + assign P13_en = P13 & !e; + assign P31_i = P31 & i; + + + // ****************************************************************************** + // Figure 12 - Decoder: 5B/6B + // ****************************************************************************** + + assign OR12_1 = P22_an_cn_eeqi | P13_en; + assign OR12_2 = a_b_e_i | cn_dn_en_in | P31_i; + assign OR12_3 = P31_i | P22_b_c_eeqi | P13_d_e_i; + assign OR12_4 = P22_a_c_eeqi | P13_en; + assign OR12_5 = P13_en | cn_dn_en_in | an_bn_en_in; + assign OR12_6 = P22_an_cn_eeqi | P13_in; + assign OR12_7 = P13_d_e_i | P22_bn_cn_eeqi; + + assign A = a ^ (OR12_7 | OR12_1 | OR12_2); + assign B = b ^ (OR12_2 | OR12_3 | OR12_4); + assign C = c ^ (OR12_1 | OR12_3 | OR12_5); + assign D = d ^ (OR12_2 | OR12_4 | OR12_7); + assign E = e ^ (OR12_5 | OR12_6 | OR12_7); + + // ****************************************************************************** + // Figure 13 - Decoder: 3B/4B + // ****************************************************************************** + + // K28 with positive disp into fghi - .1, .2, .5, and .6 specal cases + assign K28p = ! (c | d | e | i) ; + + assign F = (j & !f & (h | !g | K28p)) | (f & !j & (!h | g | !K28p)) | (K28p & g & h) | (!K28p & !g & !h) ; + + assign G = (j & !f & (h | !g | !K28p)) | (f & !j & (!h | g |K28p)) | (!K28p & g & h) | (K28p & !g & !h) ; + + assign H = ((j ^ h) & ! ((!f & g & !h & j & !K28p) | (!f & g & h & !j & K28p) | + (f & !g & !h & j & !K28p) | (f & !g & h & !j & K28p))) | (!f & g & h & j) | (f & !g & !h & !j) ; + + // ****************************************************************************** + // Registered 8B output + // ****************************************************************************** + + always @(posedge RBYTECLK or posedge reset) + if (reset) + begin + K_out <= 0; ebi[7:0] <= 8'b0; + end + else + begin + K_out <= K; ebi[7:0] <= { H, G, F, E, D, C, B, A } ; + end + + // ****************************************************************************** + // Disparity + // ****************************************************************************** + + wire heqj, fghjP13, fghjP31, fghj22; + + wire DISPARITY6p, DISPARITY6n, DISPARITY4p, DISPARITY4n; + + wire DISPARITY6b, DISPARITY6a2, DISPARITY6a0; + + assign feqg = (f & g) | (!f & !g); + assign heqj = (h & j) | (!h & !j); + + assign fghjP13 = ( !feqg & !h & !j) | ( !heqj & !f & !g) ; + assign fghjP31 = ( (!feqg) & h & j) | ( !heqj & f & g) ; + assign fghj22 = (f & g & !h & !j) | (!f & !g & h & j) | ( !feqg & !heqj) ; + + assign DISPARITY6p = (P31 & (e | i)) | (P22 & e & i) ; + assign DISPARITY6n = (P13 & ! (e & i)) | (P22 & !e & !i); + + assign DISPARITY4p = fghjP31 ; + assign DISPARITY4n = fghjP13 ; + + assign DISPARITY6a = P31 | (P22 & disparity); // pos disp if P22 and was pos, or P31. + assign DISPARITY6a2 = P31 & disparity; // disp is ++ after 4 bts + assign DISPARITY6a0 = P13 & ! disparity; // -- disp after 4 bts + + assign DISPARITY6b = (e & i & ! DISPARITY6a0) | (DISPARITY6a & (e | i)) | DISPARITY6a2; + + + // ****************************************************************************** + // Disparity errors + // ****************************************************************************** + + wire derr1,derr2,derr3,derr4,derr5,derr6,derr7,derr8; + + assign derr1 = (disparity & DISPARITY6p) | (DISPARITY6n & !disparity); + assign derr2 = (disparity & !DISPARITY6n & f & g); + assign derr3 = (disparity & a & b & c); + assign derr4 = (disparity & !DISPARITY6n & DISPARITY4p); + assign derr5 = (!disparity & !DISPARITY6p & !f & !g); + assign derr6 = (!disparity & !a & !b & !c); + assign derr7 = (!disparity & !DISPARITY6p & DISPARITY4n); + assign derr8 = (DISPARITY6p & DISPARITY4p) | (DISPARITY6n & DISPARITY4n); + + // ****************************************************************************** + // Register disparity and disparity_err output + // ****************************************************************************** + + reg derr12, derr34, derr56, derr78; + + always @(posedge RBYTECLK or posedge reset) + if (reset) + begin + disparity <= 1'b0; + derr12 <= 1; + derr34 <= 1; + derr56 <= 1; + derr78 <= 1; + end + else + begin + disparity <= fghjP31 | (DISPARITY6b & fghj22) ; + + derr12 <= derr1 | derr2; + derr34 <= derr3 | derr4; + derr56 <= derr5 | derr6; + derr78 <= derr7 | derr8; + end + + assign disparity_err = derr12|derr34|derr56|derr78; + + // ****************************************************************************** + // Coding errors as defined in patent - page 447 + // ****************************************************************************** + + wire cerr1, cerr2, cerr3, cerr4, cerr5, cerr6, cerr7, cerr8, cerr9; + + assign cerr1 = (a & b & c & d) | (!a & !b & !c & !d); + assign cerr2 = (P13 & !e & !i); + assign cerr3 = (P31 & e & i); + assign cerr4 = (f & g & h & j) | (!f & !g & !h & !j); + assign cerr5 = (e & i & f & g & h) | (!e & !i & !f & !g & !h); + assign cerr6 = (e & !i & g & h & j) | (!e & i & !g & !h & !j); + assign cerr7 = (((e & i & !g & !h & !j) | (!e & !i & g & h & j)) & !((c & d & e) | (!c & !d & !e))); + assign cerr8 = (!P31 & e & !i & !g & !h & !j); + assign cerr9 = (!P13 & !e & i & g & h & j); + + reg cerr; + + always @(posedge RBYTECLK or posedge reset) + if (reset) + cerr <= 0; + else + cerr <= cerr1|cerr2|cerr3|cerr4|cerr5|cerr6|cerr7|cerr8|cerr9; + + // ****************************************************************************** + // Disparity coding errors curtosy of http://asics.chuckbenz.com/decode.v + // ****************************************************************************** + + wire zerr1, zerr2, zerr3; + + assign zerr1 = (DISPARITY6p & DISPARITY4p) | (DISPARITY6n & DISPARITY4n); + assign zerr2 = (f & g & !h & !j & DISPARITY6p); + assign zerr3 = (!f & !g & h & j & DISPARITY6n); + + reg zerr; + + always @(posedge RBYTECLK or posedge reset) + if (reset) + zerr <= 0; + else + zerr <= zerr1|zerr2|zerr3; + + // ****************************************************************************** + // Extra coding errors - again from http://asics.chuckbenz.com/decode.v + // ****************************************************************************** + + wire xerr1, xerr2, xerr3, xerr4; + + reg xerr; + + assign xerr1 = (a & b & c & !e & !i & ((!f & !g) | fghjP13)); + assign xerr2 =(!a & !b & !c & e & i & ((f & g) | fghjP31)); + assign xerr3 = (c & d & e & i & !f & !g & !h); + assign xerr4 = (!c & !d & !e & !i & f & g & h); + + always @(posedge RBYTECLK or posedge reset) + if (reset) + xerr <= 0; + else + xerr <= xerr1|xerr2|xerr3|xerr4; + + // ****************************************************************************** + // Registered Coding error output + // ****************************************************************************** + + always @(posedge RBYTECLK or posedge reset) + if (reset) + coding_err <= 1'b1; + else + coding_err <= cerr | zerr | xerr; + +endmodule Index: rtl/verilog/ge_1000baseX_core.v =================================================================== --- rtl/verilog/ge_1000baseX_core.v (nonexistent) +++ rtl/verilog/ge_1000baseX_core.v (revision 3) @@ -0,0 +1,193 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_core.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "timescale.v" + +module ge_1000baseX_core +( + // --- Clocks -- + input core_ck, + + // --- Resets --- + input reset, + + // + input fo_tbi_tx_reset, + input fo_tbi_rx_reset, + input cu_gmii_tx_reset, + input cu_gmii_rx_reset, + + // --- FO TBI 125MHz Rx and Tx clks + input fo_tbi_rx_ck, + input fo_tbi_tx_ck, + + // --- CU GMII 125MHz Rx and Tx clks + input cu_gmii_rx_ck, + input cu_gmii_tx_ck, + + // --- Fibre-Optic (fo) GE TBI Interface + input [9:0] fo_tbi_rxd, + output [9:0] fo_tbi_txd, + +`ifdef MODEL_TECH + // -- Route GMII from IEEE 802.3 1000BaseLX out - for testing + output [7:0] fo_gmii_rxd, + output fo_gmii_rx_dv, + output fo_gmii_rx_er, + output fo_gmii_col, + output fo_gmii_cs, + + input [7:0] fo_gmii_txd, + input fo_gmii_tx_en, + input fo_gmii_tx_er, +`endif + + // --- Fibre-Optic (fo) ctrl signals + output fo_sync_en, + output fo_loop_en, + output fo_prbs_en, + input fo_signal_detect, + input fo_sync, + + // --- Copper GE GMII Interface --- + input [7:0] cu_gmii_rxd, + input cu_gmii_rx_dv, + input cu_gmii_rx_er, + // + output [7:0] cu_gmii_txd, + output cu_gmii_tx_en, + output cu_gmii_tx_er, + // + input cu_gmii_cs, + input cu_gmii_col, + + // --- MDIO interface + output mdio, + input mdc_in, + output mdc_out + ); + + assign fo_sync_en = 1'b0; + assign fo_loop_en = 1'b0; + assign fo_prbs_en = 1'b0; + + //------------------------------------------------------------------------------- + // --- IEEE 802.3-2005 1000baseLX PCS interface (gmii <-> tbi) + //------------------------------------------------------------------------------- + + wire [3:0] status_leds; + + wire repeater_mode; + + // Not in repeater mode! + assign repeater_mode = 1'b0; + + ge_1000baseX ge_1000baseXi( + + // --- Clocks --- + .ck(core_ck), .rx_ck(fo_tbi_rx_ck), .tx_ck(fo_tbi_tx_ck), + + // --- reset --- + .reset(reset), .tx_reset(fo_tbi_tx_reset), .rx_reset(fo_tbi_rx_reset), + + // --- Startup interface. --- + .startup_enable(~reset), + + // --- Signal detect from FO transceiver + .signal_detect(fo_signal_detect), + + // --- Receive GMII bus --- + .gmii_rxd(fo_gmii_rxd), + .gmii_rx_dv(fo_gmii_rx_dv), + .gmii_rx_er(fo_gmii_rx_er), + // + .gmii_col(fo_gmii_col), + .gmii_cs(fo_gmii_cs), + + // --- Transmit GMII bus --- + .gmii_tx_en(fo_gmii_tx_en), + .gmii_tx_er(fo_gmii_tx_er), + .gmii_txd(fo_gmii_txd), + + // --- RLK1221 receive TBI bus --- + .tbi_rxd(fo_tbi_rxd), + + // --- TLK1221 ransmit TBI bus --- + .tbi_txd(fo_tbi_txd), + + // --- Mode of operation --- + .repeater_mode(repeater_mode), + + // --- MDIO interface --- + .mdio(mdio), + .mdc_in(mdc_in), + .mdc_out(mdc_out), + + // --- Data interface. --- + .data_cs(data_cs_ethernet), + .data_wr_rq(data_wr_rq), + .data_rd_rq(data_rd_rq), + .data_addr(data_addr), + .data_bus_wr(data_bus_wr), + .data_bus_rd(wor_data_bus_rd_0), + .data_grant(wor_data_grant_0), + + // --- Status LEDS. --- + .status_leds(status_leds), + + // --- Debugging --- + .debug() + ); + +endmodule +
rtl/verilog/ge_1000baseX_core.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ge_1000baseX_mdio.v =================================================================== --- rtl/verilog/ge_1000baseX_mdio.v (nonexistent) +++ rtl/verilog/ge_1000baseX_mdio.v (revision 3) @@ -0,0 +1,322 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_mdio.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) //// +//// Media Independent Interface (MII)"; see //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section2.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "ge_1000baseX_constants.v" + +`include "timescale.v" + +module ge_1000baseX_mdio #( + parameter PHY_ADDR = 5'b00000 +) ( + + // reset + input reset, + // clock + input mdc, + + input mdio, + output mdio_out, + output mdio_oe, + + output [4:0] data_addr, + input [15:0] data_rd, + output [15:0] data_wr, + output reg strobe_wr + ); + + +`ifdef MODEL_TECH + enum logic [3:0] { +`else + localparam +`endif + S_PREAMBLE = 0, + S_ST = 1, + S_OP_CODE = 2, + S_PHY_ADDR = 3, + S_REG_ADDR = 4, + S_TA = 5, + S_WR_DATA = 6, + S_RD_DATA = 7, + S_WR_COMMIT = 8 +`ifdef MODEL_TECH + } present, next; +`else + ; reg [3:0] present, next; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [5:0] preamble_cnt; + + assign preamble_match = (preamble_cnt == 31); + + always @(posedge mdc or posedge reset) + if (reset) + preamble_cnt = 0; + else + preamble_cnt <= (mdio & ~preamble_match) ? preamble_cnt + 1 : + (mdio & preamble_match) ? preamble_cnt : 0; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg pos_cnt_inc; reg [4:0] pos_cnt; + + always @(posedge mdc or posedge reset) + if (reset) + pos_cnt <= 0; + else + pos_cnt <= (pos_cnt_inc) ? pos_cnt + 1 : 0; + + assign op_code_done = (pos_cnt == 1); + assign phy_addr_done = (pos_cnt == 6); + assign reg_addr_done = (pos_cnt == 11); + assign ta0_done = (pos_cnt == 12); + assign ta1_done = (pos_cnt == 13); + assign data_done = (pos_cnt == 29); + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg st; reg st_latch; + + always @(posedge mdc or posedge reset) + if (reset) + st <= 0; + else + if (st_latch) st <= mdio; + + assign st_match = ~st & mdio; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [1:0] op_code; reg op_code_shift; + + always @(posedge mdc or posedge reset) + if (reset) + op_code <= 0; + else + if (op_code_shift) op_code <= { op_code[0], mdio}; + + assign op_is_rd = (op_code == 2'b10); assign op_is_wr = (op_code == 2'b01); + + assign op_is_invalid = ~op_is_rd & ~op_is_wr; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [4:0] phy_addr; reg phy_addr_shift; + + always @(posedge mdc or posedge reset) + if (reset) + phy_addr <= 0; + else + if (phy_addr_shift) phy_addr <= { phy_addr[3:0], mdio}; + + assign phy_addr_match = (phy_addr == PHY_ADDR); + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [4:0] reg_addr; reg reg_addr_shift; + + always @(posedge mdc or posedge reset) + if (reset) + reg_addr <= 0; + else + if (reg_addr_shift) reg_addr <= { reg_addr[3:0], mdio}; + + assign data_addr = reg_addr; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] data_in; reg data_in_shift; + + always @(posedge mdc or posedge reset) + if (reset) + data_in <= 0; + else + if (data_in_shift) data_in <= { data_in[14:0], mdio}; + + assign data_wr = data_in; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] data_out; reg data_out_load, data_out_shift; + + always @(posedge mdc or posedge reset) + if (reset) + data_out <= 0; + else + if (data_out_load) data_out <= data_rd; + else if (data_out_shift) data_out <= { data_out[14:0], 1'b0 }; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + assign mdio_oe = (ta1_done & op_is_rd) | data_out_shift; + + assign mdio_out = (ta1_done & op_is_rd) ? 1'b1 : data_out[15]; + + ////////////////////////////////////////////////////////////////////////////// + // mdio/mdc state machine registered part. + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge mdc or posedge reset) + + present <= (reset) ? S_PREAMBLE : next; + + ////////////////////////////////////////////////////////////////////////////// + // IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) and + // Media Independent Interface (MII)IEEE 802.3-2005 Clause 22 + ////////////////////////////////////////////////////////////////////////////// + + always @* + begin + next = present; + + pos_cnt_inc = 0; st_latch = 0; + + op_code_shift = 0; phy_addr_shift = 0; reg_addr_shift = 0; + + data_in_shift = 0; data_out_load = 0; data_out_shift = 0; + + strobe_wr = 0; + + case (present) + + S_PREAMBLE: + begin + next = (preamble_match & ~mdio) ? S_ST : S_PREAMBLE; + end + + S_ST: + begin + next = (mdio) ? S_OP_CODE: S_PREAMBLE; + end + + S_OP_CODE: + begin + pos_cnt_inc = 1; op_code_shift = 1; + + next = (op_code_done) ? S_PHY_ADDR : S_OP_CODE; + end + + S_PHY_ADDR: + begin + pos_cnt_inc = 1; phy_addr_shift = 1; + + next = (phy_addr_done) ? S_REG_ADDR : S_PHY_ADDR; + end + + S_REG_ADDR: + begin + if (phy_addr_match) begin + + pos_cnt_inc = 1; reg_addr_shift = 1; + + next = (reg_addr_done) ? S_TA : S_REG_ADDR; + end + else + next = S_PREAMBLE; + end + + S_TA: + begin + pos_cnt_inc = 1; + + if (ta1_done) begin + + data_out_load = op_is_rd; + + next = (op_is_rd) ? S_RD_DATA : + (op_is_wr) ? S_WR_DATA : S_PREAMBLE; + end + end + + S_WR_DATA: + begin + pos_cnt_inc = 1; data_in_shift = 1; + + next = (data_done) ? S_WR_COMMIT : S_WR_DATA; + end + + S_RD_DATA: + begin + pos_cnt_inc = 1; data_out_shift = 1; + + next = (data_done) ? S_PREAMBLE : S_RD_DATA; + end + + + S_WR_COMMIT: + begin + strobe_wr = 1; next = S_PREAMBLE; + end + endcase + end + +endmodule Index: rtl/verilog/timescale.v =================================================================== --- rtl/verilog/timescale.v (nonexistent) +++ rtl/verilog/timescale.v (revision 3) @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "timescale.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// + +`timescale 1ns/10ps +
rtl/verilog/timescale.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ge_1000baseX_rx.v =================================================================== --- rtl/verilog/ge_1000baseX_rx.v (nonexistent) +++ rtl/verilog/ge_1000baseX_rx.v (revision 3) @@ -0,0 +1,928 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_rx.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "timescale.v" + +`include "ge_1000baseX_regs.v" +`include "ge_1000baseX_constants.v" + +module ge_1000baseX_rx( + + // Receive clock and reset + input ck, + input reset, + + // Receive 8B bus from 8b10 decoder + input [7:0] ebi_rxd, + + input ebi_K, + input rx_even, + input carrier_detect, + + // Receive sync status + input sync_status, + input signal_detect, + + // Frame receive pulse + output rx_frame_pulse, + + // Receive GMII bus + output reg [7:0] gmii_rxd, + output reg gmii_rx_dv, + output reg gmii_rx_er, + + output reg receiving, + + // Auto-negotiation ctrl + input [2:0] xmit, + output reg [15:0] rx_config, + output reg rx_config_set, + input mr_main_reset, + output reg [2:0] rudi, + + output reg ability_match, + output reg acknowledge_match, + + output consistency_match, + output idle_match +); + + ////////////////////////////////////////////////////////////////////////////// + // Diagnostics registers + ////////////////////////////////////////////////////////////////////////////// + +`define RX_FRAME_CNT 16'h0000 +`define RX_DATA_CNT 16'h0001 +`define EARLY_END_CNT 16'h0002 +`define CHECK_END_T_R_K28_5_CNT 16'h0003 +`define CHECK_END_R_R_K28_5_CNT 16'h0004 +`define CHECK_END_T_R_R_CNT 16'h0005 +`define CHECK_END_R_R_R_CNT 16'h0006 +`define CHECK_END_R_R_S_CNT 16'h0007 +`define RESET 16'hffff + + reg [7:0] ge_x_pcs_rx_stats_inc; + + reg [15:0] rx_frame_cnt; + reg [15:0] rx_data_cnt; + reg [15:0] early_end_cnt; + reg [15:0] check_end_T_R_K28_5_cnt; + reg [15:0] check_end_R_R_K28_5_cnt; + reg [15:0] check_end_T_R_R_cnt; + reg [15:0] check_end_R_R_R_cnt; + reg [15:0] check_end_R_R_S_cnt; + + always @(posedge ck, posedge reset) + + if (reset) + begin + rx_frame_cnt <= 0; rx_data_cnt <= 0; + early_end_cnt <= 0; check_end_T_R_K28_5_cnt <= 0; + check_end_R_R_K28_5_cnt <= 0; check_end_T_R_R_cnt <= 0; + check_end_R_R_R_cnt <= 0; check_end_R_R_S_cnt <= 0; + end + else + begin + if (ge_x_pcs_rx_stats_inc[0]) rx_frame_cnt <= rx_frame_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[1]) rx_data_cnt <= rx_data_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[2]) early_end_cnt <= early_end_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[3]) check_end_T_R_K28_5_cnt <= check_end_T_R_K28_5_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[4]) check_end_R_R_K28_5_cnt <= check_end_R_R_K28_5_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[5]) check_end_T_R_R_cnt <= check_end_T_R_R_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[6]) check_end_R_R_R_cnt <= check_end_R_R_R_cnt + 1; + else if (ge_x_pcs_rx_stats_inc[7]) check_end_R_R_S_cnt <= check_end_R_R_S_cnt + 1; + end + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + assign rx_frame_pulse = ge_x_pcs_rx_stats_inc[0]; + + ////////////////////////////////////////////////////////////////////////////// + // Soft reset + ////////////////////////////////////////////////////////////////////////////// + + reg soft_reset; + + always @(posedge ck, posedge reset) + if (reset) + soft_reset <= 0; + else + soft_reset <= mr_main_reset; + + ////////////////////////////////////////////////////////////////////////////// + // When Decoding EPDs (End_Of_Packet Delimiter) the RX state machine needs + // to compare the current code-group to the two code-groups that follow it. + ////////////////////////////////////////////////////////////////////////////// + + reg [7:0] ebi_rxd_d1; + reg [7:0] ebi_rxd_d2; + reg [7:0] ebi_rxd_d3; + + reg ebi_K_d1, ebi_K_d2, ebi_K_d3; + reg rx_even_d1, rx_even_d2, rx_even_d3; + reg sync_status_d1, sync_status_d2, sync_status_d3; + reg carrier_detect_d1, carrier_detect_d2, carrier_detect_d3; + + always @(posedge ck, posedge reset) + if (reset) + begin + ebi_K_d1 <= 0; ebi_K_d2 <= 0; ebi_K_d3 <= 0; + rx_even_d1 <= 0; rx_even_d2 <= 0; rx_even_d3 <= 0; + ebi_rxd_d1 <= 0; ebi_rxd_d2 <= 0; ebi_rxd_d3 <= 0; + sync_status_d1 <= 0; sync_status_d2 <= 0; sync_status_d3 <= 0; + carrier_detect_d1 <= 0; carrier_detect_d2 <= 0; carrier_detect_d3 <= 0; + end + else + begin + ebi_K_d3 <= ebi_K_d2; ebi_K_d2 <= ebi_K_d1; ebi_K_d1 <= ebi_K; + rx_even_d3 <= rx_even_d2; rx_even_d2 <= rx_even_d1; rx_even_d1 <= rx_even; + ebi_rxd_d3 <= ebi_rxd_d2; ebi_rxd_d2 <= ebi_rxd_d1; ebi_rxd_d1 <= ebi_rxd; + sync_status_d3 <= sync_status_d2; sync_status_d2 <= sync_status_d1; sync_status_d1 <= sync_status; + carrier_detect_d3 <= carrier_detect_d2; carrier_detect_d2 <= carrier_detect_d1; carrier_detect_d1 <= carrier_detect; + end + + +`ifdef MODEL_TECH + wire [4:0] ebi_rxd_d1_X; wire [2:0] ebi_rxd_d1_Y; + wire [4:0] ebi_rxd_d2_X; wire [2:0] ebi_rxd_d2_Y; + wire [4:0] ebi_rxd_d3_X; wire [2:0] ebi_rxd_d3_Y; + + assign {ebi_rxd_d1_Y, ebi_rxd_d1_X} = ebi_rxd_d1; + assign {ebi_rxd_d2_Y, ebi_rxd_d2_X} = ebi_rxd_d2; + assign {ebi_rxd_d3_Y, ebi_rxd_d3_X} = ebi_rxd_d3; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // Decode EARLY_END EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + wire early_end_idle; + + // Received code-group sequence K28.5/D/K28.5 + assign early_end_idle = (ebi_K_d2 & ebi_rxd_d2 == `K28_5_symbol) & + ~(ebi_K_d1) & + (ebi_K & ebi_rxd == `K28_5_symbol); + + wire early_end_config; + + // Received code-group sequence K28.5/(D21.5 | D2.2)/D0.0 + assign early_end_config = (( ebi_K_d2 & ebi_rxd_d2 == `K28_5_symbol) & + (~ebi_K_d1 & (ebi_rxd_d1 == `D21_5_symbol | ebi_rxd_d1 == `D2_2_symbol)) & + (~ebi_K & ebi_rxd == `D0_0_symbol)); + + // EARLY_END state in 802.3-2008 Clause 36 Figure 36-7b + reg early_end; + + always @(posedge ck, posedge reset) + if (reset) + early_end <= 0; + else + early_end <= (early_end_idle | early_end_config) & rx_even; + + ////////////////////////////////////////////////////////////////////////////// + // Decode /T/R/K28_5/ EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + reg check_end_T_R_K28_5; + + always @(posedge ck, posedge reset) + if (reset) + check_end_T_R_K28_5 <= 0; + else + check_end_T_R_K28_5 <= ((ebi_K_d2 & ebi_rxd_d2 == `K29_7_symbol) & + (ebi_K_d1 & ebi_rxd_d1 == `K23_7_symbol) & + (ebi_K & ebi_rxd == `K28_5_symbol) & rx_even); + + ////////////////////////////////////////////////////////////////////////////// + // Decode /T/R/R/ EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + reg check_end_T_R_R; + + always @(posedge ck, posedge reset) + if (reset) + check_end_T_R_R <= 0; + else + check_end_T_R_R <= ((ebi_K_d2 & ebi_rxd_d2 == `K29_7_symbol) & + (ebi_K_d1 & ebi_rxd_d1 == `K23_7_symbol) & + (ebi_K & ebi_rxd == `K23_7_symbol)); + + ////////////////////////////////////////////////////////////////////////////// + // Decode /R/R/R EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + reg check_end_R_R_R; + + always @(posedge ck, posedge reset) + if (reset) + check_end_R_R_R <= 0; + else + check_end_R_R_R <= ((ebi_K_d2 & ebi_rxd_d2 == `K23_7_symbol) & + (ebi_K_d1 & ebi_rxd_d1 == `K23_7_symbol) & + (ebi_K & ebi_rxd == `K23_7_symbol)); + + ////////////////////////////////////////////////////////////////////////////// + // Decode /R/R/28_5 EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + reg check_end_R_R_K28_5; + + always @(posedge ck, posedge reset) + if (reset) + check_end_R_R_K28_5 <= 0; + else + check_end_R_R_K28_5 <= ((ebi_K_d2 & ebi_rxd_d2 == `K23_7_symbol) & + (ebi_K_d1 & ebi_rxd_d1 == `K23_7_symbol) & + (ebi_K & ebi_rxd == `K28_5_symbol) & rx_even); + + ////////////////////////////////////////////////////////////////////////////// + // Decode /R/R/S EPD code sequence + ////////////////////////////////////////////////////////////////////////////// + + reg check_end_R_R_S; + + always @(posedge ck, posedge reset) + if (reset) + check_end_R_R_S <= 0; + else + check_end_R_R_S <= ((ebi_K_d2 & ebi_rxd_d2 == `K23_7_symbol) & + (ebi_K_d1 & ebi_rxd_d1 == `K23_7_symbol) & + (ebi_K & ebi_rxd == `K27_7_symbol)); + + ////////////////////////////////////////////////////////////////////////////// + // Dx.y and Kx.y symbol decoding + ////////////////////////////////////////////////////////////////////////////// + + reg K28_5_match, D2_2_match, D21_5_match, D5_6_match, D16_2_match; + + always @(posedge ck, posedge reset) + if (reset) + begin + K28_5_match <= 0; + D2_2_match <= 0; + D21_5_match <= 0; + D5_6_match <= 0; + D16_2_match <= 0; + end + else begin + K28_5_match <= (ebi_K_d2 & ebi_rxd_d2 == `K28_5_symbol); + D2_2_match <= ~ebi_K_d2 & (ebi_rxd_d2 == `D2_2_symbol); + D21_5_match <= ~ebi_K_d2 & (ebi_rxd_d2 == `D21_5_symbol); + D5_6_match <= ~ebi_K_d2 & (ebi_rxd_d2 == `D5_6_symbol); + D16_2_match <= ~ebi_K_d2 & (ebi_rxd_d2 == `D16_2_symbol); + end + + ////////////////////////////////////////////////////////////////////////////// + // Start of packet (/S/), End of Packet (/T/) and Carrier Extend + // (/R/) symbol matching + ////////////////////////////////////////////////////////////////////////////// + + reg CE_match, SPD_match, EPD_match; + + always @(posedge ck, posedge reset) + if (reset) + begin + CE_match <= 0; + SPD_match <= 0; + EPD_match <= 0; + end + else + begin + CE_match <= ebi_K_d2 & (ebi_rxd_d2 == `K23_7_symbol); + SPD_match <= ebi_K_d2 & (ebi_rxd_d2 == `K27_7_symbol); + EPD_match <= ebi_K_d2 & (ebi_rxd_d2 == `K29_7_symbol); + end + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + +`ifdef MODEL_TECH + + wire [4:0] ebi_rxd_X; wire [2:0] ebi_rxd_Y; + + assign ebi_rxd_X = ebi_rxd[4:0]; + assign ebi_rxd_Y = ebi_rxd[7:5]; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // rx_Config_reg + ////////////////////////////////////////////////////////////////////////////// + + reg [15:0] rx_config_d1; reg [15:0] rx_config_d2; reg [7:0] rx_config_lo; + + reg rx_config_lo_read, rx_config_hi_read; + + wire [15:0] rx_config_tmp = { ebi_rxd_d3, rx_config_lo }; + + always @(posedge ck, posedge reset) + if (reset) + begin + rx_config <= 0; rx_config_set <= 0; rx_config_lo <= 0; rx_config_d1 <= 0; rx_config_d2 <= 0; + end + else + begin + if (rx_config_lo_read) + begin + rx_config_d2 <= rx_config_d1; + rx_config_d1 <= rx_config; + rx_config_lo <= ebi_rxd_d3; + end + else if (rx_config_hi_read) begin + + rx_config <= rx_config_tmp; + + rx_config_set <= |rx_config_tmp; + end + end + + ////////////////////////////////////////////////////////////////////////////// + // rx_config_cnt + ////////////////////////////////////////////////////////////////////////////// + + reg [2:0] rx_config_cnt; + reg rx_config_cnt_m_inc, rx_config_cnt_m_rst; + + always @(posedge ck, posedge reset) + if (reset) + rx_config_cnt <= 0; + else + begin + if (rx_config_cnt_m_inc) rx_config_cnt <= rx_config_cnt + 1; + else if (rx_config_cnt_m_rst) rx_config_cnt <= 0; + end + + wire rx_config_cnt_done; + + assign rx_config_cnt_done = (rx_config_cnt == 3); + + ////////////////////////////////////////////////////////////////////////////// + // receive ability matching + ////////////////////////////////////////////////////////////////////////////// + + wire [6:0] ability; wire [6:0] ability_d1; wire [6:0] ability_d2; + + assign ability = { rx_config[15], rx_config[13:12], rx_config[8:5] }; + assign ability_d1 = { rx_config_d1[15], rx_config_d1[13:12], rx_config_d1[8:5]}; + assign ability_d2 = { rx_config_d2[15], rx_config_d2[13:12], rx_config_d2[8:5]}; + + assign ability_matched1 = ~| (ability ^ ability_d1); + assign ability_matched2 = ~| (ability ^ ability_d2); + + assign ability_matched = rx_config_cnt_done & ability_matched1 & ability_matched2; + + reg [6:0] ability_matched_reg; + + always @(posedge ck, posedge reset) + if (reset) + ability_matched_reg <= 0; + else begin + + ability_match <= ability_matched; + + if (ability_matched) ability_matched_reg <= ability; + end + + ////////////////////////////////////////////////////////////////////////////// + // receive config matching + ////////////////////////////////////////////////////////////////////////////// + + assign rx_config_match1 = ability_matched1 & ~(rx_config[14] ^ rx_config_d1[14]); + assign rx_config_match2 = ability_matched2 & ~(rx_config[14] ^ rx_config_d2[14]); + + assign rx_config_match = rx_config_match1 & rx_config_match2; + + ////////////////////////////////////////////////////////////////////////////// + // receive acknowledge matching + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge ck, posedge reset) + + acknowledge_match <= (reset) ? 0 : ( rx_config_match & rx_config_d2[14] ); + + ////////////////////////////////////////////////////////////////////////////// + // receive consistency matching + ////////////////////////////////////////////////////////////////////////////// + + assign consistency_match = ability_match & ~|(ability_matched_reg ^ ability); + + ////////////////////////////////////////////////////////////////////////////// + // receive idle counter/matching + ////////////////////////////////////////////////////////////////////////////// + + reg [1:0] idle_cnt; + + reg idle_cnt_m_inc, idle_cnt_m_clr; + + always @(posedge ck, posedge reset) + + if (reset) + idle_cnt <= 0; + else + begin + if (idle_cnt_m_clr) idle_cnt <= 0; + else if (idle_cnt_m_inc) idle_cnt <= idle_cnt + 1; + end + + assign idle_match = (idle_cnt == 3); + + ////////////////////////////////////////////////////////////////////////////// + // RX_UNITDATA.indicate - Signal from PCS RX -> PCS AutoNeg process + ////////////////////////////////////////////////////////////////////////////// + + reg rudi_INVALID_m_set; reg rudi_IDLE_m_set; reg rudi_CONF_m_set; + + always @(posedge ck, posedge reset) + if (reset) + rudi <= `RUDI_INVALID; + else + begin + if (rudi_INVALID_m_set) rudi <= `RUDI_INVALID; + else if (rudi_IDLE_m_set) rudi <= `RUDI_IDLE; + else if (rudi_CONF_m_set) rudi <= `RUDI_CONF; + end + + ////////////////////////////////////////////////////////////////////////////// + // GMII output + ////////////////////////////////////////////////////////////////////////////// + + reg gmii_rxd_false_carrier_m_set, gmii_rxd_preamble_m_set, gmii_rxd_ext_err_m_set; + + reg gmii_rxd_packet_burst_m_set, gmii_rxd_trr_extend_m_set, gmii_rxd_m_set; + + always @(posedge ck, posedge reset) + + if (reset) + gmii_rxd <= 0; + else + begin + gmii_rxd <= (gmii_rxd_m_set) ? ebi_rxd_d3 : + (gmii_rxd_false_carrier_m_set) ? 8'b00001110 : + (gmii_rxd_preamble_m_set) ? 8'b01010101 : + (gmii_rxd_ext_err_m_set) ? 8'b00011111 : + (gmii_rxd_trr_extend_m_set) ? 8'b00001111 : + (gmii_rxd_packet_burst_m_set) ? 8'b00001111 : 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // Current receive state + ////////////////////////////////////////////////////////////////////////////// + + reg receiving_m_set, receiving_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + receiving <= 0; + else + begin + if (receiving_m_set) receiving <= 1; + else if (receiving_m_clr) receiving <= 0; + end + + +`ifdef MODEL_TECH + enum logic [4:0] { +`else + localparam +`endif + S_PCS_RX_START = 0, + S_PCS_RX_LINK_FAILED = 1, + S_PCS_RX_WAIT_K = 2, + S_PCS_RX_K = 3, + S_PCS_RX_CONFIG_CB = 4, + S_PCS_RX_CONFIG_CC = 5, + S_PCS_RX_CONFIG_CD = 6, + S_PCS_RX_INVALID = 7, + S_PCS_RX_IDLE_D = 8, + S_PCS_RX_FALSE_CARRIER = 9, + S_PCS_RX_START_OF_PACKET = 10, + S_PCS_RX_RECEIVE = 11, + S_PCS_RX_EARLY_END = 12, + S_PCS_RX_TRI_RRI = 13, + S_PCS_RX_TRR_EXTEND = 14, + S_PCS_RX_EPD2_CHECK_END = 15, + S_PCS_RX_PACKET_BURST_RRS = 16, + S_PCS_RX_EXTEND_ERR = 17, + S_PCS_RX_EARLY_END_EXT = 18, + S_PCS_RX_DATA_ERROR = 19, + S_PCS_RX_DATA = 20 +`ifdef MODEL_TECH + } pcs_rx_present, pcs_rx_next; +`else + ; reg [4:0] pcs_rx_present, pcs_rx_next; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // gmii_rx_er ctrl + ////////////////////////////////////////////////////////////////////////////// + + reg gmii_rx_er_m_set, gmii_rx_er_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + gmii_rx_er <= 0; + else + begin + if (gmii_rx_er_m_set) gmii_rx_er <= 1; + else if (gmii_rx_er_m_clr) gmii_rx_er <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // gmii_rx_dv ctrl + ////////////////////////////////////////////////////////////////////////////// + + reg gmii_rx_dv_m_set, gmii_rx_dv_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + gmii_rx_dv <= 0; + else + begin + if (gmii_rx_dv_m_set) gmii_rx_dv <= 1; + else if (gmii_rx_dv_m_clr) gmii_rx_dv <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + wire xmit_DATA, xmit_nDATA, xmit_DATA_CD, xmit_DATA_nCD; + + assign xmit_DATA = (xmit == `XMIT_DATA); + + assign xmit_nDATA = (xmit != `XMIT_DATA); + + assign xmit_DATA_CD = (xmit_DATA & carrier_detect_d3); + + assign xmit_DATA_nCD = (xmit_DATA & ~carrier_detect_d3); + + wire xmit_DATA_CD_SPD, xmit_DATA_CD_nSPD, xmit_DATA_CD_nSPD_nK28_5; + + assign xmit_DATA_CD_SPD = xmit_DATA_CD & SPD_match; + + assign xmit_DATA_CD_nSPD = xmit_DATA_CD & ~SPD_match; + + assign xmit_DATA_CD_nSPD_nK28_5 = xmit_DATA_CD_nSPD & ~K28_5_match; + + + ////////////////////////////////////////////////////////////////////////////// + // receive state machine registered part. + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge ck, posedge reset) + + pcs_rx_present <= (reset) ? S_PCS_RX_START : pcs_rx_next; + + ////////////////////////////////////////////////////////////////////////////// + // receive state machine - IEEE 802.3-2008 Clause 36 Figure 36-7a, 36-7b + ////////////////////////////////////////////////////////////////////////////// + + always @* + begin + pcs_rx_next = pcs_rx_present; + + rx_config_lo_read = 0; rx_config_hi_read = 0; + + receiving_m_set = 0; receiving_m_clr = 0; + + gmii_rxd_false_carrier_m_set = 0; gmii_rxd_preamble_m_set = 0; gmii_rxd_ext_err_m_set = 0; + + gmii_rxd_packet_burst_m_set = 0; gmii_rxd_trr_extend_m_set = 0; gmii_rxd_m_set = 0; + + idle_cnt_m_clr = 0; idle_cnt_m_inc = 0; + + gmii_rx_er_m_set = 0; gmii_rx_er_m_clr = 0; + + gmii_rx_dv_m_set = 0; gmii_rx_dv_m_clr = 0; + + rudi_INVALID_m_set = 0; rudi_IDLE_m_set = 0; rudi_CONF_m_set = 0; + + rx_config_cnt_m_inc = 0; rx_config_cnt_m_rst = 0; + + ge_x_pcs_rx_stats_inc = 16'h0000; + + case (pcs_rx_present) + + S_PCS_RX_START: + begin + pcs_rx_next = S_PCS_RX_LINK_FAILED; + end + + S_PCS_RX_LINK_FAILED: + begin + rudi_INVALID_m_set = (xmit_nDATA); + + if (receiving) begin receiving_m_clr = 1; gmii_rx_er_m_set = 1; end + else begin gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; end + + pcs_rx_next = S_PCS_RX_WAIT_K; + end + + S_PCS_RX_WAIT_K: + begin + rx_config_cnt_m_rst = 1; + + receiving_m_clr = 1; gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; + + pcs_rx_next = (K28_5_match & rx_even_d3) ? S_PCS_RX_K : S_PCS_RX_WAIT_K; + end + + + S_PCS_RX_K: + begin + receiving_m_clr = 1; gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; + + rudi_IDLE_m_set = (xmit_nDATA & ~ebi_K_d3 & ~D21_5_match & ~D2_2_match) | + (xmit_DATA & ~D21_5_match & ~D2_2_match); + + pcs_rx_next = (D21_5_match | D2_2_match) ? S_PCS_RX_CONFIG_CB : + ((xmit_nDATA) & ~ebi_K_d3 & ~D21_5_match & ~D2_2_match) ? S_PCS_RX_IDLE_D : + ((xmit_DATA) & ~D21_5_match & ~D2_2_match) ? S_PCS_RX_IDLE_D : + ((xmit_nDATA) & ebi_K_d3) ? S_PCS_RX_INVALID : S_PCS_RX_INVALID; + end + + S_PCS_RX_CONFIG_CB: + begin + // Keep a count of the number of consecutive /C/ streams + rx_config_cnt_m_inc = ~rx_config_cnt_done; + + rx_config_lo_read = ~ebi_K_d3; + + receiving_m_clr = 1; gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; + + pcs_rx_next = (ebi_K_d3) ? S_PCS_RX_INVALID : S_PCS_RX_CONFIG_CC; + end + + + S_PCS_RX_CONFIG_CC: + begin + rx_config_hi_read = ~ebi_K_d3; idle_cnt_m_clr = 1; + + // Signal from RX -> ANEG indicating /C/ ordered set received + rudi_CONF_m_set = ~ebi_K_d3; + + pcs_rx_next = (ebi_K_d3) ? S_PCS_RX_INVALID : S_PCS_RX_CONFIG_CD; + end + + S_PCS_RX_CONFIG_CD: + begin + pcs_rx_next = (K28_5_match & rx_even_d3) ? S_PCS_RX_K : S_PCS_RX_INVALID; + end + + + S_PCS_RX_INVALID: + begin + // Signal from RX -> ANEG indicating INVALID + rudi_INVALID_m_set = (xmit == `XMIT_CONFIGURATION); + + receiving_m_set = (xmit_DATA); + + pcs_rx_next = (K28_5_match & rx_even_d3) ? S_PCS_RX_K : + (~K28_5_match & rx_even_d3) ? S_PCS_RX_WAIT_K : S_PCS_RX_INVALID; + end + + + S_PCS_RX_IDLE_D: + begin + // Must be receiving a IDLE so reset config cnt and idle_matcher logic + rx_config_cnt_m_rst = 1; idle_cnt_m_inc = ~idle_match; + + // Signal from RX -> ANEG indicating /I/ ordered set received + rudi_IDLE_m_set = 1; + + // Generate rx_dv only if we've detected a START_OF_PACKET + if (xmit_DATA_CD_SPD) gmii_rx_dv_m_set = 1; else gmii_rx_dv_m_clr = 1; + + // Generate rx_er if we've detected a FALSE_CARRIER + if (xmit_DATA_CD_nSPD_nK28_5) gmii_rx_er_m_set = 1; else gmii_rx_er_m_clr = 1; + + if (xmit_DATA_CD) + begin + if (~K28_5_match) + begin + receiving_m_set = 1; + if (SPD_match) gmii_rxd_preamble_m_set = 1; else gmii_rxd_false_carrier_m_set = 1; + end + end + else receiving_m_clr = 1; + + pcs_rx_next = (~K28_5_match & ~xmit_DATA ) ? S_PCS_RX_INVALID : + ( xmit_DATA_CD_SPD ) ? S_PCS_RX_RECEIVE : + ( xmit_DATA_nCD | K28_5_match ) ? S_PCS_RX_K : + ( xmit_DATA_CD_nSPD ) ? S_PCS_RX_FALSE_CARRIER : S_PCS_RX_IDLE_D; + + ge_x_pcs_rx_stats_inc[0] = xmit_DATA_CD_SPD; + + end + + + S_PCS_RX_FALSE_CARRIER: + begin + gmii_rx_er_m_set = 1; gmii_rxd_false_carrier_m_set = 1; + + pcs_rx_next = (K28_5_match & rx_even_d3) ? S_PCS_RX_K : S_PCS_RX_FALSE_CARRIER; + end + + //---------------------------------------------------------------------------- + // IEEE 802.3-2008 Clause 36 Figure 36-7b + + S_PCS_RX_START_OF_PACKET: + begin + gmii_rx_dv_m_set = 1; gmii_rx_er_m_clr = 1; gmii_rxd_preamble_m_set = 1; + + pcs_rx_next = S_PCS_RX_RECEIVE; + end + + S_PCS_RX_RECEIVE: + begin + + if (early_end) // EARLY_END + begin + ge_x_pcs_rx_stats_inc[2] = 1; + + gmii_rx_er_m_set = 1; pcs_rx_next = S_PCS_RX_EARLY_END; + end + + else if (check_end_T_R_K28_5) // TRI+RRI + begin + + ge_x_pcs_rx_stats_inc[3] = 1; + + receiving_m_clr = 1; gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; + + pcs_rx_next = S_PCS_RX_TRI_RRI; + end + + else if (check_end_T_R_R) // TRR+EXTEND + begin + + ge_x_pcs_rx_stats_inc[5] = 1; + + gmii_rx_dv_m_clr = 1; gmii_rx_er_m_set = 1; gmii_rxd_trr_extend_m_set = 1; + + pcs_rx_next = S_PCS_RX_EPD2_CHECK_END; + end + + else if (check_end_R_R_R) // EARLY_END_EXT + begin + + ge_x_pcs_rx_stats_inc[6] = 1; + + gmii_rx_er_m_set = 1; pcs_rx_next = S_PCS_RX_EPD2_CHECK_END; + end + + else if (~ebi_K_d3) // RX_DATA + begin + ge_x_pcs_rx_stats_inc[1] = 1; + + gmii_rx_er_m_clr = 1; gmii_rxd_m_set = 1; + end + + else // RX_DATA_ERROR + gmii_rx_er_m_set = 1; + end + + + S_PCS_RX_EARLY_END: + begin + pcs_rx_next = (D21_5_match | D2_2_match) ? S_PCS_RX_CONFIG_CB : S_PCS_RX_IDLE_D; + end + + S_PCS_RX_TRI_RRI: + begin + pcs_rx_next = (K28_5_match) ? S_PCS_RX_K : S_PCS_RX_TRI_RRI; + end + + S_PCS_RX_TRR_EXTEND: + begin + gmii_rx_dv_m_clr = 1; gmii_rx_er_m_set = 1; gmii_rxd_trr_extend_m_set = 1; + + pcs_rx_next = S_PCS_RX_EPD2_CHECK_END; + end + + + S_PCS_RX_EPD2_CHECK_END: + begin + + if (check_end_R_R_R) + begin + + gmii_rx_dv_m_clr = 1; gmii_rx_er_m_set = 1; gmii_rxd_trr_extend_m_set = 1; + end + + else if (check_end_R_R_K28_5) + begin + + ge_x_pcs_rx_stats_inc[4] = 1; + + receiving_m_clr = 1; gmii_rx_dv_m_clr = 1; gmii_rx_er_m_clr = 1; + + end + + else if (check_end_R_R_S) + begin + ge_x_pcs_rx_stats_inc[7] = 1; + end + + pcs_rx_next = (check_end_R_R_R) ? S_PCS_RX_TRR_EXTEND : + (check_end_R_R_K28_5) ? S_PCS_RX_TRI_RRI : + (check_end_R_R_S) ? S_PCS_RX_PACKET_BURST_RRS : S_PCS_RX_EXTEND_ERR; + end + + S_PCS_RX_PACKET_BURST_RRS: + begin + gmii_rx_dv_m_clr = 1; gmii_rxd_packet_burst_m_set = 1; + + pcs_rx_next = (SPD_match) ? S_PCS_RX_START_OF_PACKET : S_PCS_RX_PACKET_BURST_RRS; + end + + S_PCS_RX_EXTEND_ERR: + begin + gmii_rx_dv_m_clr = 1; gmii_rxd_ext_err_m_set = 1; + + pcs_rx_next = (SPD_match) ? S_PCS_RX_START_OF_PACKET : + (K28_5_match & rx_even_d3) ? S_PCS_RX_K : + (~SPD_match & ~K28_5_match & rx_even_d3) ? S_PCS_RX_EPD2_CHECK_END : S_PCS_RX_EXTEND_ERR; + end + + S_PCS_RX_EARLY_END_EXT: + begin + gmii_rx_er_m_set = 1; + + pcs_rx_next = S_PCS_RX_EPD2_CHECK_END; + end + + S_PCS_RX_DATA_ERROR: + begin + gmii_rx_er_m_set = 1; + + pcs_rx_next = S_PCS_RX_RECEIVE; + end + + S_PCS_RX_DATA: + begin + gmii_rx_er_m_clr = 1; gmii_rxd_m_set = 1; + + pcs_rx_next = S_PCS_RX_RECEIVE; + end + endcase + + if (~signal_detect) pcs_rx_next = S_PCS_RX_LINK_FAILED; + else if (~sync_status_d3) pcs_rx_next = S_PCS_RX_LINK_FAILED; + else if (soft_reset) pcs_rx_next = S_PCS_RX_WAIT_K; + + end + +endmodule Index: rtl/verilog/ge_1000baseX_tx.v =================================================================== --- rtl/verilog/ge_1000baseX_tx.v (nonexistent) +++ rtl/verilog/ge_1000baseX_tx.v (revision 3) @@ -0,0 +1,698 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_tx.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "ge_1000baseX_constants.v" +`include "ge_1000baseX_regs.v" + +module ge_1000baseX_tx ( + + // transmit clock and reset + input ck, + input reset, + + // SERDES transmit 10B bus + output [9:0] tbi_txd, + + // Transmit GMII bus + input gmii_tx_en_in, + input gmii_tx_er_in, + input [7:0] gmii_txd_in, + + output reg gmii_col, + + input receiving, + output reg transmitting, + + input signal_detect, + + // Frame transmit pulse + output tx_frame_pulse, + + // Auto-negotiation ctrl + input [2:0] xmit, + input [15:0] tx_config, + input mr_main_reset + + ); + + ////////////////////////////////////////////////////////////////////////////// + // Diagnostics registers + ////////////////////////////////////////////////////////////////////////////// + +`define TX_FRAME_CNT 16'h0000 +`define TX_DATA_CNT 16'h0001 +`define TX_ERROR_CNT 16'h0002 +`define END_OF_PACKET_NOEXT_CNT 16'h0003 +`define END_OF_PACKET_EXT_CNT 16'h0004 +`define EXTEND_BY_1_CNT 16'h0005 +`define CARRIER_EXTEND_CNT 16'h0006 +`define EPD2_NOEXT_CNT 16'h0007 +`define EPD3_CNT 16'h0008 +`define RESET 16'hffff + + reg [8:0] ge_x_pcs_tx_stats_inc; + + reg [15:0] tx_frame_cnt; + reg [15:0] tx_error_cnt; + reg [15:0] tx_data_cnt; + reg [15:0] end_of_packet_noext_cnt; + reg [15:0] end_of_packet_ext_cnt; + reg [15:0] extend_by_1_cnt; + reg [15:0] carrier_extend_cnt; + reg [15:0] epd2_noext_cnt; + reg [15:0] epd3_cnt; + + always @(posedge ck, posedge reset) + + if (reset) + begin + tx_frame_cnt <= 'd0; tx_data_cnt <= 'd0; + tx_error_cnt <= 'd0; end_of_packet_noext_cnt <= 'd0; + end_of_packet_ext_cnt <= 'd0; extend_by_1_cnt <= 'd0; + carrier_extend_cnt <= 'd0; epd2_noext_cnt <= 'd0; + epd3_cnt <= 'd0; + end + else + begin + if (ge_x_pcs_tx_stats_inc[0]) tx_frame_cnt <= tx_frame_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[1]) tx_data_cnt <= tx_data_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[2]) tx_error_cnt <= tx_error_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[3]) end_of_packet_noext_cnt <= end_of_packet_noext_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[4]) end_of_packet_ext_cnt <= end_of_packet_ext_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[5]) extend_by_1_cnt <= extend_by_1_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[6]) carrier_extend_cnt <= carrier_extend_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[7]) epd2_noext_cnt <= epd2_noext_cnt + 1; + else if (ge_x_pcs_tx_stats_inc[8]) epd3_cnt <= epd3_cnt + 1; + end + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + assign tx_frame_pulse = ge_x_pcs_tx_stats_inc[0]; + + ////////////////////////////////////////////////////////////////////////////// + // Soft reset + ////////////////////////////////////////////////////////////////////////////// + reg soft_reset; + + always @(posedge ck, posedge reset) + if (reset) + soft_reset <= 0; + else + soft_reset <= mr_main_reset; + + ////////////////////////////////////////////////////////////////////////////// + // Running disparity + ////////////////////////////////////////////////////////////////////////////// + + wire encoder_disparity; // 0 - Negative Running Disparity, 1 - Positive Running Disparity + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + reg gmii_tx_en_pipe, gmii_tx_er_pipe; reg [7:0] gmii_txd_pipe; + + reg gmii_d1, gmii_d1_m_set, gmii_d1_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + begin + gmii_d1 <= 0; + gmii_tx_en_pipe <= 0; gmii_tx_er_pipe <= 0; gmii_txd_pipe <= 0; + end + else + begin + gmii_tx_en_pipe <= gmii_tx_en_in; + gmii_tx_er_pipe <= gmii_tx_er_in; + gmii_txd_pipe <= gmii_txd_in; + + if (gmii_d1_m_set) gmii_d1 <= 1; + else if (gmii_d1_m_clr) gmii_d1 <= 0; + + end + + wire gmii_tx_en = (gmii_d1) ? gmii_tx_en_pipe : gmii_tx_en_in; + wire gmii_tx_er = (gmii_d1) ? gmii_tx_er_pipe : gmii_tx_er_in; + wire [7:0] gmii_txd = (gmii_d1) ? gmii_txd_pipe : gmii_txd_in; + + ////////////////////////////////////////////////////////////////////////////// + // gmii_col + ////////////////////////////////////////////////////////////////////////////// + + reg gmii_col_m_set, gmii_col_m_clr; + + + always @(posedge ck, posedge reset) + if (reset) + begin + gmii_col <= 0; + end + else + begin + if (gmii_col_m_set) begin gmii_col <= 1; end + else if (gmii_col_m_clr) begin gmii_col <= 0; end + end + + ////////////////////////////////////////////////////////////////////////////// + // Current transmit state + ////////////////////////////////////////////////////////////////////////////// + + reg transmitting_m_set, transmitting_m_clr; + + always @(posedge ck, posedge reset) + if (reset) + begin + transmitting <= 0; + end + else + begin + if (transmitting_m_set) begin transmitting <= 1; end + else if (transmitting_m_clr) begin transmitting <= 0; end + end + + ////////////////////////////////////////////////////////////////////////////// + // Configuration Counter and decode logic + ////////////////////////////////////////////////////////////////////////////// + + reg [3:0] config_cnt; + + reg config_cnt_clr, config_cnt_inc; + + always @(posedge ck, posedge reset) + if (reset) + config_cnt <= 0; + else + begin + if (config_cnt_clr) config_cnt <= 0; + else if (config_cnt_inc) config_cnt <= config_cnt + 1; + end + + assign config_C1_done = (config_cnt == 3); + assign config_C2_done = (config_cnt == 7); + + assign config_cnt_K28_5 = (config_cnt == 0 | config_cnt == 4); + assign config_cnt_D21_5 = (config_cnt == 1); + assign config_cnt_D2_2 = (config_cnt == 5); + assign config_cnt_config_lo = (config_cnt == 2 | config_cnt == 6); + assign config_cnt_config_hi = (config_cnt == 3 | config_cnt == 7); + + ////////////////////////////////////////////////////////////////////////////// + // Idle counter and decode logic + ////////////////////////////////////////////////////////////////////////////// + + reg idle_cnt; + + reg idle_cnt_m_clr, idle_cnt_m_inc; + + always @(posedge ck, posedge reset) + if (reset) + idle_cnt <= 0; + else + begin + if (idle_cnt_m_clr) idle_cnt <= 0; + else if (idle_cnt_m_inc) idle_cnt <= idle_cnt + 1; + + end + + wire idle_cnt_done, idle_cnt_is_clr, idle_cnt_is_set; + + assign idle_cnt_done = idle_cnt; + assign idle_cnt_is_clr = ~idle_cnt; + assign idle_cnt_is_set = idle_cnt; + + ////////////////////////////////////////////////////////////////////////////// + // PCS Transmit - IEEE 802.3-2005 Clause 36, Figure 36-6 page 58 + ////////////////////////////////////////////////////////////////////////////// + // + reg [7:0] encoder_8b_rxd; + + reg encoder_K; + + reg encoder_8b_rxd_gmii_txd_m_set, encoder_8b_rxd_config_lo_m_set, encoder_8b_rxd_config_hi_m_set; + + reg encoder_8b_rxd_K30_7_m_set, encoder_8b_rxd_K29_7_m_set, encoder_8b_rxd_K28_1_m_set, encoder_8b_rxd_K28_5_m_set, encoder_8b_rxd_K27_7_m_set, encoder_8b_rxd_K23_7_m_set; + + reg encoder_8b_rxd_D21_5_m_set, encoder_8b_rxd_D2_2_m_set, encoder_8b_rxd_D5_6_m_set, encoder_8b_rxd_D16_2_m_set; + + reg encoder_tx_even; + + wire encoder_tx_even_set = (encoder_8b_rxd_K28_5_m_set| encoder_8b_rxd_config_lo_m_set); + + wire encoder_tx_even_clr = (encoder_8b_rxd_D21_5_m_set|encoder_8b_rxd_D21_5_m_set|encoder_8b_rxd_D5_6_m_set|encoder_8b_rxd_D16_2_m_set|encoder_8b_rxd_config_hi_m_set); + + wire encoder_tx_even_toggle = (encoder_8b_rxd_gmii_txd_m_set|encoder_8b_rxd_K30_7_m_set|encoder_8b_rxd_K27_7_m_set|encoder_8b_rxd_K29_7_m_set|encoder_8b_rxd_K23_7_m_set); + + always @(posedge ck, posedge reset) + if (reset) + begin + encoder_K <= 0; encoder_8b_rxd <= 0; encoder_tx_even <= 0; + end + else + begin + // Input 8b10b encode K ctrl strobe + encoder_K <= encoder_8b_rxd_K30_7_m_set|encoder_8b_rxd_K29_7_m_set|encoder_8b_rxd_K28_5_m_set|encoder_8b_rxd_K27_7_m_set|encoder_8b_rxd_K23_7_m_set; + + // Input to 8b10b encode EBI (Eight Bit Interface) bus. + encoder_8b_rxd <= + // Drive special K codes onto 8b10_enc encoder_8b_rxd - K strobe high + encoder_8b_rxd_K30_7_m_set ? `K30_7_symbol : + encoder_8b_rxd_K29_7_m_set ? `K29_7_symbol : + encoder_8b_rxd_K28_5_m_set ? `K28_5_symbol : + encoder_8b_rxd_K28_1_m_set ? `K28_1_symbol : + encoder_8b_rxd_K27_7_m_set ? `K27_7_symbol : + encoder_8b_rxd_K23_7_m_set ? `K23_7_symbol : + // Drive Special Data Codes onto 8b10 enc encoder_8b_rxd - K strobe low + encoder_8b_rxd_D21_5_m_set ? `D21_5_symbol : + encoder_8b_rxd_D2_2_m_set ? `D2_2_symbol : + encoder_8b_rxd_D5_6_m_set ? `D5_6_symbol : + encoder_8b_rxd_D16_2_m_set ? `D16_2_symbol : + // Drive Tx Config register onto 8b10 enc encoder_8b_rxd - K strobe low + encoder_8b_rxd_config_lo_m_set ? tx_config[7:0] : + encoder_8b_rxd_config_hi_m_set ? tx_config[15:8] : + + // Drive GMII txd onto 8b10 enc encoder_8b_rxd - K strobe low + encoder_8b_rxd_gmii_txd_m_set ? gmii_txd : 0; + + // Keep track of even/odd TX status + encoder_tx_even <= encoder_tx_even_set ? 1 : + encoder_tx_even_clr ? 0 : + encoder_tx_even_toggle ? ~encoder_tx_even : encoder_tx_even; + end + + + + + ////////////////////////////////////////////////////////////////////////////// + // VOID - see IEEE 802.3-2005 Section 36 (PCS) page 55 + ////////////////////////////////////////////////////////////////////////////// + + assign VOID = (~gmii_tx_en & gmii_tx_er & gmii_txd != 8'b00001111) | (gmii_tx_en & gmii_tx_er); + + ////////////////////////////////////////////////////////////////////////////// + // Instantiate 8b10 Encode module + ////////////////////////////////////////////////////////////////////////////// + // + encoder_8b10b encoder_8b10bi( + + // Clocks + .SBYTECLK(ck), + + // Reset + .reset(reset), + + // eight bit interface (ebi) input + .ebi(encoder_8b_rxd), + + // ten bit interface (tbi) output to TBI bus + .tbi(tbi_txd), + + // Data/special code-group ctrl + .K(encoder_K), + + // Running Disparity + .disparity(encoder_disparity) + ); + + +`ifdef MODEL_TECH + + wire [4:0] encoder_8b_X; wire [2:0] encoder_8b_Y; + + assign encoder_8b_X = encoder_8b_rxd[4:0]; + assign encoder_8b_Y = encoder_8b_rxd[7:5]; +`endif + +`ifdef MODEL_TECH + enum logic [4:0] { +`else + localparam +`endif + S_PCS_TX_TEST_XMIT = 0, + S_PCS_TX_XMIT_DATA = 1, + S_PCS_TX_ALIGN_ERR_START = 2, + S_PCS_TX_START_ERROR = 3, + S_PCS_TX_DATA_ERROR = 4, + S_PCS_TX_START_OF_PACKET = 5, + S_PCS_TX_PACKET = 6, + S_PCS_TX_END_OF_PACKET_NOEXT = 7, + S_PCS_TX_END_OF_PACKET_EXT = 8, + S_PCS_TX_EXTEND_BY_1 = 9, + S_PCS_TX_CARRIER_EXTEND = 10, + S_PCS_TX_EPD2_NOEXT = 11, + S_PCS_TX_EPD3 = 12, + S_PCS_TX_CONFIGURATION = 13, + S_PCS_TX_IDLE = 14 +`ifdef MODEL_TECH + } pcs_tx_present, pcs_tx_next; +`else + ; reg [4:0] pcs_tx_present, pcs_tx_next; +`endif + + + ////////////////////////////////////////////////////////////////////////////// + // xmit ctrl + ////////////////////////////////////////////////////////////////////////////// + + wire xmit_idle, xmit_configuration, xmit_data; + + assign xmit_configuration = (xmit == `XMIT_CONFIGURATION); + + assign xmit_idle = (xmit == `XMIT_IDLE) | (xmit == `XMIT_DATA & (gmii_tx_en | gmii_tx_er)); + + assign xmit_data = (xmit == `XMIT_DATA & ~gmii_tx_en & ~gmii_tx_er); + + reg [2:0] xmit_saved; wire xmitCHANGE; + + always @(posedge ck, posedge reset) + + xmit_saved <= (reset) ? `XMIT_IDLE : xmit; + + assign xmitCHANGE = (xmit != xmit_saved); + + ////////////////////////////////////////////////////////////////////////////// + // transmit state machine registered part. + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge ck, posedge reset) + + pcs_tx_present <= (reset) ? S_PCS_TX_TEST_XMIT : pcs_tx_next; + + ////////////////////////////////////////////////////////////////////////////// + // transmit state machine - IEEE 802.3-2008 Clause 36 + ////////////////////////////////////////////////////////////////////////////// + + always @* + begin + pcs_tx_next = pcs_tx_present; + + encoder_8b_rxd_gmii_txd_m_set = 0; + + encoder_8b_rxd_K30_7_m_set = 0; + encoder_8b_rxd_K29_7_m_set = 0; + encoder_8b_rxd_K28_5_m_set = 0; + encoder_8b_rxd_K28_1_m_set = 0; + encoder_8b_rxd_K27_7_m_set = 0; + encoder_8b_rxd_K23_7_m_set = 0; + + encoder_8b_rxd_D21_5_m_set = 0; + encoder_8b_rxd_D2_2_m_set = 0; + encoder_8b_rxd_D5_6_m_set = 0; + encoder_8b_rxd_D16_2_m_set = 0; + + encoder_8b_rxd_config_lo_m_set = 0; + encoder_8b_rxd_config_hi_m_set = 0; + + transmitting_m_set = 0; transmitting_m_clr = 0; + + gmii_col_m_set = 0; gmii_col_m_clr = 0; + + config_cnt_clr = 0; config_cnt_inc = 0; + + idle_cnt_m_clr = 0; idle_cnt_m_inc = 0; + + gmii_d1_m_set = 0; gmii_d1_m_clr = 0; + + ge_x_pcs_tx_stats_inc = 'd0; + + case (pcs_tx_present) + + S_PCS_TX_TEST_XMIT: + begin + transmitting_m_clr = 1; gmii_col_m_clr = 1; gmii_d1_m_clr = 1; + + pcs_tx_next = xmit_configuration ? S_PCS_TX_CONFIGURATION : + xmit_idle ? S_PCS_TX_IDLE : + xmit_data ? S_PCS_TX_XMIT_DATA : S_PCS_TX_TEST_XMIT; + + idle_cnt_m_clr = xmit_idle; config_cnt_clr = xmit_configuration; + end + + S_PCS_TX_XMIT_DATA: + begin + + idle_cnt_m_inc = idle_cnt_is_clr; idle_cnt_m_clr = ~idle_cnt_is_clr; + + encoder_8b_rxd_D5_6_m_set = (~idle_cnt_is_clr & encoder_disparity); + encoder_8b_rxd_D16_2_m_set = (~idle_cnt_is_clr & ~encoder_disparity); + encoder_8b_rxd_K28_5_m_set = (idle_cnt_is_clr & ~gmii_tx_en); + + encoder_8b_rxd_K27_7_m_set = (idle_cnt_is_clr & gmii_tx_en); + + gmii_d1_m_set = ~idle_cnt_is_clr & gmii_tx_en ; + + transmitting_m_set = (idle_cnt_is_clr & gmii_tx_en); + + if (idle_cnt_is_clr & gmii_tx_en & receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + if (idle_cnt_is_clr) + begin + pcs_tx_next = (xmit != `XMIT_DATA) ? S_PCS_TX_TEST_XMIT : + (~gmii_tx_en) ? S_PCS_TX_XMIT_DATA : + (gmii_tx_er) ? S_PCS_TX_DATA_ERROR : S_PCS_TX_PACKET; + + // Keep count of good frames + ge_x_pcs_tx_stats_inc[0] = gmii_tx_en & ~gmii_tx_er; + + // Keep count of errored frames + ge_x_pcs_tx_stats_inc[2] = gmii_tx_en & gmii_tx_er; + + end + end + + + S_PCS_TX_START_ERROR: + begin + transmitting_m_set = 1; + + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + encoder_8b_rxd_K27_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_DATA_ERROR; + end + + + S_PCS_TX_DATA_ERROR: + begin + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + encoder_8b_rxd_K30_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_PACKET; + end + + + S_PCS_TX_START_OF_PACKET: + begin + transmitting_m_set = 1; encoder_8b_rxd_K27_7_m_set = 1; + + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + pcs_tx_next = S_PCS_TX_PACKET; + end + + S_PCS_TX_PACKET: + begin + idle_cnt_m_clr = 1; + + // END_OF_PACKET_NOEXT + if (~gmii_tx_en & ~gmii_tx_er) + begin + if (~encoder_tx_even) transmitting_m_clr = 1; + + gmii_col_m_clr = 1; encoder_8b_rxd_K29_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_EPD2_NOEXT; + end + + // END_OF_PACKET_EXT + else if (~gmii_tx_en & gmii_tx_er) + begin + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + if (VOID) encoder_8b_rxd_K30_7_m_set = 1; else encoder_8b_rxd_K29_7_m_set = 1; + + pcs_tx_next = (gmii_tx_er) ? S_PCS_TX_CARRIER_EXTEND : S_PCS_TX_EXTEND_BY_1; + end + + else // TX_DATA + begin + // Keep count of number of TX bytes + ge_x_pcs_tx_stats_inc[1] = 1; + + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + if (VOID) encoder_8b_rxd_K30_7_m_set = 1; else encoder_8b_rxd_gmii_txd_m_set = 1; + end + end + + S_PCS_TX_END_OF_PACKET_NOEXT: + begin + + ge_x_pcs_tx_stats_inc[3] = 1; + + if (~encoder_tx_even) transmitting_m_clr = 1; + + gmii_col_m_clr = 1; encoder_8b_rxd_K29_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_EPD2_NOEXT; + end + + + S_PCS_TX_END_OF_PACKET_EXT: + begin + + ge_x_pcs_tx_stats_inc[4] = 1; + + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + if (VOID) encoder_8b_rxd_K30_7_m_set = 1; else encoder_8b_rxd_K29_7_m_set = 1; + + pcs_tx_next = (gmii_tx_er) ? S_PCS_TX_CARRIER_EXTEND : S_PCS_TX_EXTEND_BY_1; + end + + S_PCS_TX_EXTEND_BY_1: + begin + ge_x_pcs_tx_stats_inc[5] = 1; + + if (~encoder_tx_even) transmitting_m_clr = 1; + + gmii_col_m_clr = 1; encoder_8b_rxd_K23_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_EPD2_NOEXT; + end + + + S_PCS_TX_CARRIER_EXTEND: + begin + + ge_x_pcs_tx_stats_inc[6] = 1; + + if (receiving) gmii_col_m_set = 1; else gmii_col_m_clr = 1; + + if (VOID) encoder_8b_rxd_K30_7_m_set = 1; else encoder_8b_rxd_K23_7_m_set = 1; + + pcs_tx_next = (~gmii_tx_en & ~gmii_tx_er) ? S_PCS_TX_EXTEND_BY_1 : + (gmii_tx_en & gmii_tx_er) ? S_PCS_TX_START_ERROR : + (gmii_tx_en & ~gmii_tx_er) ? S_PCS_TX_START_OF_PACKET : + S_PCS_TX_CARRIER_EXTEND; + end + + S_PCS_TX_EPD2_NOEXT: + begin + + ge_x_pcs_tx_stats_inc[7] = 1; + + gmii_d1_m_clr = 1; transmitting_m_clr = 1; encoder_8b_rxd_K23_7_m_set = 1; + + pcs_tx_next = (encoder_tx_even) ? S_PCS_TX_XMIT_DATA : S_PCS_TX_EPD3; + end + + + S_PCS_TX_EPD3: + begin + ge_x_pcs_tx_stats_inc[8] = 1; + + encoder_8b_rxd_K23_7_m_set = 1; + + pcs_tx_next = S_PCS_TX_XMIT_DATA; + end + + ////////////////////////////////////////////////////////////////////////////// + // IEEE 802.3-2005 Clause 36 Figure 36-6 + + S_PCS_TX_CONFIGURATION: + begin + encoder_8b_rxd_K28_5_m_set = config_cnt_K28_5; + encoder_8b_rxd_D21_5_m_set = config_cnt_D21_5; + encoder_8b_rxd_D2_2_m_set = config_cnt_D2_2; + encoder_8b_rxd_config_lo_m_set = config_cnt_config_lo; + + encoder_8b_rxd_config_hi_m_set = config_cnt_config_hi; + + if ((config_C1_done | config_C2_done)) + begin + pcs_tx_next = (xmit_idle) ? S_PCS_TX_IDLE : + (xmit_data) ? S_PCS_TX_XMIT_DATA : S_PCS_TX_CONFIGURATION; + + idle_cnt_m_clr = xmit_idle; + end + + if (config_C2_done | (config_C1_done & (xmit != `XMIT_CONFIGURATION))) config_cnt_clr = 1; + else config_cnt_inc = 1; + end + + + S_PCS_TX_IDLE: + begin + encoder_8b_rxd_K28_5_m_set = idle_cnt_is_clr; + encoder_8b_rxd_D5_6_m_set = (idle_cnt_is_set & encoder_disparity); + encoder_8b_rxd_D16_2_m_set = (idle_cnt_is_set & ~encoder_disparity); + + pcs_tx_next = (idle_cnt_done & xmit_data) ? S_PCS_TX_XMIT_DATA : + (idle_cnt_done & xmit_configuration) ? S_PCS_TX_CONFIGURATION : S_PCS_TX_IDLE; + + idle_cnt_m_clr = idle_cnt_done; idle_cnt_m_inc = ~idle_cnt_done; + + config_cnt_clr = (idle_cnt_done & xmit_configuration); + end + endcase + + if (mr_main_reset) pcs_tx_next = S_PCS_TX_TEST_XMIT; + + end + + +endmodule Index: rtl/verilog/clean_rst.v =================================================================== --- rtl/verilog/clean_rst.v (nonexistent) +++ rtl/verilog/clean_rst.v (revision 3) @@ -0,0 +1,63 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "clean_rst.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "timescale.v" + +module clean_rst( + input clk, + input rsti, + output reg rsto +); + reg rstt; + + always @(posedge clk, posedge rsti) + begin + rstt <= (rsti) ? 1 : 0; + rsto <= (rsti) ? 1 : rstt; + end + +endmodule + +
rtl/verilog/clean_rst.v Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: rtl/verilog/ge_1000baseX_constants.v =================================================================== --- rtl/verilog/ge_1000baseX_constants.v (nonexistent) +++ rtl/verilog/ge_1000baseX_constants.v (revision 3) @@ -0,0 +1,126 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_constants.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +// XMIT Autonegotiation parameter - ctrl for the PCS TX state machine +`define XMIT_IDLE 0 +`define XMIT_CONFIGURATION 1 +`define XMIT_DATA 2 + +`define RUDI_INVALID 0 +`define RUDI_IDLE 1 +`define RUDI_CONF 2 + +// Special K code-groups - K codes +`define K28_0_symbol 8'h1c +`define K28_1_symbol 8'h3c +`define K28_2_symbol 8'h5c +`define K28_3_symbol 8'h7c +`define K28_4_symbol 8'h9c +`define K28_5_symbol 8'hbc +`define K28_6_symbol 8'hdc +`define K28_7_symbol 8'hfc +`define K23_7_symbol 8'hf7 +`define K27_7_symbol 8'hfb +`define K29_7_symbol 8'hfd +`define K30_7_symbol 8'hfe + +// Special D code-groups - D codes +`define D21_5_symbol 8'hb5 +`define D2_2_symbol 8'h42 +`define D5_6_symbol 8'hc5 +`define D16_2_symbol 8'h50 +`define D0_0_symbol 8'h00 + +`define D21_2_symbol 8'h55 +`define D21_6_symbol 8'hd5 + +`define D6_6_symbol 8'hc6 +`define D10_1_symbol 8'h2a +`define D3_3_symbol 8'h63 +`define D27_7_symbol 8'hfb +`define D3_0_symbol 8'h03 + +`define D30_2_symbol 8'h5e +`define D12_4_symbol 8'h8c +`define D8_6_symbol 8'hc8 +`define D13_7_symbol 8'hed + +// Code group ordered_sets +`define I_CODE 4'b0001 +`define I1_CODE 4'b0010 +`define I2_CODE 4'b0011 +`define C_CODE 4'b0100 +`define C1_CODE 4'b0101 +`define C2_CODE 4'b0110 +`define R_CODE 4'b0111 +`define S_CODE 4'b1000 +`define T_CODE 4'b1001 +`define V_CODE 4'b1010 + +// -ve and +ve 10b symbols +`define pK28_5_10b_symbol 10'b1100000101 // 0x305 +`define nK28_5_10b_symbol 10'b0011111010 // 0x0fa + +`define pD5_6_10b_symbol 10'b1010010110 // 0x296 +`define nD5_6_10b_symbol 10'b1010010110 // 0x296 + +`define pD16_2_10b_symbol 10'b1001000101 // 0x245 +`define nD16_2_10b_symbol 10'b0110110101 // 0x1b5 + +`define pD0_0_10b_symbol 10'b0110001011 // 0x18b +`define nD0_0_10b_symbol 10'b1001110100 // 0x274 + +`define pK27_7_10b_symbol 10'b0010010111 // 0x097 +`define nK27_7_10b_symbol 10'b1101101000 // 0x368 + + Index: rtl/verilog/ge_1000baseX_sync.v =================================================================== --- rtl/verilog/ge_1000baseX_sync.v (nonexistent) +++ rtl/verilog/ge_1000baseX_sync.v (revision 3) @@ -0,0 +1,403 @@ + +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "ge_1000baseX_sync.v" //// +//// //// +//// This file is part of the : //// +//// //// +//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project" //// +//// //// +//// http://opencores.org/project,1000base-x //// +//// //// +//// Author(s): //// +//// - D.W.Pegler Cambridge Broadband Networks Ltd //// +//// //// +//// { peglerd@gmail.com, dwp@cambridgebroadand.com } //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2009 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file 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 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// This module is based on the coding method described in //// +//// IEEE Std 802.3-2008 Clause 36 "Physical Coding Sublayer(PCS) //// +//// and Physical Medium Attachment (PMA) sublayer, type //// +//// 1000BASE-X"; see : //// +//// //// +//// http://standards.ieee.org/about/get/802/802.3.html //// +//// and //// +//// doc/802.3-2008_section3.pdf, Clause/Section 36. //// +//// //// +////////////////////////////////////////////////////////////////////// + +`include "ge_1000baseX_constants.v" + +`include "timescale.v" + +module ge_1000baseX_sync( + + // clocks and reset + input ck, + input reset, + + // Startup interface. + input startup_enable, + + // Signal detect from FO transceiver + input signal_detect, + + // Receive EBI bus from 8b10 decode + input [7:0] ebi_rxd, + input ebi_K, + + output reg [7:0] ebi_rxd_out, + output reg ebi_K_out, + + // 8B/10B disparity and coding errors + input decoder_disparity_err, + input decoder_coding_err, + + // RX sync status + output reg sync_status, + + output reg rx_even, + + input loopback + ); + + ////////////////////////////////////////////////////////////////////////////// + // Running Disparity + ////////////////////////////////////////////////////////////////////////////// + + reg running_disparity; + reg running_disparity_positive_m_set; + reg running_disparity_negative_m_set; + + always @(posedge ck, posedge reset) + + // Assume negative (0) disparity at startup + if (reset) running_disparity <= 0; + + else + begin + if (running_disparity_positive_m_set) running_disparity <= 1; + else if (running_disparity_negative_m_set) running_disparity <= 0; + end + + ////////////////////////////////////////////////////////////////////////////// + // sync_status ctrl + ////////////////////////////////////////////////////////////////////////////// + + reg sync_m_acquired, sync_m_lost; + + always @(posedge ck, posedge reset) + if (reset) + sync_status <= 0; + else + begin + if (sync_m_acquired) begin sync_status <= 1; end + else if (sync_m_lost) begin sync_status <= 0; end + end + + ////////////////////////////////////////////////////////////////////////////// + // rx_even reg + ////////////////////////////////////////////////////////////////////////////// + + reg rx_even_m_init, rx_even_m_set, rx_even_m_clr, rx_even_m_toggle; + + always @(posedge ck, posedge reset) + if (reset) + rx_even <= 1; + else + begin + if (rx_even_m_init) rx_even <= 1; + else if (rx_even_m_set) rx_even <= 1; + else if (rx_even_m_clr) rx_even <= 0; + else if (rx_even_m_toggle) rx_even <= ~rx_even; + end + + ////////////////////////////////////////////////////////////////////////////// + // COMMAs can be K28.1, K28.5 or K28.7 - see table 36-2 pg 45 + ////////////////////////////////////////////////////////////////////////////// + + reg [7:0] ebi_rxd_d1; reg ebi_K_d1; + + always @(posedge ck, posedge reset) + if (reset) + begin ebi_rxd_d1 <= 0; ebi_K_d1 <= 0; end + else + begin ebi_rxd_d1 <= ebi_rxd; ebi_K_d1 <= ebi_K; end + + + always @(posedge ck, posedge reset) + if (reset) + begin ebi_rxd_out <= 0; ebi_K_out <=0; end + else + begin ebi_rxd_out <= ebi_rxd_d1; ebi_K_out <= ebi_K_d1; end + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + + assign K28_1_RX = (ebi_rxd_d1 == `K28_1_symbol); + assign K28_5_RX = (ebi_rxd_d1 == `K28_5_symbol); + assign K28_7_RX = (ebi_rxd_d1 == `K28_7_symbol); + + assign COMMA_RX = K28_1_RX | K28_5_RX | K28_7_RX; + + assign COMMA_match = COMMA_RX & ebi_K_d1; + +`ifdef MODEL_TECH + wire [4:0] ebi_rxd_X; wire [2:0] ebi_rxd_Y; + + assign ebi_rxd_X = ebi_rxd[4:0]; + assign ebi_rxd_Y = ebi_rxd[7:5]; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // Definition of /INVLAID/ as per section 36.2.4.6 + ////////////////////////////////////////////////////////////////////////////// + reg INVALID; + + always @(posedge ck, posedge reset) + + INVALID <= (reset) ? 0 : decoder_disparity_err | decoder_coding_err; + + assign VALID = ~INVALID; + + ////////////////////////////////////////////////////////////////////////////// + // good_cgs ctrl + ////////////////////////////////////////////////////////////////////////////// + + reg [2:0] good_cgs; + reg good_cgs_m_init, good_cgs_m_inc, good_cgs_m_cnt; + + always @(posedge ck, posedge reset) + if (reset) + good_cgs <= 0; + else + begin + if (good_cgs_m_init) good_cgs <= 0; + else if (good_cgs_m_cnt) good_cgs <= 1; + else if (good_cgs_m_inc) good_cgs <= good_cgs + 1 ; + + end + + assign good_cgs_done = (good_cgs == 3); + + assign cgbad = INVALID | (COMMA_match & rx_even); + + assign cggood = ~cgbad; + + ////////////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////////////// + +`ifdef MODEL_TECH + enum logic [3:0] { +`else + localparam +`endif + S_PCS_SYNC_RUN = 0, + S_PCS_SYNC_LOSS_OF_SYNC = 1, + S_PCS_SYNC_COMMA_DETECT_1 = 2, + S_PCS_SYNC_ACQUIRE_SYNC_1 = 3, + S_PCS_SYNC_COMMA_DETECT_2 = 4, + S_PCS_SYNC_ACQUIRE_SYNC_2 = 5, + S_PCS_SYNC_COMMA_DETECT_3 = 6, + S_PCS_SYNC_ACQUIRED_1 = 7, + S_PCS_SYNC_ACQUIRED_2 = 8, + S_PCS_SYNC_ACQUIRED_3 = 9, + S_PCS_SYNC_ACQUIRED_4 = 10, + S_PCS_SYNC_ACQUIRED_2A = 11, + S_PCS_SYNC_ACQUIRED_3A = 12, + S_PCS_SYNC_ACQUIRED_4A = 13 +`ifdef MODEL_TECH + } pcs_sync_present, pcs_sync_next; +`else + ; reg [3:0] pcs_sync_present, pcs_sync_next; +`endif + + ////////////////////////////////////////////////////////////////////////////// + // sync state machine registered part. + ////////////////////////////////////////////////////////////////////////////// + + always @(posedge ck or posedge reset) + + pcs_sync_present <= (reset) ? S_PCS_SYNC_RUN : pcs_sync_next; + + ////////////////////////////////////////////////////////////////////////////// + // sync state machine - IEEE 802.3-2008 Clause 36 Figure 36-9 + ////////////////////////////////////////////////////////////////////////////// + + always @* + begin + pcs_sync_next = pcs_sync_present; + + good_cgs_m_init = 0; good_cgs_m_inc = 0; good_cgs_m_cnt = 0; + + sync_m_acquired = 0; sync_m_lost = 0; + + rx_even_m_init = 0; rx_even_m_set = 0; rx_even_m_clr = 0; rx_even_m_toggle = 0; + + running_disparity_negative_m_set = 0; running_disparity_positive_m_set = 0; + + case (pcs_sync_present) + + S_PCS_SYNC_RUN: + begin + if (startup_enable) pcs_sync_next = S_PCS_SYNC_LOSS_OF_SYNC; + end + + S_PCS_SYNC_LOSS_OF_SYNC : + begin + + sync_m_lost = sync_status; + + if ((signal_detect | loopback) & COMMA_match) + begin + rx_even_m_set = 1; pcs_sync_next = S_PCS_SYNC_COMMA_DETECT_1; + end + else + rx_even_m_toggle = 1; + end + + S_PCS_SYNC_COMMA_DETECT_1 : + begin + rx_even_m_toggle = 1; + + pcs_sync_next = (~ebi_K_d1 & ~cgbad) ? S_PCS_SYNC_ACQUIRE_SYNC_1 : S_PCS_SYNC_LOSS_OF_SYNC; + end + + S_PCS_SYNC_ACQUIRE_SYNC_1: + begin + if (~rx_even & COMMA_match) + begin + rx_even_m_set = 1; pcs_sync_next = S_PCS_SYNC_COMMA_DETECT_2; + end + else + begin + rx_even_m_toggle = 1; + + pcs_sync_next = (~COMMA_match & ~INVALID) ? S_PCS_SYNC_ACQUIRE_SYNC_1 : S_PCS_SYNC_LOSS_OF_SYNC; + end + end + + S_PCS_SYNC_COMMA_DETECT_2: + begin + rx_even_m_toggle = 1; + + pcs_sync_next = (~ebi_K_d1 & ~cgbad) ? S_PCS_SYNC_ACQUIRE_SYNC_2 : S_PCS_SYNC_LOSS_OF_SYNC; + end + + S_PCS_SYNC_ACQUIRE_SYNC_2: + begin + if (~rx_even & COMMA_match) + begin + rx_even_m_set = 1; pcs_sync_next = S_PCS_SYNC_COMMA_DETECT_3; + end + else + begin + rx_even_m_toggle = 1; + + pcs_sync_next = (~COMMA_match & ~INVALID) ? S_PCS_SYNC_ACQUIRE_SYNC_2 : S_PCS_SYNC_LOSS_OF_SYNC; + end + end + + S_PCS_SYNC_COMMA_DETECT_3: + begin + rx_even_m_toggle = 1; + + pcs_sync_next = (~ebi_K_d1 & ~cgbad) ? S_PCS_SYNC_ACQUIRED_1 : S_PCS_SYNC_LOSS_OF_SYNC; + + sync_m_acquired = ~ebi_K_d1; + end + + S_PCS_SYNC_ACQUIRED_1: + begin + rx_even_m_toggle = 1; + + pcs_sync_next = cggood ? S_PCS_SYNC_ACQUIRED_1 : S_PCS_SYNC_ACQUIRED_2; + end + + S_PCS_SYNC_ACQUIRED_2: + begin + rx_even_m_toggle = 1; + + if (cggood) good_cgs_m_cnt = 1; else good_cgs_m_init = 1; + + pcs_sync_next = cggood ? S_PCS_SYNC_ACQUIRED_2A : S_PCS_SYNC_ACQUIRED_3; + end + + S_PCS_SYNC_ACQUIRED_3: + begin + + rx_even_m_toggle = 1; + + if (cggood) good_cgs_m_cnt = 1; else good_cgs_m_init = 1; + + pcs_sync_next = cggood ? S_PCS_SYNC_ACQUIRED_3A: S_PCS_SYNC_ACQUIRED_4; + end + + S_PCS_SYNC_ACQUIRED_4: + begin + + rx_even_m_toggle = 1; + + if (cggood) good_cgs_m_cnt = 1; else good_cgs_m_init = 1; + + pcs_sync_next = cggood ? S_PCS_SYNC_ACQUIRED_4A: S_PCS_SYNC_LOSS_OF_SYNC; + end + + S_PCS_SYNC_ACQUIRED_2A: + begin + rx_even_m_toggle = 1; good_cgs_m_inc = 1; + + pcs_sync_next = (cgbad) ? S_PCS_SYNC_ACQUIRED_3 : + (good_cgs_done) ? S_PCS_SYNC_ACQUIRED_1 : S_PCS_SYNC_ACQUIRED_2A; + end + + S_PCS_SYNC_ACQUIRED_3A: + begin + rx_even_m_toggle = 1; good_cgs_m_inc = 1; + + pcs_sync_next = (cgbad) ? S_PCS_SYNC_ACQUIRED_4 : + (good_cgs_done) ? S_PCS_SYNC_ACQUIRED_2 : S_PCS_SYNC_ACQUIRED_3A; + end + + S_PCS_SYNC_ACQUIRED_4A: + begin + rx_even_m_toggle = 1; good_cgs_m_inc = 1; + + pcs_sync_next = (cgbad) ? S_PCS_SYNC_LOSS_OF_SYNC : + (good_cgs_done) ? S_PCS_SYNC_ACQUIRED_3 : S_PCS_SYNC_ACQUIRED_4A; + end + + endcase + + if (~signal_detect) pcs_sync_next = S_PCS_SYNC_LOSS_OF_SYNC; + end + +endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.