Commit 9f7bbe7d authored by Alexey Grebenkin's avatar Alexey Grebenkin

Added gtx wrapper to implement PCS features beyond gtx inself

parent bcfe20f6
...@@ -60,7 +60,15 @@ wire [31:0] txdata_oob; ...@@ -60,7 +60,15 @@ wire [31:0] txdata_oob;
wire [3:0] txcharisk; wire [3:0] txcharisk;
wire [3:0] txcharisk_oob; wire [3:0] txcharisk_oob;
wire [63:0] rxdata; wire [63:0] rxdata;
wire [3:0] rxcharisk; wire [63:0] rxdata_gtx;
wire [7:0] rxcharisk;
wire [7:0] rxcharisk_gtx;
wire [7:0] rxchariscomma;
wire [7:0] rxchariscomma_gtx;
wire [7:0] rxdisperr;
wire [7:0] rxdisperr_gtx;
wire [7:0] rxnotintable;
wire [7:0] rxnotintable_gtx;
wire [31:0] rxdata_out; wire [31:0] rxdata_out;
wire [31:0] txdata_in; wire [31:0] txdata_in;
wire [3:0] txcharisk_in; wire [3:0] txcharisk_in;
...@@ -546,15 +554,15 @@ gtx( ...@@ -546,15 +554,15 @@ gtx(
.RX8B10BEN (1'b1), .RX8B10BEN (1'b1),
.RXUSRCLK (rxusrclk), .RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2), .RXUSRCLK2 (rxusrclk2),
.RXDATA (rxdata), .RXDATA (rxdata_gtx),
.RXPRBSERR (), .RXPRBSERR (),
.RXPRBSSEL (3'd0), .RXPRBSSEL (3'd0),
.RXPRBSCNTRESET (1'b0), .RXPRBSCNTRESET (1'b0),
.RXDFEXYDEN (1'b1), .RXDFEXYDEN (1'b1),
.RXDFEXYDHOLD (1'b0), .RXDFEXYDHOLD (1'b0),
.RXDFEXYDOVRDEN (1'b0), .RXDFEXYDOVRDEN (1'b0),
.RXDISPERR (), .RXDISPERR (rxdisperr_gtx),
.RXNOTINTABLE (), .RXNOTINTABLE (rxnotintable_gtx),
.GTXRXP (rxp), .GTXRXP (rxp),
.GTXRXN (rxn), .GTXRXN (rxn),
.RXBUFRESET (1'b0), .RXBUFRESET (1'b0),
...@@ -637,8 +645,8 @@ gtx( ...@@ -637,8 +645,8 @@ gtx(
.RXELECIDLEMODE (2'b00), .RXELECIDLEMODE (2'b00),
.RXPOLARITY (1'b0), .RXPOLARITY (1'b0),
.RXSLIDE (1'b0), .RXSLIDE (1'b0),
.RXCHARISCOMMA (), .RXCHARISCOMMA (rxchariscomma_gtx),
.RXCHARISK (rxcharisk), .RXCHARISK (rxcharisk_gtx),
.RXCHBONDI (5'b00000), .RXCHBONDI (5'b00000),
.RXRESETDONE (rxresetdone), .RXRESETDONE (rxresetdone),
.RXQPIEN (1'b0), .RXQPIEN (1'b0),
...@@ -722,6 +730,16 @@ gtx( ...@@ -722,6 +730,16 @@ gtx(
.TXSYNCIN (1'b0)*/ .TXSYNCIN (1'b0)*/
); );
// align to 4-byte boundary
reg twobytes_shift;
always @ (posedge clk)
twobytes_shift <= rst ? 1'b0 : rxchariscomma_gtx[0] === 1'bx ? 1'b0 : rxchariscomma_gtx[2] === 1'bx ? 1'b0 : rxchariscomma_gtx[2] ? 1'b1 : rxchariscomma_gtx[0] ? 1'b0 : twobytes_shift;
assign rxdata = twobytes_shift ? {rxdata_gtx[63:32] , rxdata_gtx[15:0] , rxdata_gtx[31:16] } : rxdata_gtx;
assign rxcharisk = twobytes_shift ? {rxcharisk_gtx[7:4] , rxcharisk_gtx[1:0] , rxcharisk_gtx[3:2] } : rxcharisk_gtx;
assign rxchariscomma = twobytes_shift ? {rxchariscomma_gtx[7:4], rxchariscomma_gtx[1:0], rxchariscomma_gtx[3:2]} : rxchariscomma_gtx;
assign rxdisperr = twobytes_shift ? {rxdisperr_gtx[7:4] , rxdisperr_gtx[1:0] , rxdisperr_gtx[3:2] } : rxdisperr_gtx;
assign rxnotintable = twobytes_shift ? {rxnotintable_gtx[7:4] , rxnotintable_gtx[1:0] , rxnotintable_gtx[3:2] } : rxnotintable_gtx;
/* /*
* Interfaces * Interfaces
*/ */
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
*/ */
module sata_top( module sata_top(
output wire sclk, output wire sclk,
output wire sata_rst,
input wire extrst,
/* /*
* Commands interface * Commands interface
*/ */
...@@ -146,7 +148,7 @@ ...@@ -146,7 +148,7 @@
input wire EXTCLK_N input wire EXTCLK_N
); );
wire sata_rst; //wire sata_rst;
// dma_regs <-> sata host // dma_regs <-> sata host
// tmp to cmd control // tmp to cmd control
wire cmd_val_out; wire cmd_val_out;
...@@ -223,7 +225,7 @@ wire bram_wen; ...@@ -223,7 +225,7 @@ wire bram_wen;
wire bram_ren; wire bram_ren;
wire bram_regen; wire bram_regen;
// sata logic reset // sata logic reset
wire rst; //wire rst;
// sata clk // sata clk
//wire sclk; //wire sclk;
// dma_regs <-> dma_control // dma_regs <-> dma_control
...@@ -284,7 +286,7 @@ wire [63:0] buf_rdata; ...@@ -284,7 +286,7 @@ wire [63:0] buf_rdata;
// additional adapter <-> membridge wire // additional adapter <-> membridge wire
wire rdata_done; // = membridge.is_last_in_page & membridge.afi_rready; wire rdata_done; // = membridge.is_last_in_page & membridge.afi_rready;
assign rst = ARESETN; //assign rst = ARESETN;
axi_regs axi_regs( axi_regs axi_regs(
...@@ -344,7 +346,7 @@ axi_regs axi_regs( ...@@ -344,7 +346,7 @@ axi_regs axi_regs(
* Programmable sata controller registers * Programmable sata controller registers
*/ */
dma_regs dma_regs( dma_regs dma_regs(
.rst (rst), .rst (sata_rst),
.ACLK (ACLK), .ACLK (ACLK),
.sclk (sclk), .sclk (sclk),
// control iface // control iface
...@@ -436,7 +438,7 @@ dma_regs dma_regs( ...@@ -436,7 +438,7 @@ dma_regs dma_regs(
dma_control dma_control( dma_control dma_control(
.sclk (sclk), .sclk (sclk),
.hclk (hclk), .hclk (hclk),
.rst (rst), .rst (sata_rst),
// registers iface // registers iface
.mem_address (mem_address), .mem_address (mem_address),
...@@ -484,7 +486,7 @@ dma_control dma_control( ...@@ -484,7 +486,7 @@ dma_control dma_control(
dma_adapter dma_adapter( dma_adapter dma_adapter(
.clk (hclk), .clk (hclk),
.rst (rst), .rst (sata_rst),
// command iface // command iface
.cmd_type (adp_type), .cmd_type (adp_type),
.cmd_val (adp_val), .cmd_val (adp_val),
...@@ -537,8 +539,8 @@ V .MEMBRIDGE_ADDR (), ...@@ -537,8 +539,8 @@ V .MEMBRIDGE_ADDR (),
.FRAME_HEIGHT_BITS (), .FRAME_HEIGHT_BITS (),
.FRAME_WIDTH_BITS () .FRAME_WIDTH_BITS ()
)*/ membridge( )*/ membridge(
.mrst (rst), // input .mrst (sata_rst), // input
.hrst (rst), // input .hrst (ARESETN), // input
.mclk (hclk), // input .mclk (hclk), // input
.hclk (hclk), // input .hclk (hclk), // input
.cmd_ad (cmd_ad), .cmd_ad (cmd_ad),
...@@ -611,7 +613,7 @@ V .MEMBRIDGE_ADDR (), ...@@ -611,7 +613,7 @@ V .MEMBRIDGE_ADDR (),
assign rdata_done = 1'b0; assign rdata_done = 1'b0;
sata_host sata_host( sata_host sata_host(
.extrst (rst), .extrst (extrst),
// sata rst // sata rst
.rst (sata_rst), .rst (sata_rst),
// sata clk // sata clk
......
...@@ -43,6 +43,8 @@ wire [32*REGISTERS_CNT - 1:0] outmem; ...@@ -43,6 +43,8 @@ wire [32*REGISTERS_CNT - 1:0] outmem;
wire clrstart; wire clrstart;
wire sclk; wire sclk;
wire sata_rst;
wire extrst;
wire [3:0] fclk; wire [3:0] fclk;
wire [3:0] frst; wire [3:0] frst;
wire axi_aclk; wire axi_aclk;
...@@ -166,6 +168,7 @@ end ...@@ -166,6 +168,7 @@ end
BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(/*fclk[0]*/ sclk)); BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(/*fclk[0]*/ sclk));
BUFG bufg_axi_aclk0_i (.O(axi_aclk0),.I(fclk[0])); BUFG bufg_axi_aclk0_i (.O(axi_aclk0),.I(fclk[0]));
BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre)); BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre));
BUFG bufg_extrst_i (.O(extrst),.I(axi_rst_pre));
axi_hp_clk #( axi_hp_clk #(
.CLKIN_PERIOD(6.666), .CLKIN_PERIOD(6.666),
.CLKFBOUT_MULT_AXIHP(6), .CLKFBOUT_MULT_AXIHP(6),
...@@ -179,8 +182,10 @@ axi_hp_clk #( ...@@ -179,8 +182,10 @@ axi_hp_clk #(
sata_top sata_top( sata_top sata_top(
.sclk (sclk), .sclk (sclk),
.sata_rst (sata_rst),
.extrst (extrst),
.ACLK (axi_aclk), .ACLK (axi_aclk),
.ARESETN (axi_rst), .ARESETN (axi_rst | sata_rst),
// AXI PS Master GP1: Read Address // AXI PS Master GP1: Read Address
.ARADDR (ARADDR), .ARADDR (ARADDR),
.ARVALID (ARVALID), .ARVALID (ARVALID),
......
...@@ -52,14 +52,14 @@ assign addr1 = indata[19:10]; ...@@ -52,14 +52,14 @@ assign addr1 = indata[19:10];
// get decoded values after 2 clock cycles, all '1's = cannot be decoded // get decoded values after 2 clock cycles, all '1's = cannot be decoded
wire [15:0] table0_out; wire [15:0] table0_out;
wire [15:0] table1_out; wire [15:0] table1_out;
wire [9:0] table0; wire [10:0] table0;
wire [9:0] table1; wire [10:0] table1;
assign table0 = table0_out[9:0]; assign table0 = table0_out[10:0];
assign table1 = table1_out[9:0]; assign table1 = table1_out[10:0];
assign outdata = {table1[7:0], table0[7:0]}; assign outdata = {table1[7:0], table0[7:0]};
assign outisk = {table1[8], table0[8]}; assign outisk = {table1[8], table0[8]};
assign notintable = {|table1, |table0}; assign notintable = {&table1, &table0};
// disparity control // disparity control
// last clock disparity // last clock disparity
...@@ -68,11 +68,13 @@ reg disparity; ...@@ -68,11 +68,13 @@ reg disparity;
wire disparity_interm; wire disparity_interm;
// delayed ones // delayed ones
reg disp0_r; reg disp0_r;
reg disp0_rr;
reg disp1_r; reg disp1_r;
reg disp1_rr; reg disp1_rr;
always @ (posedge clk) always @ (posedge clk)
begin begin
disp0_r <= disparity; disp0_r <= disparity;
disp0_rr <= disp0_r;
disp1_r <= disparity_interm; disp1_r <= disparity_interm;
disp1_rr <= disp1_r; disp1_rr <= disp1_r;
end end
...@@ -81,8 +83,8 @@ end ...@@ -81,8 +83,8 @@ end
wire expected_disparity; wire expected_disparity;
wire expected_disparity_interm; wire expected_disparity_interm;
assign expected_disparity = disp0_r; assign expected_disparity = disp0_rr ^ correct_table_disp;
assign expected_disparity_interm = disp1_rr; assign expected_disparity_interm = disp1_rr ^ correct_table_disp;
// invert disparity after a byte // invert disparity after a byte
// if current encoded word containg an equal amount of 1s and 0s (i.e. 5 x '1'), disp shall stay the same // if current encoded word containg an equal amount of 1s and 0s (i.e. 5 x '1'), disp shall stay the same
...@@ -99,15 +101,22 @@ always @ (posedge clk) ...@@ -99,15 +101,22 @@ always @ (posedge clk)
// to correct disparity if once an error occured // to correct disparity if once an error occured
reg correct_table_disp; reg correct_table_disp;
always @ (posedge clk) always @ (posedge clk)
correct_table_disp <= rst ? 1'b0 : disperror ? ~correct_table_disp : correct_table_disp; correct_table_disp <= rst ? 1'b0 : disperror[1] ? ~correct_table_disp : correct_table_disp;
// calculate disparity on table values // calculate disparity on table values
wire table_disp0; wire table_pos_disp0;
wire table_disp1; wire table_neg_disp0;
assign table_disp0 = table0[9] ^ correct_table_disp; wire table_pos_disp1;
assign table_disp1 = table1[9] ^ correct_table_disp; wire table_neg_disp1;
// table_pos_disp - for current 10-bit word disparity can be positive
// _neg_ - can be negative
// neg & pos - can be either of them
assign table_pos_disp0 = table0[10];
assign table_neg_disp0 = table0[9];
assign table_pos_disp1 = table1[10];
assign table_neg_disp1 = table1[9];
assign disperror = {table_disp0 == expected_disparity, table_disp1 == expected_disparity_interm}; assign disperror = ~{table_pos_disp0 & expected_disparity | table_neg_disp0 & ~expected_disparity, table_pos_disp1 & expected_disparity_interm | table_neg_disp1 & ~expected_disparity_interm};
// TODO change mem to 18 instead of 36, so the highest address bit could be dropped // TODO change mem to 18 instead of 36, so the highest address bit could be dropped
ramt_var_w_var_r #( ramt_var_w_var_r #(
......
# left_column[9] = disparity
# left_column[8] = conrtol
# left_column[7:0] = decoded 8
# right column[9:0] = encoded 10 in correct order : abcdefgh. Need to flip it, because gtx spits out flipped data with flipped bit order
#
mem7f = [] mem7f = []
for i in range(0x80): for i in range(0x80):
mem7f.append(0); mem7f.append(0);
i = 0 filecontent = {}
for line in open('gtx_10x8dec_init_stub.v').readlines(): for line in open('gtx_10x8dec_init_stub.v').readlines():
addr = int('0b' + line.split()[1], 2) address_flipped_str = line.split()[1];
a = int('0b' + line.split()[0], 2) address_str = address_flipped_str[::-1]
mem7f[addr >> 4] = (mem7f[addr >> 4] << 16) + a address = int('0b' + address_str, 2)
i += 1 # retrieve everything but disparity - highest bit
value = int('0b' + line.split()[0][1:], 2)
# retrieve disparity
disparity = int('0b' + line.split()[0][0], 2)
# if disparity = 1 -> flag positive disparity, 0 -> flag negative one
disp_pos = 1 if disparity == 1 else 0
disp_neg = 1 if disparity == 0 else 0
if address_str in filecontent:
disp_pos = 1 if filecontent[address_str][1] == 1 or disp_pos else 0
disp_neg = 1 if filecontent[address_str][2] == 1 or disp_neg else 0
filecontent[address_str] = [address, disp_pos, disp_neg, value];
for key in filecontent:
(address, disp_pos, disp_neg, value) = filecontent[key]
# if address == 0x2aa:
# print '2AA: ADDR>>4 = %X' % (address >> 4),' ADDR = ', bin(address), ' POS DISP = ', bin(disp_pos), ' NEG DISP = ', bin(disp_neg), ' VALUE = ', bin(value)
# print 'ADDR = ', bin(address), ' POS DISP = ', bin(disp_pos), ' NEG DISP = ', bin(disp_neg), ' VALUE = ', bin(value)
to_mem = (disp_pos << 10) + (disp_neg << 9) + value
mem7f[address >> 4] = mem7f[address >> 4] + (to_mem << ((address % 16) * 16))
# if (address >> 4) == 0x2a:
# print '2AA: ADDR = %X, to mem = %X, total = %X ' % ((address ),to_mem, mem7f[address >> 4])#, ' ADDR = ', bin(address), ' POS DISP = ', bin(disp_pos), ' NEG DISP = ', bin(disp_neg), ' VALUE = ', bin(value)
# if addr == 0x2aa:
# print "FLIPPED ADDR %s " % address_flipped_str, "ADDR %x " % addr, "ADDR7f %x " % (addr >> 4), "VALUE %x " % a
for i in range(0x80): for i in range(0x80):
print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i]) print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i])
...@@ -2,62 +2,62 @@ ...@@ -2,62 +2,62 @@
, .INIT_01 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_01 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_02 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_02 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_03 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_03 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_04 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_04 (256'h000004EE04ED000004EB00000000000000000000000000000000000000000000)
, .INIT_05 (256'h00000000000000000000000000000217023702570277029702B702D702F703F7) , .INIT_05 (256'h000003FE03FD000003FB00000000000003F70000000000000000000000000000)
, .INIT_06 (256'h000000000000000000000000000000000208022802480268028802A802C802E8) , .INIT_06 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_07 (256'h000000000000000000000000000000000207022702470267028702A702C702E7) , .INIT_07 (256'h00000000000003FC000000000000000000000000000000000000000000000000)
, .INIT_08 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_08 (256'h0000040E040D0000040B00000000000000000000000000000000000000000000)
, .INIT_09 (256'h0000000000000000000000000000021B023B025B027B029B02BB02DB02FB03FB) , .INIT_09 (256'h0000021E021D041C021B041A0419000002170416041500000413000000000000)
, .INIT_0A (256'h000000000000000000000000000000000204022402440264028402A402C402E4) , .INIT_0A (256'h000002010202040C0204040A0409000002080406040500000403000000000000)
, .INIT_0B (256'h001402140034023400540254007402740094029400B402B400D402D400F402F4) , .INIT_0B (256'h000000000000031C0000020F0200040700000210021F04140218041204110000)
, .INIT_0C (256'h000000000000000000000000000000000218023802580278029802B802D802F8) , .INIT_0C (256'h0000026E026D0478026B047F0470000002670460046F0000057C000000000000)
, .INIT_0D (256'h000C020C002C022C004C024C006C026C008C028C00AC02AC00CC02CC00EC02EC) , .INIT_0D (256'h000000000000027C0000027A0279046800000276027504640273046204610000)
, .INIT_0E (256'h001C021C003C023C005C025C007C027C009C029C00BC02BC00DC02DC00FC02FC) , .INIT_0E (256'h000000000000026C0000026A02690477000002660265047B0263047D047E0000)
, .INIT_0F (256'h00000000000000000000000000000000011C013C015C017C019C01BC01DC01FC) , .INIT_0F (256'h0000000000000000000000000000000000000000000002740000027202710000)
, .INIT_10 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_10 (256'h0000048E048D0000048B00000000000000000000000000000000000000000000)
, .INIT_11 (256'h0000000000000000000000000000021D023D025D027D029D02BD02DD02FD03FD) , .INIT_11 (256'h0000029E029D049C029B049A0499000002970496049500000493000000000000)
, .INIT_12 (256'h000000000000000000000000000000000202022202420262028202A202C202E2) , .INIT_12 (256'h000002810282048C0284048A0489000002880486048500000483000000000000)
, .INIT_13 (256'h001202120032023200520252007202720092029200B202B200D202D200F202F2) , .INIT_13 (256'h000000000000039C0000028F0280048700000290029F04940298049204910000)
, .INIT_14 (256'h00000000000000000000000000000000021F023F025F027F029F02BF02DF02FF) , .INIT_14 (256'h000006AE06AD04B806AB04BF04B0000002A704A004AF0000055C000000000000)
, .INIT_15 (256'h000A020A002A022A004A024A006A026A008A028A00AA02AA00CA02CA00EA02EA) , .INIT_15 (256'h000002BE02BD06BC02BB06BA06B904A802B706B606B504A406B304A204A10000)
, .INIT_16 (256'h001A021A003A023A005A025A007A027A009A029A00BA02BA00DA02DA00FA02FA) , .INIT_16 (256'h000002A102A206AC02A406AA06A904B702A806A606A504BB06A304BD04BE0000)
, .INIT_17 (256'h00000000000000000000000000000000000F002F004F006F008F00AF00CF00EF) , .INIT_17 (256'h00000000000003BC000002AF02A004A7000002B002BF06B402B806B206B10000)
, .INIT_18 (256'h000000000000000000000000000000000200022002400260028002A002C002E0) , .INIT_18 (256'h000006CE06CD04D806CB04DF04D0000002C704C004CF0000053C000000000000)
, .INIT_19 (256'h000602060026022600460246006602660086028600A602A600C602C600E602E6) , .INIT_19 (256'h000002DE02DD06DC02DB06DA06D904C802D706D606D504C406D304C204C10000)
, .INIT_1A (256'h001602160036023600560256007602760096029600B602B600D602D600F602F6) , .INIT_1A (256'h000002C102C206CC02C406CA06C904D702C806C606C504DB06C304DD04DE0000)
, .INIT_1B (256'h000000000000000000000000000000000010003000500070009000B000D000F0) , .INIT_1B (256'h00000000000003DC000002CF02C004C7000002D002DF06D402D806D206D10000)
, .INIT_1C (256'h000E020E002E022E004E024E006E026E008E028E00AE02AE00CE02CE00EE02EE) , .INIT_1C (256'h000002EE02ED04F802EB04FF04F0000002E704E004EF00000000000000000000)
, .INIT_1D (256'h000000000000000000000000000000000001002100410061008100A100C100E1) , .INIT_1D (256'h00000000000002FC000002FA02F904E8000002F602F504E402F304E204E10000)
, .INIT_1E (256'h0000000000000000000000000000001E003E005E007E009E00BE00DE00FE01FE) , .INIT_1E (256'h00000000000002EC000002EA02E904F7000002E602E504FB02E304FD04FE0000)
, .INIT_1F (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_1F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_21 (256'h0000000000000000000000000000021E023E025E027E029E02BE02DE02FE03FE) , .INIT_21 (256'h000002FE02FD04FC02FB04FA04F9000002F704F604F5000004F3000000000000)
, .INIT_22 (256'h000000000000000000000000000000000201022102410261028102A102C102E1) , .INIT_22 (256'h000002E102E204EC02E404EA04E9000002E804E604E5000004E3000000000000)
, .INIT_23 (256'h001102110031023100510251007102710091029100B102B100D102D100F102F1) , .INIT_23 (256'h0000000000000000000002EF02E004E7000002F002FF04F402F804F204F10000)
, .INIT_24 (256'h000000000000000000000000000000000210023002500270029002B002D002F0) , .INIT_24 (256'h0000062E062D0438062B043F0430000002270420042F000005DC000000000000)
, .INIT_25 (256'h000902090029022900490249006902690089028900A902A900C902C900E902E9) , .INIT_25 (256'h0000023E023D063C023B063A0639042802370636063504240633042204210000)
, .INIT_26 (256'h001902190039023900590259007902790099029900B902B900D902D900F902F9) , .INIT_26 (256'h000002210222062C0224062A06290437022806260625043B0623043D043E0000)
, .INIT_27 (256'h000000000000000000000000000000000000002000400060008000A000C000E0) , .INIT_27 (256'h000000000000033C0000022F0220042700000230023F06340238063206310000)
, .INIT_28 (256'h00000000000000000000000000000000020F022F024F026F028F02AF02CF02EF) , .INIT_28 (256'h0000064E064D0458064B045F0450000002470440044F000005BC000000000000)
, .INIT_29 (256'h000502050025022500450245006502650085028500A502A500C502C500E502E5) , .INIT_29 (256'h0000025E025D065C025B065A0659044802570656065504440653044204410000)
, .INIT_2A (256'h001502150035023500550255007502750095029500B502B500D502D500F502F5) , .INIT_2A (256'h000002410242064C0244064A06490457024806460645045B0643045D045E0000)
, .INIT_2B (256'h00000000000000000000000000000000001F003F005F007F009F00BF00DF00FF) , .INIT_2B (256'h000000000000035C0000024F0240044700000250025F06540258065206510000)
, .INIT_2C (256'h000D020D002D022D004D024D006D026D008D028D00AD02AD00CD02CD00ED02ED) , .INIT_2C (256'h0000028E028D0498028B049F0490000002870480048F0000059C000000000000)
, .INIT_2D (256'h000000000000000000000000000000000002002200420062008200A200C200E2) , .INIT_2D (256'h000000000000029C0000029A0299048800000296029504840293048204810000)
, .INIT_2E (256'h0000000000000000000000000000001D003D005D007D009D00BD00DD00FD01FD) , .INIT_2E (256'h000000000000028C0000028A02890497000002860285049B0283049D049E0000)
, .INIT_2F (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_2F (256'h0000000000000000000000000000000000000000000002940000029202910000)
, .INIT_30 (256'h00000000000000000000000000000000031C033C035C037C039C03BC03DC03FC) , .INIT_30 (256'h0000046E046D0000046B00000000000000000000000000000000000000000000)
, .INIT_31 (256'h000302030023022300430243006302630083028300A302A300C302C300E302E3) , .INIT_31 (256'h0000027E027D047C027B047A0479000002770476047500000473000000000000)
, .INIT_32 (256'h001302130033023300530253007302730093029300B302B300D302D300F302F3) , .INIT_32 (256'h000002610262046C0264046A0469000002680466046500000463000000000000)
, .INIT_33 (256'h000000000000000000000000000000000018003800580078009800B800D800F8) , .INIT_33 (256'h000000000000037C0000026F0260046700000270027F04740278047204710000)
, .INIT_34 (256'h000B020B002B022B004B024B006B026B008B028B00AB02AB00CB02CB00EB02EB) , .INIT_34 (256'h0000020E020D0418020B041F0410000002070400040F0000051C000000000000)
, .INIT_35 (256'h000000000000000000000000000000000004002400440064008400A400C400E4) , .INIT_35 (256'h000000000000021C0000021A0219040800000216021504040213040204010000)
, .INIT_36 (256'h0000000000000000000000000000001B003B005B007B009B00BB00DB00FB01FB) , .INIT_36 (256'h000000000000020C0000020A02090417000002060205041B0203041D041E0000)
, .INIT_37 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_37 (256'h0000000000000000000000000000000000000000000002140000021202110000)
, .INIT_38 (256'h000000000000000000000000000000000007002700470067008700A700C700E7) , .INIT_38 (256'h00000000000000000000000000000000000000000000000005FC000000000000)
, .INIT_39 (256'h000000000000000000000000000000000008002800480068008800A800C800E8) , .INIT_39 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3A (256'h00000000000000000000000000000017003700570077009700B700D700F701F7) , .INIT_3A (256'h000000000000000000000000000005F700000000000005FB000005FD05FE0000)
, .INIT_3B (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3B (256'h0000000000000000000000000000000000000000000002F4000002F202F10000)
, .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3E (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3E (256'h0000000000000000000000000000000000000000000000000000000000000000)
......
...@@ -65,8 +65,8 @@ always @ (posedge clk) ...@@ -65,8 +65,8 @@ always @ (posedge clk)
// select encoded bytes depending on a previous disparity // select encoded bytes depending on a previous disparity
assign enc0 = ~disparity & table0[19:10] | disparity & table0[9:0]; assign enc0 = {10{~disparity}} & table0[19:10] | {10{disparity}} & table0[9:0];
assign enc1 = ~disparity_interm & table1[19:10] | disparity_interm & table1[9:0]; assign enc1 = {10{~disparity_interm}} & table1[19:10] | {10{disparity_interm}} & table1[9:0];
// latch output data // latch output data
reg [19:0] outdata_l; reg [19:0] outdata_l;
......
...@@ -2,13 +2,15 @@ mem7f = [] ...@@ -2,13 +2,15 @@ mem7f = []
for i in range(0x80): for i in range(0x80):
mem7f.append(0); mem7f.append(0);
i = 0
for line in open('gtx_8x10enc_init_stub.v').readlines(): for line in open('gtx_8x10enc_init_stub.v').readlines():
addr = int('0b' + line.split()[0], 2) addr = int('0b' + line.split()[0], 2)
a = int('0b' + line.split()[1], 2) a = int('0b' + line.split()[1], 2)
b = int('0b' + line.split()[2], 2) b = int('0b' + line.split()[2], 2)
mem7f[addr >> 3] = (((mem7f[addr >> 3] << 16) + b) << 16) + a # mem7f[addr >> 3] = (((mem7f[addr >> 3] << 16) + b) << 16) + a
i += 1 to_mem = (b << 10) + a
# if addr == 0x1bc or addr == 0x4a:
# print addr, ' = ', to_mem, ' : ', b, ' :', a
mem7f[addr >> 3] = mem7f[addr >> 3] + (to_mem << ((addr % 8) * 32))
for i in range(0x80): for i in range(0x80):
print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i]) print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i])
, .INIT_00 (256'h018B0274022B01D4012B02D40314031B00AB03540294029B0194019B0074038B) , .INIT_00 (256'h0002E34700029B6600029765000D50AB00028F63000D48AD000D44AE000D18B9)
, .INIT_01 (256'h006B03940254025B0154015B0344034B00D400DB02C402CB01C401CB028B0174) , .INIT_01 (256'h000D14BA00023B4E0002374D0002B36C00022F4B0002AB6A0002A769000D60A7)
, .INIT_02 (256'h024B01B40234023B0134013B0324032B00B400BB02A402AB01A401AB005B03A4) , .INIT_02 (256'h000DA09700025B56000257550002D37400024F530002CB720002C771000D24B6)
, .INIT_03 (256'h00CB03340264026B0164016B009B036400E400EB011B02E4021B01E4014B02B4) , .INIT_03 (256'h000D28B5000D849E000D889D0002735C000D909B00026B5A00026759000D30B3)
, .INIT_04 (256'h01890279022901D9012902D90319031900A90359029902990199019900790389) , .INIT_04 (256'h0009E24700099A66000996650009526B00098E6300094A6D0009466E00091A79)
, .INIT_05 (256'h0069039902590259015901590349034900D900D902C902C901C901C902890179) , .INIT_05 (256'h0009167A00093A4E0009364D0009B26C00092E4B0009AA6A0009A66900096267)
, .INIT_06 (256'h024901B902390239013901390329032900B900B902A902A901A901A9005903A9) , .INIT_06 (256'h0009A25700095A56000956550009D27400094E530009CA720009C67100092676)
, .INIT_07 (256'h00C9033902690269016901690099036900E900E9011902E9021901E9014902B9) , .INIT_07 (256'h00092A750009865E00098A5D0009725C0009925B00096A5A0009665900093273)
, .INIT_08 (256'h01850275022501D5012502D50315031500A50355029502950195019500750385) , .INIT_08 (256'h000AE287000A9AA6000A96A5000A52AB000A8EA3000A4AAD000A46AE000A1AB9)
, .INIT_09 (256'h0065039502550255015501550345034500D500D502C502C501C501C502850175) , .INIT_09 (256'h000A16BA000A3A8E000A368D000AB2AC000A2E8B000AAAAA000AA6A9000A62A7)
, .INIT_0A (256'h024501B502350235013501350325032500B500B502A502A501A501A5005503A5) , .INIT_0A (256'h000AA297000A5A96000A5695000AD2B4000A4E93000ACAB2000AC6B1000A26B6)
, .INIT_0B (256'h00C5033502650265016501650095036500E500E5011502E5021501E5014502B5) , .INIT_0B (256'h000A2AB5000A869E000A8A9D000A729C000A929B000A6A9A000A6699000A32B3)
, .INIT_0C (256'h018C0273022C01D3012C02D30313031C00AC03530293029C0193019C0073038C) , .INIT_0C (256'h000CE0C7000C98E6000C94E50003532B000C8CE300034B2D0003472E00031B39)
, .INIT_0D (256'h006C03930253025C0153015C0343034C00D300DC02C302CC01C301CC028C0173) , .INIT_0D (256'h0003173A000C38CE000C34CD000CB0EC000C2CCB000CA8EA000CA4E900036327)
, .INIT_0E (256'h024C01B30233023C0133013C0323032C00B300BC02A302AC01A301AC005C03A3) , .INIT_0E (256'h0003A317000C58D6000C54D5000CD0F4000C4CD3000CC8F2000CC4F100032736)
, .INIT_0F (256'h00CC03330263026C0163016C009C036300E300EC011C02E3021C01E3014C02B3) , .INIT_0F (256'h00032B350003871E00038B1D000C70DC0003931B000C68DA000C64D900033333)
, .INIT_10 (256'h018D0272022D01D2012D02D20312031D00AD03520292029D0192019D0072038D) , .INIT_10 (256'h0004E2C700049AE6000496E5000B512B00048EE3000B492D000B452E000B1939)
, .INIT_11 (256'h006D03920252025D0152015D0342034D00D200DD02C202CD01C201CD028D0172) , .INIT_11 (256'h000B153A00043ACE000436CD0004B2EC00042ECB0004AAEA0004A6E9000B6127)
, .INIT_12 (256'h024D01B20232023D0132013D0322032D00B200BD02A202AD01A201AD005D03A2) , .INIT_12 (256'h000BA11700045AD6000456D50004D2F400044ED30004CAF20004C6F1000B2536)
, .INIT_13 (256'h00CD03320262026D0162016D009D036200E200ED011D02E2021D01E2014D02B2) , .INIT_13 (256'h000B2935000B851E000B891D000472DC000B911B00046ADA000466D9000B3133)
, .INIT_14 (256'h018A027A022A01DA012A02DA031A031A00AA035A029A029A019A019A007A038A) , .INIT_14 (256'h0005E14700059966000595650005516B00058D630005496D0005456E00051979)
, .INIT_15 (256'h006A039A025A025A015A015A034A034A00DA00DA02CA02CA01CA01CA028A017A) , .INIT_15 (256'h0005157A0005394E0005354D0005B16C00052D4B0005A96A0005A56900056167)
, .INIT_16 (256'h024A01BA023A023A013A013A032A032A00BA00BA02AA02AA01AA01AA005A03AA) , .INIT_16 (256'h0005A15700055956000555550005D17400054D530005C9720005C57100052576)
, .INIT_17 (256'h00CA033A026A026A016A016A009A036A00EA00EA011A02EA021A01EA014A02BA) , .INIT_17 (256'h000529750005855E0005895D0005715C0005915B0005695A0005655900053173)
, .INIT_18 (256'h01860276022601D6012602D60316031600A60356029602960196019600760386) , .INIT_18 (256'h0006E187000699A6000695A5000651AB00068DA3000649AD000645AE000619B9)
, .INIT_19 (256'h0066039602560256015601560346034600D600D602C602C601C601C602860176) , .INIT_19 (256'h000615BA0006398E0006358D0006B1AC00062D8B0006A9AA0006A5A9000661A7)
, .INIT_1A (256'h024601B602360236013601360326032600B600B602A602A601A601A6005603A6) , .INIT_1A (256'h0006A19700065996000655950006D1B400064D930006C9B20006C5B1000625B6)
, .INIT_1B (256'h00C6033602660266016601660096036600E600E6011602E6021601E6014602B6) , .INIT_1B (256'h000629B50006859E0006899D0006719C0006919B0006699A00066599000631B3)
, .INIT_1C (256'h018E0271022E01D1012E02D10311031E00AE03510291029E0191019E0071038E) , .INIT_1C (256'h0008E1C7000899E6000895E50007522B00088DE300074A2D0007462E00071A39)
, .INIT_1D (256'h006E03910251025E0151015E0348034E00D100DE02C802CE01C801CE028E0171) , .INIT_1D (256'h0007163A000139CE000135CD0008B1EC00012DCB0008A9EA0008A5E900076227)
, .INIT_1E (256'h024E01B102310237013101370321032E00B100B702A102AE01A101AE005E03A1) , .INIT_1E (256'h0007A217000859D6000855D50008D3B400084DD30008CBB20008C7B100072636)
, .INIT_1F (256'h00CE03310261026E0161016E009E036100E100EE011E02E1021E01E1014E02B1) , .INIT_1F (256'h00072A350007861E00078A1D000871DC0007921B000869DA000865D900073233)
, .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_21 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_21 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_22 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_22 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_23 (256'h00000000000000000000000000000000000000000000000000000000030B00F4) , .INIT_23 (256'h000000000000000000000000000D0CBC00000000000000000000000000000000)
, .INIT_24 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_24 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_25 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_25 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_26 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_26 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_27 (256'h00000000000000000000000000000000000000000000000000000000030600F9) , .INIT_27 (256'h00000000000000000000000000060E7C00000000000000000000000000000000)
, .INIT_28 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_28 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_29 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_29 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2A (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_2A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2B (256'h00000000000000000000000000000000000000000000000000000000030A00F5) , .INIT_2B (256'h00000000000000000000000000050EBC00000000000000000000000000000000)
, .INIT_2C (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_2C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2D (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_2D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2E (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_2E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2F (256'h00000000000000000000000000000000000000000000000000000000030C00F3) , .INIT_2F (256'h00000000000000000000000000030F3C00000000000000000000000000000000)
, .INIT_30 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_30 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_31 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_31 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_32 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_32 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_33 (256'h00000000000000000000000000000000000000000000000000000000030D00F2) , .INIT_33 (256'h000000000000000000000000000B0D3C00000000000000000000000000000000)
, .INIT_34 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_34 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_35 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_35 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_36 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_36 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_37 (256'h00000000000000000000000000000000000000000000000000000000030500FA) , .INIT_37 (256'h000000000000000000000000000A0D7C00000000000000000000000000000000)
, .INIT_38 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_38 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_39 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_39 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3A (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3B (256'h00000000000000000000000000000000000000000000000000000000030900F6) , .INIT_3B (256'h00000000000000000000000000090DBC00000000000000000000000000000000)
, .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3E (256'h00000000000000000000000000000000000000000000000000000000005703A8) , .INIT_3E (256'h000EA05700000000000000000000000000000000000000000000000000000000)
, .INIT_3F (256'h00000000000000000000000000000000030700F800970368011702E8021701E8) , .INIT_3F (256'h00000000000E845E000E885D000E0C7C000E905B000000000000000000000000)
, .INIT_40 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_40 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_41 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_41 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_42 (256'h0000000000000000000000000000000000000000000000000000000000000000) , .INIT_42 (256'h0000000000000000000000000000000000000000000000000000000000000000)
......
This diff is collapsed.
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
module gtx_comma_align( module gtx_comma_align(
input wire rst, input wire rst,
input wire clk, input wire clk,
// input data comes this way (standart 8/10 bit notation)
// cycle 0: {[hgfedcba]=1st byte,[hgfedcba]=0st byte}
// cycle 1: {[hgfedcba]=3rd byte,[hgfedcba]=2dn byte}
// => {[cycle1 data], [cycle0 data]} = as if we were reading by dwords
input wire [19:0] indata, input wire [19:0] indata,
output wire [19:0] outdata, output wire [19:0] outdata,
// outdata contains comma // outdata contains comma
...@@ -67,7 +71,7 @@ reg [19:0] indata_r; ...@@ -67,7 +71,7 @@ reg [19:0] indata_r;
wire [38:0] window; wire [38:0] window;
always @ (posedge clk) always @ (posedge clk)
indata_r <= indata; indata_r <= indata;
assign window = {indata_r, indata}; assign window = {indata, indata_r};
// there is only 1 matched subwindow due to 20-bit comma's non-repetative pattern // there is only 1 matched subwindow due to 20-bit comma's non-repetative pattern
wire [19:0] subwindow [19:0]; wire [19:0] subwindow [19:0];
...@@ -81,7 +85,9 @@ generate ...@@ -81,7 +85,9 @@ generate
for (ii = 0; ii < 20; ii = ii + 1) for (ii = 0; ii < 20; ii = ii + 1)
begin: look_for_comma begin: look_for_comma
assign subwindow[ii] = window[ii + 19:ii]; assign subwindow[ii] = window[ii + 19:ii];
assign comma_match[ii] = subwindow[ii] == 20'b01010101010011111010; // assign comma_match[ii] = subwindow[ii] == 20'b01010101010011111010 | subwindow[ii] == 20'b01010101011100000101;
// stream comes inverted
assign comma_match[ii] = subwindow[ii] == 20'b10101010100101111100 | subwindow[ii] == 20'b10101010101010000011;
end end
endgenerate endgenerate
...@@ -89,7 +95,7 @@ assign comma_detected = |comma_match; ...@@ -89,7 +95,7 @@ assign comma_detected = |comma_match;
// save the shift count // save the shift count
always @ (posedge clk) always @ (posedge clk)
comma_match_prev <= rst ? 20'h0 : comma_detected ? comma_match : comma_match_prev; comma_match_prev <= rst ? 20'h1 : comma_detected ? comma_match : comma_match_prev;
// shift // shift
wire [38:0] shifted_window; wire [38:0] shifted_window;
assign shifted_window = comma_detected ? {window >> (comma_match - 1)} : {window >> (comma_match_prev - 1)}; assign shifted_window = comma_detected ? {window >> (comma_match - 1)} : {window >> (comma_match_prev - 1)};
......
...@@ -51,9 +51,9 @@ wire [22:0] indata; ...@@ -51,9 +51,9 @@ wire [22:0] indata;
wire [22:0] outdata; wire [22:0] outdata;
assign indata = {isaligned_in, notintable_in, disperror_in, charisk_in, data_in}; assign indata = {isaligned_in, notintable_in, disperror_in, charisk_in, data_in};
assign isaligned_out = outdata[22]; assign isaligned_out = outdata[22];
assign charisk_out = outdata[21:20]; assign notintable_out = outdata[21:20];
assign notintable_out = outdata[19:18]; assign disperror_out = outdata[19:18];
assign disperror_out = outdata[17:16]; assign charisk_out = outdata[17:16];
assign data_out = outdata[15:0]; assign data_out = outdata[15:0];
localparam HI = DEPTH_LOG2 - 1; // hi bus index localparam HI = DEPTH_LOG2 - 1; // hi bus index
...@@ -61,7 +61,7 @@ localparam HI = DEPTH_LOG2 - 1; // hi bus index ...@@ -61,7 +61,7 @@ localparam HI = DEPTH_LOG2 - 1; // hi bus index
* buffer itself * buffer itself
*/ */
// data storage // data storage
reg [22:0] ram [HI:0]; reg [22:0] ram [(1 << DEPTH_LOG2) - 1:0];
// data to/from fifo // data to/from fifo
wire [22:0] inram; wire [22:0] inram;
wire [22:0] outram; wire [22:0] outram;
...@@ -105,26 +105,26 @@ end ...@@ -105,26 +105,26 @@ end
// write address -> rclk (rd) domain to compare // write address -> rclk (rd) domain to compare
always @ (posedge rclk) always @ (posedge rclk)
begin begin
wr_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr; wr_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr_gr;
wr_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr_gr_r; wr_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr_gr_r;
end end
// read address -> wclk (wr) domain to compare // read address -> wclk (wr) domain to compare
always @ (posedge wclk) always @ (posedge wclk)
begin begin
rd_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr; rd_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr_gr;
rd_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr_gr_r; rd_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr_gr_r;
end end
// translate resynced write address into ordinary (non-gray) address // translate resynced write address into ordinary (non-gray) address
genvar ii; genvar ii;
generate generate
for (ii = 0; ii < HI; ii = ii + 1) for (ii = 0; ii <= HI; ii = ii + 1)
begin: wr_antigray begin: wr_antigray
assign wr_addr_r[ii] = ^wr_addr_gr_rr[HI:ii]; assign wr_addr_r[ii] = ^wr_addr_gr_rr[HI:ii];
end end
endgenerate endgenerate
// translate resynced read address into ordinary (non-gray) address // translate resynced read address into ordinary (non-gray) address
generate generate
for (ii = 0; ii < HI; ii = ii + 1) for (ii = 0; ii <= HI; ii = ii + 1)
begin: rd_antigray begin: rd_antigray
assign rd_addr_r[ii] = ^rd_addr_gr_rr[HI:ii]; assign rd_addr_r[ii] = ^rd_addr_gr_rr[HI:ii];
end end
...@@ -310,7 +310,7 @@ begin ...@@ -310,7 +310,7 @@ begin
state_send_ack <= (state_send_ack | set_send_ack ) & ~clr_send_ack & ~rst; state_send_ack <= (state_send_ack | set_send_ack ) & ~clr_send_ack & ~rst;
end end
assign skip_write = ~set_skip1_align & ~state_skip1_align; assign skip_write = set_skip1_align | state_skip1_align;
assign inram = indata_r; assign inram = indata_r;
assign we = ~skip_write; assign we = ~skip_write;
...@@ -387,12 +387,22 @@ always @ (posedge rclk) ...@@ -387,12 +387,22 @@ always @ (posedge rclk)
// choose 1 of 2 words of ALIGNP // choose 1 of 2 words of ALIGNP
wire [22:0] align_word; wire [22:0] align_word;
assign align_word = {outram[22], 22'h007B4A} & ~align_altern | {outram[22], 22'h014ABC} & align_altern; assign align_word = {outram[22], 22'h007B4A} & {23{~align_altern}} | {outram[22], 22'h014ABC} & {23{align_altern}};
// read when compensation is not issued and when fifo gets required fullfillment // read when compensation is not issued and when fifo gets required fullfillment
assign re = ~pause_read & fifo_stable; assign re = ~pause_read & fifo_stable;
assign outdata = {23{~pause_read}} & outram | {23{pause_read}} & align_word; assign outdata = {23{~pause_read}} & outram | {23{pause_read}} & align_word;
// indicates last cycle before the next primitive // indicates last cycle before the next primitive
assign lword_strobe = align_1st & align_2nd; wire fword_strobe_correction;
reg fword_strobe;
`ifdef SIMULATION
assign fword_strobe_correction = (align_1st === 1'bx || align_2nd === 1'bx) ? 1'b0 : align_1st & align_2nd ;
`else
assign fword_strobe_correction = align_1st & align_2nd;
`endif
always @ (posedge rclk)
fword_strobe <= rst ? 1'b0 : fword_strobe_correction ? 1'b1 : lword_strobe;
assign lword_strobe = ~fword_strobe;
endmodule endmodule
...@@ -74,6 +74,10 @@ module gtx_wrap #( ...@@ -74,6 +74,10 @@ module gtx_wrap #(
output wire [DATA_BYTE_WIDTH - 1:0] rxdisperr output wire [DATA_BYTE_WIDTH - 1:0] rxdisperr
); );
// resets while PCS resets
assign wrap_rxreset_ = rxuserrdy & rxresetdone_gtx;
assign wrap_txreset_ = txuserrdy & txresetdone_gtx;
wire [63:0] rxdata_gtx; wire [63:0] rxdata_gtx;
wire [7:0] rxcharisk_gtx; wire [7:0] rxcharisk_gtx;
wire [7:0] rxdisperr_gtx; wire [7:0] rxdisperr_gtx;
...@@ -98,8 +102,8 @@ assign txchardispval_gtx = {6'h0, txdata_enc_out[18], txdata_enc_out[8]}; ...@@ -98,8 +102,8 @@ assign txchardispval_gtx = {6'h0, txdata_enc_out[18], txdata_enc_out[8]};
// Interface part // Interface part
/* /*
input wire cpllreset, - async input wire cpllreset, - async
input wire rxuserrdy, - async input wire wrap_rxreset_, - async
input wire txuserrdy, - async input wire wrap_txreset_, - async
input wire rxreset, - async input wire rxreset, - async
input wire txreset, - async input wire txreset, - async
input wire txelecidle, - txusrclk2 - need to resync to gtx iface clk - txusrclk input wire txelecidle, - txusrclk2 - need to resync to gtx iface clk - txusrclk
...@@ -124,12 +128,12 @@ if (DATA_BYTE_WIDTH == 4) begin ...@@ -124,12 +128,12 @@ if (DATA_BYTE_WIDTH == 4) begin
wire [38:0] txdata_resync_out; wire [38:0] txdata_resync_out;
reg [35:0] txdata_resync; reg [35:0] txdata_resync;
assign txdata_enc_in = {16{~txdata_resync_strobe}} & txdata_resync[15:0] | {16{txdata_resync_strobe}} & txdata_resync[33:18]; assign txdata_enc_in = {16{~txdata_resync_strobe}} & txdata_resync[15:0] | {16{txdata_resync_strobe}} & txdata_resync[31:16];
assign txcharisk_enc_in = {2{~txdata_resync_strobe}} & txdata_resync[17:16] | {2{txdata_resync_strobe}} & txdata_resync[35:34]; assign txcharisk_enc_in = {2{~txdata_resync_strobe}} & txdata_resync[33:32] | {2{txdata_resync_strobe}} & txdata_resync[35:34];
always @ (posedge txusrclk) always @ (posedge txusrclk)
begin begin
txdata_resync <= ~txuserrdy ? 36'h0 : txdata_resync_nempty & txdata_resync_strobe ? txdata_resync_out[35:0] : txdata_resync; txdata_resync <= ~wrap_txreset_ ? 36'h0 : txdata_resync_nempty & txdata_resync_strobe ? txdata_resync_out[35:0] : txdata_resync;
txdata_resync_strobe <= ~txuserrdy ? 1'b0 : ~txdata_resync_nempty ? txdata_resync_strobe : ~txdata_resync_strobe; // -> 1 once every resynced dword = signal to latch it txdata_resync_strobe <= ~wrap_txreset_ ? 1'b0 : ~txdata_resync_nempty ? txdata_resync_strobe : ~txdata_resync_strobe; // -> 1 once every resynced dword = signal to latch it
end end
// nempty_rr & nempty => shall be at least 2 elements in fifo - safe to read // nempty_rr & nempty => shall be at least 2 elements in fifo - safe to read
...@@ -155,8 +159,8 @@ if (DATA_BYTE_WIDTH == 4) begin ...@@ -155,8 +159,8 @@ if (DATA_BYTE_WIDTH == 4) begin
.half_empty () .half_empty ()
); );
assign txcominit_gtx = txdata_resync_out[36]; assign txcomwake_gtx = txdata_resync_out[36];
assign txcomwake_gtx = txdata_resync_out[37]; assign txcominit_gtx = txdata_resync_out[37];
assign txelecidle_gtx = txdata_resync_out[38]; assign txelecidle_gtx = txdata_resync_out[38];
end end
else else
...@@ -179,7 +183,7 @@ endgenerate ...@@ -179,7 +183,7 @@ endgenerate
// 8/10 encoder @ txusrclk, 16 + 1 bits -> 20 // 8/10 encoder @ txusrclk, 16 + 1 bits -> 20
gtx_8x10enc gtx_8x10enc( gtx_8x10enc gtx_8x10enc(
.rst (~txuserrdy), .rst (~wrap_txreset_),
.clk (txusrclk), .clk (txusrclk),
.indata (txdata_enc_in), .indata (txdata_enc_in),
.inisk (txcharisk_enc_in), .inisk (txcharisk_enc_in),
...@@ -195,7 +199,7 @@ wire xclk; ...@@ -195,7 +199,7 @@ wire xclk;
// comma aligner // comma aligner
wire [19:0] rxdata_comma_in; wire [19:0] rxdata_comma_in;
wire [19:0] rxdata_comma_out; wire [19:0] rxdata_comma_out;
assign rxdata_comma_in = {rxdisperr_gtx[1], rxcharisk_gtx[1], rxdata[15:8], rxdisperr_gtx[0], rxcharisk_gtx[0], rxdata[7:0]}; assign rxdata_comma_in = {rxdisperr_gtx[1], rxcharisk_gtx[1], rxdata_gtx[15:8], rxdisperr_gtx[0], rxcharisk_gtx[0], rxdata_gtx[7:0]};
// aligner status generation // aligner status generation
// if we detected comma & there was 1st realign after non-aligned state -> triggered, we wait until the next comma // if we detected comma & there was 1st realign after non-aligned state -> triggered, we wait until the next comma
...@@ -218,12 +222,12 @@ assign clr_triggered = realign; ...@@ -218,12 +222,12 @@ assign clr_triggered = realign;
always @ (posedge xclk) always @ (posedge xclk)
begin begin
state_aligned <= (set_aligned | state_aligned ) & rxuserrdy & ~clr_aligned; state_aligned <= (set_aligned | state_aligned ) & wrap_rxreset_ & ~clr_aligned;
state_triggered <= (set_triggered | state_triggered) & rxuserrdy & ~clr_triggered; state_triggered <= (set_triggered | state_triggered) & wrap_rxreset_ & ~clr_triggered;
end end
gtx_comma_align gtx_comma_align( gtx_comma_align gtx_comma_align(
.rst (~rxuserrdy), .rst (~wrap_rxreset_),
.clk (xclk), .clk (xclk),
.indata (rxdata_comma_in), .indata (rxdata_comma_in),
.outdata (rxdata_comma_out), .outdata (rxdata_comma_out),
...@@ -240,7 +244,7 @@ wire [1:0] rxnotintable_dec_out; ...@@ -240,7 +244,7 @@ wire [1:0] rxnotintable_dec_out;
wire [1:0] rxdisperr_dec_out; wire [1:0] rxdisperr_dec_out;
gtx_10x8dec gtx_10x8dec( gtx_10x8dec gtx_10x8dec(
.rst (~rxuserrdy), .rst (~wrap_rxreset_),
.clk (xclk), .clk (xclk),
.indata (rxdata_comma_out), .indata (rxdata_comma_out),
.outdata (rxdata_dec_out), .outdata (rxdata_dec_out),
...@@ -262,7 +266,7 @@ gtx_elastic #( ...@@ -262,7 +266,7 @@ gtx_elastic #(
.OFFSET (4) .OFFSET (4)
) )
gtx_elastic( gtx_elastic(
.rst (~rxuserrdy), .rst (~wrap_rxreset_),
.wclk (xclk), .wclk (xclk),
.rclk (rxusrclk), .rclk (rxusrclk),
...@@ -306,6 +310,8 @@ generate ...@@ -306,6 +310,8 @@ generate
if (DATA_BYTE_WIDTH == 4) begin if (DATA_BYTE_WIDTH == 4) begin
// resync to rxusrclk // resync to rxusrclk
// Fin = 2*Fout => 2*WIDTHin = WIDTHout // Fin = 2*Fout => 2*WIDTHin = WIDTHout
// first data word arrived = last word of a primitive, second arrived - first one
// lword_strobe indicates that second data word is arrived
wire rxdata_resync_nempty; wire rxdata_resync_nempty;
reg rxdata_resync_nempty_r; reg rxdata_resync_nempty_r;
wire rxdata_resync_strobe; wire rxdata_resync_strobe;
...@@ -328,7 +334,7 @@ if (DATA_BYTE_WIDTH == 4) begin ...@@ -328,7 +334,7 @@ if (DATA_BYTE_WIDTH == 4) begin
rxdata_els_out, // 16 rxdata_els_out, // 16
rxdata_resync_buf[21:0]}; // 22 / 51 total rxdata_resync_buf[21:0]}; // 22 / 51 total
always @ (posedge rxusrclk) always @ (posedge rxusrclk)
rxdata_resync_buf <= ~rxuserrdy ? 36'h0 : rxdata_resync_strobe ? {elastic_full, elastic_empty, rxdisperr_els_out, rxnotintable_els_out, rxcharisk_els_out, rxdata_els_out} : rxdata_resync_buf; rxdata_resync_buf <= ~wrap_rxreset_ ? 36'h0 : ~rxdata_resync_strobe ? {elastic_full, elastic_empty, rxdisperr_els_out, rxnotintable_els_out, rxcharisk_els_out, rxdata_els_out} : rxdata_resync_buf;
always @ (posedge rxusrclk2) always @ (posedge rxusrclk2)
rxdata_resync_nempty_r <= rxdata_resync_nempty; rxdata_resync_nempty_r <= rxdata_resync_nempty;
...@@ -338,10 +344,10 @@ if (DATA_BYTE_WIDTH == 4) begin ...@@ -338,10 +344,10 @@ if (DATA_BYTE_WIDTH == 4) begin
.DATA_DEPTH (4) .DATA_DEPTH (4)
) )
rxdata_resynchro( rxdata_resynchro(
.rst (~rxuserrdy), .rst (~wrap_rxreset_),
.rclk (rxusrclk2), .rclk (rxusrclk2),
.wclk (rxusrclk), .wclk (rxusrclk),
.we (1'b1), .we (rxdata_resync_strobe),
.re (rxdata_resync_nempty & rxdata_resync_nempty_r), .re (rxdata_resync_nempty & rxdata_resync_nempty_r),
.data_in (rxdata_resync_in), .data_in (rxdata_resync_in),
.data_out (rxdata_resync_out), .data_out (rxdata_resync_out),
...@@ -355,10 +361,10 @@ if (DATA_BYTE_WIDTH == 4) begin ...@@ -355,10 +361,10 @@ if (DATA_BYTE_WIDTH == 4) begin
assign txresetdone = rxdata_resync_out[46]; assign txresetdone = rxdata_resync_out[46];
assign rxelsfull = rxdata_resync_out[45]; assign rxelsfull = rxdata_resync_out[45];
assign rxelsempty = rxdata_resync_out[44]; assign rxelsempty = rxdata_resync_out[44];
assign rxdisperr = {rxdata_resync_out[43:42], rxdata_resync_out[21:20]}; assign rxdisperr = {rxdata_resync_out[43:42], rxdata_resync_out[20:20]};
assign rxnotintable = {rxdata_resync_out[41:40], rxdata_resync_out[19:18]}; assign rxnotintable = {rxdata_resync_out[41:40], rxdata_resync_out[19:18]};
assign rxcharisk = {rxdata_resync_out[39:38], rxdata_resync_out[17:16]}; assign rxcharisk = {rxdata_resync_out[39:38], rxdata_resync_out[17:16]};
assign rxdata = {rxdata_resync_out[37:22], rxdata_resync_out[15:0]}; assign rxdata = {rxdata_resync_out[37:22], rxdata_resync_out[15:0] };
end end
else else
if (DATA_BYTE_WIDTH == 2) begin if (DATA_BYTE_WIDTH == 2) begin
...@@ -474,7 +480,7 @@ GTXE2_CHANNEL #( ...@@ -474,7 +480,7 @@ GTXE2_CHANNEL #(
.RXBUF_ADDR_MODE ("FAST"), .RXBUF_ADDR_MODE ("FAST"),
.RXBUF_EIDLE_HI_CNT (4'b1000), .RXBUF_EIDLE_HI_CNT (4'b1000),
.RXBUF_EIDLE_LO_CNT (4'b0000), .RXBUF_EIDLE_LO_CNT (4'b0000),
.RXBUF_EN ("TRUE"), .RXBUF_EN ("FALSE"),
.RX_BUFFER_CFG (6'b000000), .RX_BUFFER_CFG (6'b000000),
.RXBUF_RESET_ON_CB_CHANGE ("TRUE"), .RXBUF_RESET_ON_CB_CHANGE ("TRUE"),
.RXBUF_RESET_ON_COMMAALIGN ("FALSE"), .RXBUF_RESET_ON_COMMAALIGN ("FALSE"),
...@@ -644,7 +650,7 @@ gtx( ...@@ -644,7 +650,7 @@ gtx(
.RXCLKCORCNT (), .RXCLKCORCNT (),
.RX8B10BEN (1'b0), .RX8B10BEN (1'b0),
.RXUSRCLK (rxusrclk), .RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2), .RXUSRCLK2 (rxusrclk),
.RXDATA (rxdata_gtx), .RXDATA (rxdata_gtx),
.RXPRBSERR (), .RXPRBSERR (),
.RXPRBSSEL (3'd0), .RXPRBSSEL (3'd0),
...@@ -676,9 +682,9 @@ gtx( ...@@ -676,9 +682,9 @@ gtx(
.RXBYTEISALIGNED (), .RXBYTEISALIGNED (),
.RXBYTEREALIGN (), .RXBYTEREALIGN (),
.RXCOMMADET (), .RXCOMMADET (),
.RXCOMMADETEN (1'b1), .RXCOMMADETEN (1'b0),
.RXMCOMMAALIGNEN (1'b1), .RXMCOMMAALIGNEN (1'b0),
.RXPCOMMAALIGNEN (1'b1), .RXPCOMMAALIGNEN (1'b0),
.RXCHANBONDSEQ (), .RXCHANBONDSEQ (),
.RXCHBONDEN (1'b0), .RXCHBONDEN (1'b0),
.RXCHBONDLEVEL (3'd0), .RXCHBONDLEVEL (3'd0),
......
...@@ -182,7 +182,7 @@ wire clr_wait_synp; ...@@ -182,7 +182,7 @@ wire clr_wait_synp;
wire clr_wait_linkup; wire clr_wait_linkup;
wire clr_error; wire clr_error;
assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error & ~state_recal_tx; assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error & ~state_recal_tx & ~state_wait_rxrst & ~state_wait_eidle;
always @ (posedge clk) always @ (posedge clk)
begin begin
state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst; state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst;
...@@ -391,6 +391,24 @@ generate ...@@ -391,6 +391,24 @@ generate
end end
endgenerate endgenerate
`ifdef SIMULATION
// info msgs
always @ (posedge clk)
begin
if (txcominit) begin
$display("[Host] OOB: Issued cominit");
end
if (txcomwake) begin
$display("[Host] OOB: Issued comwake");
end
if (state_wait_linkup) begin
$display("[Host] OOB: Link is up");
end
if (set_wait_synp) begin
$display("[Host] OOB: Started continious align sending");
end
end
always @ (posedge clk) always @ (posedge clk)
rxcom_timer <= rst | rxcominit_done & state_wait_cominit | rxcomwake_done & state_wait_comwake | rxcominitdet & state_wait_cominit | rxcomwakedet & state_wait_comwake ? 10'h0 : cominit_req_l & state_idle | rxcominitdet_l & state_wait_cominit | rxcomwakedet_l & state_wait_comwake ? rxcom_timer + CLK_TO_TIMER_CONTRIB : 10'h0; rxcom_timer <= rst | rxcominit_done & state_wait_cominit | rxcomwake_done & state_wait_comwake | rxcominitdet & state_wait_cominit | rxcomwakedet & state_wait_comwake ? 10'h0 : cominit_req_l & state_idle | rxcominitdet_l & state_wait_cominit | rxcomwakedet_l & state_wait_comwake ? rxcom_timer + CLK_TO_TIMER_CONTRIB : 10'h0;
......
...@@ -17,7 +17,8 @@ if [ "$GTX_PATH" == '' ] ...@@ -17,7 +17,8 @@ if [ "$GTX_PATH" == '' ]
then then
export GTX_PATH=$SATA_PATH export GTX_PATH=$SATA_PATH
fi fi
iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED #iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -I$SATA_PATH/x393/wrap -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED
iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -I$SATA_PATH/x393/wrap -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED
#iverilog $SATA_PATH/neat_phy.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v $SATA_PATH/neat_oob.v -y$UNISIMS_PATH #iverilog $SATA_PATH/neat_phy.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v $SATA_PATH/neat_oob.v -y$UNISIMS_PATH
#iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -f opts -stb -sglbl $1 2>&1| tee $LOGFILE_PATH #iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -f opts -stb -sglbl $1 2>&1| tee $LOGFILE_PATH
......
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