1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
module gige_phy
(input reset,
input independent_clock,
// input ETH_CLK_p, input ETH_CLK_n,
input sfp_clk,
input SFP_RX_p, input SFP_RX_n,
output SFP_TX_p, output SFP_TX_n,
output gmii_clk,
input [7:0] gmii_txd, input gmii_tx_en, input gmii_tx_er,
output [7:0] gmii_rxd, output gmii_rx_dv, output gmii_rx_er,
output [31:0] misc_debug,
output [15:0] int_data,
output [15:0] status_vector);
// wire sfp_clk;
wire mmcm_locked, mmcm_reset, resetdone, clkfbout;
wire userclk, userclk2;
wire txoutclk, txoutclk_bufg;
assign gmii_clk = userclk2; // 125 MHz
// IBUFDS_GTE2 clk_sfp_pin (.O(sfp_clk),.I(ETH_CLK_p),.IB(ETH_CLK_n), .CEB(1'b0));
// Route txoutclk input through a BUFG
// FIXME is this really necessary? It seems wasteful.
BUFG bufg_txoutclk (.I (txoutclk), .O (txoutclk_bufg));
// This 62.5MHz clock is placed onto global clock routing and is then used
// for tranceiver TXUSRCLK/RXUSRCLK.
BUFG bufg_userclk (.I (clkout1), .O (userclk));
// This 125MHz clock is placed onto global clock routing and is then used
// to clock all Ethernet core logic.
BUFG bufg_userclk2 (.I (clkout0), .O (userclk2));
// The GT transceiver provides a 62.5MHz clock to the FPGA fabric. This is
// routed to an MMCM module where it is used to create phase and frequency
// related 62.5MHz and 125MHz clock sources
MMCME2_ADV #
(.BANDWIDTH ("OPTIMIZED"),
.CLKOUT4_CASCADE ("FALSE"),
.COMPENSATION ("ZHOLD"),
.STARTUP_WAIT ("FALSE"),
.DIVCLK_DIVIDE (1),
.CLKFBOUT_MULT_F (16.000),
.CLKFBOUT_PHASE (0.000),
.CLKFBOUT_USE_FINE_PS ("FALSE"),
.CLKOUT0_DIVIDE_F (8.000),
.CLKOUT0_PHASE (0.000),
.CLKOUT0_DUTY_CYCLE (0.5),
.CLKOUT0_USE_FINE_PS ("FALSE"),
.CLKOUT1_DIVIDE (16),
.CLKOUT1_PHASE (0.000),
.CLKOUT1_DUTY_CYCLE (0.5),
.CLKOUT1_USE_FINE_PS ("FALSE"),
.CLKIN1_PERIOD (16.0),
.REF_JITTER1 (0.010)
) mmcm_adv_inst
(// Output clocks
.CLKFBOUT (clkfbout),
.CLKFBOUTB (),
.CLKOUT0 (clkout0),
.CLKOUT0B (),
.CLKOUT1 (clkout1),
.CLKOUT1B (),
.CLKOUT2 (),
.CLKOUT2B (),
.CLKOUT3 (),
.CLKOUT3B (),
.CLKOUT4 (),
.CLKOUT5 (),
.CLKOUT6 (),
// Input clock control
.CLKFBIN (clkfbout),
.CLKIN1 (txoutclk_bufg),
.CLKIN2 (1'b0),
// Tied to always select the primary input clock
.CLKINSEL (1'b1),
// Ports for dynamic reconfiguration
.DADDR (7'h0),
.DCLK (1'b0),
.DEN (1'b0),
.DI (16'h0),
.DO (),
.DRDY (),
.DWE (1'b0),
// Ports for dynamic phase shift
.PSCLK (1'b0),
.PSEN (1'b0),
.PSINCDEC (1'b0),
.PSDONE (),
// Other control and status signals
.LOCKED (mmcm_locked),
.CLKINSTOPPED (),
.CLKFBSTOPPED (),
.PWRDWN (1'b0),
.RST (mmcm_reset)
);
assign mmcm_reset = reset | ~resetdone;
gige_sfp_block gige_sfp_block
(.gtrefclk(sfp_clk), .txp(SFP_TX_p), .txn(SFP_TX_n), .rxp(SFP_RX_p), .rxn(SFP_RX_n),
.txoutclk(txoutclk), .resetdone(resetdone), .mmcm_locked(mmcm_locked), .userclk(userclk), .userclk2(userclk2),
.independent_clock_bufg(independent_clock),
.pma_reset(reset),
.gmii_txd(gmii_txd), .gmii_tx_en(gmii_tx_en), .gmii_tx_er(gmii_tx_er),
.gmii_rxd(gmii_rxd), .gmii_rx_dv(gmii_rx_dv), .gmii_rx_er(gmii_rx_er),
.gmii_isolate(), // unused
.configuration_vector(5'b00000),
.status_vector(status_vector), .reset(reset), .signal_detect(1'b1),
.misc_debug(misc_debug),
.int_data(int_data));
endmodule // gige_phy
|