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])
This diff is collapsed.
This diff is collapsed.
/*******************************************************************************
* 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])
This diff is collapsed.
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
This diff is collapsed.
This diff is collapsed.
......@@ -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),
......
This diff is collapsed.
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