Loading GTXE2_CHANNEL.v +309 −47 Original line number Diff line number Diff line /******************************************************************************* * Module: GTXE2_CHANNEL * Date: 2015-07-08 * Date: 2015-08-24 * Author: Alexey * Description: emulates GTXE2_CHANNEL primitive behaviour. * The file is gathered from multiple files Loading Loading @@ -256,6 +256,7 @@ module gtxe2_chnl_clocking( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -363,6 +364,7 @@ tx_toserialclk_div( .div (tx_serial_divider) ); wire rx_sipo_clk; clock_divider #( // .divide_by (rx_serial_divider), .divide_by_param (0) Loading Loading @@ -629,7 +631,7 @@ wire [word_count - 1:0] word_disparity; wire [word_count - 1:0] interm_disparity; wire [5:0] six [word_count - 1:0]; wire [3:0] four [word_count - 1:0]; wire [owidth - 1:0] oword [word_count - 1:0]; wire [9:0] oword [word_count - 1:0]; wire [iwidth - 1:0] iword [word_count - 1:0]; wire [word_count - 1:0] is_control; Loading @@ -644,7 +646,7 @@ begin: encode_by_word assign iword[ii] = data_in[ii*8 + 7:ii*8]; assign interm_disparity[ii]= ^six[ii] ? word_disparity[ii] : ~word_disparity[ii]; assign word_disparity[ii] = (ii == 0) ? disparity : (^oword[ii - 1] ? ~word_disparity[ii - 1] : word_disparity[ii - 1]); (^oword[ii - 1] ? word_disparity[ii - 1] : ~word_disparity[ii - 1]); // if there're 5 '1's - do no change the disparity, 6 or 4 - change assign six[ii] = iword[ii][4:0] == 5'b00000 ? (~word_disparity[ii] ? 6'b100111 : 6'b011000) : iword[ii][4:0] == 5'b00001 ? (~word_disparity[ii] ? 6'b011101 : 6'b100010) : iword[ii][4:0] == 5'b00010 ? (~word_disparity[ii] ? 6'b101101 : 6'b010010) Loading Loading @@ -684,7 +686,7 @@ begin: encode_by_word : iword[ii][7:5] == 3'd4 ? (~interm_disparity[ii] ? 4'b1101 : 4'b0010) : iword[ii][7:5] == 3'd5 ? (~interm_disparity[ii] ? 4'b1010 : 4'b1010) : iword[ii][7:5] == 3'd6 ? (~interm_disparity[ii] ? 4'b0110 : 4'b0110) :/*iword[ii][7:5] == 3'd7*/(~interm_disparity[ii] ? (six[ii][1:0] == 2'b00 ? 4'b1110 : 4'b0111) :/*iword[ii][7:5] == 3'd7*/(~interm_disparity[ii] ? (six[ii][1:0] == 2'b11 ? 4'b0111 : 4'b1110) : (six[ii][1:0] == 2'b00 ? 4'b1000 : 4'b0001)); assign oword[ii] = ~is_control[ii] ? {six[ii], four[ii]} : iword[ii][7:0] == 8'b00011100 ? (~word_disparity[ii] ? 10'b0011110100 : 10'b1100001011) Loading @@ -703,7 +705,7 @@ begin: encode_by_word assign data_out[ii*10 + 9:ii * 10] = oword[ii]; end endgenerate assign next_disparity = ^oword[word_count - 1] ? ~word_disparity[word_count - 1] : word_disparity[word_count - 1]; assign next_disparity = ^oword[word_count - 1] ? word_disparity[word_count - 1] : ~word_disparity[word_count - 1]; endmodule Loading @@ -726,10 +728,10 @@ module gtxe2_chnl_tx_oob #( parameter [3:0] SATA_BURST_SEQ_LEN = 4'b0101; parameter SATA_CPLL_CFG = "VCO_3000MHZ"; localparam burst_len_mult = SATA_CPLL_CFG == "VCO_3000MHZ" ? 4 : SATA_CPLL_CFG == "VCO_1500MHZ" ? 2 : /* VCO_750MHZ */ 1; localparam burst_len = burst_len_mult * 8; // = 106.7ns; each burst contains 16 SATA Gen1 words localparam burst_len_mult = SATA_CPLL_CFG == "VCO_3000MHZ" ? 2 // assuming each usrclk cycle == 20 sata serial clk cycles : SATA_CPLL_CFG == "VCO_1500MHZ" ? 4 : /* VCO_6000MHZ */ 1; localparam burst_len = /*burst_len_mult * 8*/ 32; // = 106.7ns; each burst contains 16 SATA Gen1 words localparam quiet_len_init = burst_len * 3; // = 320ns localparam quiet_len_wake = burst_len; // = 106.7ns localparam init_bursts_cnt = SATA_BURST_SEQ_LEN;//3; Loading Loading @@ -777,8 +779,8 @@ end assign set_burst = state_idle & (TXCOMINIT | TXCOMWAKE) | state_quiet & clr_quiet & ~TXCOMFINISH; assign set_quiet = state_burst & (bursts_cnt < bursts_cnt_togo - 1) & clr_burst; assign clr_burst = state_burst & stopwatch == burst_len; assign clr_quiet = state_quiet & stopwatch == quiet_len; assign clr_burst = state_burst & stopwatch == (burst_len - burst_len_mult); assign clr_quiet = state_quiet & stopwatch == (quiet_len - burst_len_mult); // bursts timing assign quiet_len = issued_wake ? quiet_len_wake : quiet_len_init; Loading Loading @@ -808,6 +810,67 @@ assign TXCOMFINISH = bursts_cnt_clr & bursts_cnt == bursts_cnt_togo; endmodule /* * According to the doc, p110 * If TX_INT_DATAWIDTH, the inner width = 32 bits, otherwise 16. */ module gtxe2_chnl_tx_dataiface #( parameter internal_data_width = 16, parameter interface_data_width = 32, parameter internal_isk_width = 2, parameter interface_isk_width = 4 ) ( input wire usrclk, input wire usrclk2, input wire reset, output wire [internal_data_width - 1:0] outdata, output wire [internal_isk_width - 1:0] outisk, input wire [interface_data_width - 1:0] indata, input wire [interface_isk_width - 1:0] inisk ); localparam div = interface_data_width / internal_data_width; wire [interface_data_width + interface_isk_width - 1:0] data_resynced; reg [31:0] wordcounter; wire almost_empty_rd; wire empty_rd; wire full_wr; wire val_rd; always @ (posedge usrclk) wordcounter <= reset | wordcounter == (div - 1) ? 32'h0 : wordcounter + 1'b1; assign outdata = data_resynced[(wordcounter + 1) * internal_data_width - 1 -: internal_data_width]; assign outisk = data_resynced[(wordcounter + 1) * internal_isk_width + internal_data_width * div - 1 -: internal_isk_width]; assign val_rd = ~almost_empty_rd & ~empty_rd & wordcounter == (div - 1); resync_fifo_nonsynt #( .width (interface_data_width + interface_isk_width), .log_depth (3) ) fifo( .rst_rd (reset), .rst_wr (reset), .clk_wr (usrclk2), .val_wr (1'b1), .data_wr ({inisk, indata}), .clk_rd (usrclk), .val_rd (val_rd), .data_rd ({data_resynced}), .empty_rd (empty_rd), .full_wr (full_wr), .almost_empty_rd (almost_empty_rd) ); endmodule module gtxe2_chnl_tx( input wire reset, output wire TXP, Loading Loading @@ -883,12 +946,15 @@ wire line_idle; wire line_idle_pcs; // line_idle in pcs clock domain wire [internal_data_width - 1:0] ser_input; wire oob_active; reg oob_in_process; always @ (posedge TXUSRCLK) oob_in_process <= reset | TXCOMFINISH ? 1'b0 : TXCOMINIT | TXCOMWAKE ? 1'b1 : oob_in_process; assign TXP = ~line_idle ? serial_data : 1'bx; assign TXN = ~line_idle ? ~serial_data : 1'bx; assign line_idle_pcs = TXELECIDLE & ~oob_active | reset; assign line_idle_pcs = (TXELECIDLE | oob_in_process) & ~oob_active | reset; // Serializer wire [internal_data_width - 1:0] parallel_data; Loading @@ -909,6 +975,35 @@ ser( // TX PCS // fit data width // TODO make parameters awesome localparam data_width = 16; localparam if_data_width = 32; localparam isk_width = 2; localparam if_isk_width = 4; wire [data_width - 1:0] internal_data; wire [isk_width - 1:0] internal_isk; gtxe2_chnl_tx_dataiface #( .internal_data_width (data_width), .interface_data_width (if_data_width), .internal_isk_width (isk_width), .interface_isk_width (if_isk_width) ) dataiface ( .usrclk (TXUSRCLK), .usrclk2 (TXUSRCLK2), .reset (reset), .outdata (internal_data), .outisk (internal_isk), .indata (TXDATA[if_data_width - 1:0]), .inisk (TXCHARISK[if_isk_width - 1:0]) ); wire [internal_data_width - 1:0] polarized_data; // invert data (get words as [abdceifghj] after 8/10, each word shall be transmitter in a reverse bit order) genvar ii; genvar jj; Loading @@ -923,7 +1018,6 @@ generate endgenerate // Polarity: wire [internal_data_width - 1:0] polarized_data; assign ser_input = polarized_data; generate Loading @@ -941,7 +1035,9 @@ wire oob_val; assign oob_active = oob_val; gtxe2_chnl_tx_oob #( .width (internal_data_width) .width (internal_data_width), .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN), .SATA_CPLL_CFG (SATA_CPLL_CFG) ) tx_oob( .TXCOMINIT (TXCOMINIT), Loading Loading @@ -971,9 +1067,9 @@ encoder_8x10( .TX8B10BEN (TX8B10BEN), .TXCHARDISPMODE (TXCHARDISPMODE), .TXCHARDISPVAL (TXCHARDISPVAL), .TXCHARISK (TXCHARISK), .TXCHARISK (internal_isk), .disparity (disparity), .data_in (TXDATA[15:0]), .data_in (internal_data), .data_out (encoded_data), .next_disparity (next_disparity) ); Loading Loading @@ -1130,6 +1226,7 @@ module gtxe2_chnl_rx_oob #( ( input wire reset, input wire clk, input wire usrclk2, input wire RXN, input wire RXP, Loading @@ -1147,11 +1244,11 @@ localparam wake_idle_min_len = 150; localparam wake_idle_max_len = 340; localparam init_idle_min_len = 450; localparam init_idle_max_len = 990; localparam wake_bursts_cnt = 5; localparam init_bursts_cnt = 5; localparam wake_bursts_cnt = SATA_BURST_VAL; localparam init_bursts_cnt = SATA_BURST_VAL; wire idle; assign idle = (RXN == RXP) | (RXP === 1'bx); assign idle = (RXN == RXP) | (RXP === 1'bx) | (RXP === 1'bz); wire state_notrans; wire state_error; //nostrans substate Loading Loading @@ -1224,8 +1321,24 @@ assign done_init = state_burst & ~idle & bursts_cnt == (init_bursts_cnt - 1)& assign set_error = idle_len_violation | burst_len_violation; assign set_done = ~set_error & (done_wake | done_init); assign RXCOMINITDET = done_init; assign RXCOMWAKEDET = done_wake; // just to rxcominit(wake)det be synchronous to usrclk2 reg rxcominitdet_clk; reg rxcominitdet_usrclk2; reg rxcomwakedet_clk; reg rxcomwakedet_usrclk2; always @ (posedge clk) begin rxcominitdet_clk <= reset ? 1'b0 : done_init | rxcominitdet_clk & ~rxcominitdet_usrclk2; rxcomwakedet_clk <= reset ? 1'b0 : done_wake | rxcomwakedet_clk & ~rxcomwakedet_usrclk2; end always @ (posedge usrclk2) begin rxcominitdet_usrclk2 <= reset ? 1'b0 : rxcominitdet_clk & ~rxcominitdet_usrclk2; rxcomwakedet_usrclk2 <= reset ? 1'b0 : rxcomwakedet_clk & ~rxcomwakedet_usrclk2; end assign RXCOMINITDET = rxcominitdet_usrclk2; assign RXCOMWAKEDET = rxcomwakedet_usrclk2; assign RXELECIDLE = RXP === 1'bz ? 1'b1 : RXP === 1'bx ? 1'b1 : RXP == RXN; endmodule Loading Loading @@ -1438,6 +1551,8 @@ module gtxe2_chnl_rx_align #( input wire [width - 1:0] indata, output wire [width - 1:0] outdata, input wire rxelecidle, output wire RXBYTEISALIGNED, output wire RXBYTEREALIGN, output wire RXCOMMADET, Loading @@ -1461,6 +1576,29 @@ always @ (posedge clk) // finding matches wire [comma_width - 1:0] comma_window [window_size - 1:0]; //initial // for (idx = 0; idx < window_size; idx = idx + 1) $dumpvars(0, comma_width[idx]); wire [comma_width - 1:0] comma_window0 = comma_window[0]; wire [comma_width - 1:0] comma_window1 = comma_window[1]; wire [comma_width - 1:0] comma_window2 = comma_window[2]; wire [comma_width - 1:0] comma_window3 = comma_window[3]; wire [comma_width - 1:0] comma_window4 = comma_window[4]; wire [comma_width - 1:0] comma_window5 = comma_window[5]; wire [comma_width - 1:0] comma_window6 = comma_window[6]; wire [comma_width - 1:0] comma_window7 = comma_window[7]; wire [comma_width - 1:0] comma_window8 = comma_window[8]; wire [comma_width - 1:0] comma_window9 = comma_window[9]; wire [comma_width - 1:0] comma_window10 = comma_window[10]; wire [comma_width - 1:0] comma_window11 = comma_window[11]; wire [comma_width - 1:0] comma_window12 = comma_window[12]; wire [comma_width - 1:0] comma_window13 = comma_window[13]; wire [comma_width - 1:0] comma_window14 = comma_window[14]; wire [comma_width - 1:0] comma_window15 = comma_window[15]; wire [comma_width - 1:0] comma_window16 = comma_window[16]; wire [comma_width - 1:0] comma_window17 = comma_window[17]; wire [comma_width - 1:0] comma_window18 = comma_window[18]; wire [comma_width - 1:0] comma_window19 = comma_window[19]; wire [window_size - 1:0] comma_match; // shows all matches wire [window_size - 1:0] comma_pos; // shows the first match wire [window_size - 1:0] pcomma_match; Loading Loading @@ -1537,12 +1675,101 @@ assign RXBYTEREALIGN = RXCOMMADETEN & is_aligned & pointer_set; always @ (posedge clk) begin is_aligned <= rst ? 1'b0 : ~is_aligned & pointer_set | is_aligned; is_aligned <= rst | pointer_set === 1'bx | rxelecidle ? 1'b0 : ~is_aligned & pointer_set | is_aligned; pointer_latched <= rst ? 1'b0 : pointer_set ? pointer : pointer_latched; end endmodule /* * According to the doc, p110 * If RX_INT_DATAWIDTH, the inner width = 32 bits, otherwise 16. */ module gtxe2_chnl_rx_dataiface #( parameter internal_data_width = 16, parameter interface_data_width = 32, parameter internal_isk_width = 2, parameter interface_isk_width = 4 ) ( input wire usrclk, input wire usrclk2, input wire reset, output wire [interface_data_width - 1:0] outdata, output wire [interface_isk_width - 1:0] outisk, input wire [internal_data_width - 1:0] indata, input wire [internal_isk_width - 1:0] inisk, input wire realign ); localparam div = interface_data_width / internal_data_width; localparam internal_total_width = internal_data_width + internal_isk_width; localparam interface_total_width = interface_data_width + interface_isk_width; reg [interface_data_width - 1:0] inbuffer_data; reg [interface_isk_width - 1:0] inbuffer_isk; reg [31:0] wordcounter; wire empty_rd; wire full_wr; wire val_wr; wire val_rd; always @ (posedge usrclk) wordcounter <= reset ? 32'h0 : realign & ~(div == 0) ? 31'b1 : wordcounter == (div - 1) ? 32'h0 : wordcounter + 1'b1; genvar ii; generate for (ii = 0; ii < div; ii = ii + 1) begin: splicing always @ (posedge usrclk) inbuffer_data[(ii + 1) * internal_data_width - 1 -: internal_data_width] <= reset ? {interface_data_width{1'b0}} : ((wordcounter == ii) | realign & (0 == ii)) ? indata : inbuffer_data[(ii + 1) * internal_data_width - 1 -: internal_data_width]; end endgenerate generate for (ii = 0; ii < div; ii = ii + 1) begin: splicing2 always @ (posedge usrclk) inbuffer_isk[(ii + 1) * internal_isk_width - 1 -: internal_isk_width] <= reset ? {interface_isk_width{1'b0}} : ((wordcounter == ii) | realign & (0 == ii)) ? inisk : inbuffer_isk[(ii + 1) * internal_isk_width - 1 -: internal_isk_width]; end endgenerate assign val_rd = ~empty_rd & ~almost_empty_rd; assign val_wr = ~full_wr & wordcounter == (div - 1); always @ (posedge usrclk) if (full_wr) begin $display("FIFO in %m is full, that is not an appropriate behaviour"); $finish; end wire [interface_total_width - 1:0] resync; assign outdata = resync[interface_data_width - 1:0]; assign outisk = resync[interface_data_width + interface_isk_width - 1:interface_data_width]; resync_fifo_nonsynt #( .width (interface_total_width), .log_depth (3) ) fifo( .rst_rd (reset), .rst_wr (reset), .clk_wr (usrclk2), .val_wr (val_wr), .data_wr ({inisk, inbuffer_isk[interface_isk_width - internal_isk_width - 1 : 0], indata, inbuffer_data[interface_data_width - internal_data_width - 1 : 0]}), .clk_rd (usrclk2), .val_rd (val_rd), .data_rd (resync), .empty_rd (empty_rd), .full_wr (full_wr), .almost_empty_rd (almost_empty_rd) ); endmodule module gtxe2_chnl_rx( input wire reset, input wire RXP, Loading Loading @@ -1629,6 +1856,7 @@ gtxe2_chnl_rx_oob #( rx_oob( .reset (reset), .clk (serial_clk), .usrclk2 (RXUSRCLK2), .RXN (RXN), .RXP (RXP), Loading Loading @@ -1676,6 +1904,8 @@ aligner( .indata (parallel_data), .outdata (aligned_data), .rxelecidle (RXELECIDLE), .RXBYTEISALIGNED (RXBYTEISALIGNED), .RXBYTEREALIGN (RXBYTEREALIGN), .RXCOMMADET (RXCOMMADET), Loading @@ -1685,6 +1915,8 @@ aligner( .RXMCOMMAALIGNEN (RXMCOMMAALIGNEN) ); wire [data_width - 1:0] internal_data; wire [isk_width - 1:0] internal_isk; // 10x8 decoder gtxe2_chnl_rx_10x8dec #( .iwidth (internal_data_width), Loading @@ -1699,14 +1931,43 @@ decoder_10x8( .RX8B10BEN (RX8B10BEN), .RXCHARISCOMMA (RXCHARISCOMMA), .RXCHARISK (RXCHARISK), .RXCHARISK (internal_isk), .RXDISPERR (RXDISPERR), .RXNOTINTABLE (RXNOTINTABLE), .outdata (), .RXDATA (RXDATA) .RXDATA (internal_data) ); // fit data width // TODO make parameters awesome localparam data_width = 16; localparam if_data_width = 32; localparam isk_width = 2; localparam if_isk_width = 4; gtxe2_chnl_rx_dataiface #( .internal_data_width (data_width), .interface_data_width (if_data_width), .internal_isk_width (isk_width), .interface_isk_width (if_isk_width) ) dataiface ( .usrclk (RXUSRCLK), .usrclk2 (RXUSRCLK2), .reset (reset), .indata (internal_data), .inisk (internal_isk), .outdata (RXDATA[if_data_width - 1:0]), .outisk (RXCHARISK[if_isk_width - 1:0]), .realign (RXBYTEREALIGN === 1'bx ? 1'b0 : RXBYTEREALIGN) ); assign RXDATA[63:if_data_width] = 0; assign RXCHARISK[7:if_isk_width] = 0; endmodule module gtxe2_chnl( Loading Loading @@ -1805,6 +2066,7 @@ module gtxe2_chnl( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -1963,11 +2225,6 @@ gtxe2_chnl_clocking #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), Loading @@ -1989,6 +2246,7 @@ clocking( .TXOUTCLKSEL (TXOUTCLKSEL), .RXOUTCLKSEL (RXOUTCLKSEL), .TXDLYBYPASS (TXDLYBYPASS), .RXDLYBYPASS (RXDLYBYPASS), .GTREFCLKMONITOR (GTREFCLKMONITOR), .CPLLLOCKDETCLK (CPLLLOCKDETCLK), Loading Loading @@ -2080,13 +2338,13 @@ module GTXE2_CHANNEL( input [8:0] DRPADDR, input DRPCLK, input [15:0] DRPDI, input [15:0] DRPDO, output [15:0] DRPDO, input DRPEN, output DRPRDY, input DRPWE, // Digital Monitor Ports, ug476 p.95 input [3:0] CLKRSVD, input [7:0] DMONITOROUT, output [7:0] DMONITOROUT, // TX Interface Ports, ug476 p.110 input [7:0] TXCHARDISPMODE, input [7:0] TXCHARDISPVAL, Loading @@ -2103,7 +2361,7 @@ module GTXE2_CHANNEL( input [6:0] TXSEQUENCE, input TXSTARTSEQ, // TX BUffer Ports, ug476 p.134 input [1:0] TXBUFSTATUS, output [1:0] TXBUFSTATUS, // TX Buffer Bypass Ports, ug476 p.136 input TXDLYSRESET, input TXPHALIGN, Loading @@ -2123,8 +2381,8 @@ module GTXE2_CHANNEL( input TXSYNCMODE, input TXSYNCALLIN, input TXSYNCIN, input TXSYNCOUT, input TXSYNCDONE, output TXSYNCOUT, output TXSYNCDONE, // TX Pattern Generator, ug476 p.147 input [2:0] TXPRBSSEL, input TXPRBSFORCEERR, Loading Loading @@ -2167,7 +2425,7 @@ module GTXE2_CHANNEL( // TX Receiver Detection Ports, ug476 p.165 input TXDETECTRX, output PHYSTATUS, input [2:0] RXSTATUS, output [2:0] RXSTATUS, // TX OOB Signaling Ports, ug476 p.166 output TXCOMFINISH, input TXCOMINIT, Loading Loading @@ -2212,7 +2470,7 @@ module GTXE2_CHANNEL( input RXDFEXYDOVRDEN, input RXDFEXYDEN, input [1:0] RXMONITORSEL, input [6:0] RXMONITOROUT, output [6:0] RXMONITOROUT, // CDR Ports, ug476 p.202 input RXCDRHOLD, input RXCDROVRDEN, Loading Loading @@ -2265,9 +2523,9 @@ module GTXE2_CHANNEL( output RXPHSLIPMONITOR, output RXDLYSRESETDONE, // RX Buffer Ports, ug476 p.259 input [2:0] RXBUFSTATUS, output [2:0] RXBUFSTATUS, // RX Clock Correction Ports, ug476 p.263 input [1:0] RXCLKCORCNT, output [1:0] RXCLKCORCNT, // RX Channel Bonding Ports, ug476 p.274 output RXCHANBONDSEQ, output RXCHANISALIGNED, Loading @@ -2281,7 +2539,7 @@ module GTXE2_CHANNEL( // RX Gearbox Ports, ug476 p.285 output RXDATAVALID, input RXGEARBOXSLIP, input [2:0] RXHEADER, output [2:0] RXHEADER, output RXHEADERVALID, output RXSTARTOFSEQ, // FPGA RX Interface Ports, ug476 p.299 Loading Loading @@ -2551,7 +2809,17 @@ parameter RXGEARBOX_EN = "FALSE"; parameter RX_CLK25_DIV = 6; parameter TX_CLK25_DIV = 6; wire reset = EYESCANRESET | RXCDRFREQRESET | RXCDRRESET | RXCDRRESETRSV | RXPRBSCNTRESET | RXBUFRESET | RXDLYSRESET | RXPHDLYRESET | RXDFELPMRESET | GTRXRESET | RXOOBRESET | RXPCSRESET | RXPMARESET | CFGRESET | GTTXRESET | GTRESETSEL | RESETOVRD | TXDLYSRESET | TXPHDLYRESET | TXPCSRESET | TXPMARESET; // clocking reset ( + TX PMA) wire clk_reset = EYESCANRESET | RXCDRFREQRESET | RXCDRRESET | RXCDRRESETRSV | RXPRBSCNTRESET | RXBUFRESET | RXDLYSRESET | RXPHDLYRESET | RXDFELPMRESET | GTRXRESET | RXOOBRESET | RXPCSRESET | RXPMARESET | CFGRESET | GTTXRESET | GTRESETSEL | RESETOVRD | TXDLYSRESET | TXPHDLYRESET | TXPCSRESET | TXPMARESET; // have to wait before an external pll (mmcm) locks with usrclk, after that PCS can be resetted. Actually, we reset PMA also, because why not reg reset; reg [31:0] reset_timer = 0; always @ (posedge TXUSRCLK) reset_timer <= ~TXUSERRDY ? 32'h0 : reset_timer == 32'hffffffff ? reset_timer : reset_timer + 1'b1; always @ (posedge TXUSRCLK) reset <= ~TXUSERRDY ? 1'b0 : reset_timer < 32'd20 ? 1'b1 : 1'b0; reg rx_rst_done = 1'b0; reg tx_rst_done = 1'b0; Loading Loading @@ -2588,11 +2856,6 @@ gtxe2_chnl #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), Loading @@ -2614,8 +2877,7 @@ gtxe2_chnl #( .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .PTX8B10BEN (1), .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN), .SATA_CPLL_CFG (SATA_CPLL_CFG) .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN) ) channel( .reset (reset), Loading gtxe2_channel/GTXE2_CHANNEL_GPL.v +23 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes gtxe2_channel/gtxe2_chnl.v +5 −8 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_clocking.v" //`include "gtxe2_chnl_tx.v" //`include "gtxe2_chnl_rx.v" `include "gtxe2_chnl_clocking.v" `include "gtxe2_chnl_tx.v" `include "gtxe2_chnl_rx.v" module gtxe2_chnl( input wire reset, /* Loading Loading @@ -117,6 +117,7 @@ module gtxe2_chnl( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -275,11 +276,6 @@ gtxe2_chnl_clocking #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), Loading @@ -301,6 +297,7 @@ clocking( .TXOUTCLKSEL (TXOUTCLKSEL), .RXOUTCLKSEL (RXOUTCLKSEL), .TXDLYBYPASS (TXDLYBYPASS), .RXDLYBYPASS (RXDLYBYPASS), .GTREFCLKMONITOR (GTREFCLKMONITOR), .CPLLLOCKDETCLK (CPLLLOCKDETCLK), Loading gtxe2_channel/gtxe2_chnl_clocking.v +6 −4 Original line number Diff line number Diff line Loading @@ -19,10 +19,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_cpll_inmux.v" //`include "gtxe2_chnl_outclk_mux.v" //`include "gtxe2_chnl_cpll.v" //`include "clock_divider.v" `include "gtxe2_chnl_cpll_inmux.v" `include "gtxe2_chnl_outclk_mux.v" `include "gtxe2_chnl_cpll.v" `include "clock_divider.v" module gtxe2_chnl_clocking( // top-level interfaces input wire [2:0] CPLLREFCLKSEL, Loading @@ -40,6 +40,7 @@ module gtxe2_chnl_clocking( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -147,6 +148,7 @@ tx_toserialclk_div( .div (tx_serial_divider) ); wire rx_sipo_clk; clock_divider #( // .divide_by (rx_serial_divider), .divide_by_param (0) Loading gtxe2_channel/gtxe2_chnl_cpll.v +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_cpll_def.v" `include "gtxe2_chnl_cpll_def.v" module gtxe2_chnl_cpll( // top-level interfaces input wire CPLLLOCKDETCLK, Loading Loading
GTXE2_CHANNEL.v +309 −47 Original line number Diff line number Diff line /******************************************************************************* * Module: GTXE2_CHANNEL * Date: 2015-07-08 * Date: 2015-08-24 * Author: Alexey * Description: emulates GTXE2_CHANNEL primitive behaviour. * The file is gathered from multiple files Loading Loading @@ -256,6 +256,7 @@ module gtxe2_chnl_clocking( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -363,6 +364,7 @@ tx_toserialclk_div( .div (tx_serial_divider) ); wire rx_sipo_clk; clock_divider #( // .divide_by (rx_serial_divider), .divide_by_param (0) Loading Loading @@ -629,7 +631,7 @@ wire [word_count - 1:0] word_disparity; wire [word_count - 1:0] interm_disparity; wire [5:0] six [word_count - 1:0]; wire [3:0] four [word_count - 1:0]; wire [owidth - 1:0] oword [word_count - 1:0]; wire [9:0] oword [word_count - 1:0]; wire [iwidth - 1:0] iword [word_count - 1:0]; wire [word_count - 1:0] is_control; Loading @@ -644,7 +646,7 @@ begin: encode_by_word assign iword[ii] = data_in[ii*8 + 7:ii*8]; assign interm_disparity[ii]= ^six[ii] ? word_disparity[ii] : ~word_disparity[ii]; assign word_disparity[ii] = (ii == 0) ? disparity : (^oword[ii - 1] ? ~word_disparity[ii - 1] : word_disparity[ii - 1]); (^oword[ii - 1] ? word_disparity[ii - 1] : ~word_disparity[ii - 1]); // if there're 5 '1's - do no change the disparity, 6 or 4 - change assign six[ii] = iword[ii][4:0] == 5'b00000 ? (~word_disparity[ii] ? 6'b100111 : 6'b011000) : iword[ii][4:0] == 5'b00001 ? (~word_disparity[ii] ? 6'b011101 : 6'b100010) : iword[ii][4:0] == 5'b00010 ? (~word_disparity[ii] ? 6'b101101 : 6'b010010) Loading Loading @@ -684,7 +686,7 @@ begin: encode_by_word : iword[ii][7:5] == 3'd4 ? (~interm_disparity[ii] ? 4'b1101 : 4'b0010) : iword[ii][7:5] == 3'd5 ? (~interm_disparity[ii] ? 4'b1010 : 4'b1010) : iword[ii][7:5] == 3'd6 ? (~interm_disparity[ii] ? 4'b0110 : 4'b0110) :/*iword[ii][7:5] == 3'd7*/(~interm_disparity[ii] ? (six[ii][1:0] == 2'b00 ? 4'b1110 : 4'b0111) :/*iword[ii][7:5] == 3'd7*/(~interm_disparity[ii] ? (six[ii][1:0] == 2'b11 ? 4'b0111 : 4'b1110) : (six[ii][1:0] == 2'b00 ? 4'b1000 : 4'b0001)); assign oword[ii] = ~is_control[ii] ? {six[ii], four[ii]} : iword[ii][7:0] == 8'b00011100 ? (~word_disparity[ii] ? 10'b0011110100 : 10'b1100001011) Loading @@ -703,7 +705,7 @@ begin: encode_by_word assign data_out[ii*10 + 9:ii * 10] = oword[ii]; end endgenerate assign next_disparity = ^oword[word_count - 1] ? ~word_disparity[word_count - 1] : word_disparity[word_count - 1]; assign next_disparity = ^oword[word_count - 1] ? word_disparity[word_count - 1] : ~word_disparity[word_count - 1]; endmodule Loading @@ -726,10 +728,10 @@ module gtxe2_chnl_tx_oob #( parameter [3:0] SATA_BURST_SEQ_LEN = 4'b0101; parameter SATA_CPLL_CFG = "VCO_3000MHZ"; localparam burst_len_mult = SATA_CPLL_CFG == "VCO_3000MHZ" ? 4 : SATA_CPLL_CFG == "VCO_1500MHZ" ? 2 : /* VCO_750MHZ */ 1; localparam burst_len = burst_len_mult * 8; // = 106.7ns; each burst contains 16 SATA Gen1 words localparam burst_len_mult = SATA_CPLL_CFG == "VCO_3000MHZ" ? 2 // assuming each usrclk cycle == 20 sata serial clk cycles : SATA_CPLL_CFG == "VCO_1500MHZ" ? 4 : /* VCO_6000MHZ */ 1; localparam burst_len = /*burst_len_mult * 8*/ 32; // = 106.7ns; each burst contains 16 SATA Gen1 words localparam quiet_len_init = burst_len * 3; // = 320ns localparam quiet_len_wake = burst_len; // = 106.7ns localparam init_bursts_cnt = SATA_BURST_SEQ_LEN;//3; Loading Loading @@ -777,8 +779,8 @@ end assign set_burst = state_idle & (TXCOMINIT | TXCOMWAKE) | state_quiet & clr_quiet & ~TXCOMFINISH; assign set_quiet = state_burst & (bursts_cnt < bursts_cnt_togo - 1) & clr_burst; assign clr_burst = state_burst & stopwatch == burst_len; assign clr_quiet = state_quiet & stopwatch == quiet_len; assign clr_burst = state_burst & stopwatch == (burst_len - burst_len_mult); assign clr_quiet = state_quiet & stopwatch == (quiet_len - burst_len_mult); // bursts timing assign quiet_len = issued_wake ? quiet_len_wake : quiet_len_init; Loading Loading @@ -808,6 +810,67 @@ assign TXCOMFINISH = bursts_cnt_clr & bursts_cnt == bursts_cnt_togo; endmodule /* * According to the doc, p110 * If TX_INT_DATAWIDTH, the inner width = 32 bits, otherwise 16. */ module gtxe2_chnl_tx_dataiface #( parameter internal_data_width = 16, parameter interface_data_width = 32, parameter internal_isk_width = 2, parameter interface_isk_width = 4 ) ( input wire usrclk, input wire usrclk2, input wire reset, output wire [internal_data_width - 1:0] outdata, output wire [internal_isk_width - 1:0] outisk, input wire [interface_data_width - 1:0] indata, input wire [interface_isk_width - 1:0] inisk ); localparam div = interface_data_width / internal_data_width; wire [interface_data_width + interface_isk_width - 1:0] data_resynced; reg [31:0] wordcounter; wire almost_empty_rd; wire empty_rd; wire full_wr; wire val_rd; always @ (posedge usrclk) wordcounter <= reset | wordcounter == (div - 1) ? 32'h0 : wordcounter + 1'b1; assign outdata = data_resynced[(wordcounter + 1) * internal_data_width - 1 -: internal_data_width]; assign outisk = data_resynced[(wordcounter + 1) * internal_isk_width + internal_data_width * div - 1 -: internal_isk_width]; assign val_rd = ~almost_empty_rd & ~empty_rd & wordcounter == (div - 1); resync_fifo_nonsynt #( .width (interface_data_width + interface_isk_width), .log_depth (3) ) fifo( .rst_rd (reset), .rst_wr (reset), .clk_wr (usrclk2), .val_wr (1'b1), .data_wr ({inisk, indata}), .clk_rd (usrclk), .val_rd (val_rd), .data_rd ({data_resynced}), .empty_rd (empty_rd), .full_wr (full_wr), .almost_empty_rd (almost_empty_rd) ); endmodule module gtxe2_chnl_tx( input wire reset, output wire TXP, Loading Loading @@ -883,12 +946,15 @@ wire line_idle; wire line_idle_pcs; // line_idle in pcs clock domain wire [internal_data_width - 1:0] ser_input; wire oob_active; reg oob_in_process; always @ (posedge TXUSRCLK) oob_in_process <= reset | TXCOMFINISH ? 1'b0 : TXCOMINIT | TXCOMWAKE ? 1'b1 : oob_in_process; assign TXP = ~line_idle ? serial_data : 1'bx; assign TXN = ~line_idle ? ~serial_data : 1'bx; assign line_idle_pcs = TXELECIDLE & ~oob_active | reset; assign line_idle_pcs = (TXELECIDLE | oob_in_process) & ~oob_active | reset; // Serializer wire [internal_data_width - 1:0] parallel_data; Loading @@ -909,6 +975,35 @@ ser( // TX PCS // fit data width // TODO make parameters awesome localparam data_width = 16; localparam if_data_width = 32; localparam isk_width = 2; localparam if_isk_width = 4; wire [data_width - 1:0] internal_data; wire [isk_width - 1:0] internal_isk; gtxe2_chnl_tx_dataiface #( .internal_data_width (data_width), .interface_data_width (if_data_width), .internal_isk_width (isk_width), .interface_isk_width (if_isk_width) ) dataiface ( .usrclk (TXUSRCLK), .usrclk2 (TXUSRCLK2), .reset (reset), .outdata (internal_data), .outisk (internal_isk), .indata (TXDATA[if_data_width - 1:0]), .inisk (TXCHARISK[if_isk_width - 1:0]) ); wire [internal_data_width - 1:0] polarized_data; // invert data (get words as [abdceifghj] after 8/10, each word shall be transmitter in a reverse bit order) genvar ii; genvar jj; Loading @@ -923,7 +1018,6 @@ generate endgenerate // Polarity: wire [internal_data_width - 1:0] polarized_data; assign ser_input = polarized_data; generate Loading @@ -941,7 +1035,9 @@ wire oob_val; assign oob_active = oob_val; gtxe2_chnl_tx_oob #( .width (internal_data_width) .width (internal_data_width), .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN), .SATA_CPLL_CFG (SATA_CPLL_CFG) ) tx_oob( .TXCOMINIT (TXCOMINIT), Loading Loading @@ -971,9 +1067,9 @@ encoder_8x10( .TX8B10BEN (TX8B10BEN), .TXCHARDISPMODE (TXCHARDISPMODE), .TXCHARDISPVAL (TXCHARDISPVAL), .TXCHARISK (TXCHARISK), .TXCHARISK (internal_isk), .disparity (disparity), .data_in (TXDATA[15:0]), .data_in (internal_data), .data_out (encoded_data), .next_disparity (next_disparity) ); Loading Loading @@ -1130,6 +1226,7 @@ module gtxe2_chnl_rx_oob #( ( input wire reset, input wire clk, input wire usrclk2, input wire RXN, input wire RXP, Loading @@ -1147,11 +1244,11 @@ localparam wake_idle_min_len = 150; localparam wake_idle_max_len = 340; localparam init_idle_min_len = 450; localparam init_idle_max_len = 990; localparam wake_bursts_cnt = 5; localparam init_bursts_cnt = 5; localparam wake_bursts_cnt = SATA_BURST_VAL; localparam init_bursts_cnt = SATA_BURST_VAL; wire idle; assign idle = (RXN == RXP) | (RXP === 1'bx); assign idle = (RXN == RXP) | (RXP === 1'bx) | (RXP === 1'bz); wire state_notrans; wire state_error; //nostrans substate Loading Loading @@ -1224,8 +1321,24 @@ assign done_init = state_burst & ~idle & bursts_cnt == (init_bursts_cnt - 1)& assign set_error = idle_len_violation | burst_len_violation; assign set_done = ~set_error & (done_wake | done_init); assign RXCOMINITDET = done_init; assign RXCOMWAKEDET = done_wake; // just to rxcominit(wake)det be synchronous to usrclk2 reg rxcominitdet_clk; reg rxcominitdet_usrclk2; reg rxcomwakedet_clk; reg rxcomwakedet_usrclk2; always @ (posedge clk) begin rxcominitdet_clk <= reset ? 1'b0 : done_init | rxcominitdet_clk & ~rxcominitdet_usrclk2; rxcomwakedet_clk <= reset ? 1'b0 : done_wake | rxcomwakedet_clk & ~rxcomwakedet_usrclk2; end always @ (posedge usrclk2) begin rxcominitdet_usrclk2 <= reset ? 1'b0 : rxcominitdet_clk & ~rxcominitdet_usrclk2; rxcomwakedet_usrclk2 <= reset ? 1'b0 : rxcomwakedet_clk & ~rxcomwakedet_usrclk2; end assign RXCOMINITDET = rxcominitdet_usrclk2; assign RXCOMWAKEDET = rxcomwakedet_usrclk2; assign RXELECIDLE = RXP === 1'bz ? 1'b1 : RXP === 1'bx ? 1'b1 : RXP == RXN; endmodule Loading Loading @@ -1438,6 +1551,8 @@ module gtxe2_chnl_rx_align #( input wire [width - 1:0] indata, output wire [width - 1:0] outdata, input wire rxelecidle, output wire RXBYTEISALIGNED, output wire RXBYTEREALIGN, output wire RXCOMMADET, Loading @@ -1461,6 +1576,29 @@ always @ (posedge clk) // finding matches wire [comma_width - 1:0] comma_window [window_size - 1:0]; //initial // for (idx = 0; idx < window_size; idx = idx + 1) $dumpvars(0, comma_width[idx]); wire [comma_width - 1:0] comma_window0 = comma_window[0]; wire [comma_width - 1:0] comma_window1 = comma_window[1]; wire [comma_width - 1:0] comma_window2 = comma_window[2]; wire [comma_width - 1:0] comma_window3 = comma_window[3]; wire [comma_width - 1:0] comma_window4 = comma_window[4]; wire [comma_width - 1:0] comma_window5 = comma_window[5]; wire [comma_width - 1:0] comma_window6 = comma_window[6]; wire [comma_width - 1:0] comma_window7 = comma_window[7]; wire [comma_width - 1:0] comma_window8 = comma_window[8]; wire [comma_width - 1:0] comma_window9 = comma_window[9]; wire [comma_width - 1:0] comma_window10 = comma_window[10]; wire [comma_width - 1:0] comma_window11 = comma_window[11]; wire [comma_width - 1:0] comma_window12 = comma_window[12]; wire [comma_width - 1:0] comma_window13 = comma_window[13]; wire [comma_width - 1:0] comma_window14 = comma_window[14]; wire [comma_width - 1:0] comma_window15 = comma_window[15]; wire [comma_width - 1:0] comma_window16 = comma_window[16]; wire [comma_width - 1:0] comma_window17 = comma_window[17]; wire [comma_width - 1:0] comma_window18 = comma_window[18]; wire [comma_width - 1:0] comma_window19 = comma_window[19]; wire [window_size - 1:0] comma_match; // shows all matches wire [window_size - 1:0] comma_pos; // shows the first match wire [window_size - 1:0] pcomma_match; Loading Loading @@ -1537,12 +1675,101 @@ assign RXBYTEREALIGN = RXCOMMADETEN & is_aligned & pointer_set; always @ (posedge clk) begin is_aligned <= rst ? 1'b0 : ~is_aligned & pointer_set | is_aligned; is_aligned <= rst | pointer_set === 1'bx | rxelecidle ? 1'b0 : ~is_aligned & pointer_set | is_aligned; pointer_latched <= rst ? 1'b0 : pointer_set ? pointer : pointer_latched; end endmodule /* * According to the doc, p110 * If RX_INT_DATAWIDTH, the inner width = 32 bits, otherwise 16. */ module gtxe2_chnl_rx_dataiface #( parameter internal_data_width = 16, parameter interface_data_width = 32, parameter internal_isk_width = 2, parameter interface_isk_width = 4 ) ( input wire usrclk, input wire usrclk2, input wire reset, output wire [interface_data_width - 1:0] outdata, output wire [interface_isk_width - 1:0] outisk, input wire [internal_data_width - 1:0] indata, input wire [internal_isk_width - 1:0] inisk, input wire realign ); localparam div = interface_data_width / internal_data_width; localparam internal_total_width = internal_data_width + internal_isk_width; localparam interface_total_width = interface_data_width + interface_isk_width; reg [interface_data_width - 1:0] inbuffer_data; reg [interface_isk_width - 1:0] inbuffer_isk; reg [31:0] wordcounter; wire empty_rd; wire full_wr; wire val_wr; wire val_rd; always @ (posedge usrclk) wordcounter <= reset ? 32'h0 : realign & ~(div == 0) ? 31'b1 : wordcounter == (div - 1) ? 32'h0 : wordcounter + 1'b1; genvar ii; generate for (ii = 0; ii < div; ii = ii + 1) begin: splicing always @ (posedge usrclk) inbuffer_data[(ii + 1) * internal_data_width - 1 -: internal_data_width] <= reset ? {interface_data_width{1'b0}} : ((wordcounter == ii) | realign & (0 == ii)) ? indata : inbuffer_data[(ii + 1) * internal_data_width - 1 -: internal_data_width]; end endgenerate generate for (ii = 0; ii < div; ii = ii + 1) begin: splicing2 always @ (posedge usrclk) inbuffer_isk[(ii + 1) * internal_isk_width - 1 -: internal_isk_width] <= reset ? {interface_isk_width{1'b0}} : ((wordcounter == ii) | realign & (0 == ii)) ? inisk : inbuffer_isk[(ii + 1) * internal_isk_width - 1 -: internal_isk_width]; end endgenerate assign val_rd = ~empty_rd & ~almost_empty_rd; assign val_wr = ~full_wr & wordcounter == (div - 1); always @ (posedge usrclk) if (full_wr) begin $display("FIFO in %m is full, that is not an appropriate behaviour"); $finish; end wire [interface_total_width - 1:0] resync; assign outdata = resync[interface_data_width - 1:0]; assign outisk = resync[interface_data_width + interface_isk_width - 1:interface_data_width]; resync_fifo_nonsynt #( .width (interface_total_width), .log_depth (3) ) fifo( .rst_rd (reset), .rst_wr (reset), .clk_wr (usrclk2), .val_wr (val_wr), .data_wr ({inisk, inbuffer_isk[interface_isk_width - internal_isk_width - 1 : 0], indata, inbuffer_data[interface_data_width - internal_data_width - 1 : 0]}), .clk_rd (usrclk2), .val_rd (val_rd), .data_rd (resync), .empty_rd (empty_rd), .full_wr (full_wr), .almost_empty_rd (almost_empty_rd) ); endmodule module gtxe2_chnl_rx( input wire reset, input wire RXP, Loading Loading @@ -1629,6 +1856,7 @@ gtxe2_chnl_rx_oob #( rx_oob( .reset (reset), .clk (serial_clk), .usrclk2 (RXUSRCLK2), .RXN (RXN), .RXP (RXP), Loading Loading @@ -1676,6 +1904,8 @@ aligner( .indata (parallel_data), .outdata (aligned_data), .rxelecidle (RXELECIDLE), .RXBYTEISALIGNED (RXBYTEISALIGNED), .RXBYTEREALIGN (RXBYTEREALIGN), .RXCOMMADET (RXCOMMADET), Loading @@ -1685,6 +1915,8 @@ aligner( .RXMCOMMAALIGNEN (RXMCOMMAALIGNEN) ); wire [data_width - 1:0] internal_data; wire [isk_width - 1:0] internal_isk; // 10x8 decoder gtxe2_chnl_rx_10x8dec #( .iwidth (internal_data_width), Loading @@ -1699,14 +1931,43 @@ decoder_10x8( .RX8B10BEN (RX8B10BEN), .RXCHARISCOMMA (RXCHARISCOMMA), .RXCHARISK (RXCHARISK), .RXCHARISK (internal_isk), .RXDISPERR (RXDISPERR), .RXNOTINTABLE (RXNOTINTABLE), .outdata (), .RXDATA (RXDATA) .RXDATA (internal_data) ); // fit data width // TODO make parameters awesome localparam data_width = 16; localparam if_data_width = 32; localparam isk_width = 2; localparam if_isk_width = 4; gtxe2_chnl_rx_dataiface #( .internal_data_width (data_width), .interface_data_width (if_data_width), .internal_isk_width (isk_width), .interface_isk_width (if_isk_width) ) dataiface ( .usrclk (RXUSRCLK), .usrclk2 (RXUSRCLK2), .reset (reset), .indata (internal_data), .inisk (internal_isk), .outdata (RXDATA[if_data_width - 1:0]), .outisk (RXCHARISK[if_isk_width - 1:0]), .realign (RXBYTEREALIGN === 1'bx ? 1'b0 : RXBYTEREALIGN) ); assign RXDATA[63:if_data_width] = 0; assign RXCHARISK[7:if_isk_width] = 0; endmodule module gtxe2_chnl( Loading Loading @@ -1805,6 +2066,7 @@ module gtxe2_chnl( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -1963,11 +2225,6 @@ gtxe2_chnl_clocking #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), Loading @@ -1989,6 +2246,7 @@ clocking( .TXOUTCLKSEL (TXOUTCLKSEL), .RXOUTCLKSEL (RXOUTCLKSEL), .TXDLYBYPASS (TXDLYBYPASS), .RXDLYBYPASS (RXDLYBYPASS), .GTREFCLKMONITOR (GTREFCLKMONITOR), .CPLLLOCKDETCLK (CPLLLOCKDETCLK), Loading Loading @@ -2080,13 +2338,13 @@ module GTXE2_CHANNEL( input [8:0] DRPADDR, input DRPCLK, input [15:0] DRPDI, input [15:0] DRPDO, output [15:0] DRPDO, input DRPEN, output DRPRDY, input DRPWE, // Digital Monitor Ports, ug476 p.95 input [3:0] CLKRSVD, input [7:0] DMONITOROUT, output [7:0] DMONITOROUT, // TX Interface Ports, ug476 p.110 input [7:0] TXCHARDISPMODE, input [7:0] TXCHARDISPVAL, Loading @@ -2103,7 +2361,7 @@ module GTXE2_CHANNEL( input [6:0] TXSEQUENCE, input TXSTARTSEQ, // TX BUffer Ports, ug476 p.134 input [1:0] TXBUFSTATUS, output [1:0] TXBUFSTATUS, // TX Buffer Bypass Ports, ug476 p.136 input TXDLYSRESET, input TXPHALIGN, Loading @@ -2123,8 +2381,8 @@ module GTXE2_CHANNEL( input TXSYNCMODE, input TXSYNCALLIN, input TXSYNCIN, input TXSYNCOUT, input TXSYNCDONE, output TXSYNCOUT, output TXSYNCDONE, // TX Pattern Generator, ug476 p.147 input [2:0] TXPRBSSEL, input TXPRBSFORCEERR, Loading Loading @@ -2167,7 +2425,7 @@ module GTXE2_CHANNEL( // TX Receiver Detection Ports, ug476 p.165 input TXDETECTRX, output PHYSTATUS, input [2:0] RXSTATUS, output [2:0] RXSTATUS, // TX OOB Signaling Ports, ug476 p.166 output TXCOMFINISH, input TXCOMINIT, Loading Loading @@ -2212,7 +2470,7 @@ module GTXE2_CHANNEL( input RXDFEXYDOVRDEN, input RXDFEXYDEN, input [1:0] RXMONITORSEL, input [6:0] RXMONITOROUT, output [6:0] RXMONITOROUT, // CDR Ports, ug476 p.202 input RXCDRHOLD, input RXCDROVRDEN, Loading Loading @@ -2265,9 +2523,9 @@ module GTXE2_CHANNEL( output RXPHSLIPMONITOR, output RXDLYSRESETDONE, // RX Buffer Ports, ug476 p.259 input [2:0] RXBUFSTATUS, output [2:0] RXBUFSTATUS, // RX Clock Correction Ports, ug476 p.263 input [1:0] RXCLKCORCNT, output [1:0] RXCLKCORCNT, // RX Channel Bonding Ports, ug476 p.274 output RXCHANBONDSEQ, output RXCHANISALIGNED, Loading @@ -2281,7 +2539,7 @@ module GTXE2_CHANNEL( // RX Gearbox Ports, ug476 p.285 output RXDATAVALID, input RXGEARBOXSLIP, input [2:0] RXHEADER, output [2:0] RXHEADER, output RXHEADERVALID, output RXSTARTOFSEQ, // FPGA RX Interface Ports, ug476 p.299 Loading Loading @@ -2551,7 +2809,17 @@ parameter RXGEARBOX_EN = "FALSE"; parameter RX_CLK25_DIV = 6; parameter TX_CLK25_DIV = 6; wire reset = EYESCANRESET | RXCDRFREQRESET | RXCDRRESET | RXCDRRESETRSV | RXPRBSCNTRESET | RXBUFRESET | RXDLYSRESET | RXPHDLYRESET | RXDFELPMRESET | GTRXRESET | RXOOBRESET | RXPCSRESET | RXPMARESET | CFGRESET | GTTXRESET | GTRESETSEL | RESETOVRD | TXDLYSRESET | TXPHDLYRESET | TXPCSRESET | TXPMARESET; // clocking reset ( + TX PMA) wire clk_reset = EYESCANRESET | RXCDRFREQRESET | RXCDRRESET | RXCDRRESETRSV | RXPRBSCNTRESET | RXBUFRESET | RXDLYSRESET | RXPHDLYRESET | RXDFELPMRESET | GTRXRESET | RXOOBRESET | RXPCSRESET | RXPMARESET | CFGRESET | GTTXRESET | GTRESETSEL | RESETOVRD | TXDLYSRESET | TXPHDLYRESET | TXPCSRESET | TXPMARESET; // have to wait before an external pll (mmcm) locks with usrclk, after that PCS can be resetted. Actually, we reset PMA also, because why not reg reset; reg [31:0] reset_timer = 0; always @ (posedge TXUSRCLK) reset_timer <= ~TXUSERRDY ? 32'h0 : reset_timer == 32'hffffffff ? reset_timer : reset_timer + 1'b1; always @ (posedge TXUSRCLK) reset <= ~TXUSERRDY ? 1'b0 : reset_timer < 32'd20 ? 1'b1 : 1'b0; reg rx_rst_done = 1'b0; reg tx_rst_done = 1'b0; Loading Loading @@ -2588,11 +2856,6 @@ gtxe2_chnl #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), Loading @@ -2614,8 +2877,7 @@ gtxe2_chnl #( .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .PTX8B10BEN (1), .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN), .SATA_CPLL_CFG (SATA_CPLL_CFG) .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN) ) channel( .reset (reset), Loading
gtxe2_channel/GTXE2_CHANNEL_GPL.v +23 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes
gtxe2_channel/gtxe2_chnl.v +5 −8 Original line number Diff line number Diff line Loading @@ -18,9 +18,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_clocking.v" //`include "gtxe2_chnl_tx.v" //`include "gtxe2_chnl_rx.v" `include "gtxe2_chnl_clocking.v" `include "gtxe2_chnl_tx.v" `include "gtxe2_chnl_rx.v" module gtxe2_chnl( input wire reset, /* Loading Loading @@ -117,6 +117,7 @@ module gtxe2_chnl( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -275,11 +276,6 @@ gtxe2_chnl_clocking #( .SATA_CPLL_CFG (SATA_CPLL_CFG), .PMA_RSV3 (PMA_RSV3), .TXOUT_DIV (TXOUT_DIV), // .TXRATE (TXRATE), .RXOUT_DIV (RXOUT_DIV), // .RXRATE (RXRATE), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), Loading @@ -301,6 +297,7 @@ clocking( .TXOUTCLKSEL (TXOUTCLKSEL), .RXOUTCLKSEL (RXOUTCLKSEL), .TXDLYBYPASS (TXDLYBYPASS), .RXDLYBYPASS (RXDLYBYPASS), .GTREFCLKMONITOR (GTREFCLKMONITOR), .CPLLLOCKDETCLK (CPLLLOCKDETCLK), Loading
gtxe2_channel/gtxe2_chnl_clocking.v +6 −4 Original line number Diff line number Diff line Loading @@ -19,10 +19,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_cpll_inmux.v" //`include "gtxe2_chnl_outclk_mux.v" //`include "gtxe2_chnl_cpll.v" //`include "clock_divider.v" `include "gtxe2_chnl_cpll_inmux.v" `include "gtxe2_chnl_outclk_mux.v" `include "gtxe2_chnl_cpll.v" `include "clock_divider.v" module gtxe2_chnl_clocking( // top-level interfaces input wire [2:0] CPLLREFCLKSEL, Loading @@ -40,6 +40,7 @@ module gtxe2_chnl_clocking( input wire [2:0] TXOUTCLKSEL, input wire [2:0] RXOUTCLKSEL, input wire TXDLYBYPASS, input wire RXDLYBYPASS, output wire GTREFCLKMONITOR, input wire CPLLLOCKDETCLK, Loading Loading @@ -147,6 +148,7 @@ tx_toserialclk_div( .div (tx_serial_divider) ); wire rx_sipo_clk; clock_divider #( // .divide_by (rx_serial_divider), .divide_by_param (0) Loading
gtxe2_channel/gtxe2_chnl_cpll.v +1 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ //`include "gtxe2_chnl_cpll_def.v" `include "gtxe2_chnl_cpll_def.v" module gtxe2_chnl_cpll( // top-level interfaces input wire CPLLLOCKDETCLK, Loading