Commit c4c7e576 authored by Alexey Grebenkin's avatar Alexey Grebenkin

Ability to bypass aligner and 8/10 enc/dec added, flexible widths support

parent 9aabc22e
This diff is collapsed.
...@@ -613,7 +613,6 @@ gtxe2_chnl #( ...@@ -613,7 +613,6 @@ gtxe2_chnl #(
.RX_DATA_WIDTH (RX_DATA_WIDTH), .RX_DATA_WIDTH (RX_DATA_WIDTH),
.RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH),
.PRX8B10BEN (1),
.DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT), .DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT),
.DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT), .DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT),
...@@ -627,7 +626,6 @@ gtxe2_chnl #( ...@@ -627,7 +626,6 @@ gtxe2_chnl #(
.TX_DATA_WIDTH (TX_DATA_WIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH),
.TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH),
.PTX8B10BEN (1),
.SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN) .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN)
) )
......
...@@ -156,11 +156,9 @@ parameter RXOUT_DIV = 2; ...@@ -156,11 +156,9 @@ parameter RXOUT_DIV = 2;
parameter integer TX_INT_DATAWIDTH = 0; parameter integer TX_INT_DATAWIDTH = 0;
parameter integer TX_DATA_WIDTH = 20; parameter integer TX_DATA_WIDTH = 20;
parameter integer PTX8B10BEN = 1;
parameter integer RX_DATA_WIDTH = 20; parameter integer RX_DATA_WIDTH = 20;
parameter integer RX_INT_DATAWIDTH = 0; parameter integer RX_INT_DATAWIDTH = 0;
parameter integer PRX8B10BEN = 1;
parameter DEC_MCOMMA_DETECT = "TRUE"; parameter DEC_MCOMMA_DETECT = "TRUE";
parameter DEC_PCOMMA_DETECT = "TRUE"; parameter DEC_PCOMMA_DETECT = "TRUE";
...@@ -179,7 +177,6 @@ parameter SATA_CPLL_CFG = "VCO_3000MHZ"; ...@@ -179,7 +177,6 @@ parameter SATA_CPLL_CFG = "VCO_3000MHZ";
gtxe2_chnl_tx #( gtxe2_chnl_tx #(
.TX_DATA_WIDTH (TX_DATA_WIDTH), .TX_DATA_WIDTH (TX_DATA_WIDTH),
.TX_INT_DATAWIDTH (TX_INT_DATAWIDTH), .TX_INT_DATAWIDTH (TX_INT_DATAWIDTH),
.PTX8B10BEN (PTX8B10BEN),
.SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN), .SATA_BURST_SEQ_LEN (SATA_BURST_SEQ_LEN),
.SATA_CPLL_CFG (SATA_CPLL_CFG) .SATA_CPLL_CFG (SATA_CPLL_CFG)
) )
...@@ -217,7 +214,6 @@ tx( ...@@ -217,7 +214,6 @@ tx(
gtxe2_chnl_rx #( gtxe2_chnl_rx #(
.RX_DATA_WIDTH (RX_DATA_WIDTH), .RX_DATA_WIDTH (RX_DATA_WIDTH),
.RX_INT_DATAWIDTH (RX_INT_DATAWIDTH), .RX_INT_DATAWIDTH (RX_INT_DATAWIDTH),
.PRX8B10BEN (PRX8B10BEN),
.DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT), .DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT),
.DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT), .DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT),
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
/** /**
* For now contains only deserializer, oob, 10x8 decoder, aligner and polarity invertor blocks * For now contains only deserializer, oob, 10x8 decoder, aligner and polarity invertor blocks
**/ **/
// TODO resync all output signals
`include "gtxe2_chnl_rx_des.v" `include "gtxe2_chnl_rx_des.v"
`include "gtxe2_chnl_rx_oob.v" `include "gtxe2_chnl_rx_oob.v"
`include "gtxe2_chnl_rx_10x8dec.v" `include "gtxe2_chnl_rx_10x8dec.v"
...@@ -70,7 +71,6 @@ module gtxe2_chnl_rx( ...@@ -70,7 +71,6 @@ module gtxe2_chnl_rx(
parameter integer RX_DATA_WIDTH = 20; parameter integer RX_DATA_WIDTH = 20;
parameter integer RX_INT_DATAWIDTH = 0; parameter integer RX_INT_DATAWIDTH = 0;
parameter integer PRX8B10BEN = 1;
parameter DEC_MCOMMA_DETECT = "TRUE"; parameter DEC_MCOMMA_DETECT = "TRUE";
parameter DEC_PCOMMA_DETECT = "TRUE"; parameter DEC_PCOMMA_DETECT = "TRUE";
...@@ -83,27 +83,29 @@ parameter [9:0] ALIGN_COMMA_ENABLE = 10'b1111111111; ...@@ -83,27 +83,29 @@ parameter [9:0] ALIGN_COMMA_ENABLE = 10'b1111111111;
parameter ALIGN_COMMA_DOUBLE = "FALSE"; parameter ALIGN_COMMA_DOUBLE = "FALSE";
function integer calc_idw; function integer calc_idw;
input RX8B10BEN; input dummy;
input RX_INT_DATAWIDTH;
input RX_DATA_WIDTH;
begin begin
if (RX8B10BEN == 1) calc_idw = RX_INT_DATAWIDTH == 1 ? 40 : 20;
calc_idw = RX_INT_DATAWIDTH == 1 ? 40 : 20;
else
begin
if (RX_INT_DATAWIDTH == 1)
calc_idw = RX_DATA_WIDTH == 32 ? 32
: RX_DATA_WIDTH == 40 ? 40
: RX_DATA_WIDTH == 64 ? 32 : 40;
else
calc_idw = RX_DATA_WIDTH == 16 ? 16
: RX_DATA_WIDTH == 20 ? 20
: RX_DATA_WIDTH == 32 ? 16 : 20;
end
end end
endfunction endfunction
localparam internal_data_width = calc_idw(PRX8B10BEN, RX_INT_DATAWIDTH, RX_DATA_WIDTH); function integer calc_ifdw;
input dummy;
begin
calc_ifdw = RX_DATA_WIDTH == 16 ? 20 :
RX_DATA_WIDTH == 32 ? 40 :
RX_DATA_WIDTH == 64 ? 80 : RX_DATA_WIDTH;
end
endfunction
// can be 20 or 40, if it shall be 16 or 32, extra bits wont be used
localparam internal_data_width = calc_idw(1);
localparam interface_data_width = calc_ifdw(1);
localparam internal_isk_width = internal_data_width / 10;
localparam interface_isk_width = interface_data_width / 10;
// used in case of TX8B10BEN = 0
localparam data_width_odd = RX_DATA_WIDTH == 16 | RX_DATA_WIDTH == 32 | RX_DATA_WIDTH == 64;
// OOB // OOB
gtxe2_chnl_rx_oob #( gtxe2_chnl_rx_oob #(
...@@ -131,12 +133,13 @@ assign indata_ser = RXPOLARITY ^ RXP; ...@@ -131,12 +133,13 @@ assign indata_ser = RXPOLARITY ^ RXP;
// due to non-syntasisable usage, CDR is missing // due to non-syntasisable usage, CDR is missing
// deserializer // deserializer
wire [internal_data_width - 1:0] parallel_data; wire [internal_data_width - 1:0] parallel_data; // in trimmed case highest bites shall be 'x'
gtxe2_chnl_rx_des #( gtxe2_chnl_rx_des #(
.width (internal_data_width) .width (internal_data_width)
) )
des( des(
.reset (reset), .reset (reset),
.trim (data_width_odd & ~RX8B10BEN),
.inclk (serial_clk), .inclk (serial_clk),
.outclk (RXUSRCLK), .outclk (RXUSRCLK),
.indata (indata_ser), .indata (indata_ser),
...@@ -171,12 +174,19 @@ aligner( ...@@ -171,12 +174,19 @@ aligner(
.RXMCOMMAALIGNEN (RXMCOMMAALIGNEN) .RXMCOMMAALIGNEN (RXMCOMMAALIGNEN)
); );
wire [data_width - 1:0] internal_data; localparam iface_databus_width = interface_data_width * 8 / 10;
wire [isk_width - 1:0] internal_isk; localparam intern_databus_width = internal_data_width * 8 / 10;
wire [intern_databus_width - 1:0] internal_data;
wire [internal_isk_width - 1:0] internal_isk;
wire [internal_isk_width - 1:0] internal_chariscomma;
wire [internal_isk_width - 1:0] internal_notintable;
wire [internal_isk_width - 1:0] internal_disperr;
// 10x8 decoder // 10x8 decoder
gtxe2_chnl_rx_10x8dec #( gtxe2_chnl_rx_10x8dec #(
.iwidth (internal_data_width), .iwidth (internal_data_width),
.owidth (RX_DATA_WIDTH), .iskwidth (internal_isk_width),
.owidth (intern_databus_width),
.DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT), .DEC_MCOMMA_DETECT (DEC_MCOMMA_DETECT),
.DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT) .DEC_PCOMMA_DETECT (DEC_PCOMMA_DETECT)
) )
...@@ -185,43 +195,61 @@ decoder_10x8( ...@@ -185,43 +195,61 @@ decoder_10x8(
.rst (reset), .rst (reset),
.indata (aligned_data), .indata (aligned_data),
.RX8B10BEN (RX8B10BEN), .RX8B10BEN (RX8B10BEN),
.data_width_odd (data_width_odd),
.RXCHARISCOMMA (RXCHARISCOMMA), .rxchariscomma (internal_chariscomma),
.RXCHARISK (internal_isk), .rxcharisk (internal_isk),
.RXDISPERR (RXDISPERR), .rxdisperr (internal_disperr),
.RXNOTINTABLE (RXNOTINTABLE), .rxnotintable (internal_notintable),
.outdata (), .outdata (internal_data)
.RXDATA (internal_data)
); );
// fit data width // 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;
localparam outdiv = interface_data_width / internal_data_width;
// if something is written into dataiface_data_in _except_ internal_data and internal_isk => count all extra bits in this parameter
localparam internal_data_extra = 4;
localparam interface_data_extra = outdiv * internal_data_extra;
wire [interface_data_width - 1 + interface_data_extra:0] dataiface_data_out;
wire [internal_data_width - 1 + internal_data_extra:0] dataiface_data_in;
assign dataiface_data_in = {internal_notintable, internal_chariscomma, internal_disperr, internal_isk, internal_data};
genvar ii;
generate
for (ii = 1; ii < (outdiv + 1); ii = ii + 1)
begin: asdadfdsf
assign RXDATA[ii*intern_databus_width - 1 -: intern_databus_width] = dataiface_data_out[(ii-1)*(internal_data_width + internal_data_extra) + intern_databus_width - 1 -: intern_databus_width];
assign RXCHARISK[ii*internal_isk_width - 1 -: internal_isk_width] = dataiface_data_out[(ii-1)*(internal_data_width + internal_data_extra) + intern_databus_width - 1 + internal_isk_width -: internal_isk_width];
assign RXDISPERR[ii*internal_isk_width - 1 -: internal_isk_width] = dataiface_data_out[(ii-1)*(internal_data_width + internal_data_extra) + intern_databus_width - 1 + internal_isk_width*2 -: internal_isk_width];
assign RXCHARISCOMMA[ii*internal_isk_width - 1 -: internal_isk_width] = dataiface_data_out[(ii-1)*(internal_data_width + internal_data_extra) + intern_databus_width - 1 + internal_isk_width*3 -: internal_isk_width];
assign RXNOTINTABLE[ii*internal_isk_width - 1 -: internal_isk_width] = dataiface_data_out[(ii-1)*(internal_data_width + internal_data_extra) + intern_databus_width - 1 + internal_isk_width*4 -: internal_isk_width];
end
endgenerate
assign RXDATA[63:iface_databus_width] = {64 - iface_databus_width{1'bx}};
assign RXDISPERR[7:interface_isk_width] = {7 - interface_isk_width{1'bx}};
assign RXCHARISK[7:interface_isk_width] = {7 - interface_isk_width{1'bx}};
assign RXCHARISCOMMA[7:interface_isk_width] = {7 - interface_isk_width{1'bx}};
assign RXNOTINTABLE[7:interface_isk_width] = {7 - interface_isk_width{1'bx}};
gtxe2_chnl_rx_dataiface #( gtxe2_chnl_rx_dataiface #(
.internal_data_width (data_width), .internal_data_width (internal_data_width + internal_data_extra),
.interface_data_width (if_data_width), .interface_data_width (interface_data_width + interface_data_extra),
.internal_isk_width (isk_width), .internal_isk_width (internal_isk_width),
.interface_isk_width (if_isk_width) .interface_isk_width (interface_isk_width)
) )
dataiface dataiface
( (
.usrclk (RXUSRCLK), .usrclk (RXUSRCLK),
.usrclk2 (RXUSRCLK2), .usrclk2 (RXUSRCLK2),
.reset (reset), .reset (reset),
.indata (internal_data), .indata (dataiface_data_in),
.inisk (internal_isk), .inisk (internal_isk), // not used actually
.outdata (RXDATA[if_data_width - 1:0]), .outdata (dataiface_data_out),
.outisk (RXCHARISK[if_isk_width - 1:0]), .outisk (),
.realign (RXBYTEREALIGN === 1'bx ? 1'b0 : RXBYTEREALIGN) .realign (RXBYTEREALIGN === 1'bx ? 1'b0 : RXBYTEREALIGN)
); );
assign RXDATA[63:if_data_width] = 0;
assign RXCHARISK[7:if_isk_width] = 0;
endmodule endmodule
...@@ -21,26 +21,29 @@ ...@@ -21,26 +21,29 @@
// always enabled, wasnt tested with width parameters, disctinct from 20 // always enabled, wasnt tested with width parameters, disctinct from 20
module gtxe2_chnl_rx_10x8dec #( module gtxe2_chnl_rx_10x8dec #(
parameter iwidth = 20, parameter iwidth = 20,
parameter iskwidth = 2,
parameter owidth = 20, parameter owidth = 20,
parameter DEC_MCOMMA_DETECT = "TRUE", parameter DEC_MCOMMA_DETECT = "TRUE",
parameter DEC_PCOMMA_DETECT = "TRUE" parameter DEC_PCOMMA_DETECT = "TRUE"
) )
( (
input wire clk, input wire clk,
input wire rst, input wire rst,
input wire [iwidth - 1:0] indata, input wire [iwidth - 1:0] indata,
input wire RX8B10BEN, input wire RX8B10BEN,
input wire data_width_odd,
output wire [7:0] RXCHARISCOMMA,
output wire [7:0] RXCHARISK, output wire [iskwidth - 1:0] rxchariscomma,
output wire [7:0] RXDISPERR, output wire [iskwidth - 1:0] rxcharisk,
output wire [7:0] RXNOTINTABLE, output wire [iskwidth - 1:0] rxdisperr,
output wire [iskwidth - 1:0] rxnotintable,
output wire [owidth - 1:0] outdata,
output wire [63:0] RXDATA output wire [owidth - 1:0] outdata
); );
wire [iskwidth - 1:0] rxcharisk_dec;
wire [iskwidth - 1:0] rxdisperr_dec;
wire [owidth - 1:0] outdata_dec;
localparam word_count = iwidth / 10; localparam word_count = iwidth / 10;
localparam add_2out_bits = owidth == 20 | owidth == 40 | owidth == 80 ? "TRUE" : "FALSE"; localparam add_2out_bits = owidth == 20 | owidth == 40 | owidth == 80 ? "TRUE" : "FALSE";
...@@ -63,7 +66,7 @@ begin: asdf ...@@ -63,7 +66,7 @@ begin: asdf
//data = {1'(is in table) + 3'(decoded 4/3) + 1'(is in table) + 5'(decoded 6/5)} //data = {1'(is in table) + 3'(decoded 4/3) + 1'(is in table) + 5'(decoded 6/5)}
//6/5 decoding //6/5 decoding
assign data[ii*10+5:ii*10] = RXCHARISK[ii] ? ( assign data[ii*10+5:ii*10] = rxcharisk_dec[ii] ? (
indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 ? 6'b011100 : indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 ? 6'b011100 :
indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 ? 6'b011100 : indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 ? 6'b011100 :
indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 ? 6'b011100 : indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 ? 6'b011100 :
...@@ -124,7 +127,7 @@ begin: asdf ...@@ -124,7 +127,7 @@ begin: asdf
indata[ii*10 + 5:ii*10] == 6'b011110 | indata[ii*10 + 5:ii*10] == 6'b100001 ? 6'b011110 :*/ indata[ii*10 + 5:ii*10] == 6'b011110 | indata[ii*10 + 5:ii*10] == 6'b100001 ? 6'b011110 :*/
6'b100000); // not in a table 6'b100000); // not in a table
//4/3 decoding //4/3 decoding
assign data[ii*10+ 9:ii*10+ 6] = RXCHARISK[ii] ? ( assign data[ii*10+ 9:ii*10+ 6] = rxcharisk_dec[ii] ? (
indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 ? 4'b0000 : indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 ? 4'b0000 :
indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 ? 4'b0001 : indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 ? 4'b0001 :
indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 ? 4'b0010 : indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 ? 4'b0010 :
...@@ -164,41 +167,52 @@ begin: asdf ...@@ -164,41 +167,52 @@ begin: asdf
assign pure_data[ii*8 + 7:ii*8] = {data[ii*10 + 8:ii*10 + 6], data[ii*10 + 4:ii*10]}; assign pure_data[ii*8 + 7:ii*8] = {data[ii*10 + 8:ii*10 + 6], data[ii*10 + 4:ii*10]};
if (add_2out_bits == "TRUE") assign outdata_dec[ii*8 + 7:ii*8] = pure_data[ii*8 + 7:ii*8];
assign outdata[ii*10 + 9:ii*10]= {RXDISPERR[ii], RXCHARISK[ii], pure_data[ii*8 + 7:ii*8]};
else assign outdata[ii*8 + 7:ii*8] = RX8B10BEN ? outdata_dec[ii*8 + 7:ii*8] : ~data_width_odd ? indata[ii*10 + 7:ii*10] : indata[ii*8 + 7:ii*8];
assign outdata[ii*8 + 7:ii*8] = pure_data[ii*8 + 7:ii*8]; assign rxcharisk[ii] = RX8B10BEN ? rxcharisk_dec[ii] : ~data_width_odd ? indata[ii*10 + 8] : 1'bx;
assign rxdisperr[ii] = RX8B10BEN ? rxdisperr_dec[ii] : ~data_width_odd ? indata[ii*10 + 9] : 1'bx;
/* if (RX8B10BEN) begin
end
else
if (data_width_odd) begin
assign outdata[ii*8 + 7:ii*8] = indata[ii*8 + 7:ii*8];
assign rxcharisk[ii] = 1'bx;
assign rxdisperr[ii] = 1'bx;
end
else begin
assign outdata[ii*8 + 7:ii*8] = indata[ii*10 + 7:ii*10];
assign rxcharisk[ii] = indata[ii*10 + 8];
assign rxdisperr[ii] = indata[ii*10 + 9];
end*/
end end
endgenerate endgenerate
//disperr[ii] = no_disp_word[ii] ? 1'b0 : ~disp_word[ii] ^ disp[ii-1];
//disp[ii] = no_disp_word[ii] ? disp[ii-1] : disp_word[ii]
assign disp_err = ~no_disp_word & (~disp_word ^ {disp[word_count - 2:0], disp_init}); assign disp_err = ~no_disp_word & (~disp_word ^ {disp[word_count - 2:0], disp_init});
assign disp = ~no_disp_word & disp_word | no_disp_word & {disp[word_count - 2:0], disp_init}; assign disp = ~no_disp_word & disp_word | no_disp_word & {disp[word_count - 2:0], disp_init};
generate generate
for (ii = 0; ii < 8; ii = ii + 1) for (ii = 0; ii < word_count; ii = ii + 1)
begin:dfsga begin:dfsga
assign RXDATA[ii*8+7:ii*8] = ii >= word_count ? 8'h0 : pure_data[ii*8+7:ii*8]; assign rxnotintable[ii] = ii >= word_count ? 1'b0 : data[ii*10 + 9] | data[ii*10 + 5];
assign RXNOTINTABLE[ii] = ii >= word_count ? 1'b0 : data[ii*10 + 9] | data[ii*10 + 5];
assign rxdisperr_dec[ii] = ii >= word_count ? 1'b0 : disp_err[ii];
assign RXDISPERR[ii] = ii >= word_count ? 1'b0 : disp_err[ii]; assign rxcharisk_dec[ii] = ii >= word_count ? 1'b0 :
assign RXCHARISK[ii] = ii >= word_count ? 1'b0 : indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 |
indata[ii*10 + 9:ii*10] == 10'b0010111100 | indata[ii*10 + 9:ii*10] == 10'b1101000011 | indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 |
indata[ii*10 + 9:ii*10] == 10'b1001111100 | indata[ii*10 + 9:ii*10] == 10'b0110000011 | indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 |
indata[ii*10 + 9:ii*10] == 10'b1010111100 | indata[ii*10 + 9:ii*10] == 10'b0101000011 | indata[ii*10 + 9:ii*10] == 10'b1100111100 | indata[ii*10 + 9:ii*10] == 10'b0011000011 |
indata[ii*10 + 9:ii*10] == 10'b1100111100 | indata[ii*10 + 9:ii*10] == 10'b0011000011 | indata[ii*10 + 9:ii*10] == 10'b0100111100 | indata[ii*10 + 9:ii*10] == 10'b1011000011 |
indata[ii*10 + 9:ii*10] == 10'b0100111100 | indata[ii*10 + 9:ii*10] == 10'b1011000011 | indata[ii*10 + 9:ii*10] == 10'b0101111100 | indata[ii*10 + 9:ii*10] == 10'b1010000011 |
indata[ii*10 + 9:ii*10] == 10'b0101111100 | indata[ii*10 + 9:ii*10] == 10'b1010000011 | indata[ii*10 + 9:ii*10] == 10'b0110111100 | indata[ii*10 + 9:ii*10] == 10'b1001000011 |
indata[ii*10 + 9:ii*10] == 10'b0110111100 | indata[ii*10 + 9:ii*10] == 10'b1001000011 | indata[ii*10 + 9:ii*10] == 10'b0001111100 | indata[ii*10 + 9:ii*10] == 10'b1110000011 |
indata[ii*10 + 9:ii*10] == 10'b0001111100 | indata[ii*10 + 9:ii*10] == 10'b1110000011 | indata[ii*10 + 9:ii*10] == 10'b0001010111 | indata[ii*10 + 9:ii*10] == 10'b1110101000 |
indata[ii*10 + 9:ii*10] == 10'b0001010111 | indata[ii*10 + 9:ii*10] == 10'b1110101000 | indata[ii*10 + 9:ii*10] == 10'b0001011011 | indata[ii*10 + 9:ii*10] == 10'b1110100100 |
indata[ii*10 + 9:ii*10] == 10'b0001011011 | indata[ii*10 + 9:ii*10] == 10'b1110100100 | indata[ii*10 + 9:ii*10] == 10'b0001011101 | indata[ii*10 + 9:ii*10] == 10'b1110100010 |
indata[ii*10 + 9:ii*10] == 10'b0001011101 | indata[ii*10 + 9:ii*10] == 10'b1110100010 | indata[ii*10 + 9:ii*10] == 10'b0001011110 | indata[ii*10 + 9:ii*10] == 10'b1110100001;
indata[ii*10 + 9:ii*10] == 10'b0001011110 | indata[ii*10 + 9:ii*10] == 10'b1110100001;
assign rxchariscomma[ii] = ii >= word_count ? 1'b0 :
assign RXCHARISCOMMA[ii] = ii >= word_count ? 1'b0 :
(indata[ii*10 + 9:ii*10] == 10'b1001111100 | (indata[ii*10 + 9:ii*10] == 10'b1001111100 |
indata[ii*10 + 9:ii*10] == 10'b0101111100 | indata[ii*10 + 9:ii*10] == 10'b0101111100 |
indata[ii*10 + 9:ii*10] == 10'b0001111100) & DEC_PCOMMA_DETECT | indata[ii*10 + 9:ii*10] == 10'b0001111100) & DEC_PCOMMA_DETECT |
......
...@@ -85,6 +85,14 @@ wire [interface_total_width - 1:0] resync; ...@@ -85,6 +85,14 @@ wire [interface_total_width - 1:0] resync;
assign outdata = resync[interface_data_width - 1:0]; assign outdata = resync[interface_data_width - 1:0];
assign outisk = resync[interface_data_width + interface_isk_width - 1:interface_data_width]; assign outisk = resync[interface_data_width + interface_isk_width - 1:interface_data_width];
wire [interface_total_width - 1:0] data_wr;
generate
if (interface_data_width > internal_data_width)
assign data_wr = {inisk, inbuffer_isk[interface_isk_width - internal_isk_width - 1 : 0], indata, inbuffer_data[interface_data_width - internal_data_width - 1 : 0]};
else
assign data_wr = {inisk, indata};
endgenerate
resync_fifo_nonsynt #( resync_fifo_nonsynt #(
.width (interface_total_width), .width (interface_total_width),
.log_depth (3) .log_depth (3)
...@@ -92,9 +100,9 @@ resync_fifo_nonsynt #( ...@@ -92,9 +100,9 @@ resync_fifo_nonsynt #(
fifo( fifo(
.rst_rd (reset), .rst_rd (reset),
.rst_wr (reset), .rst_wr (reset),
.clk_wr (usrclk2), .clk_wr (usrclk),
.val_wr (val_wr), .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]}), .data_wr (data_wr),
.clk_rd (usrclk2), .clk_rd (usrclk2),
.val_rd (val_rd), .val_rd (val_rd),
.data_rd (resync), .data_rd (resync),
......
...@@ -24,28 +24,37 @@ module gtxe2_chnl_rx_des #( ...@@ -24,28 +24,37 @@ module gtxe2_chnl_rx_des #(
) )
( (
input wire reset, input wire reset,
input wire trim,
input wire inclk, input wire inclk,
input wire outclk, input wire outclk,
input wire indata, input wire indata,
output wire [width - 1:0] outdata output wire [width - 1:0] outdata
); );
localparam trimmed_width = width * 4 / 5;
reg [31:0] bitcounter; reg [31:0] bitcounter;
reg [width - 1:0] inbuffer; reg [width - 1:0] inbuffer;
wire empty_rd; wire empty_rd;
wire full_wr; wire full_wr;
wire val_wr; wire val_wr;
wire val_rd; wire val_rd;
wire bitcounter_limit;
assign bitcounter_limit = trim ? bitcounter == (trimmed_width - 1) : bitcounter == (width - 1);
always @ (posedge inclk) always @ (posedge inclk)
bitcounter <= reset | bitcounter == (width - 1) ? 32'h0 : bitcounter + 1'b1; bitcounter <= reset | bitcounter_limit ? 32'h0 : bitcounter + 1'b1;
genvar ii; genvar ii;
generate generate
for (ii = 0; ii < width; ii = ii + 1) for (ii = 0; ii < width; ii = ii + 1)
begin: splicing begin: splicing
always @ (posedge inclk) always @ (posedge inclk)
inbuffer[ii] <= reset ? 1'b0 : (bitcounter == ii) ? indata : inbuffer[ii]; if ((ii >= trimmed_width) & trim)
inbuffer[ii] <= 1'bx;
else
inbuffer[ii] <= reset ? 1'b0 : (bitcounter == ii) ? indata : inbuffer[ii];
end end
endgenerate endgenerate
......
...@@ -132,10 +132,10 @@ assign set_error = idle_len_violation | burst_len_violation; ...@@ -132,10 +132,10 @@ assign set_error = idle_len_violation | burst_len_violation;
assign set_done = ~set_error & (done_wake | done_init); assign set_done = ~set_error & (done_wake | done_init);
// just to rxcominit(wake)det be synchronous to usrclk2 // just to rxcominit(wake)det be synchronous to usrclk2
reg rxcominitdet_clk; reg rxcominitdet_clk = 1'b0;
reg rxcominitdet_usrclk2; reg rxcominitdet_usrclk2 = 1'b0;
reg rxcomwakedet_clk; reg rxcomwakedet_clk = 1'b0;
reg rxcomwakedet_usrclk2; reg rxcomwakedet_usrclk2 = 1'b0;
always @ (posedge clk) always @ (posedge clk)
begin begin
rxcominitdet_clk <= reset ? 1'b0 : done_init | rxcominitdet_clk & ~rxcominitdet_usrclk2; rxcominitdet_clk <= reset ? 1'b0 : done_init | rxcominitdet_clk & ~rxcominitdet_usrclk2;
......
...@@ -62,7 +62,6 @@ module gtxe2_chnl_tx( ...@@ -62,7 +62,6 @@ module gtxe2_chnl_tx(
); );
parameter TX_DATA_WIDTH = 20; parameter TX_DATA_WIDTH = 20;
parameter TX_INT_DATAWIDTH = 0; parameter TX_INT_DATAWIDTH = 0;
parameter PTX8B10BEN = 1;
parameter [3:0] SATA_BURST_SEQ_LEN = 4'b1111; parameter [3:0] SATA_BURST_SEQ_LEN = 4'b1111;
parameter SATA_CPLL_CFG = "VCO_3000MHZ"; parameter SATA_CPLL_CFG = "VCO_3000MHZ";
...@@ -72,9 +71,9 @@ function integer calc_idw; ...@@ -72,9 +71,9 @@ function integer calc_idw;
// input TX_INT_DATAWIDTH; // input TX_INT_DATAWIDTH;
// input TX_DATA_WIDTH; // input TX_DATA_WIDTH;
begin begin
if (TX8B10BEN == 1) // if (TX8B10BEN == 1)
calc_idw = TX_INT_DATAWIDTH == 1 ? 40 : 20; calc_idw = TX_INT_DATAWIDTH == 1 ? 40 : 20;
else /* else
begin begin
if (TX_INT_DATAWIDTH == 1) if (TX_INT_DATAWIDTH == 1)
calc_idw = TX_DATA_WIDTH == 32 ? 32 calc_idw = TX_DATA_WIDTH == 32 ? 32
...@@ -84,12 +83,38 @@ function integer calc_idw; ...@@ -84,12 +83,38 @@ function integer calc_idw;
calc_idw = TX_DATA_WIDTH == 16 ? 16 calc_idw = TX_DATA_WIDTH == 16 ? 16
: TX_DATA_WIDTH == 20 ? 20 : TX_DATA_WIDTH == 20 ? 20
: TX_DATA_WIDTH == 32 ? 16 : 20; : TX_DATA_WIDTH == 32 ? 16 : 20;
end end*/
end end
endfunction endfunction
localparam internal_data_width = calc_idw(PTX8B10BEN);//, TX_INT_DATAWIDTH, TX_DATA_WIDTH); function integer calc_ifdw;
input TX8B10BEN;
begin
// if (TX8B10BEN == 1)
calc_ifdw = TX_DATA_WIDTH == 16 ? 20 :
TX_DATA_WIDTH == 32 ? 40 :
TX_DATA_WIDTH == 64 ? 80 : TX_DATA_WIDTH;
/* else
begin
if (TX_INT_DATAWIDTH == 1)
calc_ifdw = TX_DATA_WIDTH == 32 ? 32
: TX_DATA_WIDTH == 40 ? 40
: TX_DATA_WIDTH == 64 ? 64 : 80;
else
calc_ifdw = TX_DATA_WIDTH == 16 ? 16
: TX_DATA_WIDTH == 20 ? 20
: TX_DATA_WIDTH == 32 ? 16 : 20;
end*/
end
endfunction
// can be 20 or 40, if it shall be 16 or 32, extra bits wont be used
localparam internal_data_width = calc_idw(1);//PTX8B10BEN);//, TX_INT_DATAWIDTH, TX_DATA_WIDTH);
localparam interface_data_width = calc_ifdw(1);
localparam internal_isk_width = internal_data_width / 10;
localparam interface_isk_width = interface_data_width / 10;
// used in case of TX8B10BEN = 0
localparam data_width_odd = TX_DATA_WIDTH == 16 | TX_DATA_WIDTH == 32 | TX_DATA_WIDTH == 64;
// TX PMA // TX PMA
// serializer // serializer
...@@ -117,6 +142,7 @@ gtxe2_chnl_tx_ser #( ...@@ -117,6 +142,7 @@ gtxe2_chnl_tx_ser #(
) )
ser( ser(
.reset (reset), .reset (reset),
.trim (data_width_odd & ~TX8B10BEN),
.inclk (TXUSRCLK), .inclk (TXUSRCLK),
.outclk (serial_clk), .outclk (serial_clk),
.indata (inv_parallel_data), .indata (inv_parallel_data),
...@@ -128,32 +154,50 @@ ser( ...@@ -128,32 +154,50 @@ ser(
// TX PCS // TX PCS
// fit data width // fit data width
// TODO make parameters awesome localparam iface_databus_width = interface_data_width * 8 / 10;
localparam data_width = 16; localparam intern_databus_width = internal_data_width * 8 / 10;
localparam if_data_width = 32;
localparam isk_width = 2; wire [intern_databus_width - 1:0] internal_data;
localparam if_isk_width = 4; wire [internal_isk_width - 1:0] internal_isk;
wire [internal_isk_width - 1:0] internal_dispval;
wire [internal_isk_width - 1:0] internal_dispmode;
wire [internal_data_width - 1:0] dataiface_data_out;
wire [interface_data_width - 1:0] dataiface_data_in;
//assign dataiface_data_in = {TXCHARDISPMODE[interface_isk_width - 1:0], TXCHARDISPVAL[interface_isk_width - 1:0], TXDATA[iface_databus_width - 1:0]};
localparam outdiv = interface_data_width / internal_data_width;
generate
for (ii = 1; ii < (outdiv + 1); ii = ii + 1)
begin: asdadfdsf
assign dataiface_data_in[ii*internal_data_width - 1-:internal_data_width] = {TXCHARDISPMODE[ii*interface_isk_width - 1-:interface_isk_width],
TXCHARDISPVAL[ii*interface_isk_width - 1-:interface_isk_width],
TXDATA[ii*intern_databus_width - 1-:intern_databus_width]
};
end
endgenerate
wire [data_width - 1:0] internal_data; assign internal_dispmode = dataiface_data_out[intern_databus_width + internal_isk_width + internal_isk_width - 1-:internal_isk_width];
wire [isk_width - 1:0] internal_isk; assign internal_dispval = dataiface_data_out[intern_databus_width + internal_isk_width - 1-:internal_isk_width];
assign internal_data = dataiface_data_out[intern_databus_width - 1:0];
gtxe2_chnl_tx_dataiface #( gtxe2_chnl_tx_dataiface #(
.internal_data_width (data_width), .internal_data_width (internal_data_width),
.interface_data_width (if_data_width), .interface_data_width (interface_data_width),
.internal_isk_width (isk_width), .internal_isk_width (internal_isk_width),
.interface_isk_width (if_isk_width) .interface_isk_width (interface_isk_width)
) )
dataiface dataiface
( (
.usrclk (TXUSRCLK), .usrclk (TXUSRCLK),
.usrclk2 (TXUSRCLK2), .usrclk2 (TXUSRCLK2),
.reset (reset), .reset (reset),
.outdata (internal_data), .outdata (dataiface_data_out),
.outisk (internal_isk), .outisk (internal_isk),
.indata (TXDATA[if_data_width - 1:0]), .indata (dataiface_data_in),
.inisk (TXCHARISK[if_isk_width - 1:0]) .inisk (TXCHARISK[interface_isk_width - 1:0])
); );
wire [internal_data_width - 1:0] polarized_data; 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) // invert data (get words as [abdceifghj] after 8/10, each word shall be transmitter in a reverse bit order)
...@@ -164,7 +208,7 @@ generate ...@@ -164,7 +208,7 @@ generate
begin: select_each_word begin: select_each_word
for (jj = 0; jj < 10; jj = jj + 1) for (jj = 0; jj < 10; jj = jj + 1)
begin: reverse_bits begin: reverse_bits
assign inv_parallel_data[ii + jj] = polarized_data[ii + 9 - jj]; assign inv_parallel_data[ii + jj] = TX8B10BEN ? polarized_data[ii + 9 - jj] : polarized_data[ii + jj];
end end
end end
endgenerate endgenerate
...@@ -211,14 +255,16 @@ always @ (posedge TXUSRCLK) ...@@ -211,14 +255,16 @@ always @ (posedge TXUSRCLK)
// 8/10 endoding // 8/10 endoding
wire [internal_data_width - 1:0] encoded_data; wire [internal_data_width - 1:0] encoded_data;
gtxe2_chnl_tx_8x10enc #( gtxe2_chnl_tx_8x10enc #(
.iwidth (16),//TX_DATA_WIDTH), .iwidth (intern_databus_width),//TX_DATA_WIDTH),
.iskwidth (internal_isk_width),
.owidth (internal_data_width) .owidth (internal_data_width)
// .oddwidth (data_width_odd)
) )
encoder_8x10( encoder_8x10(
.TX8B10BBYPASS (TX8B10BBYPASS), .TX8B10BBYPASS (TX8B10BBYPASS[internal_isk_width - 1:0]),
.TX8B10BEN (TX8B10BEN), .TX8B10BEN (TX8B10BEN),
.TXCHARDISPMODE (TXCHARDISPMODE), .TXCHARDISPMODE (internal_dispmode),
.TXCHARDISPVAL (TXCHARDISPVAL), .TXCHARDISPVAL (internal_dispval),
.TXCHARISK (internal_isk), .TXCHARISK (internal_isk),
.disparity (disparity), .disparity (disparity),
.data_in (internal_data), .data_in (internal_data),
......
...@@ -21,20 +21,27 @@ ...@@ -21,20 +21,27 @@
// for some reason overall trasmitted disparity is tracked at the top level // for some reason overall trasmitted disparity is tracked at the top level
module gtxe2_chnl_tx_8x10enc #( module gtxe2_chnl_tx_8x10enc #(
parameter iwidth = 16, parameter iwidth = 16,
parameter iskwidth = 2,
parameter owidth = 20 parameter owidth = 20
) )
( (
input wire [7:0] TX8B10BBYPASS, input wire [iskwidth - 1:0] TX8B10BBYPASS,
input wire TX8B10BEN, input wire TX8B10BEN,
input wire [7:0] TXCHARDISPMODE, input wire [iskwidth - 1:0] TXCHARDISPMODE,
input wire [7:0] TXCHARDISPVAL, input wire [iskwidth - 1:0] TXCHARDISPVAL,
input wire [7:0] TXCHARISK, input wire [iskwidth - 1:0] TXCHARISK,
input wire disparity, input wire disparity,
input wire [iwidth - 1:0] data_in, input wire [iwidth - 1:0] data_in,
output wire [owidth - 1:0] data_out, output wire [owidth - 1:0] data_out,
output wire next_disparity output wire next_disparity
); );
wire [owidth - 1:0] enc_data_out;
wire [owidth - 1:0] bp_data_out;
assign data_out = TX8B10BEN ? enc_data_out : bp_data_out;
// only full 8/10 encoding and width=20 case is implemented // only full 8/10 encoding and width=20 case is implemented
localparam word_count = owidth / 10; localparam word_count = owidth / 10;
...@@ -114,7 +121,10 @@ begin: encode_by_word ...@@ -114,7 +121,10 @@ begin: encode_by_word
: iword[ii][7:0] == 8'b11111101 ? (~word_disparity[ii] ? 10'b1011101000 : 10'b0100010111) : iword[ii][7:0] == 8'b11111101 ? (~word_disparity[ii] ? 10'b1011101000 : 10'b0100010111)
:/*iword[ii][7:0] == 8'b11111110*/(~word_disparity[ii] ? 10'b0111101000 : 10'b1000010111); :/*iword[ii][7:0] == 8'b11111110*/(~word_disparity[ii] ? 10'b0111101000 : 10'b1000010111);
assign data_out[ii*10 + 9:ii * 10] = oword[ii]; assign enc_data_out[ii*10 + 9:ii * 10] = oword[ii];
// case of a disabled encoder
assign bp_data_out[ii*10 + 9:ii*10] = {TXCHARDISPMODE[ii], TXCHARDISPVAL[ii], data_in[ii*8 + 7:ii*8]};
end end
endgenerate 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];
......
...@@ -24,6 +24,7 @@ module gtxe2_chnl_tx_ser #( ...@@ -24,6 +24,7 @@ module gtxe2_chnl_tx_ser #(
) )
( (
input wire reset, input wire reset,
input wire trim,
input wire inclk, input wire inclk,
input wire outclk, input wire outclk,
input wire [width - 1:0] indata, input wire [width - 1:0] indata,
...@@ -32,18 +33,23 @@ module gtxe2_chnl_tx_ser #( ...@@ -32,18 +33,23 @@ module gtxe2_chnl_tx_ser #(
output wire idle_out output wire idle_out
); );
localparam trimmed_width = width * 4 / 5;
reg [31:0] bitcounter; reg [31:0] bitcounter;
wire [width - 1:0] data_resynced; wire [width - 1:0] data_resynced;
wire almost_empty_rd; wire almost_empty_rd;
wire empty_rd; wire empty_rd;
wire full_wr; wire full_wr;
wire val_rd; wire val_rd;
wire bitcounter_limit;
assign bitcounter_limit = trim ? bitcounter == (trimmed_width - 1) : bitcounter == (width - 1);
always @ (posedge outclk) always @ (posedge outclk)
bitcounter <= reset | bitcounter == (width - 1) ? 32'h0 : bitcounter + 1'b1; bitcounter <= reset | bitcounter_limit ? 32'h0 : bitcounter + 1'b1;
assign outdata = data_resynced[bitcounter]; assign outdata = data_resynced[bitcounter];
assign val_rd = ~almost_empty_rd & ~empty_rd & bitcounter == (width - 1); assign val_rd = ~almost_empty_rd & ~empty_rd & bitcounter_limit;
resync_fifo_nonsynt #( resync_fifo_nonsynt #(
.width (width + 1), // +1 is for a flag of an idle line (both TXP and TXN = 0) .width (width + 1), // +1 is for a flag of an idle line (both TXP and TXN = 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment