Commit bcfe20f6 authored by Alexey Grebenkin's avatar Alexey Grebenkin

GTX parallel logic is implemented externally

parent 7b39c393
......@@ -19,7 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`include "oob_dev.v"
module sata_phy_dev(
module sata_phy_dev #(
parameter DATA_BYTE_WIDTH = 4
)
(
// initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
input wire extrst,
// sata clk, generated in pll as usrclk2
......
......@@ -88,7 +88,7 @@ axibram_write #(
)
axibram_write(
.aclk (ACLK),
.rst (ARESETN),
.arst (ARESETN),
.awaddr (AWADDR),
.awvalid (AWVALID),
.awready (AWREADY),
......@@ -120,7 +120,7 @@ axibram_read #(
)
axibram_read(
.aclk (ACLK),
.rst (ARESETN),
.arst (ARESETN),
.araddr (ARADDR),
.arvalid (ARVALID),
.arready (ARREADY),
......
......@@ -537,7 +537,8 @@ V .MEMBRIDGE_ADDR (),
.FRAME_HEIGHT_BITS (),
.FRAME_WIDTH_BITS ()
)*/ membridge(
.rst (rst), // input
.mrst (rst), // input
.hrst (rst), // input
.mclk (hclk), // input
.hclk (hclk), // input
.cmd_ad (cmd_ad),
......@@ -604,9 +605,10 @@ V .MEMBRIDGE_ADDR (),
.afi_rresp (afi_rresp), // input[2:0]
.afi_rcount (afi_rcount), // input[7:0]
.afi_racount (afi_racount), // input[2:0]
.afi_rdissuecap1en (afi_rdissuecap1en), // output
.rdata_done (rdata_done)
.afi_rdissuecap1en (afi_rdissuecap1en)/*, // output
.rdata_done (rdata_done)*/
);
assign rdata_done = 1'b0;
sata_host sata_host(
.extrst (rst),
......
/*******************************************************************************
* Module: gtx_10x8dec
* Date: 2015-07-11
* Author: Alexey
* Description: 8x10 encoder implementation
*
* Copyright (c) 2015 Elphel, Inc.
* gtx_10x8dec.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gtx_10x8dec.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
module gtx_10x8dec(
input wire rst,
input wire clk,
input wire [19:0] indata,
output wire [15:0] outdata,
output wire [1:0] outisk,
output wire [1:0] notintable,
output wire [1:0] disperror
/* uncomment if necessary
input wire [0:0] inaux,
output wire [0:0] outaux, */
);
/*
uncomment if necessary
// bypass auxilary informational signals
reg [0:0] aux_r;
reg [0:0] aux_rr;
always @ (posedge clk)
begin
aux_r <= inaux;
aux_rr <= aux_r;
end
assign outaux = aux_rr;
*/
// split incoming data in 2 bytes
wire [9:0] addr0;
wire [9:0] addr1;
assign addr0 = indata[9:0];
assign addr1 = indata[19:10];
// get decoded values after 2 clock cycles, all '1's = cannot be decoded
wire [15:0] table0_out;
wire [15:0] table1_out;
wire [9:0] table0;
wire [9:0] table1;
assign table0 = table0_out[9:0];
assign table1 = table1_out[9:0];
assign outdata = {table1[7:0], table0[7:0]};
assign outisk = {table1[8], table0[8]};
assign notintable = {|table1, |table0};
// disparity control
// last clock disparity
reg disparity;
// disparity after 1st byte
wire disparity_interm;
// delayed ones
reg disp0_r;
reg disp1_r;
reg disp1_rr;
always @ (posedge clk)
begin
disp0_r <= disparity;
disp1_r <= disparity_interm;
disp1_rr <= disp1_r;
end
// overall expected disparity when the table values would apper - disp0_r.
// disp1_rr shows expected after 0st byte would be considered
wire expected_disparity;
wire expected_disparity_interm;
assign expected_disparity = disp0_r;
assign expected_disparity_interm = disp1_rr;
// 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 amounts are unequal, there are either 4 or 6 '1's. in either case disp shall be inverted
wire inv_disp0;
wire inv_disp1;
assign inv_disp0 = ~^(indata[9:0]);
assign inv_disp1 = ~^(indata[19:10]);
assign disparity_interm = inv_disp0 ? ~disparity : disparity;
always @ (posedge clk)
disparity <= rst ? 1'b0 : inv_disp1 ^ inv_disp0 ? ~disparity : disparity;
// to correct disparity if once an error occured
reg correct_table_disp;
always @ (posedge clk)
correct_table_disp <= rst ? 1'b0 : disperror ? ~correct_table_disp : correct_table_disp;
// calculate disparity on table values
wire table_disp0;
wire table_disp1;
assign table_disp0 = table0[9] ^ correct_table_disp;
assign table_disp1 = table1[9] ^ correct_table_disp;
assign disperror = {table_disp0 == expected_disparity, table_disp1 == expected_disparity_interm};
// TODO change mem to 18 instead of 36, so the highest address bit could be dropped
ramt_var_w_var_r #(
.REGISTERS_A (1),
.REGISTERS_B (1),
.LOG2WIDTH_A (4),
.LOG2WIDTH_B (4)
`include "gtx_10x8dec_init.v"
)
decoding_table(
.clk_a (clk),
.addr_a ({1'b0, addr0}),
.en_a (1'b1),
.regen_a (1'b1),
.we_a (1'b0),
.data_out_a (table0_out),
.data_in_a (16'h0),
.clk_b (clk),
.addr_b ({1'b0, addr1}),
.en_b (1'b1),
.regen_b (1'b1),
.we_b (1'b0),
.data_out_b (table1_out),
.data_in_b (16'h0)
);
endmodule
mem7f = []
for i in range(0x80):
mem7f.append(0);
i = 0
for line in open('gtx_10x8dec_init_stub.v').readlines():
addr = int('0b' + line.split()[1], 2)
a = int('0b' + line.split()[0], 2)
mem7f[addr >> 4] = (mem7f[addr >> 4] << 16) + a
i += 1
for i in range(0x80):
print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i])
, .INIT_00 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_01 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_02 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_03 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_04 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_05 (256'h00000000000000000000000000000217023702570277029702B702D702F703F7)
, .INIT_06 (256'h000000000000000000000000000000000208022802480268028802A802C802E8)
, .INIT_07 (256'h000000000000000000000000000000000207022702470267028702A702C702E7)
, .INIT_08 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_09 (256'h0000000000000000000000000000021B023B025B027B029B02BB02DB02FB03FB)
, .INIT_0A (256'h000000000000000000000000000000000204022402440264028402A402C402E4)
, .INIT_0B (256'h001402140034023400540254007402740094029400B402B400D402D400F402F4)
, .INIT_0C (256'h000000000000000000000000000000000218023802580278029802B802D802F8)
, .INIT_0D (256'h000C020C002C022C004C024C006C026C008C028C00AC02AC00CC02CC00EC02EC)
, .INIT_0E (256'h001C021C003C023C005C025C007C027C009C029C00BC02BC00DC02DC00FC02FC)
, .INIT_0F (256'h00000000000000000000000000000000011C013C015C017C019C01BC01DC01FC)
, .INIT_10 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_11 (256'h0000000000000000000000000000021D023D025D027D029D02BD02DD02FD03FD)
, .INIT_12 (256'h000000000000000000000000000000000202022202420262028202A202C202E2)
, .INIT_13 (256'h001202120032023200520252007202720092029200B202B200D202D200F202F2)
, .INIT_14 (256'h00000000000000000000000000000000021F023F025F027F029F02BF02DF02FF)
, .INIT_15 (256'h000A020A002A022A004A024A006A026A008A028A00AA02AA00CA02CA00EA02EA)
, .INIT_16 (256'h001A021A003A023A005A025A007A027A009A029A00BA02BA00DA02DA00FA02FA)
, .INIT_17 (256'h00000000000000000000000000000000000F002F004F006F008F00AF00CF00EF)
, .INIT_18 (256'h000000000000000000000000000000000200022002400260028002A002C002E0)
, .INIT_19 (256'h000602060026022600460246006602660086028600A602A600C602C600E602E6)
, .INIT_1A (256'h001602160036023600560256007602760096029600B602B600D602D600F602F6)
, .INIT_1B (256'h000000000000000000000000000000000010003000500070009000B000D000F0)
, .INIT_1C (256'h000E020E002E022E004E024E006E026E008E028E00AE02AE00CE02CE00EE02EE)
, .INIT_1D (256'h000000000000000000000000000000000001002100410061008100A100C100E1)
, .INIT_1E (256'h0000000000000000000000000000001E003E005E007E009E00BE00DE00FE01FE)
, .INIT_1F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_21 (256'h0000000000000000000000000000021E023E025E027E029E02BE02DE02FE03FE)
, .INIT_22 (256'h000000000000000000000000000000000201022102410261028102A102C102E1)
, .INIT_23 (256'h001102110031023100510251007102710091029100B102B100D102D100F102F1)
, .INIT_24 (256'h000000000000000000000000000000000210023002500270029002B002D002F0)
, .INIT_25 (256'h000902090029022900490249006902690089028900A902A900C902C900E902E9)
, .INIT_26 (256'h001902190039023900590259007902790099029900B902B900D902D900F902F9)
, .INIT_27 (256'h000000000000000000000000000000000000002000400060008000A000C000E0)
, .INIT_28 (256'h00000000000000000000000000000000020F022F024F026F028F02AF02CF02EF)
, .INIT_29 (256'h000502050025022500450245006502650085028500A502A500C502C500E502E5)
, .INIT_2A (256'h001502150035023500550255007502750095029500B502B500D502D500F502F5)
, .INIT_2B (256'h00000000000000000000000000000000001F003F005F007F009F00BF00DF00FF)
, .INIT_2C (256'h000D020D002D022D004D024D006D026D008D028D00AD02AD00CD02CD00ED02ED)
, .INIT_2D (256'h000000000000000000000000000000000002002200420062008200A200C200E2)
, .INIT_2E (256'h0000000000000000000000000000001D003D005D007D009D00BD00DD00FD01FD)
, .INIT_2F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_30 (256'h00000000000000000000000000000000031C033C035C037C039C03BC03DC03FC)
, .INIT_31 (256'h000302030023022300430243006302630083028300A302A300C302C300E302E3)
, .INIT_32 (256'h001302130033023300530253007302730093029300B302B300D302D300F302F3)
, .INIT_33 (256'h000000000000000000000000000000000018003800580078009800B800D800F8)
, .INIT_34 (256'h000B020B002B022B004B024B006B026B008B028B00AB02AB00CB02CB00EB02EB)
, .INIT_35 (256'h000000000000000000000000000000000004002400440064008400A400C400E4)
, .INIT_36 (256'h0000000000000000000000000000001B003B005B007B009B00BB00DB00FB01FB)
, .INIT_37 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_38 (256'h000000000000000000000000000000000007002700470067008700A700C700E7)
, .INIT_39 (256'h000000000000000000000000000000000008002800480068008800A800C800E8)
, .INIT_3A (256'h00000000000000000000000000000017003700570077009700B700D700F701F7)
, .INIT_3B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_40 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_41 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_42 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_43 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_44 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_45 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_46 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_47 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_48 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_49 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_50 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_51 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_52 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_53 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_54 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_55 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_56 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_57 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_58 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_59 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_60 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_61 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_62 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_63 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_64 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_65 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_66 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_67 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_68 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_69 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_70 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_71 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_72 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_73 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_74 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_75 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_76 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_77 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_78 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_79 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7F (256'h0000000000000000000000000000000000000000000000000000000000000000)
0000000000 1001110100
1000000000 0110001011
0000000001 0111010100
1000000001 1000101011
0000000010 1011010100
1000000010 0100101011
0000000011 1100011011
1000000011 1100010100
0000000100 1101010100
1000000100 0010101011
0000000101 1010011011
1000000101 1010010100
0000000110 0110011011
1000000110 0110010100
0000000111 1110001011
1000000111 0001110100
0000001000 1110010100
1000001000 0001101011
0000001001 1001011011
1000001001 1001010100
0000001010 0101011011
1000001010 0101010100
0000001011 1101001011
1000001011 1101000100
0000001100 0011011011
1000001100 0011010100
0000001101 1011001011
1000001101 1011000100
0000001110 0111001011
1000001110 0111000100
0000001111 0101110100
1000001111 1010001011
0000010000 0110110100
1000010000 1001001011
0000010001 1000111011
1000010001 1000110100
0000010010 0100111011
1000010010 0100110100
0000010011 1100101011
1000010011 1100100100
0000010100 0010111011
1000010100 0010110100
0000010101 1010101011
1000010101 1010100100
0000010110 0110101011
1000010110 0110100100
0000010111 1110100100
1000010111 0001011011
0000011000 1100110100
1000011000 0011001011
0000011001 1001101011
1000011001 1001100100
0000011010 0101101011
1000011010 0101100100
0000011011 1101100100
1000011011 0010011011
0000011100 0011101011
1000011100 0011100100
0000011101 1011100100
1000011101 0100011011
0000011110 0111100100
1000011110 1000011011
0000011111 1010110100
1000011111 0101001011
0000100000 1001111001
1000100000 0110001001
0000100001 0111011001
1000100001 1000101001
0000100010 1011011001
1000100010 0100101001
0000100011 1100011001
1000100011 1100011001
0000100100 1101011001
1000100100 0010101001
0000100101 1010011001
1000100101 1010011001
0000100110 0110011001
1000100110 0110011001
0000100111 1110001001
1000100111 0001111001
0000101000 1110011001
1000101000 0001101001
0000101001 1001011001
1000101001 1001011001
0000101010 0101011001
1000101010 0101011001
0000101011 1101001001
1000101011 1101001001
0000101100 0011011001
1000101100 0011011001
0000101101 1011001001
1000101101 1011001001
0000101110 0111001001
1000101110 0111001001
0000101111 0101111001
1000101111 1010001001
0000110000 0110111001
1000110000 1001001001
0000110001 1000111001
1000110001 1000111001
0000110010 0100111001
1000110010 0100111001
0000110011 1100101001
1000110011 1100101001
0000110100 0010111001
1000110100 0010111001
0000110101 1010101001
1000110101 1010101001
0000110110 0110101001
1000110110 0110101001
0000110111 1110101001
1000110111 0001011001
0000111000 1100111001
1000111000 0011001001
0000111001 1001101001
1000111001 1001101001
0000111010 0101101001
1000111010 0101101001
0000111011 1101101001
1000111011 0010011001
0000111100 0011101001
1000111100 0011101001
0000111101 1011101001
1000111101 0100011001
0000111110 0111101001
1000111110 1000011001
0000111111 1010111001
1000111111 0101001001
0001000000 1001110101
1001000000 0110000101
0001000001 0111010101
1001000001 1000100101
0001000010 1011010101
1001000010 0100100101
0001000011 1100010101
1001000011 1100010101
0001000100 1101010101
1001000100 0010100101
0001000101 1010010101
1001000101 1010010101
0001000110 0110010101
1001000110 0110010101
0001000111 1110000101
1001000111 0001110101
0001001000 1110010101
1001001000 0001100101
0001001001 1001010101
1001001001 1001010101
0001001010 0101010101
1001001010 0101010101
0001001011 1101000101
1001001011 1101000101
0001001100 0011010101
1001001100 0011010101
0001001101 1011000101
1001001101 1011000101
0001001110 0111000101
1001001110 0111000101
0001001111 0101110101
1001001111 1010000101
0001010000 0110110101
1001010000 1001000101
0001010001 1000110101
1001010001 1000110101
0001010010 0100110101
1001010010 0100110101
0001010011 1100100101
1001010011 1100100101
0001010100 0010110101
1001010100 0010110101
0001010101 1010100101
1001010101 1010100101
0001010110 0110100101
1001010110 0110100101
0001010111 1110100101
1001010111 0001010101
0001011000 1100110101
1001011000 0011000101
0001011001 1001100101
1001011001 1001100101
0001011010 0101100101
1001011010 0101100101
0001011011 1101100101
1001011011 0010010101
0001011100 0011100101
1001011100 0011100101
0001011101 1011100101
1001011101 0100010101
0001011110 0111100101
1001011110 1000010101
0001011111 1010110101
1001011111 0101000101
0001100000 1001110011
1001100000 0110001100
0001100001 0111010011
1001100001 1000101100
0001100010 1011010011
1001100010 0100101100
0001100011 1100011100
1001100011 1100010011
0001100100 1101010011
1001100100 0010101100
0001100101 1010011100
1001100101 1010010011
0001100110 0110011100
1001100110 0110010011
0001100111 1110001100
1001100111 0001110011
0001101000 1110010011
1001101000 0001101100
0001101001 1001011100
1001101001 1001010011
0001101010 0101011100
1001101010 0101010011
0001101011 1101001100
1001101011 1101000011
0001101100 0011011100
1001101100 0011010011
0001101101 1011001100
1001101101 1011000011
0001101110 0111001100
1001101110 0111000011
0001101111 0101110011
1001101111 1010001100
0001110000 0110110011
1001110000 1001001100
0001110001 1000111100
1001110001 1000110011
0001110010 0100111100
1001110010 0100110011
0001110011 1100101100
1001110011 1100100011
0001110100 0010111100
1001110100 0010110011
0001110101 1010101100
1001110101 1010100011
0001110110 0110101100
1001110110 0110100011
0001110111 1110100011
1001110111 0001011100
0001111000 1100110011
1001111000 0011001100
0001111001 1001101100
1001111001 1001100011
0001111010 0101101100
1001111010 0101100011
0001111011 1101100011
1001111011 0010011100
0001111100 0011101100
1001111100 0011100011
0001111101 1011100011
1001111101 0100011100
0001111110 0111100011
1001111110 1000011100
0001111111 1010110011
1001111111 0101001100
0010000000 1001110010
1010000000 0110001101
0010000001 0111010010
1010000001 1000101101
0010000010 1011010010
1010000010 0100101101
0010000011 1100011101
1010000011 1100010010
0010000100 1101010010
1010000100 0010101101
0010000101 1010011101
1010000101 1010010010
0010000110 0110011101
1010000110 0110010010
0010000111 1110001101
1010000111 0001110010
0010001000 1110010010
1010001000 0001101101
0010001001 1001011101
1010001001 1001010010
0010001010 0101011101
1010001010 0101010010
0010001011 1101001101
1010001011 1101000010
0010001100 0011011101
1010001100 0011010010
0010001101 1011001101
1010001101 1011000010
0010001110 0111001101
1010001110 0111000010
0010001111 0101110010
1010001111 1010001101
0010010000 0110110010
1010010000 1001001101
0010010001 1000111101
1010010001 1000110010
0010010010 0100111101
1010010010 0100110010
0010010011 1100101101
1010010011 1100100010
0010010100 0010111101
1010010100 0010110010
0010010101 1010101101
1010010101 1010100010
0010010110 0110101101
1010010110 0110100010
0010010111 1110100010
1010010111 0001011101
0010011000 1100110010
1010011000 0011001101
0010011001 1001101101
1010011001 1001100010
0010011010 0101101101
1010011010 0101100010
0010011011 1101100010
1010011011 0010011101
0010011100 0011101101
1010011100 0011100010
0010011101 1011100010
1010011101 0100011101
0010011110 0111100010
1010011110 1000011101
0010011111 1010110010
1010011111 0101001101
0010100000 1001111010
1010100000 0110001010
0010100001 0111011010
1010100001 1000101010
0010100010 1011011010
1010100010 0100101010
0010100011 1100011010
1010100011 1100011010
0010100100 1101011010
1010100100 0010101010
0010100101 1010011010
1010100101 1010011010
0010100110 0110011010
1010100110 0110011010
0010100111 1110001010
1010100111 0001111010
0010101000 1110011010
1010101000 0001101010
0010101001 1001011010
1010101001 1001011010
0010101010 0101011010
1010101010 0101011010
0010101011 1101001010
1010101011 1101001010
0010101100 0011011010
1010101100 0011011010
0010101101 1011001010
1010101101 1011001010
0010101110 0111001010
1010101110 0111001010
0010101111 0101111010
1010101111 1010001010
0010110000 0110111010
1010110000 1001001010
0010110001 1000111010
1010110001 1000111010
0010110010 0100111010
1010110010 0100111010
0010110011 1100101010
1010110011 1100101010
0010110100 0010111010
1010110100 0010111010
0010110101 1010101010
1010110101 1010101010
0010110110 0110101010
1010110110 0110101010
0010110111 1110101010
1010110111 0001011010
0010111000 1100111010
1010111000 0011001010
0010111001 1001101010
1010111001 1001101010
0010111010 0101101010
1010111010 0101101010
0010111011 1101101010
1010111011 0010011010
0010111100 0011101010
1010111100 0011101010
0010111101 1011101010
1010111101 0100011010
0010111110 0111101010
1010111110 1000011010
0010111111 1010111010
1010111111 0101001010
0011000000 1001110110
1011000000 0110000110
0011000001 0111010110
1011000001 1000100110
0011000010 1011010110
1011000010 0100100110
0011000011 1100010110
1011000011 1100010110
0011000100 1101010110
1011000100 0010100110
0011000101 1010010110
1011000101 1010010110
0011000110 0110010110
1011000110 0110010110
0011000111 1110000110
1011000111 0001110110
0011001000 1110010110
1011001000 0001100110
0011001001 1001010110
1011001001 1001010110
0011001010 0101010110
1011001010 0101010110
0011001011 1101000110
1011001011 1101000110
0011001100 0011010110
1011001100 0011010110
0011001101 1011000110
1011001101 1011000110
0011001110 0111000110
1011001110 0111000110
0011001111 0101110110
1011001111 1010000110
0011010000 0110110110
1011010000 1001000110
0011010001 1000110110
1011010001 1000110110
0011010010 0100110110
1011010010 0100110110
0011010011 1100100110
1011010011 1100100110
0011010100 0010110110
1011010100 0010110110
0011010101 1010100110
1011010101 1010100110
0011010110 0110100110
1011010110 0110100110
0011010111 1110100110
1011010111 0001010110
0011011000 1100110110
1011011000 0011000110
0011011001 1001100110
1011011001 1001100110
0011011010 0101100110
1011011010 0101100110
0011011011 1101100110
1011011011 0010010110
0011011100 0011100110
1011011100 0011100110
0011011101 1011100110
1011011101 0100010110
0011011110 0111100110
1011011110 1000010110
0011011111 1010110110
1011011111 0101000110
0011100000 1001110001
1011100000 0110001110
0011100001 0111010001
1011100001 1000101110
0011100010 1011010001
1011100010 0100101110
0011100011 1100011110
1011100011 1100010001
0011100100 1101010001
1011100100 0010101110
0011100101 1010011110
1011100101 1010010001
0011100110 0110011110
1011100110 0110010001
0011100111 1110001110
1011100111 0001110001
0011101000 1110010001
1011101000 0001101110
0011101001 1001011110
1011101001 1001010001
0011101010 0101011110
1011101010 0101010001
0011101011 1101001110
1011101011 1101001000
0011101100 0011011110
1011101100 0011010001
0011101101 1011001110
1011101101 1011001000
0011101110 0111001110
1011101110 0111001000
0011101111 0101110001
1011101111 1010001110
0011110000 0110110001
1011110000 1001001110
0011110001 1000110111
1011110001 1000110001
0011110010 0100110111
1011110010 0100110001
0011110011 1100101110
1011110011 1100100001
0011110100 0010110111
1011110100 0010110001
0011110101 1010101110
1011110101 1010100001
0011110110 0110101110
1011110110 0110100001
0011110111 1110100001
1011110111 0001011110
0011111000 1100110001
1011111000 0011001110
0011111001 1001101110
1011111001 1001100001
0011111010 0101101110
1011111010 0101100001
0011111011 1101100001
1011111011 0010011110
0011111100 0011101110
1011111100 0011100001
0011111101 1011100001
1011111101 0100011110
0011111110 0111100001
1011111110 1000011110
0011111111 1010110001
1011111111 0101001110
0100011100 0011110100
1100011100 1100001011
0100111100 0011111001
1100111100 1100000110
0101011100 0011110101
1101011100 1100001010
0101111100 0011110011
1101111100 1100001100
0110011100 0011110010
1110011100 1100001101
0110111100 0011111010
1110111100 1100000101
0111011100 0011110110
1111011100 1100001001
0111111100 0011111000
1111111100 1100000111
0111110111 1110101000
1111110111 0001010111
0111111011 1101101000
1111111011 0010010111
0111111101 1011101000
1111111101 0100010111
0111111110 0111101000
1111111110 1000010111
/*******************************************************************************
* Module: gtx_8x10enc
* Date: 2015-07-11
* Author: Alexey
* Description: 8x10 encoder implementation
*
* Copyright (c) 2015 Elphel, Inc.
* gtx_8x10enc.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gtx_8x10enc.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
module gtx_8x10enc(
input wire rst,
input wire clk,
input wire [1:0] inisk,
input wire [15:0] indata,
output wire [19:0] outdata
);
// addresses to reference an encoding table
wire [8:0] addr0;
wire [8:0] addr1;
assign addr0 = {inisk[0], indata[7:0]};
assign addr1 = {inisk[1], indata[15:8]};
// possible encoded data - both disparities, for both bytes
// due to registered memory output, this values will be valid after 2 clock cycles
// table[i] [9:0] in case of current disparity +, [19:10] in case of -
wire [31:0] table0_out;
wire [31:0] table1_out;
wire [19:0] table0;
wire [19:0] table1;
assign table0 = table0_out[19:0];
assign table1 = table1_out[19:0];
// encoded bytes
wire [9:0] enc0;
wire [9:0] enc1;
reg [9:0] enc0_r;
reg [9:0] enc1_r;
// running displarity, 0 = -, 1 = +
reg disparity;
// running disparity after encoding 1st byte
wire disparity_interm;
// 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 amounts are unequal, there are either 4 or 6 '1's. in either case disp shall be inverted
wire inv_disp0;
wire inv_disp1;
assign inv_disp0 = ~^enc0;
assign inv_disp1 = ~^enc1;
assign disparity_interm = inv_disp0 ? ~disparity : disparity;
always @ (posedge clk)
disparity <= rst ? 1'b0 : inv_disp1 ^ inv_disp0 ? ~disparity : disparity;
// select encoded bytes depending on a previous disparity
assign enc0 = ~disparity & table0[19:10] | disparity & table0[9:0];
assign enc1 = ~disparity_interm & table1[19:10] | disparity_interm & table1[9:0];
// latch output data
reg [19:0] outdata_l;
assign outdata = outdata_l;
always @ (posedge clk)
outdata_l <= {enc1, enc0};
ramt_var_w_var_r #(
.REGISTERS_A (1),
.REGISTERS_B (1),
.LOG2WIDTH_A (5),
.LOG2WIDTH_B (5)
`include "gtx_8x10enc_init.v"
)
encoding_table(
.clk_a (clk),
.addr_a ({1'b0, addr0}),
.en_a (1'b1),
.regen_a (1'b1),
.we_a (1'b0),
.data_out_a (table0_out),
.data_in_a (32'h0),
.clk_b (clk),
.addr_b ({1'b0, addr1}),
.en_b (1'b1),
.regen_b (1'b1),
.we_b (1'b0),
.data_out_b (table1_out),
.data_in_b (32'h0)
);
`ifdef CHECKERS_ENABLED
reg [8:0] addr0_r;
reg [8:0] addr1_r;
reg [8:0] addr0_rr;
reg [8:0] addr1_rr;
always @ (posedge clk)
begin
addr0_r <= addr0;
addr1_r <= addr1;
addr0_rr <= addr0_r;
addr1_rr <= addr1_r;
end
always @ (posedge clk)
if (~rst)
if (|table0 | |table1) begin
// all good
end
else begin
// got xxxx or 0000, both cases tell us addresses were bad
$display("Error in %m: bad incoming data: 1) K = %h, Data = %h 2) K = %h, Data = %h", addr0_rr[8], addr0_rr[7:0], addr1_rr[8], addr1_rr[7:0]);
$finish;
end
`endif // CHECKERS_ENABLED
endmodule
mem7f = []
for i in range(0x80):
mem7f.append(0);
i = 0
for line in open('gtx_8x10enc_init_stub.v').readlines():
addr = int('0b' + line.split()[0], 2)
a = int('0b' + line.split()[1], 2)
b = int('0b' + line.split()[2], 2)
mem7f[addr >> 3] = (((mem7f[addr >> 3] << 16) + b) << 16) + a
i += 1
for i in range(0x80):
print ', .INIT_%02X\t(256\'h%064X)' % (i, mem7f[i])
, .INIT_00 (256'h018B0274022B01D4012B02D40314031B00AB03540294029B0194019B0074038B)
, .INIT_01 (256'h006B03940254025B0154015B0344034B00D400DB02C402CB01C401CB028B0174)
, .INIT_02 (256'h024B01B40234023B0134013B0324032B00B400BB02A402AB01A401AB005B03A4)
, .INIT_03 (256'h00CB03340264026B0164016B009B036400E400EB011B02E4021B01E4014B02B4)
, .INIT_04 (256'h01890279022901D9012902D90319031900A90359029902990199019900790389)
, .INIT_05 (256'h0069039902590259015901590349034900D900D902C902C901C901C902890179)
, .INIT_06 (256'h024901B902390239013901390329032900B900B902A902A901A901A9005903A9)
, .INIT_07 (256'h00C9033902690269016901690099036900E900E9011902E9021901E9014902B9)
, .INIT_08 (256'h01850275022501D5012502D50315031500A50355029502950195019500750385)
, .INIT_09 (256'h0065039502550255015501550345034500D500D502C502C501C501C502850175)
, .INIT_0A (256'h024501B502350235013501350325032500B500B502A502A501A501A5005503A5)
, .INIT_0B (256'h00C5033502650265016501650095036500E500E5011502E5021501E5014502B5)
, .INIT_0C (256'h018C0273022C01D3012C02D30313031C00AC03530293029C0193019C0073038C)
, .INIT_0D (256'h006C03930253025C0153015C0343034C00D300DC02C302CC01C301CC028C0173)
, .INIT_0E (256'h024C01B30233023C0133013C0323032C00B300BC02A302AC01A301AC005C03A3)
, .INIT_0F (256'h00CC03330263026C0163016C009C036300E300EC011C02E3021C01E3014C02B3)
, .INIT_10 (256'h018D0272022D01D2012D02D20312031D00AD03520292029D0192019D0072038D)
, .INIT_11 (256'h006D03920252025D0152015D0342034D00D200DD02C202CD01C201CD028D0172)
, .INIT_12 (256'h024D01B20232023D0132013D0322032D00B200BD02A202AD01A201AD005D03A2)
, .INIT_13 (256'h00CD03320262026D0162016D009D036200E200ED011D02E2021D01E2014D02B2)
, .INIT_14 (256'h018A027A022A01DA012A02DA031A031A00AA035A029A029A019A019A007A038A)
, .INIT_15 (256'h006A039A025A025A015A015A034A034A00DA00DA02CA02CA01CA01CA028A017A)
, .INIT_16 (256'h024A01BA023A023A013A013A032A032A00BA00BA02AA02AA01AA01AA005A03AA)
, .INIT_17 (256'h00CA033A026A026A016A016A009A036A00EA00EA011A02EA021A01EA014A02BA)
, .INIT_18 (256'h01860276022601D6012602D60316031600A60356029602960196019600760386)
, .INIT_19 (256'h0066039602560256015601560346034600D600D602C602C601C601C602860176)
, .INIT_1A (256'h024601B602360236013601360326032600B600B602A602A601A601A6005603A6)
, .INIT_1B (256'h00C6033602660266016601660096036600E600E6011602E6021601E6014602B6)
, .INIT_1C (256'h018E0271022E01D1012E02D10311031E00AE03510291029E0191019E0071038E)
, .INIT_1D (256'h006E03910251025E0151015E0348034E00D100DE02C802CE01C801CE028E0171)
, .INIT_1E (256'h024E01B102310237013101370321032E00B100B702A102AE01A101AE005E03A1)
, .INIT_1F (256'h00CE03310261026E0161016E009E036100E100EE011E02E1021E01E1014E02B1)
, .INIT_20 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_21 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_22 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_23 (256'h00000000000000000000000000000000000000000000000000000000030B00F4)
, .INIT_24 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_25 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_26 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_27 (256'h00000000000000000000000000000000000000000000000000000000030600F9)
, .INIT_28 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_29 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2B (256'h00000000000000000000000000000000000000000000000000000000030A00F5)
, .INIT_2C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_2F (256'h00000000000000000000000000000000000000000000000000000000030C00F3)
, .INIT_30 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_31 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_32 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_33 (256'h00000000000000000000000000000000000000000000000000000000030D00F2)
, .INIT_34 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_35 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_36 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_37 (256'h00000000000000000000000000000000000000000000000000000000030500FA)
, .INIT_38 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_39 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3B (256'h00000000000000000000000000000000000000000000000000000000030900F6)
, .INIT_3C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_3E (256'h00000000000000000000000000000000000000000000000000000000005703A8)
, .INIT_3F (256'h00000000000000000000000000000000030700F800970368011702E8021701E8)
, .INIT_40 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_41 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_42 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_43 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_44 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_45 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_46 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_47 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_48 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_49 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_4F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_50 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_51 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_52 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_53 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_54 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_55 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_56 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_57 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_58 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_59 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_5F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_60 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_61 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_62 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_63 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_64 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_65 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_66 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_67 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_68 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_69 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_6F (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_70 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_71 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_72 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_73 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_74 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_75 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_76 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_77 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_78 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_79 (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7A (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7B (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7C (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7D (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7E (256'h0000000000000000000000000000000000000000000000000000000000000000)
, .INIT_7F (256'h0000000000000000000000000000000000000000000000000000000000000000)
000000000 1001110100 0110001011
000000001 0111010100 1000101011
000000010 1011010100 0100101011
000000011 1100011011 1100010100
000000100 1101010100 0010101011
000000101 1010011011 1010010100
000000110 0110011011 0110010100
000000111 1110001011 0001110100
000001000 1110010100 0001101011
000001001 1001011011 1001010100
000001010 0101011011 0101010100
000001011 1101001011 1101000100
000001100 0011011011 0011010100
000001101 1011001011 1011000100
000001110 0111001011 0111000100
000001111 0101110100 1010001011
000010000 0110110100 1001001011
000010001 1000111011 1000110100
000010010 0100111011 0100110100
000010011 1100101011 1100100100
000010100 0010111011 0010110100
000010101 1010101011 1010100100
000010110 0110101011 0110100100
000010111 1110100100 0001011011
000011000 1100110100 0011001011
000011001 1001101011 1001100100
000011010 0101101011 0101100100
000011011 1101100100 0010011011
000011100 0011101011 0011100100
000011101 1011100100 0100011011
000011110 0111100100 1000011011
000011111 1010110100 0101001011
000100000 1001111001 0110001001
000100001 0111011001 1000101001
000100010 1011011001 0100101001
000100011 1100011001 1100011001
000100100 1101011001 0010101001
000100101 1010011001 1010011001
000100110 0110011001 0110011001
000100111 1110001001 0001111001
000101000 1110011001 0001101001
000101001 1001011001 1001011001
000101010 0101011001 0101011001
000101011 1101001001 1101001001
000101100 0011011001 0011011001
000101101 1011001001 1011001001
000101110 0111001001 0111001001
000101111 0101111001 1010001001
000110000 0110111001 1001001001
000110001 1000111001 1000111001
000110010 0100111001 0100111001
000110011 1100101001 1100101001
000110100 0010111001 0010111001
000110101 1010101001 1010101001
000110110 0110101001 0110101001
000110111 1110101001 0001011001
000111000 1100111001 0011001001
000111001 1001101001 1001101001
000111010 0101101001 0101101001
000111011 1101101001 0010011001
000111100 0011101001 0011101001
000111101 1011101001 0100011001
000111110 0111101001 1000011001
000111111 1010111001 0101001001
001000000 1001110101 0110000101
001000001 0111010101 1000100101
001000010 1011010101 0100100101
001000011 1100010101 1100010101
001000100 1101010101 0010100101
001000101 1010010101 1010010101
001000110 0110010101 0110010101
001000111 1110000101 0001110101
001001000 1110010101 0001100101
001001001 1001010101 1001010101
001001010 0101010101 0101010101
001001011 1101000101 1101000101
001001100 0011010101 0011010101
001001101 1011000101 1011000101
001001110 0111000101 0111000101
001001111 0101110101 1010000101
001010000 0110110101 1001000101
001010001 1000110101 1000110101
001010010 0100110101 0100110101
001010011 1100100101 1100100101
001010100 0010110101 0010110101
001010101 1010100101 1010100101
001010110 0110100101 0110100101
001010111 1110100101 0001010101
001011000 1100110101 0011000101
001011001 1001100101 1001100101
001011010 0101100101 0101100101
001011011 1101100101 0010010101
001011100 0011100101 0011100101
001011101 1011100101 0100010101
001011110 0111100101 1000010101
001011111 1010110101 0101000101
001100000 1001110011 0110001100
001100001 0111010011 1000101100
001100010 1011010011 0100101100
001100011 1100011100 1100010011
001100100 1101010011 0010101100
001100101 1010011100 1010010011
001100110 0110011100 0110010011
001100111 1110001100 0001110011
001101000 1110010011 0001101100
001101001 1001011100 1001010011
001101010 0101011100 0101010011
001101011 1101001100 1101000011
001101100 0011011100 0011010011
001101101 1011001100 1011000011
001101110 0111001100 0111000011
001101111 0101110011 1010001100
001110000 0110110011 1001001100
001110001 1000111100 1000110011
001110010 0100111100 0100110011
001110011 1100101100 1100100011
001110100 0010111100 0010110011
001110101 1010101100 1010100011
001110110 0110101100 0110100011
001110111 1110100011 0001011100
001111000 1100110011 0011001100
001111001 1001101100 1001100011
001111010 0101101100 0101100011
001111011 1101100011 0010011100
001111100 0011101100 0011100011
001111101 1011100011 0100011100
001111110 0111100011 1000011100
001111111 1010110011 0101001100
010000000 1001110010 0110001101
010000001 0111010010 1000101101
010000010 1011010010 0100101101
010000011 1100011101 1100010010
010000100 1101010010 0010101101
010000101 1010011101 1010010010
010000110 0110011101 0110010010
010000111 1110001101 0001110010
010001000 1110010010 0001101101
010001001 1001011101 1001010010
010001010 0101011101 0101010010
010001011 1101001101 1101000010
010001100 0011011101 0011010010
010001101 1011001101 1011000010
010001110 0111001101 0111000010
010001111 0101110010 1010001101
010010000 0110110010 1001001101
010010001 1000111101 1000110010
010010010 0100111101 0100110010
010010011 1100101101 1100100010
010010100 0010111101 0010110010
010010101 1010101101 1010100010
010010110 0110101101 0110100010
010010111 1110100010 0001011101
010011000 1100110010 0011001101
010011001 1001101101 1001100010
010011010 0101101101 0101100010
010011011 1101100010 0010011101
010011100 0011101101 0011100010
010011101 1011100010 0100011101
010011110 0111100010 1000011101
010011111 1010110010 0101001101
010100000 1001111010 0110001010
010100001 0111011010 1000101010
010100010 1011011010 0100101010
010100011 1100011010 1100011010
010100100 1101011010 0010101010
010100101 1010011010 1010011010
010100110 0110011010 0110011010
010100111 1110001010 0001111010
010101000 1110011010 0001101010
010101001 1001011010 1001011010
010101010 0101011010 0101011010
010101011 1101001010 1101001010
010101100 0011011010 0011011010
010101101 1011001010 1011001010
010101110 0111001010 0111001010
010101111 0101111010 1010001010
010110000 0110111010 1001001010
010110001 1000111010 1000111010
010110010 0100111010 0100111010
010110011 1100101010 1100101010
010110100 0010111010 0010111010
010110101 1010101010 1010101010
010110110 0110101010 0110101010
010110111 1110101010 0001011010
010111000 1100111010 0011001010
010111001 1001101010 1001101010
010111010 0101101010 0101101010
010111011 1101101010 0010011010
010111100 0011101010 0011101010
010111101 1011101010 0100011010
010111110 0111101010 1000011010
010111111 1010111010 0101001010
011000000 1001110110 0110000110
011000001 0111010110 1000100110
011000010 1011010110 0100100110
011000011 1100010110 1100010110
011000100 1101010110 0010100110
011000101 1010010110 1010010110
011000110 0110010110 0110010110
011000111 1110000110 0001110110
011001000 1110010110 0001100110
011001001 1001010110 1001010110
011001010 0101010110 0101010110
011001011 1101000110 1101000110
011001100 0011010110 0011010110
011001101 1011000110 1011000110
011001110 0111000110 0111000110
011001111 0101110110 1010000110
011010000 0110110110 1001000110
011010001 1000110110 1000110110
011010010 0100110110 0100110110
011010011 1100100110 1100100110
011010100 0010110110 0010110110
011010101 1010100110 1010100110
011010110 0110100110 0110100110
011010111 1110100110 0001010110
011011000 1100110110 0011000110
011011001 1001100110 1001100110
011011010 0101100110 0101100110
011011011 1101100110 0010010110
011011100 0011100110 0011100110
011011101 1011100110 0100010110
011011110 0111100110 1000010110
011011111 1010110110 0101000110
011100000 1001110001 0110001110
011100001 0111010001 1000101110
011100010 1011010001 0100101110
011100011 1100011110 1100010001
011100100 1101010001 0010101110
011100101 1010011110 1010010001
011100110 0110011110 0110010001
011100111 1110001110 0001110001
011101000 1110010001 0001101110
011101001 1001011110 1001010001
011101010 0101011110 0101010001
011101011 1101001110 1101001000
011101100 0011011110 0011010001
011101101 1011001110 1011001000
011101110 0111001110 0111001000
011101111 0101110001 1010001110
011110000 0110110001 1001001110
011110001 1000110111 1000110001
011110010 0100110111 0100110001
011110011 1100101110 1100100001
011110100 0010110111 0010110001
011110101 1010101110 1010100001
011110110 0110101110 0110100001
011110111 1110100001 0001011110
011111000 1100110001 0011001110
011111001 1001101110 1001100001
011111010 0101101110 0101100001
011111011 1101100001 0010011110
011111100 0011101110 0011100001
011111101 1011100001 0100011110
011111110 0111100001 1000011110
011111111 1010110001 0101001110
100011100 0011110100 1100001011
100111100 0011111001 1100000110
101011100 0011110101 1100001010
101111100 0011110011 1100001100
110011100 0011110010 1100001101
110111100 0011111010 1100000101
111011100 0011110110 1100001001
111111100 0011111000 1100000111
111110111 1110101000 0001010111
111111011 1101101000 0010010111
111111101 1011101000 0100010111
111111110 0111101000 1000010111
/*******************************************************************************
* Module: gtx_comma_align
* Date: 2015-07-11
* Author: Alexey
* Description: comma aligner implementation
*
* Copyright (c) 2015 Elphel, Inc.
* gtx_comma_align.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gtx_comma_align.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
module gtx_comma_align(
input wire rst,
input wire clk,
input wire [19:0] indata,
output wire [19:0] outdata,
// outdata contains comma
output wire comma,
// pulse, indicating that stream was once again adjusted to a comma
// if asserted after link was down - OK
// if asserted during a work - most likely indicates an error in a stream
output wire realign
// asserted when input stream looks like comma, but it is not
// later on after 10/8 it would get something link NOTINTHETABLE error anyways
// output wire error
);
// only comma character = K28.5, has 5 '1's or 5 '0's in a row.
// after we met it, call it a comma group, we could compare other symbols
/*
// create a window
reg [19:0] indata_r;
wire [23:0] window;
always @ (posedge clk)
indata_r <= indata;
assign window = {indata_r[17:0], indata[19:14]};
// search for a comma group - parallel 24-bit window into 20 5-bit words
// transposed -> 5 x 20-bit words
wire [19:0] lane0;
wire [19:0] lane1;
wire [19:0] lane2;
wire [19:0] lane3;
wire [19:0] lane4;
assign lane0 = window[19:0];
assign lane1 = window[20:1];
assign lane2 = window[21:2];
assign lane3 = window[22:3];
assign lane4 = window[23:4];
// calcute at what position in a window comma group is detected,
// so the position in actual {indata_r, indata} would be +2 from the left side
wire [19:0] comma_pos;
assign comma_pos = lane0 & lane1 & lane2 & lane3 & lane4;
*/
// seach for a comma
// TODO make it less expensive
reg [19:0] indata_r;
wire [38:0] window;
always @ (posedge clk)
indata_r <= indata;
assign window = {indata_r, indata};
// there is only 1 matched subwindow due to 20-bit comma's non-repetative pattern
wire [19:0] subwindow [19:0];
wire [19:0] comma_match;
reg [19:0] aligned_data;
reg [19:0] comma_match_prev;
wire comma_detected;
genvar ii;
generate
for (ii = 0; ii < 20; ii = ii + 1)
begin: look_for_comma
assign subwindow[ii] = window[ii + 19:ii];
assign comma_match[ii] = subwindow[ii] == 20'b01010101010011111010;
end
endgenerate
assign comma_detected = |comma_match;
// save the shift count
always @ (posedge clk)
comma_match_prev <= rst ? 20'h0 : comma_detected ? comma_match : comma_match_prev;
// shift
wire [38:0] shifted_window;
assign shifted_window = comma_detected ? {window >> (comma_match - 1)} : {window >> (comma_match_prev - 1)};
always @ (posedge clk)
// aligned_data <= comma_detected ? {window >> (comma_match - 1)}[19:0] : {window >> (comma_match_prev - 1)}[19:0];
aligned_data <= shifted_window[19:0];
// form outputs
assign comma = comma_detected;
assign realign = comma_detected & |(comma_match_prev ^ comma_match);
assign outdata = aligned_data;
endmodule
/*******************************************************************************
* Module: gtx_elastic
* Date: 2015-07-11
* Author: Alexey
* Description: elastic buffer implementation
*
* Copyright (c) 2015 Elphel, Inc.
* gtx_elastic.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gtx_elastic.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
module gtx_elastic #(
parameter DEPTH_LOG2 = 3, // => 8 total rows
parameter OFFSET = 4 // distance between read and write pointers, = wr_ptr - rd_ptr
)
(
input wire rst,
input wire wclk,
input wire rclk,
input wire isaligned_in,
input wire [1:0] charisk_in,
input wire [1:0] notintable_in,
input wire [1:0] disperror_in,
input wire [15:0] data_in,
output wire isaligned_out,
output wire [1:0] charisk_out,
output wire [1:0] notintable_out,
output wire [1:0] disperror_out,
output wire [15:0] data_out,
// strobes LAST word in a dword primitive
output wire lword_strobe,
// status outputs, just in case
output wire full,
output wire empty
);
// gather inputs and outputs
wire [22:0] indata;
wire [22:0] outdata;
assign indata = {isaligned_in, notintable_in, disperror_in, charisk_in, data_in};
assign isaligned_out = outdata[22];
assign charisk_out = outdata[21:20];
assign notintable_out = outdata[19:18];
assign disperror_out = outdata[17:16];
assign data_out = outdata[15:0];
localparam HI = DEPTH_LOG2 - 1; // hi bus index
/*
* buffer itself
*/
// data storage
reg [22:0] ram [HI:0];
// data to/from fifo
wire [22:0] inram;
wire [22:0] outram;
// adresses in their natural clock domains
reg [HI:0] rd_addr;
reg [HI:0] wr_addr;
// incremened addresses
wire [HI:0] wr_next_addr;
wire [HI:0] rd_next_addr;
// gray coded addresses
reg [HI:0] rd_addr_gr;
reg [HI:0] wr_addr_gr;
// anti-metastability shift registers for gray-coded addresses
reg [HI:0] rd_addr_gr_r;
reg [HI:0] wr_addr_gr_r;
reg [HI:0] rd_addr_gr_rr;
reg [HI:0] wr_addr_gr_rr;
// resynced to opposite clks addresses
wire [HI:0] rd_addr_r;
wire [HI:0] wr_addr_r;
// fifo states
//wire full; // MAY BE full. ~full -> MUST NOT be full
//wire empty; // MAY BE empty. ~empty -> MUST NOT be empty
wire re;
wire we;
assign wr_next_addr = wr_addr + 1'b1;
assign rd_next_addr = rd_addr + 1'b1;
// wclk domain counters
always @ (posedge wclk)
begin
wr_addr <= rst ? {DEPTH_LOG2{1'b0}} : we ? wr_next_addr : wr_addr;
wr_addr_gr <= rst ? {DEPTH_LOG2{1'b0}} : we ? wr_next_addr ^ {1'b0, wr_next_addr[HI:1]} : wr_addr_gr;
end
// rclk domain counters
always @ (posedge rclk)
begin
rd_addr <= rst ? {DEPTH_LOG2{1'b0}} : re ? rd_next_addr : rd_addr;
rd_addr_gr <= rst ? {DEPTH_LOG2{1'b0}} : re ? rd_next_addr ^ {1'b0, rd_next_addr[HI:1]} : rd_addr_gr;
end
// write address -> rclk (rd) domain to compare
always @ (posedge rclk)
begin
wr_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr;
wr_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : wr_addr_gr_r;
end
// read address -> wclk (wr) domain to compare
always @ (posedge wclk)
begin
rd_addr_gr_r <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr;
rd_addr_gr_rr <= rst ? {DEPTH_LOG2{1'b0}} : rd_addr_gr_r;
end
// translate resynced write address into ordinary (non-gray) address
genvar ii;
generate
for (ii = 0; ii < HI; ii = ii + 1)
begin: wr_antigray
assign wr_addr_r[ii] = ^wr_addr_gr_rr[HI:ii];
end
endgenerate
// translate resynced read address into ordinary (non-gray) address
generate
for (ii = 0; ii < HI; ii = ii + 1)
begin: rd_antigray
assign rd_addr_r[ii] = ^rd_addr_gr_rr[HI:ii];
end
endgenerate
// so we've got the following:
// wclk domain: wr_addr - current write address
// rd_addr_r - read address some wclk ticks ago
// => we can say if the fifo have the possibility to be full
// since actual rd_addr could only be incremented
//
// rclk domain: rd_addr - current read address
// wr_addr_r - write address some rclk ticks ago
// => we can say if the fifo have the possibility to be empty
// since actual wr_addr could only be incremented
assign full = {wr_addr, 1'b0} == rd_addr_r + 1'b1;
assign empty = {wr_addr_r, 1'b0} == rd_addr;
assign outram = ram[rd_addr];
always @ (posedge wclk)
if (we)
ram[wr_addr] <= inram;
// elactic part
// control fifo state @ rclk domain
// sends a pulse to wclk domain for every necessary ALIGNP removal
// waits for response from wclk domain of a successful removal
// pauses fifo read and inserts ALIGNP
// @ rclk
// calculating an offset - a distance between write and read pointers
wire [HI:0] current_offset;
assign current_offset = wr_addr_r - rd_addr;
// more records in fifo than expected on 1 primitive = 2 words = 2 records
wire offset_more_on_1;
// more records in fifo than expected on 2 primitives or more = 4 words + = 4 records +
wire offset_more_on_2;
// less records than expected - can insert a lot of alignes instantly, so exact count is not important
wire offset_less;
// doesnt bother if offset is more on 1 word.
assign offset_more_on_1 = current_offset == (OFFSET + 2) | current_offset == (OFFSET + 3);
assign offset_more_on_2 = (current_offset > (OFFSET + 1)) & ~offset_more_on_1;
assign offset_less = current_offset < OFFSET;
`ifdef ENABLE_CHECKERS
always @ (posedge clk)
if (offset_less & (offset_more_on_1 | offset_more_on_1)) begin
$display("Error in %m. Wrong offset calculations");
$finish;
end
`endif
/*
* Case when we need to get rid of extra elements in fifo
*/
// control part @ rclk
wire rmv_ack_rclk;
wire state_idle_rmv;
reg state_rmv1_req;
reg state_rmv2_req;
reg state_wait_ack;
wire set_rmv1_req;
wire set_rmv2_req;
wire set_wait_ack;
wire clr_rmv1_req;
wire clr_rmv2_req;
wire clr_wait_ack;
assign state_idle_rmv = ~state_rmv1_req & ~state_rmv2_req & ~state_wait_ack;
assign set_rmv1_req = state_idle_rmv & offset_more_on_1;
assign set_rmv2_req = state_idle_rmv & offset_more_on_2;
assign set_wait_ack = state_rmv1_req | state_rmv2_req;
assign clr_rmv1_req = set_wait_ack;
assign clr_rmv2_req = set_wait_ack;
assign clr_wait_ack = rmv_ack_rclk;
always @ (posedge rclk)
begin
state_rmv1_req <= (state_rmv1_req | set_rmv1_req) & ~clr_rmv1_req & ~rst;
state_rmv2_req <= (state_rmv2_req | set_rmv2_req) & ~clr_rmv2_req & ~rst;
state_wait_ack <= (state_wait_ack | set_wait_ack) & ~clr_wait_ack & ~rst;
end
`ifdef ENABLE_CHECKERS
always @ (posedge rclk)
if (~rst)
if ((4'h0
+ state_rmv1_req
+ state_rmv2_req
+ state_wait_ack
+ state_idle_rmv
) == 4'h1) begin
// all good
end
else
begin
$display("Error in %m: wrong fsm states: %b", {state_rmv1_req, state_rmv2_req, state_wait_ack, state_idle_rmv});
$finish;
end
`endif
// align removal logic @ wclk
// we MUST compare current and next data pack even if the current one is a comma because
// the next data word could be either valid ALIGNP's or any other 2 bytes, which shall tell
// link layer that incorrect primitive has been received, so it can't be skipped
// also NO DISPARITY ERROR would be dropped
reg [22:0] indata_r;
always @ (posedge wclk)
indata_r <= indata;
// align is stored in a buffer right now
// ALIGNP = 7B4A4ABC
// charisk : 0 0 0 1
// notintbl: 0 0 0 0
// disperr: 0 0 0 0
wire align_det;
assign align_det = {indata[15:0], indata_r[15:0]} == 32'h7B4A4ABC
& {indata[17:16], indata_r[17:16]} == 4'b0001
& {indata[19:18], indata_r[19:18]} == 4'b0000
& {indata[21:20], indata_r[21:20]} == 4'b0000;
// fsm
/*
* bypass --req1--> wait for align --------------------------------------------------------> skip 1 primitive -> send ack -> bypass
* \ | /\
* req2--> wait for align -> skip 1 primitive -> wait until next ------align in buf--+ |
* prim is in buffer --not align in buf------------------------------+
*/
wire skip_write;
wire rmv1_req_wclk;
wire rmv2_req_wclk;
reg next_prim_loaded;
always @ (wclk)
next_prim_loaded <= state_wait_next_p;
wire state_bypass_rmv;
reg state_wait1_align;
reg state_skip1_align;
reg state_wait2_align;
reg state_skip2_align;
reg state_wait_next_p;
reg state_send_ack;
wire set_wait1_align;
wire set_skip1_align;
wire set_wait2_align;
wire set_skip2_align;
wire set_wait_next_p;
wire set_send_ack;
wire clr_wait1_align;
wire clr_skip1_align;
wire clr_wait2_align;
wire clr_skip2_align;
wire clr_wait_next_p;
wire clr_send_ack;
assign state_bypass_rmv = ~state_wait1_align & ~state_skip1_align & ~state_wait2_align & ~state_skip2_align & ~state_wait_next_p & ~state_send_ack;
assign set_wait1_align = state_bypass_rmv & rmv1_req_wclk & ~rmv2_req_wclk;
assign set_skip1_align = state_wait1_align & align_det | state_wait_next_p & next_prim_loaded & align_det;
assign set_wait2_align = state_bypass_rmv & rmv2_req_wclk;
assign set_skip2_align = state_wait2_align & align_det;
assign set_wait_next_p = state_skip2_align;
assign set_send_ack = state_skip1_align | state_wait_next_p & next_prim_loaded & ~align_det; // 1 cycle skip - while set_skip1, 2nd cycle - while state_skip1
assign clr_wait1_align = set_skip1_align;
assign clr_skip1_align = set_send_ack;
assign clr_wait2_align = set_skip2_align;
assign clr_skip2_align = set_wait_next_p;
assign clr_wait_next_p = set_send_ack | set_skip1_align;
assign clr_send_ack = state_send_ack;
always @ (posedge wclk)
begin
state_wait1_align <= (state_wait1_align | set_wait1_align) & ~clr_wait1_align & ~rst;
state_skip1_align <= (state_skip1_align | set_skip1_align) & ~clr_skip1_align & ~rst;
state_wait2_align <= (state_wait2_align | set_wait2_align) & ~clr_wait2_align & ~rst;
state_skip2_align <= (state_skip2_align | set_skip2_align) & ~clr_skip2_align & ~rst;
state_wait_next_p <= (state_wait_next_p | set_wait_next_p) & ~clr_wait_next_p & ~rst;
state_send_ack <= (state_send_ack | set_send_ack ) & ~clr_send_ack & ~rst;
end
assign skip_write = ~set_skip1_align & ~state_skip1_align;
assign inram = indata_r;
assign we = ~skip_write;
// cross-domain messaging
// just to simplify an algorithm, we don't serialize a request to remove 2 ALIGNP,
// instead make 2 independent request lines
pulse_cross_clock remove1_req(
.rst (rst),
.src_clk (rclk),
.dst_clk (wclk),
.in_pulse (state_rmv1_req),
.out_pulse (rmv1_req_wclk),
.busy ()
);
pulse_cross_clock remove2_req(
.rst (rst),
.src_clk (rclk),
.dst_clk (wclk),
.in_pulse (state_rmv2_req),
.out_pulse (rmv2_req_wclk),
.busy ()
);
// removal request ack
pulse_cross_clock remove_ack(
.rst (rst),
.src_clk (wclk),
.dst_clk (rclk),
.in_pulse (state_send_ack),
.out_pulse (rmv_ack_rclk),
.busy ()
);
// insert additional ALINGPs to head @ rclk
// 1 way to implement - search for align primitive at the head of fifo, and insert enough alignes right after detected one
// 2nd way - continiously send a pulse, indicating 1st word of each primitive.
// Choosing the 1st way
// start algorithm after fifo gets in a stable state - let it fill to predefined offset count
reg fifo_stable;
always @ (posedge rclk)
fifo_stable <= rst ? 1'b0 : ~fifo_stable & ~offset_less | fifo_stable;
// once again check if the current half-primitive is a part of an align
// no need to latch the whole outram
// indicator, that @ previous clock cycle there was a first word of ALIGNP
reg align_1st;
always @ (posedge rclk)
align_1st <= outram[15:0] == 16'h4ABC
& outram[17:16] == 2'b01
& outram[19:18] == 2'b00
& outram[21:20] == 2'b00;
// indicates that current word is a second word of ALIGNP
wire align_2nd;
assign align_2nd = outram[15:0] == 16'h7B4A
& outram[17:16] == 2'b00
& outram[19:18] == 2'b00
& outram[21:20] == 2'b00;
// whole align primitive is the last thing we read from fifo
reg read_align;
always @ (posedge rclk)
read_align <= rst ? 1'b0 : pause_read | align_1st & align_2nd;
// just to alternate alignp's words, = 0 => 1st word, = 1 => 2nd word
reg align_altern;
wire pause_read;
// also pause when offset gets ok, but only 1st word of alignp is sent - need to send 2nd word
assign pause_read = read_align & offset_less & fifo_stable | align_altern;
always @ (posedge rclk)
align_altern <= rst | ~pause_read ? 1'b0 : ~align_altern;
// choose 1 of 2 words of ALIGNP
wire [22:0] align_word;
assign align_word = {outram[22], 22'h007B4A} & ~align_altern | {outram[22], 22'h014ABC} & align_altern;
// read when compensation is not issued and when fifo gets required fullfillment
assign re = ~pause_read & fifo_stable;
assign outdata = {23{~pause_read}} & outram | {23{pause_read}} & align_word;
// indicates last cycle before the next primitive
assign lword_strobe = align_1st & align_2nd;
endmodule
/*******************************************************************************
* Module: gtx_wrap
* Date: 2015-08-24
* Author: Alexey
* Description: shall replace gtx's PCS part functions, bypassing PCS itself in gtx
*
* Copyright (c) 2015 Elphel, Inc.
* gtx_wrap.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* gtx_wrap.v file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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 "gtx_8x10enc.v"
`include "gtx_10x8dec.v"
`include "gtx_comma_align.v"
`include "gtx_elastic.v"
// All computations have been done in assumption of GTX interface being 20 bits wide!
module gtx_wrap #(
parameter DATA_BYTE_WIDTH = 4,
parameter TXPMARESET_TIME = 5'h1,
parameter RXPMARESET_TIME = 5'h11,
parameter RXCDRPHRESET_TIME = 5'h1,
parameter RXCDRFREQRESET_TIME = 5'h1,
parameter RXDFELPMRESET_TIME = 7'hf,
parameter RXISCANRESET_TIME = 5'h1,
parameter RXEYERESET_TIME = 7'h25
)
(
output wire cplllock,
input wire cplllockdetclk,
input wire cpllreset,
input wire gtrefclk,
input wire drpclk,
input wire rxuserrdy,
input wire txuserrdy,
input wire rxusrclk,
input wire rxusrclk2,
input wire rxp,
input wire rxn,
output wire rxbyteisaligned,
input wire rxreset,
output wire rxcomwakedet,
output wire rxcominitdet,
output wire rxelecidle,
output wire rxresetdone,
input wire txreset,
input wire txusrclk,
input wire txusrclk2,
input wire txelecidle,
output wire txp,
output wire txn,
output wire txoutclk,
input wire txpcsreset,
output wire txresetdone,
input wire txcominit,
input wire txcomwake,
// elastic buffer status
output wire rxelsfull,
output wire rxelsempty,
input wire [DATA_BYTE_WIDTH * 8 - 1:0] txdata,
input wire [DATA_BYTE_WIDTH - 1:0] txcharisk,
output wire [DATA_BYTE_WIDTH * 8 - 1:0] rxdata,
output wire [DATA_BYTE_WIDTH - 1:0] rxcharisk,
output wire [DATA_BYTE_WIDTH - 1:0] rxnotintable,
output wire [DATA_BYTE_WIDTH - 1:0] rxdisperr
);
wire [63:0] rxdata_gtx;
wire [7:0] rxcharisk_gtx;
wire [7:0] rxdisperr_gtx;
wire [63:0] txdata_gtx;
wire [7:0] txcharisk_gtx;
wire [7:0] txchardispval_gtx;
wire [7:0] txchardispmode_gtx;
// 8/10 encoder ifaces
wire [19:0] txdata_enc_out;
wire [15:0] txdata_enc_in;
wire [1:0] txcharisk_enc_in;
/*
* TX PCS, minor changes: 8/10 encoder + user interface resync
*/
// assuming GTX interface width = 20 bits
assign txdata_gtx = {48'h0, txdata_enc_out[17:10], txdata_enc_out[7:0]};
assign txcharisk_gtx = 8'h0; // 8/10 encoder is bypassed in gtx
assign txchardispmode_gtx = {6'h0, txdata_enc_out[19], txdata_enc_out[9]};
assign txchardispval_gtx = {6'h0, txdata_enc_out[18], txdata_enc_out[8]};
// Interface part
/*
input wire cpllreset, - async
input wire rxuserrdy, - async
input wire txuserrdy, - async
input wire rxreset, - async
input wire txreset, - async
input wire txelecidle, - txusrclk2 - need to resync to gtx iface clk - txusrclk
input wire txpcsreset, - async
input wire txcominit, - txusrclk2 - need to resync to gtx iface clk - txusrclk
input wire txcomwake, - txusrclk2 - need to resync to gtx iface clk - txusrclk
*/
// @ gtx iface clk
wire txcominit_gtx;
wire txcomwake_gtx;
wire txelecidle_gtx;
// insert resync if it's necessary
generate
if (DATA_BYTE_WIDTH == 4) begin
// resync to txusrclk
// 2*Fin = Fout => WIDTHin = 2*WIDTHout
wire txdata_resync_nempty;
reg txdata_resync_nempty_r;
reg txdata_resync_nempty_rr;
reg txdata_resync_strobe;
wire [38:0] txdata_resync_out;
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 txcharisk_enc_in = {2{~txdata_resync_strobe}} & txdata_resync[17:16] | {2{txdata_resync_strobe}} & txdata_resync[35:34];
always @ (posedge txusrclk)
begin
txdata_resync <= ~txuserrdy ? 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
end
// nempty_rr & nempty => shall be at least 2 elements in fifo - safe to read
always @ (posedge txusrclk2)
begin
txdata_resync_nempty_r <= txdata_resync_nempty;
txdata_resync_nempty_rr <= txdata_resync_nempty_r;
end
fifo_cross_clocks #(
.DATA_WIDTH (39),
.DATA_DEPTH (4)
)
txdata_resynchro(
.rst (txreset),
.rclk (txusrclk),
.wclk (txusrclk2),
.we (1'b1),
.re (txdata_resync_nempty & txdata_resync_nempty_rr & txdata_resync_strobe),
.data_in ({txelecidle, txcominit, txcomwake, txcharisk, txdata}),
.data_out (txdata_resync_out),
.nempty (txdata_resync_nempty),
.half_empty ()
);
assign txcominit_gtx = txdata_resync_out[36];
assign txcomwake_gtx = txdata_resync_out[37];
assign txelecidle_gtx = txdata_resync_out[38];
end
else
if (DATA_BYTE_WIDTH == 2) begin
// no resync is needed => straightforward assignments
assign txdata_enc_in = txdata;
assign txcharisk_enc_in = txcharisk;
assign txcominit_gtx = txcominit;
assign txcomwake_gtx = txcomwake;
assign txelecidle_gtx = txelecidle;
end
else begin
// unconsidered case
always @ (posedge txusrclk)
begin
$display("Wrong width set in %m, value is %d", DATA_BYTE_WIDTH);
end
end
endgenerate
// 8/10 encoder @ txusrclk, 16 + 1 bits -> 20
gtx_8x10enc gtx_8x10enc(
.rst (~txuserrdy),
.clk (txusrclk),
.indata (txdata_enc_in),
.inisk (txcharisk_enc_in),
.outdata (txdata_enc_out)
);
/*
* RX PCS part: comma detect + align module, 10/8 decoder, elastic buffer, interface resynchronisation
* all modules before elastic buffer shall work on a restored clock - xclk
*/
wire xclk;
// assuming GTX interface width = 20 bits
// comma aligner
wire [19:0] rxdata_comma_in;
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]};
// aligner status generation
// if we detected comma & there was 1st realign after non-aligned state -> triggered, we wait until the next comma
// if no realign would be issued, assumes, that we've aligned to the stream otherwise go back to non-aligned state
wire comma;
wire realign;
wire state_nonaligned;
reg state_aligned;
reg state_triggered;
wire set_aligned;
wire set_triggered;
wire clr_aligned;
wire clr_triggered;
assign state_nonaligned = ~state_aligned & ~state_triggered;
assign set_aligned = state_triggered & comma & ~realign;
assign set_triggered = state_nonaligned & comma;
assign clr_aligned = realign;
assign clr_triggered = realign;
always @ (posedge xclk)
begin
state_aligned <= (set_aligned | state_aligned ) & rxuserrdy & ~clr_aligned;
state_triggered <= (set_triggered | state_triggered) & rxuserrdy & ~clr_triggered;
end
gtx_comma_align gtx_comma_align(
.rst (~rxuserrdy),
.clk (xclk),
.indata (rxdata_comma_in),
.outdata (rxdata_comma_out),
.comma (comma),
.realign (realign)
);
//
// 10x8 decoder
wire [15:0] rxdata_dec_out;
wire [1:0] rxcharisk_dec_out;
wire [1:0] rxnotintable_dec_out;
wire [1:0] rxdisperr_dec_out;
gtx_10x8dec gtx_10x8dec(
.rst (~rxuserrdy),
.clk (xclk),
.indata (rxdata_comma_out),
.outdata (rxdata_dec_out),
.outisk (rxcharisk_dec_out),
.notintable (rxnotintable_dec_out),
.disperror (rxdisperr_dec_out)
);
// elastic buffer: transition from xclk to rxusrclk
wire [15:0] rxdata_els_out;
wire [1:0] rxcharisk_els_out;
wire [1:0] rxnotintable_els_out;
wire [1:0] rxdisperr_els_out;
wire lword_strobe;
wire isaligned;
gtx_elastic #(
.DEPTH_LOG2 (3),
.OFFSET (4)
)
gtx_elastic(
.rst (~rxuserrdy),
.wclk (xclk),
.rclk (rxusrclk),
.isaligned_in (state_aligned),
.charisk_in (rxcharisk_dec_out),
.notintable_in (rxnotintable_dec_out),
.disperror_in (rxdisperr_dec_out),
.data_in (rxdata_dec_out),
.isaligned_out (isaligned),
.charisk_out (rxcharisk_els_out),
.notintable_out (rxnotintable_els_out),
.disperror_out (rxdisperr_els_out),
.data_out (rxdata_els_out),
.lword_strobe (lword_strobe),
.full (elastic_full),
.empty (elastic_empty)
);
// iface resync
/*
output wire cplllock, - async
output wire rxbyteisaligned,- rxusrclk2
output wire rxcomwakedet, - rxusrclk2
output wire rxcominitdet, - rxusrclk2
output wire rxelecidle, - async
output wire rxresetdone, - rxusrclk2
output wire txresetdone, - txusrclk2
*/
wire rxcomwakedet_gtx;
wire rxcominitdet_gtx;
wire rxresetdone_gtx;
wire txresetdone_gtx;
// insert resync if it's necessary
generate
if (DATA_BYTE_WIDTH == 4) begin
// resync to rxusrclk
// Fin = 2*Fout => 2*WIDTHin = WIDTHout
wire rxdata_resync_nempty;
reg rxdata_resync_nempty_r;
wire rxdata_resync_strobe;
wire [50:0] rxdata_resync_in;
wire [50:0] rxdata_resync_out;
reg [23:0] rxdata_resync_buf;
assign rxdata_resync_strobe = lword_strobe;
assign rxdata_resync_in = {
isaligned, // 1
rxcomwakedet_gtx, // 1
rxcominitdet_gtx, // 1
rxresetdone_gtx, // 1
txresetdone_gtx, // 1
elastic_full | rxdata_resync_buf[23], // 1
elastic_empty | rxdata_resync_buf[22], // 1
rxdisperr_els_out, // 2
rxnotintable_els_out, // 2
rxcharisk_els_out, // 2
rxdata_els_out, // 16
rxdata_resync_buf[21:0]}; // 22 / 51 total
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;
always @ (posedge rxusrclk2)
rxdata_resync_nempty_r <= rxdata_resync_nempty;
fifo_cross_clocks #(
.DATA_WIDTH (51),
.DATA_DEPTH (4)
)
rxdata_resynchro(
.rst (~rxuserrdy),
.rclk (rxusrclk2),
.wclk (rxusrclk),
.we (1'b1),
.re (rxdata_resync_nempty & rxdata_resync_nempty_r),
.data_in (rxdata_resync_in),
.data_out (rxdata_resync_out),
.nempty (rxdata_resync_nempty),
.half_empty ()
);
assign rxbyteisaligned = rxdata_resync_out[50];
assign rxcomwakedet = rxdata_resync_out[49];
assign rxcominitdet = rxdata_resync_out[48];
assign rxresetdone = rxdata_resync_out[47];
assign txresetdone = rxdata_resync_out[46];
assign rxelsfull = rxdata_resync_out[45];
assign rxelsempty = rxdata_resync_out[44];
assign rxdisperr = {rxdata_resync_out[43:42], rxdata_resync_out[21:20]};
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 rxdata = {rxdata_resync_out[37:22], rxdata_resync_out[15:0]};
end
else
if (DATA_BYTE_WIDTH == 2) begin
// no resync is needed => straightforward assignments
assign rxbyteisaligned = isaligned;
assign rxcomwakedet = rxcomwakedet_gtx;
assign rxcominitdet = rxcominitdet_gtx;
assign rxresetdone = rxresetdone_gtx;
assign txresetdone = txresetdone_gtx;
assign rxelsfull = elastic_full;
assign rxelsempty = elastic_empty;
assign rxdisperr = rxdisperr_els_out;
assign rxnotintable = rxnotintable_els_out;
assign rxcharisk = rxcharisk_els_out;
assign rxdata = rxdata_els_out;
end
else begin
// unconsidered case
always @ (posedge txusrclk)
begin
$display("Wrong width set in %m, value is %d", DATA_BYTE_WIDTH);
end
end
endgenerate
GTXE2_CHANNEL #(
.SIM_RECEIVER_DETECT_PASS ("TRUE"),
.SIM_TX_EIDLE_DRIVE_LEVEL ("X"),
.SIM_RESET_SPEEDUP ("FALSE"),
.SIM_CPLLREFCLK_SEL (3'b001),
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
.ALIGN_PCOMMA_VALUE (10'b0101111100),
.SHOW_REALIGN_COMMA ("TRUE"),
.RXSLIDE_AUTO_WAIT (7),
.RXSLIDE_MODE ("OFF"),
.RX_SIG_VALID_DLY (10),
.RX_DISPERR_SEQ_MATCH ("TRUE"),
.DEC_MCOMMA_DETECT ("TRUE"),
.DEC_PCOMMA_DETECT ("TRUE"),
.DEC_VALID_COMMA_ONLY ("FALSE"),
.CBCC_DATA_SOURCE_SEL ("DECODED"),
.CLK_COR_SEQ_2_USE ("FALSE"),
.CLK_COR_KEEP_IDLE ("FALSE"),
.CLK_COR_MAX_LAT (9),
.CLK_COR_MIN_LAT (7),
.CLK_COR_PRECEDENCE ("TRUE"),
.CLK_COR_REPEAT_WAIT (0),
.CLK_COR_SEQ_LEN (1),
.CLK_COR_SEQ_1_ENABLE (4'b1111),
.CLK_COR_SEQ_1_1 (10'b0100000000),
.CLK_COR_SEQ_1_2 (10'b0000000000),
.CLK_COR_SEQ_1_3 (10'b0000000000),
.CLK_COR_SEQ_1_4 (10'b0000000000),
.CLK_CORRECT_USE ("FALSE"),
.CLK_COR_SEQ_2_ENABLE (4'b1111),
.CLK_COR_SEQ_2_1 (10'b0100000000),
.CLK_COR_SEQ_2_2 (10'b0000000000),
.CLK_COR_SEQ_2_3 (10'b0000000000),
.CLK_COR_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_KEEP_ALIGN ("FALSE"),
.CHAN_BOND_MAX_SKEW (1),
.CHAN_BOND_SEQ_LEN (1),
.CHAN_BOND_SEQ_1_1 (10'b0000000000),
.CHAN_BOND_SEQ_1_2 (10'b0000000000),
.CHAN_BOND_SEQ_1_3 (10'b0000000000),
.CHAN_BOND_SEQ_1_4 (10'b0000000000),
.CHAN_BOND_SEQ_1_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_1 (10'b0000000000),
.CHAN_BOND_SEQ_2_2 (10'b0000000000),
.CHAN_BOND_SEQ_2_3 (10'b0000000000),
.CHAN_BOND_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_SEQ_2_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_USE ("FALSE"),
.FTS_DESKEW_SEQ_ENABLE (4'b1111),
.FTS_LANE_DESKEW_CFG (4'b1111),
.FTS_LANE_DESKEW_EN ("FALSE"),
.ES_CONTROL (6'b000000),
.ES_ERRDET_EN ("FALSE"),
.ES_EYE_SCAN_EN ("TRUE"),
.ES_HORZ_OFFSET (12'h000),
.ES_PMA_CFG (10'b0000000000),
.ES_PRESCALE (5'b00000),
.ES_QUALIFIER (80'h00000000000000000000),
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
.PMA_RSV3 (2'b00),
.PMA_RSV4 (32'h00000000),
.RX_BIAS_CFG (12'b000000000100),
.DMONITOR_CFG (24'h000A00),
.RX_CM_SEL (2'b11),
.RX_CM_TRIM (3'b010),
.RX_DEBUG_CFG (12'b000000000000),
.RX_OS_CFG (13'b0000010000000),
.TERM_RCAL_CFG (5'b10000),
.TERM_RCAL_OVRD (1'b0),
.TST_RSV (32'h00000000),
.RX_CLK25_DIV (6),
.TX_CLK25_DIV (6),
.UCODEER_CLR (1'b0),
.PCS_PCIE_EN ("FALSE"),
.PCS_RSVD_ATTR (48'h0100),
.RXBUF_ADDR_MODE ("FAST"),
.RXBUF_EIDLE_HI_CNT (4'b1000),
.RXBUF_EIDLE_LO_CNT (4'b0000),
.RXBUF_EN ("TRUE"),
.RX_BUFFER_CFG (6'b000000),
.RXBUF_RESET_ON_CB_CHANGE ("TRUE"),
.RXBUF_RESET_ON_COMMAALIGN ("FALSE"),
.RXBUF_RESET_ON_EIDLE ("FALSE"),
.RXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.RXBUFRESET_TIME (5'b00001),
.RXBUF_THRESH_OVFLW (61),
.RXBUF_THRESH_OVRD ("FALSE"),
.RXBUF_THRESH_UNDFLW (4),
.RXDLY_CFG (16'h001F),
.RXDLY_LCFG (9'h030),
.RXDLY_TAP_CFG (16'h0000),
.RXPH_CFG (24'h000000),
.RXPHDLY_CFG (24'h084020),
.RXPH_MONITOR_SEL (5'b00000),
.RX_XCLK_SEL ("RXREC"),
.RX_DDI_SEL (6'b000000),
.RX_DEFER_RESET_BUF_EN ("TRUE"),
.RXCDR_CFG (72'h03000023ff10200020),
.RXCDR_FR_RESET_ON_EIDLE (1'b0),
.RXCDR_HOLD_DURING_EIDLE (1'b0),
.RXCDR_PH_RESET_ON_EIDLE (1'b0),
.RXCDR_LOCK_CFG (6'b010101),
.RXCDRFREQRESET_TIME (RXCDRFREQRESET_TIME),
.RXCDRPHRESET_TIME (RXCDRPHRESET_TIME),
.RXISCANRESET_TIME (RXISCANRESET_TIME),
.RXPCSRESET_TIME (5'b00001),
.RXPMARESET_TIME (RXPMARESET_TIME),
.RXOOB_CFG (7'b0000110),
.RXGEARBOX_EN ("FALSE"),
.GEARBOX_MODE (3'b000),
.RXPRBS_ERR_LOOPBACK (1'b0),
.PD_TRANS_TIME_FROM_P2 (12'h03c),
.PD_TRANS_TIME_NONE_P2 (8'h3c),
.PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64),
.SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0110),
.SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8),
.SATA_MAX_INIT (21),
.SATA_MAX_WAKE (7),
.SATA_MIN_BURST (4),
.SATA_MIN_INIT (12),
.SATA_MIN_WAKE (4),
.TRANS_TIME_RATE (8'h0E),
.TXBUF_EN ("TRUE"),
.TXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.TXDLY_CFG (16'h001F),
.TXDLY_LCFG (9'h030),
.TXDLY_TAP_CFG (16'h0000),
.TXPH_CFG (16'h0780),
.TXPHDLY_CFG (24'h084020),
.TXPH_MONITOR_SEL (5'b00000),
.TX_XCLK_SEL ("TXOUT"),
.TX_DATA_WIDTH (20),
.TX_DEEMPH0 (5'b00000),
.TX_DEEMPH1 (5'b00000),
.TX_EIDLE_ASSERT_DELAY (3'b110),
.TX_EIDLE_DEASSERT_DELAY (3'b100),
.TX_LOOPBACK_DRIVE_HIZ ("FALSE"),
.TX_MAINCURSOR_SEL (1'b0),
.TX_DRIVE_MODE ("DIRECT"),
.TX_MARGIN_FULL_0 (7'b1001110),
.TX_MARGIN_FULL_1 (7'b1001001),
.TX_MARGIN_FULL_2 (7'b1000101),
.TX_MARGIN_FULL_3 (7'b1000010),
.TX_MARGIN_FULL_4 (7'b1000000),
.TX_MARGIN_LOW_0 (7'b1000110),
.TX_MARGIN_LOW_1 (7'b1000100),
.TX_MARGIN_LOW_2 (7'b1000010),
.TX_MARGIN_LOW_3 (7'b1000000),
.TX_MARGIN_LOW_4 (7'b1000000),
.TXGEARBOX_EN ("FALSE"),
.TXPCSRESET_TIME (5'b00001),
.TXPMARESET_TIME (TXPMARESET_TIME),
.TX_RXDETECT_CFG (14'h1832),
.TX_RXDETECT_REF (3'b100),
.CPLL_CFG (24'hBC07DC),
.CPLL_FBDIV (4),
.CPLL_FBDIV_45 (5),
.CPLL_INIT_CFG (24'h00001E),
.CPLL_LOCK_CFG (16'h01E8),
.CPLL_REFCLK_DIV (1),
.RXOUT_DIV (2),
.TXOUT_DIV (2),
.SATA_CPLL_CFG ("VCO_3000MHZ"),
.RXDFELPMRESET_TIME (RXDFELPMRESET_TIME),
.RXLPM_HF_CFG (14'b00000011110000),
.RXLPM_LF_CFG (14'b00000011110000),
.RX_DFE_GAIN_CFG (23'h020FEA),
.RX_DFE_H2_CFG (12'b000000000000),
.RX_DFE_H3_CFG (12'b000001000000),
.RX_DFE_H4_CFG (11'b00011110000),
.RX_DFE_H5_CFG (11'b00011100000),
.RX_DFE_KL_CFG (13'b0000011111110),
.RX_DFE_LPM_CFG (16'h0954),
.RX_DFE_LPM_HOLD_DURING_EIDLE (1'b0),
.RX_DFE_UT_CFG (17'b10001111000000000),
.RX_DFE_VP_CFG (17'b00011111100000011),
.RX_CLKMUX_PD (1'b1),
.TX_CLKMUX_PD (1'b1),
.RX_INT_DATAWIDTH (0),
.TX_INT_DATAWIDTH (0),
.TX_QPI_STATUS_EN (1'b0),
.RX_DFE_KL_CFG2 (32'h301148AC),
.RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0)
)
gtx(
.CPLLFBCLKLOST (),
.CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk),
.CPLLLOCKEN (1'b1),
.CPLLPD (1'b0),
.CPLLREFCLKLOST (),
.CPLLREFCLKSEL (3'b001),
.CPLLRESET (cpllreset),
.GTRSVD (1'b0),
.PCSRSVDIN (1'b0),
.PCSRSVDIN2 (1'b0),
.PMARSVDIN (1'b0),
.PMARSVDIN2 (1'b0),
.TSTIN (1'b1),
.TSTOUT (),
.CLKRSVD (4'b0000),
.GTGREFCLK (1'b0),
.GTNORTHREFCLK0 (1'b0),
.GTNORTHREFCLK1 (1'b0),
.GTREFCLK0 (gtrefclk),
.GTREFCLK1 (1'b0),
.GTSOUTHREFCLK0 (1'b0),
.GTSOUTHREFCLK1 (1'b0),
.DRPADDR (9'b0),
.DRPCLK (drpclk),
.DRPDI (16'b0),
.DRPDO (),
.DRPEN (1'b0),
.DRPRDY (),
.DRPWE (1'b0),
.GTREFCLKMONITOR (),
.QPLLCLK (gtrefclk),
.QPLLREFCLK (gtrefclk),
.RXSYSCLKSEL (2'b00),
.TXSYSCLKSEL (2'b00),
.DMONITOROUT (),
.TX8B10BEN (1'b0),
.LOOPBACK (3'd0),
.PHYSTATUS (),
.RXRATE (3'd0),
.RXVALID (),
.RXPD (2'b00),
.TXPD (2'b00),
.SETERRSTATUS (1'b0),
.EYESCANRESET (1'b0),//rxreset), // p78
.RXUSERRDY (rxuserrdy),
.EYESCANDATAERROR (),
.EYESCANMODE (1'b0),
.EYESCANTRIGGER (1'b0),
.RXCDRFREQRESET (1'b0),
.RXCDRHOLD (1'b0),
.RXCDRLOCK (),
.RXCDROVRDEN (1'b0),
.RXCDRRESET (1'b0),
.RXCDRRESETRSV (1'b0),
.RXCLKCORCNT (),
.RX8B10BEN (1'b0),
.RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2),
.RXDATA (rxdata_gtx),
.RXPRBSERR (),
.RXPRBSSEL (3'd0),
.RXPRBSCNTRESET (1'b0),
.RXDFEXYDEN (1'b1),
.RXDFEXYDHOLD (1'b0),
.RXDFEXYDOVRDEN (1'b0),
.RXDISPERR (rxdisperr_gtx),
.RXNOTINTABLE (),
.GTXRXP (rxp),
.GTXRXN (rxn),
.RXBUFRESET (1'b0),
.RXBUFSTATUS (),
.RXDDIEN (1'b0),
.RXDLYBYPASS (1'b1),
.RXDLYEN (1'b0),
.RXDLYOVRDEN (1'b0),
.RXDLYSRESET (1'b0),
.RXDLYSRESETDONE (),
.RXPHALIGN (1'b0),
.RXPHALIGNDONE (),
.RXPHALIGNEN (1'b0),
.RXPHDLYPD (1'b0),
.RXPHDLYRESET (1'b0),
.RXPHMONITOR (),
.RXPHOVRDEN (1'b0),
.RXPHSLIPMONITOR (),
.RXSTATUS (),
.RXBYTEISALIGNED (),
.RXBYTEREALIGN (),
.RXCOMMADET (),
.RXCOMMADETEN (1'b1),
.RXMCOMMAALIGNEN (1'b1),
.RXPCOMMAALIGNEN (1'b1),
.RXCHANBONDSEQ (),
.RXCHBONDEN (1'b0),
.RXCHBONDLEVEL (3'd0),
.RXCHBONDMASTER (1'b0),
.RXCHBONDO (),
.RXCHBONDSLAVE (1'b0),
.RXCHANISALIGNED (),
.RXCHANREALIGN (),
.RXLPMHFHOLD (1'b0),
.RXLPMHFOVRDEN (1'b0),
.RXLPMLFHOLD (1'b0),
.RXDFEAGCHOLD (1'b0),
.RXDFEAGCOVRDEN (1'b0),
.RXDFECM1EN (1'b0),
.RXDFELFHOLD (1'b0),
.RXDFELFOVRDEN (1'b1),
.RXDFELPMRESET (rxreset),
.RXDFETAP2HOLD (1'b0),
.RXDFETAP2OVRDEN (1'b0),
.RXDFETAP3HOLD (1'b0),
.RXDFETAP3OVRDEN (1'b0),
.RXDFETAP4HOLD (1'b0),
.RXDFETAP4OVRDEN (1'b0),
.RXDFETAP5HOLD (1'b0),
.RXDFETAP5OVRDEN (1'b0),
.RXDFEUTHOLD (1'b0),
.RXDFEUTOVRDEN (1'b0),
.RXDFEVPHOLD (1'b0),
.RXDFEVPOVRDEN (1'b0),
// .RXDFEVSEN (1'b0),
.RXLPMLFKLOVRDEN (1'b0),
.RXMONITOROUT (),
.RXMONITORSEL (2'b01),
.RXOSHOLD (1'b0),
.RXOSOVRDEN (1'b0),
.RXRATEDONE (),
.RXOUTCLK (xclk),
.RXOUTCLKFABRIC (),
.RXOUTCLKPCS (),
.RXOUTCLKSEL (3'b010),
.RXDATAVALID (),
.RXHEADER (),
.RXHEADERVALID (),
.RXSTARTOFSEQ (),
.RXGEARBOXSLIP (1'b0),
.GTRXRESET (rxreset),
.RXOOBRESET (1'b0),
.RXPCSRESET (1'b0),
.RXPMARESET (1'b0),//rxreset), // p78
.RXLPMEN (1'b0),
.RXCOMSASDET (),
.RXCOMWAKEDET (rxcomwakedet_gtx),
.RXCOMINITDET (rxcominitdet_gtx),
.RXELECIDLE (rxelecidle),
.RXELECIDLEMODE (2'b00),
.RXPOLARITY (1'b0),
.RXSLIDE (1'b0),
.RXCHARISCOMMA (),
.RXCHARISK (rxcharisk_gtx),
.RXCHBONDI (5'b00000),
.RXRESETDONE (rxresetdone_gtx),
.RXQPIEN (1'b0),
.RXQPISENN (),
.RXQPISENP (),
.TXPHDLYTSTCLK (1'b0),
.TXPOSTCURSOR (5'b00000),
.TXPOSTCURSORINV (1'b0),
.TXPRECURSOR (5'd0),
.TXPRECURSORINV (1'b0),
.TXQPIBIASEN (1'b0),
.TXQPISTRONGPDOWN (1'b0),
.TXQPIWEAKPUP (1'b0),
.CFGRESET (1'b0),
.GTTXRESET (txreset),
.PCSRSVDOUT (),
.TXUSERRDY (txuserrdy),
.GTRESETSEL (1'b0),
.RESETOVRD (1'b0),
.TXCHARDISPMODE (txchardispmode_gtx),
.TXCHARDISPVAL (txchardispval_gtx),
.TXUSRCLK (txusrclk),
.TXUSRCLK2 (txusrclk),
.TXELECIDLE (txelecidle),
.TXMARGIN (3'd0),
.TXRATE (3'd0),
.TXSWING (1'b0),
.TXPRBSFORCEERR (1'b0),
.TXDLYBYPASS (1'b1),
.TXDLYEN (1'b0),
.TXDLYHOLD (1'b0),
.TXDLYOVRDEN (1'b0),
.TXDLYSRESET (1'b0),
.TXDLYSRESETDONE (),
.TXDLYUPDOWN (1'b0),
.TXPHALIGN (1'b0),
.TXPHALIGNDONE (),
.TXPHALIGNEN (1'b0),
.TXPHDLYPD (1'b0),
.TXPHDLYRESET (1'b0),
.TXPHINIT (1'b0),
.TXPHINITDONE (),
.TXPHOVRDEN (1'b0),
.TXBUFSTATUS (),
.TXBUFDIFFCTRL (3'b100),
.TXDEEMPH (1'b0),
.TXDIFFCTRL (4'b1000),
.TXDIFFPD (1'b0),
.TXINHIBIT (1'b0),
.TXMAINCURSOR (7'b0000000),
.TXPISOPD (1'b0),
.TXDATA (txdata_gtx),
.GTXTXN (txn),
.GTXTXP (txp),
.TXOUTCLK (txoutclk),
.TXOUTCLKFABRIC (),
.TXOUTCLKPCS (),
.TXOUTCLKSEL (3'b010),
.TXRATEDONE (),
.TXCHARISK (txcharisk_gtx),
.TXGEARBOXREADY (),
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone_gtx),
.TXCOMFINISH (),
.TXCOMINIT (txcominit_gtx),
.TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake_gtx),
.TXPDELECIDLEMODE (1'b0),
.TXPOLARITY (1'b0),
.TXDETECTRX (1'b0),
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP ()
);
endmodule
......@@ -41,9 +41,12 @@ module oob #(
output wire txcominit,
output wire txcomwake,
output wire txelecidle,
// partial tx reset
output wire txpcsreset_req,
input wire recal_tx_done,
// rx reset (after rxelecidle -> 0)
output wire rxreset_req,
input wire rxreset_ack,
// input data stream (if any data during OOB setting => ignored)
input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in,
......@@ -140,11 +143,21 @@ reg [9:0] rxcom_timer;
localparam COMINIT_DONE_TIME = 896; // 300Mhz cycles
localparam COMWAKE_DONE_TIME = 448; // 300Mhz cycles
// wait until rxelecidle is not stable (more or less) deasserted
// let's say, if rxelecidle = 0 longer, than 2 comwake burst duration (2 * 106.7 ns), elecidle is stable and we're receiving some data
// 2 * 106.7ns = 64 clock cycles @ 300 MHz, 32 @ 150, 16 @ 75
// rxelecidle is synchronous to sata host clk, sooo some idle raises can occur insensibly. Still, it means line issues,
// not affecting the fact, oob was done and a stage when device sends alignps started
reg [7:0] eidle_timer;
wire eidle_timer_done;
// fsm, doc p265,266
wire state_idle;
reg state_wait_cominit;
reg state_wait_comwake;
reg state_recal_tx;
reg state_wait_eidle;
reg state_wait_rxrst;
reg state_wait_align;
reg state_wait_synp;
reg state_wait_linkup;
......@@ -153,6 +166,8 @@ reg state_error;
wire set_wait_cominit;
wire set_wait_comwake;
wire set_recal_tx;
wire set_wait_eidle;
wire set_wait_rxrst;
wire set_wait_align;
wire set_wait_synp;
wire set_wait_linkup;
......@@ -160,6 +175,8 @@ wire set_error;
wire clr_wait_cominit;
wire clr_wait_comwake;
wire clr_recal_tx;
wire clr_wait_eidle;
wire clr_wait_rxrst;
wire clr_wait_align;
wire clr_wait_synp;
wire clr_wait_linkup;
......@@ -171,6 +188,8 @@ begin
state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst;
state_wait_comwake <= (state_wait_comwake | set_wait_comwake) & ~clr_wait_comwake & ~rst;
state_recal_tx <= (state_recal_tx | set_recal_tx ) & ~clr_recal_tx & ~rst;
state_wait_eidle <= (state_wait_eidle | set_wait_eidle ) & ~clr_wait_eidle & ~rst;
state_wait_rxrst <= (state_wait_rxrst | set_wait_rxrst ) & ~clr_wait_rxrst & ~rst;
state_wait_align <= (state_wait_align | set_wait_align ) & ~clr_wait_align & ~rst;
state_wait_synp <= (state_wait_synp | set_wait_synp ) & ~clr_wait_synp & ~rst;
state_wait_linkup <= (state_wait_linkup | set_wait_linkup ) & ~clr_wait_linkup & ~rst;
......@@ -180,13 +199,17 @@ end
assign set_wait_cominit = state_idle & oob_start & ~cominit_req;
assign set_wait_comwake = state_idle & cominit_req_l & cominit_allow & rxcominit_done | state_wait_cominit & rxcominitdet_l & rxcominit_done;
assign set_recal_tx = state_wait_comwake & rxcomwakedet_l & rxcomwake_done;
assign set_wait_align = state_recal_tx & recal_tx_done;
assign set_wait_eidle = state_recal_tx & recal_tx_done;
assign set_wait_rxrst = state_wait_eidle & eidle_timer_done;
assign set_wait_align = state_wait_rxrst & rxreset_ack;
assign set_wait_synp = state_wait_align & detected_alignp;
assign set_wait_linkup = state_wait_synp & detected_syncp;
assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_wait_align | state_wait_synp/* | state_wait_linkup*/);
assign set_error = timer_fin & (state_wait_cominit | state_wait_comwake | state_recal_tx | state_wait_eidle | state_wait_rxrst | state_wait_align | state_wait_synp/* | state_wait_linkup*/);
assign clr_wait_cominit = set_wait_comwake | set_error;
assign clr_wait_comwake = set_recal_tx | set_error;
assign clr_recal_tx = set_wait_align | set_error;
assign clr_recal_tx = set_wait_eidle | set_error;
assign clr_wait_eidle = set_wait_rxrst | set_error;
assign clr_wait_rxrst = set_wait_align | set_error;
assign clr_wait_align = set_wait_synp | set_error;
assign clr_wait_synp = set_wait_linkup | set_error;
assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
......@@ -216,6 +239,9 @@ assign oob_busy = ~state_idle;
// ask for recalibration
assign txpcsreset_req = state_recal_tx;
// ask for rxreset
assign rxreset_req = state_wait_rxrst;
// set gtx controls
reg txelecidle_r;
always @ (posedge clk)
......@@ -372,4 +398,10 @@ always @ (posedge clk)
assign txdata_out = txdata;
assign txcharisk_out = txcharisk;
// rxelectidle timer logic
assign eidle_timer_done = eidle_timer == 64;
always @ (posedge clk)
eidle_timer <= rst | rxelecidle | ~state_wait_eidle ? 8'b0 : eidle_timer + CLK_TO_TIMER_CONTRIB;
endmodule
......@@ -38,9 +38,12 @@ module oob_ctrl #(
output wire txcominit,
output wire txcomwake,
output wire txelecidle,
// partial tx reset
output wire txpcsreset_req,
input wire recal_tx_done,
// rx reset (after rxelecidle -> 0)
output wire rxreset_req,
input wire rxreset_ack,
// input data stream (if any data during OOB setting => ignored)
input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in,
......@@ -86,21 +89,12 @@ wire oob_silence;
// obvious
wire oob_busy;
// for the resync sake
reg rxbyteisaligned_r;
reg rxbyteisaligned_rr;
always @ (posedge clk)
begin
rxbyteisaligned_rr <= rxbyteisaligned_r;
rxbyteisaligned_r <= rxbyteisaligned;
end
// 1 - link is up and running, 0 - probably not
reg link_state;
// 1 - connection is being established OR already established, 0 - is not
reg oob_state;
assign phy_ready = link_state & gtx_ready & rxbyteisaligned_rr;
assign phy_ready = link_state & gtx_ready & rxbyteisaligned;
always @ (posedge clk)
link_state <= (link_state | link_up) & ~link_down & ~rst;
......@@ -140,6 +134,9 @@ oob
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
.rxreset_req (rxreset_req),
.rxreset_ack (rxreset_ack),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
......
......@@ -19,7 +19,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
`include "oob_ctrl.v"
module sata_phy(
`include "gtx_wrap.v"
module sata_phy #(
parameter DATA_BYTE_WIDTH = 4
)
(
// initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
input wire extrst,
// sata clk, generated in pll as usrclk2
......@@ -40,26 +44,30 @@ module sata_phy(
input wire rxn_in,
// to link layer
output wire [31:0] ll_data_out,
output wire [3:0] ll_charisk_out,
output wire [3:0] ll_err_out, // TODO!!!
output wire [DATA_BYTE_WIDTH * 8 - 1:0] ll_data_out,
output wire [DATA_BYTE_WIDTH - 1:0] ll_charisk_out,
output wire [DATA_BYTE_WIDTH - 1:0] ll_err_out, // TODO!!!
// from link layer
input wire [31:0] ll_data_in,
input wire [3:0] ll_charisk_in
input wire [DATA_BYTE_WIDTH * 8 - 1:0] ll_data_in,
input wire [DATA_BYTE_WIDTH - 1:0] ll_charisk_in
);
parameter CHIPSCOPE = "FALSE";
wire [31:0] txdata;
wire [3:0] txcharisk;
wire [63:0] rxdata;
wire [7:0] rxcharisk;
wire [31:0] rxdata_out;
wire [31:0] txdata_in;
wire [3:0] txcharisk_in;
wire [3:0] rxcharisk_out;
wire [DATA_BYTE_WIDTH * 8 - 1:0] txdata;
wire [DATA_BYTE_WIDTH * 8 - 1:0] rxdata;
wire [DATA_BYTE_WIDTH * 8 - 1:0] rxdata_out;
wire [DATA_BYTE_WIDTH * 8 - 1:0] txdata_in;
wire [DATA_BYTE_WIDTH - 1:0] txcharisk;
wire [DATA_BYTE_WIDTH - 1:0] rxcharisk;
wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in;
wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_out;
// once gtx_ready -> 1, gtx_configured latches
// after this point it's possible to perform additional resets and reconfigurations by higher-level logic
reg gtx_configured;
// after external rst -> 0, after sata logic resets -> 1
wire sata_reset_done;
wire rxcomwakedet;
wire rxcominitdet;
wire cplllock;
......@@ -71,6 +79,12 @@ wire txelecidle;
wire rxbyteisaligned;
wire txpcsreset_req;
wire recal_tx_done;
wire rxreset_req;
wire rxreset_ack;
wire rxreset_oob;
// elastic buffer status signals TODO
wire rxelsfull;
wire rxelsempty;
wire gtx_ready;
......@@ -94,6 +108,9 @@ oob_ctrl oob_ctrl(
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
.rxreset_req (rxreset_req),
.rxreset_ack (rxreset_ack),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
......@@ -161,24 +178,40 @@ always @ (posedge gtrefclk)
wire usrpll_locked;
assign cpllreset = extrst;
assign rxreset = ~cplllock | cpllreset;
assign rxreset = ~cplllock | cpllreset | rxreset_oob & gtx_configured;
assign txreset = ~cplllock | cpllreset;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done & sata_reset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done & sata_reset_done;
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// assert gtx_configured. Once gtx_ready -> 1, gtx_configured latches
always @ (posedge clk or posedge extrst)
gtx_configured <= extrst ? 1'b0 : gtx_ready | gtx_configured;
// issue partial tx reset to restore functionality after oob sequence. Let it lasts 8 clock lycles
reg [3:0] txpcsreset_cnt;
wire txpcsreset_stop;
assign txpcsreset_stop = txpcsreset_cnt[3];
assign txpcsreset = txpcsreset_req & ~txpcsreset_stop;
assign txpcsreset = txpcsreset_req & ~txpcsreset_stop & gtx_configured;
assign recal_tx_done = txpcsreset_stop & gtx_ready;
always @ (posedge clk or posedge extrst)
txpcsreset_cnt <= extrst | rst | ~txpcsreset_req ? 4'h0 : txpcsreset_stop ? txpcsreset_cnt : txpcsreset_cnt + 1'b1;
// issue rx reset to restore functionality after oob sequence. Let it lasts 8 clock lycles
reg [3:0] rxreset_oob_cnt;
wire rxreset_oob_stop;
assign rxreset_oob_stop = rxreset_oob_cnt[3];
assign rxreset_oob = rxreset_req & ~rxreset_oob_stop;
assign rxreset_ack = rxreset_oob_stop & gtx_ready;
always @ (posedge clk or posedge extrst)
rxreset_oob_cnt <= extrst | rst | ~rxreset_req ? 4'h0 : rxreset_oob_stop ? rxreset_oob_cnt : rxreset_oob_cnt + 1'b1;
// generate internal reset after a clock is established
// !!!ATTENTION!!!
// async rst block
......@@ -186,11 +219,13 @@ reg [7:0] rst_timer;
reg rst_r;
localparam [7:0] RST_TIMER_LIMIT = 8'b1000;
always @ (posedge clk or posedge extrst)
rst_timer <= extrst | ~cplllock | ~usrpll_locked ? 8'h0 : rst_timer == RST_TIMER_LIMIT ? rst_timer : rst_timer + 1'b1;
rst_timer <= extrst | ~cplllock | ~usrpll_locked ? 8'h0 : sata_reset_done ? rst_timer : rst_timer + 1'b1;
assign rst = rst_r;
always @ (posedge clk or posedge extrst)
rst_r <= extrst | ~|rst_timer ? 1'b0 : rst_timer[3] ? 1'b0 : 1'b1;
rst_r <= extrst | ~|rst_timer ? 1'b0 : sata_reset_done ? 1'b0 : 1'b1;
assign sata_reset_done = rst_timer == RST_TIMER_LIMIT;
/*
* USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
......@@ -280,443 +315,53 @@ ext_clock_buf(
.ODIV2 ()
);
GTXE2_CHANNEL #(
.SIM_RECEIVER_DETECT_PASS ("TRUE"),
.SIM_TX_EIDLE_DRIVE_LEVEL ("X"),
.SIM_RESET_SPEEDUP ("FALSE"),
.SIM_CPLLREFCLK_SEL (3'b001),
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
.ALIGN_PCOMMA_VALUE (10'b0101111100),
.SHOW_REALIGN_COMMA ("TRUE"),
.RXSLIDE_AUTO_WAIT (7),
.RXSLIDE_MODE ("OFF"),
.RX_SIG_VALID_DLY (10),
.RX_DISPERR_SEQ_MATCH ("TRUE"),
.DEC_MCOMMA_DETECT ("TRUE"),
.DEC_PCOMMA_DETECT ("TRUE"),
.DEC_VALID_COMMA_ONLY ("FALSE"),
.CBCC_DATA_SOURCE_SEL ("DECODED"),
.CLK_COR_SEQ_2_USE ("FALSE"),
.CLK_COR_KEEP_IDLE ("FALSE"),
.CLK_COR_MAX_LAT (9),
.CLK_COR_MIN_LAT (7),
.CLK_COR_PRECEDENCE ("TRUE"),
.CLK_COR_REPEAT_WAIT (0),
.CLK_COR_SEQ_LEN (1),
.CLK_COR_SEQ_1_ENABLE (4'b1111),
.CLK_COR_SEQ_1_1 (10'b0100000000),
.CLK_COR_SEQ_1_2 (10'b0000000000),
.CLK_COR_SEQ_1_3 (10'b0000000000),
.CLK_COR_SEQ_1_4 (10'b0000000000),
.CLK_CORRECT_USE ("FALSE"),
.CLK_COR_SEQ_2_ENABLE (4'b1111),
.CLK_COR_SEQ_2_1 (10'b0100000000),
.CLK_COR_SEQ_2_2 (10'b0000000000),
.CLK_COR_SEQ_2_3 (10'b0000000000),
.CLK_COR_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_KEEP_ALIGN ("FALSE"),
.CHAN_BOND_MAX_SKEW (1),
.CHAN_BOND_SEQ_LEN (1),
.CHAN_BOND_SEQ_1_1 (10'b0000000000),
.CHAN_BOND_SEQ_1_2 (10'b0000000000),
.CHAN_BOND_SEQ_1_3 (10'b0000000000),
.CHAN_BOND_SEQ_1_4 (10'b0000000000),
.CHAN_BOND_SEQ_1_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_1 (10'b0000000000),
.CHAN_BOND_SEQ_2_2 (10'b0000000000),
.CHAN_BOND_SEQ_2_3 (10'b0000000000),
.CHAN_BOND_SEQ_2_4 (10'b0000000000),
.CHAN_BOND_SEQ_2_ENABLE (4'b1111),
.CHAN_BOND_SEQ_2_USE ("FALSE"),
.FTS_DESKEW_SEQ_ENABLE (4'b1111),
.FTS_LANE_DESKEW_CFG (4'b1111),
.FTS_LANE_DESKEW_EN ("FALSE"),
.ES_CONTROL (6'b000000),
.ES_ERRDET_EN ("FALSE"),
.ES_EYE_SCAN_EN ("TRUE"),
.ES_HORZ_OFFSET (12'h000),
.ES_PMA_CFG (10'b0000000000),
.ES_PRESCALE (5'b00000),
.ES_QUALIFIER (80'h00000000000000000000),
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (40),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
.PMA_RSV3 (2'b00),
.PMA_RSV4 (32'h00000000),
.RX_BIAS_CFG (12'b000000000100),
.DMONITOR_CFG (24'h000A00),
.RX_CM_SEL (2'b11),
.RX_CM_TRIM (3'b010),
.RX_DEBUG_CFG (12'b000000000000),
.RX_OS_CFG (13'b0000010000000),
.TERM_RCAL_CFG (5'b10000),
.TERM_RCAL_OVRD (1'b0),
.TST_RSV (32'h00000000),
.RX_CLK25_DIV (6),
.TX_CLK25_DIV (6),
.UCODEER_CLR (1'b0),
.PCS_PCIE_EN ("FALSE"),
.PCS_RSVD_ATTR (48'h0100),
.RXBUF_ADDR_MODE ("FAST"),
.RXBUF_EIDLE_HI_CNT (4'b1000),
.RXBUF_EIDLE_LO_CNT (4'b0000),
.RXBUF_EN ("TRUE"),
.RX_BUFFER_CFG (6'b000000),
.RXBUF_RESET_ON_CB_CHANGE ("TRUE"),
.RXBUF_RESET_ON_COMMAALIGN ("FALSE"),
.RXBUF_RESET_ON_EIDLE ("FALSE"),
.RXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.RXBUFRESET_TIME (5'b00001),
.RXBUF_THRESH_OVFLW (61),
.RXBUF_THRESH_OVRD ("FALSE"),
.RXBUF_THRESH_UNDFLW (4),
.RXDLY_CFG (16'h001F),
.RXDLY_LCFG (9'h030),
.RXDLY_TAP_CFG (16'h0000),
.RXPH_CFG (24'h000000),
.RXPHDLY_CFG (24'h084020),
.RXPH_MONITOR_SEL (5'b00000),
.RX_XCLK_SEL ("RXREC"),
.RX_DDI_SEL (6'b000000),
.RX_DEFER_RESET_BUF_EN ("TRUE"),
.RXCDR_CFG (72'h03000023ff10200020),
.RXCDR_FR_RESET_ON_EIDLE (1'b0),
.RXCDR_HOLD_DURING_EIDLE (1'b0),
.RXCDR_PH_RESET_ON_EIDLE (1'b0),
.RXCDR_LOCK_CFG (6'b010101),
.RXCDRFREQRESET_TIME (RXCDRFREQRESET_TIME),
.RXCDRPHRESET_TIME (RXCDRPHRESET_TIME),
.RXISCANRESET_TIME (RXISCANRESET_TIME),
.RXPCSRESET_TIME (5'b00001),
.RXPMARESET_TIME (RXPMARESET_TIME),
.RXOOB_CFG (7'b0000110),
.RXGEARBOX_EN ("FALSE"),
.GEARBOX_MODE (3'b000),
.RXPRBS_ERR_LOOPBACK (1'b0),
.PD_TRANS_TIME_FROM_P2 (12'h03c),
.PD_TRANS_TIME_NONE_P2 (8'h3c),
.PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64),
.SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0110),
.SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8),
.SATA_MAX_INIT (21),
.SATA_MAX_WAKE (7),
.SATA_MIN_BURST (4),
.SATA_MIN_INIT (12),
.SATA_MIN_WAKE (4),
.TRANS_TIME_RATE (8'h0E),
.TXBUF_EN ("TRUE"),
.TXBUF_RESET_ON_RATE_CHANGE ("TRUE"),
.TXDLY_CFG (16'h001F),
.TXDLY_LCFG (9'h030),
.TXDLY_TAP_CFG (16'h0000),
.TXPH_CFG (16'h0780),
.TXPHDLY_CFG (24'h084020),
.TXPH_MONITOR_SEL (5'b00000),
.TX_XCLK_SEL ("TXOUT"),
.TX_DATA_WIDTH (40),
.TX_DEEMPH0 (5'b00000),
.TX_DEEMPH1 (5'b00000),
.TX_EIDLE_ASSERT_DELAY (3'b110),
.TX_EIDLE_DEASSERT_DELAY (3'b100),
.TX_LOOPBACK_DRIVE_HIZ ("FALSE"),
.TX_MAINCURSOR_SEL (1'b0),
.TX_DRIVE_MODE ("DIRECT"),
.TX_MARGIN_FULL_0 (7'b1001110),
.TX_MARGIN_FULL_1 (7'b1001001),
.TX_MARGIN_FULL_2 (7'b1000101),
.TX_MARGIN_FULL_3 (7'b1000010),
.TX_MARGIN_FULL_4 (7'b1000000),
.TX_MARGIN_LOW_0 (7'b1000110),
.TX_MARGIN_LOW_1 (7'b1000100),
.TX_MARGIN_LOW_2 (7'b1000010),
.TX_MARGIN_LOW_3 (7'b1000000),
.TX_MARGIN_LOW_4 (7'b1000000),
.TXGEARBOX_EN ("FALSE"),
.TXPCSRESET_TIME (5'b00001),
.TXPMARESET_TIME (TXPMARESET_TIME),
.TX_RXDETECT_CFG (14'h1832),
.TX_RXDETECT_REF (3'b100),
.CPLL_CFG (24'hBC07DC),
.CPLL_FBDIV (4),
.CPLL_FBDIV_45 (5),
.CPLL_INIT_CFG (24'h00001E),
.CPLL_LOCK_CFG (16'h01E8),
.CPLL_REFCLK_DIV (1),
.RXOUT_DIV (2),
.TXOUT_DIV (2),
.SATA_CPLL_CFG ("VCO_3000MHZ"),
.RXDFELPMRESET_TIME (RXDFELPMRESET_TIME),
.RXLPM_HF_CFG (14'b00000011110000),
.RXLPM_LF_CFG (14'b00000011110000),
.RX_DFE_GAIN_CFG (23'h020FEA),
.RX_DFE_H2_CFG (12'b000000000000),
.RX_DFE_H3_CFG (12'b000001000000),
.RX_DFE_H4_CFG (11'b00011110000),
.RX_DFE_H5_CFG (11'b00011100000),
.RX_DFE_KL_CFG (13'b0000011111110),
.RX_DFE_LPM_CFG (16'h0954),
.RX_DFE_LPM_HOLD_DURING_EIDLE (1'b0),
.RX_DFE_UT_CFG (17'b10001111000000000),
.RX_DFE_VP_CFG (17'b00011111100000011),
.RX_CLKMUX_PD (1'b1),
.TX_CLKMUX_PD (1'b1),
.RX_INT_DATAWIDTH (0),
.TX_INT_DATAWIDTH (0),
.TX_QPI_STATUS_EN (1'b0),
.RX_DFE_KL_CFG2 (32'h301148AC),
.RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0)
)
gtx(
.CPLLFBCLKLOST (),
.CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk),
.CPLLLOCKEN (1'b1),
.CPLLPD (1'b0),
.CPLLREFCLKLOST (),
.CPLLREFCLKSEL (3'b001),
.CPLLRESET (cpllreset),
.GTRSVD (1'b0),
.PCSRSVDIN (1'b0),
.PCSRSVDIN2 (1'b0),
.PMARSVDIN (1'b0),
.PMARSVDIN2 (1'b0),
.TSTIN (1'b1),
.TSTOUT (),
.CLKRSVD (4'b0000),
.GTGREFCLK (1'b0),
.GTNORTHREFCLK0 (1'b0),
.GTNORTHREFCLK1 (1'b0),
.GTREFCLK0 (gtrefclk),
.GTREFCLK1 (1'b0),
.GTSOUTHREFCLK0 (1'b0),
.GTSOUTHREFCLK1 (1'b0),
.DRPADDR (9'b0),
.DRPCLK (drpclk),
.DRPDI (16'b0),
.DRPDO (),
.DRPEN (1'b0),
.DRPRDY (),
.DRPWE (1'b0),
.GTREFCLKMONITOR (),
.QPLLCLK (gtrefclk),
.QPLLREFCLK (gtrefclk),
.RXSYSCLKSEL (2'b00),
.TXSYSCLKSEL (2'b00),
.DMONITOROUT (),
.TX8B10BEN (1'b1),
.LOOPBACK (3'd0),
.PHYSTATUS (),
.RXRATE (3'd0),
.RXVALID (),
.RXPD (2'b00),
.TXPD (2'b00),
.SETERRSTATUS (1'b0),
.EYESCANRESET (1'b0),//rxreset), // p78
.RXUSERRDY (rxuserrdy),
.EYESCANDATAERROR (),
.EYESCANMODE (1'b0),
.EYESCANTRIGGER (1'b0),
.RXCDRFREQRESET (1'b0),
.RXCDRHOLD (1'b0),
.RXCDRLOCK (),
.RXCDROVRDEN (1'b0),
.RXCDRRESET (1'b0),
.RXCDRRESETRSV (1'b0),
.RXCLKCORCNT (),
.RX8B10BEN (1'b1),
.RXUSRCLK (rxusrclk),
.RXUSRCLK2 (rxusrclk2),
.RXDATA (rxdata),
.RXPRBSERR (),
.RXPRBSSEL (3'd0),
.RXPRBSCNTRESET (1'b0),
.RXDFEXYDEN (1'b1),
.RXDFEXYDHOLD (1'b0),
.RXDFEXYDOVRDEN (1'b0),
.RXDISPERR (),
.RXNOTINTABLE (),
.GTXRXP (rxp),
.GTXRXN (rxn),
.RXBUFRESET (1'b0),
.RXBUFSTATUS (),
.RXDDIEN (1'b0),
.RXDLYBYPASS (1'b1),
.RXDLYEN (1'b0),
.RXDLYOVRDEN (1'b0),
.RXDLYSRESET (1'b0),
.RXDLYSRESETDONE (),
.RXPHALIGN (1'b0),
.RXPHALIGNDONE (),
.RXPHALIGNEN (1'b0),
.RXPHDLYPD (1'b0),
.RXPHDLYRESET (1'b0),
.RXPHMONITOR (),
.RXPHOVRDEN (1'b0),
.RXPHSLIPMONITOR (),
.RXSTATUS (),
.RXBYTEISALIGNED (rxbyteisaligned),
.RXBYTEREALIGN (),
.RXCOMMADET (),
.RXCOMMADETEN (1'b1),
.RXMCOMMAALIGNEN (1'b1),
.RXPCOMMAALIGNEN (1'b1),
.RXCHANBONDSEQ (),
.RXCHBONDEN (1'b0),
.RXCHBONDLEVEL (3'd0),
.RXCHBONDMASTER (1'b0),
.RXCHBONDO (),
.RXCHBONDSLAVE (1'b0),
.RXCHANISALIGNED (),
.RXCHANREALIGN (),
.RXLPMHFHOLD (1'b0),
.RXLPMHFOVRDEN (1'b0),
.RXLPMLFHOLD (1'b0),
.RXDFEAGCHOLD (1'b0),
.RXDFEAGCOVRDEN (1'b0),
.RXDFECM1EN (1'b0),
.RXDFELFHOLD (1'b0),
.RXDFELFOVRDEN (1'b1),
.RXDFELPMRESET (rxreset),
.RXDFETAP2HOLD (1'b0),
.RXDFETAP2OVRDEN (1'b0),
.RXDFETAP3HOLD (1'b0),
.RXDFETAP3OVRDEN (1'b0),
.RXDFETAP4HOLD (1'b0),
.RXDFETAP4OVRDEN (1'b0),
.RXDFETAP5HOLD (1'b0),
.RXDFETAP5OVRDEN (1'b0),
.RXDFEUTHOLD (1'b0),
.RXDFEUTOVRDEN (1'b0),
.RXDFEVPHOLD (1'b0),
.RXDFEVPOVRDEN (1'b0),
// .RXDFEVSEN (1'b0),
.RXLPMLFKLOVRDEN (1'b0),
.RXMONITOROUT (),
.RXMONITORSEL (2'b01),
.RXOSHOLD (1'b0),
.RXOSOVRDEN (1'b0),
.RXRATEDONE (),
.RXOUTCLK (),
.RXOUTCLKFABRIC (),
.RXOUTCLKPCS (),
.RXOUTCLKSEL (3'b010),
.RXDATAVALID (),
.RXHEADER (),
.RXHEADERVALID (),
.RXSTARTOFSEQ (),
.RXGEARBOXSLIP (1'b0),
.GTRXRESET (rxreset),
.RXOOBRESET (1'b0),
.RXPCSRESET (1'b0),
.RXPMARESET (1'b0),//rxreset), // p78
.RXLPMEN (1'b0),
.RXCOMSASDET (),
.RXCOMWAKEDET (rxcomwakedet),
.RXCOMINITDET (rxcominitdet),
.RXELECIDLE (rxelecidle),
.RXELECIDLEMODE (2'b00),
.RXPOLARITY (1'b0),
.RXSLIDE (1'b0),
.RXCHARISCOMMA (),
.RXCHARISK (rxcharisk),
.RXCHBONDI (5'b00000),
.RXRESETDONE (rxresetdone),
.RXQPIEN (1'b0),
.RXQPISENN (),
.RXQPISENP (),
.TXPHDLYTSTCLK (1'b0),
.TXPOSTCURSOR (5'b00000),
.TXPOSTCURSORINV (1'b0),
.TXPRECURSOR (5'd0),
.TXPRECURSORINV (1'b0),
.TXQPIBIASEN (1'b0),
.TXQPISTRONGPDOWN (1'b0),
.TXQPIWEAKPUP (1'b0),
.CFGRESET (1'b0),
.GTTXRESET (txreset),
.PCSRSVDOUT (),
.TXUSERRDY (txuserrdy),
.GTRESETSEL (1'b0),
.RESETOVRD (1'b0),
.TXCHARDISPMODE (8'd0),
.TXCHARDISPVAL (8'd0),
.TXUSRCLK (txusrclk),
.TXUSRCLK2 (txusrclk2),
.TXELECIDLE (txelecidle),
.TXMARGIN (3'd0),
.TXRATE (3'd0),
.TXSWING (1'b0),
.TXPRBSFORCEERR (1'b0),
.TXDLYBYPASS (1'b1),
.TXDLYEN (1'b0),
.TXDLYHOLD (1'b0),
.TXDLYOVRDEN (1'b0),
.TXDLYSRESET (1'b0),
.TXDLYSRESETDONE (),
.TXDLYUPDOWN (1'b0),
.TXPHALIGN (1'b0),
.TXPHALIGNDONE (),
.TXPHALIGNEN (1'b0),
.TXPHDLYPD (1'b0),
.TXPHDLYRESET (1'b0),
.TXPHINIT (1'b0),
.TXPHINITDONE (),
.TXPHOVRDEN (1'b0),
.TXBUFSTATUS (),
.TXBUFDIFFCTRL (3'b100),
.TXDEEMPH (1'b0),
.TXDIFFCTRL (4'b1000),
.TXDIFFPD (1'b0),
.TXINHIBIT (1'b0),
.TXMAINCURSOR (7'b0000000),
.TXPISOPD (1'b0),
.TXDATA ({32'h0, txdata}),
.GTXTXN (txn),
.GTXTXP (txp),
.TXOUTCLK (txoutclk),
.TXOUTCLKFABRIC (),
.TXOUTCLKPCS (),
.TXOUTCLKSEL (3'b010),
.TXRATEDONE (),
.TXCHARISK ({4'b0, txcharisk}),
.TXGEARBOXREADY (),
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone),
.TXCOMFINISH (),
.TXCOMINIT (txcominit),
.TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake),
.TXPDELECIDLEMODE (1'b0),
.TXPOLARITY (1'b0),
.TXDETECTRX (1'b0),
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP ()/*,
.TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0)*/
gtx_wrap #(
.DATA_BYTE_WIDTH (DATA_BYTE_WIDTH),
.TXPMARESET_TIME (TXPMARESET_TIME),
.RXPMARESET_TIME (RXPMARESET_TIME),
.RXCDRPHRESET_TIME (RXCDRPHRESET_TIME),
.RXCDRFREQRESET_TIME (RXCDRFREQRESET_TIME),
.RXDFELPMRESET_TIME (RXDFELPMRESET_TIME),
.RXISCANRESET_TIME (RXISCANRESET_TIME),
.RXEYERESET_TIME (RXEYERESET_TIME)
)
gtx_wrap
(
.cplllock (cplllock),
.cplllockdetclk (cplllockdetclk),
.cpllreset (cpllreset),
.gtrefclk (gtrefclk),
.drpclk (drpclk),
.rxuserrdy (rxuserrdy),
.txuserrdy (txuserrdy),
.rxusrclk (rxusrclk),
.rxusrclk2 (rxusrclk2),
.rxp (rxp),
.rxn (rxn),
.rxbyteisaligned (rxbyteisaligned),
.rxreset (rxreset),
.rxcomwakedet (rxcomwakedet),
.rxcominitdet (rxcominitdet),
.rxelecidle (rxelecidle),
.rxresetdone (rxresetdone),
.txreset (txreset),
.txusrclk (txusrclk),
.txusrclk2 (txusrclk2),
.txelecidle (txelecidle),
.txp (txp),
.txn (txn),
.txoutclk (txoutclk),
.txpcsreset (txpcsreset),
.txresetdone (txresetdone),
.txcominit (txcominit),
.txcomwake (txcomwake),
.rxelsfull (rxelsfull),
.rxelsempty (rxelsempty),
.txdata (txdata),
.txcharisk (txcharisk),
.rxdata (rxdata),
.rxcharisk (rxcharisk)
);
/*
* Interfaces
*/
......
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