Commit 2371769e authored by Alexey Grebenkin's avatar Alexey Grebenkin

Fixes after simulation with xilinx's GTX

parent a4102b78
...@@ -44,6 +44,9 @@ module oob_dev #( ...@@ -44,6 +44,9 @@ module oob_dev #(
output reg txcomwake, output reg txcomwake,
output reg txelecidle, output reg txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// output data stream to gtx // output data stream to gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out, output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out, output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
...@@ -60,6 +63,7 @@ localparam STATE_AWAITCOMWAKE = 2; ...@@ -60,6 +63,7 @@ localparam STATE_AWAITCOMWAKE = 2;
localparam STATE_AWAITNOCOMWAKE = 3; localparam STATE_AWAITNOCOMWAKE = 3;
localparam STATE_CALIBRATE = 4; localparam STATE_CALIBRATE = 4;
localparam STATE_COMWAKE = 5; localparam STATE_COMWAKE = 5;
localparam STATE_RECAL = 55;
localparam STATE_SENDALIGN = 6; localparam STATE_SENDALIGN = 6;
localparam STATE_READY = 7; localparam STATE_READY = 7;
localparam STATE_PARTIAL = 8; localparam STATE_PARTIAL = 8;
...@@ -115,26 +119,33 @@ begin ...@@ -115,26 +119,33 @@ begin
rxcharisk <= rxcharisk_in; rxcharisk <= rxcharisk_in;
end end
reg [9:0] txelecidle_cnt;
assign aligndet = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5} assign aligndet = ~|(rxdata ^ {8'b01111011, 8'b01001010, 8'b01001010, 8'b10111100}) & ~|(rxcharisk ^ 4'h1); // {D27.3, D10.2, D10.2, K28.5}
assign syncdet = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3} assign syncdet = ~|(rxdata ^ {8'b10110101, 8'b10110101, 8'b10010101, 8'b01111100}) & ~|(rxcharisk ^ 4'h1); // {D21.5, D21.5, D21.4, K28.3}
assign txpcsreset_req = state == STATE_RECAL & (txelecidle_cnt == 10'd160);
always @ (posedge clk) always @ (posedge clk)
if (rst | ~gtx_ready) if (rst | (~gtx_ready & ~(state == STATE_RECAL)))
begin begin
state <= STATE_RESET; state <= STATE_RESET;
txelecidle <= 1'b1; txelecidle <= 1'b1;
txcominit <= 1'b0; txcominit <= 1'b0;
txcomwake <= 1'b0; txcomwake <= 1'b0;
txelecidle_cnt <= 10'h0;
end end
else else
case (state) case (state)
STATE_RESET: STATE_RESET:
begin begin
if (rxcominitdet_in) if (rxcominitdet) begin
txelecidle_cnt <= 10'h0;
state <= STATE_COMINIT; state <= STATE_COMINIT;
txelecidle <= 1'b1; txelecidle <= 1'b1;
txcominit <= 1'b0; txcominit <= 1'b0;
txcomwake <= 1'b0; txcomwake <= 1'b0;
end
end end
STATE_COMINIT: STATE_COMINIT:
begin begin
...@@ -144,7 +155,7 @@ always @ (posedge clk) ...@@ -144,7 +155,7 @@ always @ (posedge clk)
STATE_AWAITCOMWAKE: STATE_AWAITCOMWAKE:
begin begin
txcominit <= 1'b0; txcominit <= 1'b0;
if (rxcomwakedet_in) if (rxcomwakedet)
state <= STATE_AWAITNOCOMWAKE; state <= STATE_AWAITNOCOMWAKE;
else else
if (retry_interval_elapsed) if (retry_interval_elapsed)
...@@ -166,12 +177,27 @@ always @ (posedge clk) ...@@ -166,12 +177,27 @@ always @ (posedge clk)
STATE_COMWAKE: STATE_COMWAKE:
begin begin
txcomwake <= 1'b1; txcomwake <= 1'b1;
state <= STATE_SENDALIGN; state <= STATE_RECAL;
txelecidle_cnt <= 10'h0;
end end
STATE_SENDALIGN: STATE_RECAL:
begin begin
data <= align;
isk <= 4'h1;
txcomwake <= 1'b0; txcomwake <= 1'b0;
txelecidle <= 1'b0; // txcomwake period = 213.333 ns times let's say 10 pulses => 2133.333 ns = 160 cycles of 75Mhz
if (txelecidle_cnt == 10'd160) begin
txelecidle <= 1'b0;
end
else begin
txelecidle_cnt <= txelecidle_cnt + 1'b1;
end
if (recal_tx_done) begin
state <= STATE_SENDALIGN;
end
end
STATE_SENDALIGN:
begin
data <= align; data <= align;
isk <= 4'h1; isk <= 4'h1;
if (aligndet) if (aligndet)
...@@ -184,6 +210,7 @@ always @ (posedge clk) ...@@ -184,6 +210,7 @@ always @ (posedge clk)
end end
STATE_READY: STATE_READY:
begin begin
txelecidle <= 1'b0;
data <= sync; data <= sync;
isk <= 4'h1; isk <= 4'h1;
if (rxelecidle_in) if (rxelecidle_in)
...@@ -191,6 +218,7 @@ always @ (posedge clk) ...@@ -191,6 +218,7 @@ always @ (posedge clk)
end end
STATE_ERROR: STATE_ERROR:
begin begin
txelecidle <= 1'b0;
state <= STATE_RESET; state <= STATE_RESET;
end end
endcase endcase
......
...@@ -51,6 +51,7 @@ module sata_phy_dev( ...@@ -51,6 +51,7 @@ module sata_phy_dev(
parameter CHIPSCOPE = "FALSE"; parameter CHIPSCOPE = "FALSE";
wire txcomfinish;
wire [31:0] txdata; wire [31:0] txdata;
wire [31:0] txdata_oob; wire [31:0] txdata_oob;
wire [3:0] txcharisk; wire [3:0] txcharisk;
...@@ -71,6 +72,8 @@ wire rxreset; ...@@ -71,6 +72,8 @@ wire rxreset;
wire rxelecidle; wire rxelecidle;
wire txelecidle; wire txelecidle;
wire rxbyteisaligned; wire rxbyteisaligned;
wire txpcsreset_req;
wire recal_tx_done;
wire gtx_ready; wire gtx_ready;
...@@ -97,6 +100,9 @@ oob_dev oob_dev( ...@@ -97,6 +100,9 @@ oob_dev oob_dev(
.txcomwake (txcomwake), .txcomwake (txcomwake),
.txelecidle (txelecidle), .txelecidle (txelecidle),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// output data stream to gtx // output data stream to gtx
.txdata_out (txdata_oob), .txdata_out (txdata_oob),
.txcharisk_out (txcharisk_oob), .txcharisk_out (txcharisk_oob),
...@@ -114,6 +120,7 @@ wire cpllreset; ...@@ -114,6 +120,7 @@ wire cpllreset;
wire gtrefclk; wire gtrefclk;
wire rxresetdone; wire rxresetdone;
wire txresetdone; wire txresetdone;
wire txpcsreset;
wire txreset; wire txreset;
wire txuserrdy; wire txuserrdy;
wire rxuserrdy; wire rxuserrdy;
...@@ -161,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese ...@@ -161,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone; assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// 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 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;
// generate internal reset after a clock is established // generate internal reset after a clock is established
// !!!ATTENTION!!! // !!!ATTENTION!!!
// async rst block // async rst block
...@@ -174,6 +192,8 @@ assign rst = rst_r; ...@@ -174,6 +192,8 @@ assign rst = rst_r;
always @ (posedge clk or posedge extrst) 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 : rst_timer[3] ? 1'b0 : 1'b1;
/* /*
* USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk * USRCLKs generation. USRCLK @ 150MHz, same as TXOUTCLK; USRCLK2 @ 75Mhz -> sata_clk === sclk
* It's recommended to use MMCM instead of PLL, whatever * It's recommended to use MMCM instead of PLL, whatever
...@@ -329,7 +349,7 @@ GTXE2_CHANNEL #( ...@@ -329,7 +349,7 @@ GTXE2_CHANNEL #(
.ES_QUAL_MASK (80'h00000000000000000000), .ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000), .ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000), .ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20), .RX_DATA_WIDTH (40),
.OUTREFCLK_SEL_INV (2'b11), .OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480), .PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050), .PMA_RSV2 (16'h2050),
...@@ -680,10 +700,10 @@ gtx( ...@@ -680,10 +700,10 @@ gtx(
.TXHEADER (3'd0), .TXHEADER (3'd0),
.TXSEQUENCE (7'd0), .TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0), .TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0), .TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0), .TXPMARESET (1'b0),
.TXRESETDONE (txresetdone), .TXRESETDONE (txresetdone),
.TXCOMFINISH (), .TXCOMFINISH (txcomfinish),
.TXCOMINIT (txcominit), .TXCOMINIT (txcominit),
.TXCOMSAS (1'b0), .TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake), .TXCOMWAKE (txcomwake),
......
...@@ -71,6 +71,7 @@ module dma_adapter( ...@@ -71,6 +71,7 @@ module dma_adapter(
// additinal wire to indicate if membridge recieved a packet // additinal wire to indicate if membridge recieved a packet
input wire rdata_done // = membridge.is_last_in_page & membridge.afi_rready; input wire rdata_done // = membridge.is_last_in_page & membridge.afi_rready;
); );
reg [2:0] membr_state;
// cmd handling // cmd handling
// if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm // if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm
wire wr_start; wire wr_start;
...@@ -299,7 +300,6 @@ reg [32:0] membr_data; ...@@ -299,7 +300,6 @@ reg [32:0] membr_data;
reg [15:0] membr_addr; reg [15:0] membr_addr;
reg membr_start; reg membr_start;
reg membr_done; reg membr_done;
reg [2:0] membr_state;
reg membr_setup; // indicates the first tick of the state reg membr_setup; // indicates the first tick of the state
wire membr_inprocess; wire membr_inprocess;
......
...@@ -109,40 +109,6 @@ wire adp_val_sclk; ...@@ -109,40 +109,6 @@ wire adp_val_sclk;
reg [31:7] current_addr; reg [31:7] current_addr;
reg current_type; reg current_type;
// synchronize with host fsm
reg adp_done;
wire adp_done_clr;
wire adp_done_set;
assign dma_done_adp = adp_done;
assign adp_done_set = state_wait_done & clr_wait_done & ~set_wait_busy; // = state_wait_done & set_idle;
assign adp_done_clr = dma_done;
always @ (posedge sclk)
adp_done <= (adp_done | adp_done_set) & ~adp_done_clr & ~rst;
// calculate sent sector count
// 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes
always @ (posedge sclk)
quarter_sector_cnt <= ~set_wait_busy ? quarter_sector_cnt :
state_idle ? 34'h0 : // new dma request
quarter_sector_cnt + 1'b1; // same dma request, next 128 bytes
// flags if we're currently sending the last data piece of dma transaction
assign last_data = (sector_cnt == quarter_sector_cnt[33:2] + 1'b1) & (&quarter_sector_cnt[1:0]);
// calculate outgoing address
// increment every transaction to adapter
always @ (posedge sclk)
current_addr <= ~set_wait_busy ? current_addr :
state_idle ? mem_address : // new dma request
current_addr + 1'b1; // same dma request, next 128 bytes
always @ (posedge sclk)
current_type <= ~set_wait_busy ? current_type :
state_idle ? dma_type : // new dma request
current_type; // same dma request, next 128 bytes
// fsm itself // fsm itself
wire state_idle; wire state_idle;
...@@ -216,6 +182,40 @@ pulse_cross_clock adp_busy_clr_pulse( ...@@ -216,6 +182,40 @@ pulse_cross_clock adp_busy_clr_pulse(
.busy () .busy ()
); );
// synchronize with host fsm
reg adp_done;
wire adp_done_clr;
wire adp_done_set;
assign dma_done_adp = adp_done;
assign adp_done_set = state_wait_done & clr_wait_done & ~set_wait_busy; // = state_wait_done & set_idle;
assign adp_done_clr = dma_done;
always @ (posedge sclk)
adp_done <= (adp_done | adp_done_set) & ~adp_done_clr & ~rst;
// calculate sent sector count
// 1 sector = 512 bytes for now => 1 quarter_sector = 128 bytes
always @ (posedge sclk)
quarter_sector_cnt <= ~set_wait_busy ? quarter_sector_cnt :
state_idle ? 34'h0 : // new dma request
quarter_sector_cnt + 1'b1; // same dma request, next 128 bytes
// flags if we're currently sending the last data piece of dma transaction
assign last_data = (sector_cnt == quarter_sector_cnt[33:2] + 1'b1) & (&quarter_sector_cnt[1:0]);
// calculate outgoing address
// increment every transaction to adapter
always @ (posedge sclk)
current_addr <= ~set_wait_busy ? current_addr :
state_idle ? mem_address : // new dma request
current_addr + 1'b1; // same dma request, next 128 bytes
always @ (posedge sclk)
current_type <= ~set_wait_busy ? current_type :
state_idle ? dma_type : // new dma request
current_type; // same dma request, next 128 bytes
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
//// DATA //// DATA
......
...@@ -167,8 +167,8 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(/*fclk[0]*/ sclk)); ...@@ -167,8 +167,8 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(/*fclk[0]*/ sclk));
BUFG bufg_axi_aclk0_i (.O(axi_aclk0),.I(fclk[0])); BUFG bufg_axi_aclk0_i (.O(axi_aclk0),.I(fclk[0]));
BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre)); BUFG bufg_axi_rst_i (.O(axi_rst),.I(axi_rst_pre));
axi_hp_clk #( axi_hp_clk #(
.CLKIN_PERIOD(20), .CLKIN_PERIOD(6.666),
.CLKFBOUT_MULT_AXIHP(18), .CLKFBOUT_MULT_AXIHP(6),
.CLKFBOUT_DIV_AXIHP(6) .CLKFBOUT_DIV_AXIHP(6)
) axi_hp_clk_i ( ) axi_hp_clk_i (
.rst (axi_rst), // input .rst (axi_rst), // input
......
...@@ -483,7 +483,7 @@ always @ (posedge clk) ...@@ -483,7 +483,7 @@ always @ (posedge clk)
// incoming data is data // incoming data is data
wire inc_is_data; wire inc_is_data;
assign inc_is_data = dword_val & rcvd_dword[CODE_DATA] & (state_rcvr_data | state_rcvr_rhold) & ~alignes_pair; assign inc_is_data = dword_val & rcvd_dword[CODE_DATA] & (state_rcvr_data | state_rcvr_rhold);
/* /*
* Scrambler can work both as a scrambler and a descramler, because data stream could be * Scrambler can work both as a scrambler and a descramler, because data stream could be
* one direction at a time * one direction at a time
......
...@@ -42,6 +42,9 @@ module oob #( ...@@ -42,6 +42,9 @@ module oob #(
output wire txcomwake, output wire txcomwake,
output wire txelecidle, output wire txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// input data stream (if any data during OOB setting => ignored) // input data stream (if any data during OOB setting => ignored)
input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in, input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in, input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in,
...@@ -136,19 +139,12 @@ reg [9:0] rxcom_timer; ...@@ -136,19 +139,12 @@ reg [9:0] rxcom_timer;
// for 75MHz : period of cominit = 426.7 ns = 32 ticks => need to wait x6 pulses + 1 as an insurance => 224 clock cycles. Same thoughts for comwake // for 75MHz : period of cominit = 426.7 ns = 32 ticks => need to wait x6 pulses + 1 as an insurance => 224 clock cycles. Same thoughts for comwake
localparam COMINIT_DONE_TIME = 896; // 300Mhz cycles localparam COMINIT_DONE_TIME = 896; // 300Mhz cycles
localparam COMWAKE_DONE_TIME = 448; // 300Mhz cycles localparam COMWAKE_DONE_TIME = 448; // 300Mhz cycles
assign rxcominit_done = rxcom_timer == COMINIT_DONE_TIME & state_wait_cominit;
assign rxcomwake_done = rxcom_timer == COMWAKE_DONE_TIME & state_wait_comwake;
always @ (posedge clk) begin
cominit_req_l <= rst | rxcominit_done | ~state_idle ? 1'b0 : cominit_req ? 1'b1 : cominit_req_l;
rxcominitdet_l <= rst | rxcominit_done | ~state_wait_cominit ? 1'b0 : rxcominitdet ? 1'b1 : rxcominitdet_l;
rxcomwakedet_l <= rst | rxcomwake_done | ~state_wait_comwake ? 1'b0 : rxcomwakedet ? 1'b1 : rxcomwakedet_l;
end
// fsm, doc p265,266 // fsm, doc p265,266
wire state_idle; wire state_idle;
reg state_wait_cominit; reg state_wait_cominit;
reg state_wait_comwake; reg state_wait_comwake;
reg state_recal_tx;
reg state_wait_align; reg state_wait_align;
reg state_wait_synp; reg state_wait_synp;
reg state_wait_linkup; reg state_wait_linkup;
...@@ -156,22 +152,25 @@ reg state_error; ...@@ -156,22 +152,25 @@ reg state_error;
wire set_wait_cominit; wire set_wait_cominit;
wire set_wait_comwake; wire set_wait_comwake;
wire set_recal_tx;
wire set_wait_align; wire set_wait_align;
wire set_wait_synp; wire set_wait_synp;
wire set_wait_linkup; wire set_wait_linkup;
wire set_error; wire set_error;
wire clr_wait_cominit; wire clr_wait_cominit;
wire clr_wait_comwake; wire clr_wait_comwake;
wire clr_recal_tx;
wire clr_wait_align; wire clr_wait_align;
wire clr_wait_synp; wire clr_wait_synp;
wire clr_wait_linkup; wire clr_wait_linkup;
wire clr_error; wire clr_error;
assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error; assign state_idle = ~state_wait_cominit & ~state_wait_comwake & ~state_wait_align & ~state_wait_synp & ~state_wait_linkup & ~state_error & ~state_recal_tx;
always @ (posedge clk) always @ (posedge clk)
begin begin
state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst; state_wait_cominit <= (state_wait_cominit | set_wait_cominit) & ~clr_wait_cominit & ~rst;
state_wait_comwake <= (state_wait_comwake | set_wait_comwake) & ~clr_wait_comwake & ~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_align <= (state_wait_align | set_wait_align ) & ~clr_wait_align & ~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_synp <= (state_wait_synp | set_wait_synp ) & ~clr_wait_synp & ~rst;
state_wait_linkup <= (state_wait_linkup | set_wait_linkup ) & ~clr_wait_linkup & ~rst; state_wait_linkup <= (state_wait_linkup | set_wait_linkup ) & ~clr_wait_linkup & ~rst;
...@@ -180,12 +179,14 @@ end ...@@ -180,12 +179,14 @@ end
assign set_wait_cominit = state_idle & oob_start & ~cominit_req; 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_wait_comwake = state_idle & cominit_req_l & cominit_allow & rxcominit_done | state_wait_cominit & rxcominitdet_l & rxcominit_done;
assign set_wait_align = state_wait_comwake & rxcomwakedet_l & rxcomwake_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_synp = state_wait_align & detected_alignp; assign set_wait_synp = state_wait_align & detected_alignp;
assign set_wait_linkup = state_wait_synp & detected_syncp; 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_wait_align | state_wait_synp/* | state_wait_linkup*/);
assign clr_wait_cominit = set_wait_comwake | set_error; assign clr_wait_cominit = set_wait_comwake | set_error;
assign clr_wait_comwake = set_wait_align | set_error; assign clr_wait_comwake = set_recal_tx | set_error;
assign clr_recal_tx = set_wait_align | set_error;
assign clr_wait_align = set_wait_synp | set_error; assign clr_wait_align = set_wait_synp | set_error;
assign clr_wait_synp = set_wait_linkup | 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 assign clr_wait_linkup = state_wait_linkup; //TODO not so important, but still have to trace 3 back-to-back non alignp primitives
...@@ -212,6 +213,9 @@ assign oob_error = set_error & ~oob_silence & ~oob_incompatible; ...@@ -212,6 +213,9 @@ assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
// obvioud // obvioud
assign oob_busy = ~state_idle; assign oob_busy = ~state_idle;
// ask for recalibration
assign txpcsreset_req = state_recal_tx;
// set gtx controls // set gtx controls
reg txelecidle_r; reg txelecidle_r;
always @ (posedge clk) always @ (posedge clk)
...@@ -282,6 +286,16 @@ generate ...@@ -282,6 +286,16 @@ generate
end end
endgenerate endgenerate
// calculate an aproximate time when oob burst shall be done
assign rxcominit_done = rxcom_timer == COMINIT_DONE_TIME & state_wait_cominit;
assign rxcomwake_done = rxcom_timer == COMWAKE_DONE_TIME & state_wait_comwake;
always @ (posedge clk) begin
cominit_req_l <= rst | rxcominit_done | ~state_idle ? 1'b0 : cominit_req ? 1'b1 : cominit_req_l;
rxcominitdet_l <= rst | rxcominit_done | ~state_wait_cominit ? 1'b0 : rxcominitdet ? 1'b1 : rxcominitdet_l;
rxcomwakedet_l <= rst | rxcomwake_done | ~state_wait_comwake ? 1'b0 : rxcomwakedet ? 1'b1 : rxcomwakedet_l;
end
// buf inputs from gtx // buf inputs from gtx
always @ (posedge clk) always @ (posedge clk)
begin begin
...@@ -308,8 +322,10 @@ wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align; ...@@ -308,8 +322,10 @@ wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align;
always @ (posedge clk) always @ (posedge clk)
begin begin
txdata <= state_wait_align ? txdata_d102 : txdata <= state_wait_align ? txdata_d102 :
state_wait_rxrst ? txdata_d102 :
state_wait_synp ? txdata_align : txdata_in; state_wait_synp ? txdata_align : txdata_in;
txcharisk <= state_wait_align ? txcharisk_d102 : txcharisk <= state_wait_align ? txcharisk_d102 :
state_wait_rxrst ? txcharisk_d102 :
state_wait_synp ? txcharisk_align : txcharisk_in; state_wait_synp ? txcharisk_align : txcharisk_in;
end end
......
...@@ -39,6 +39,9 @@ module oob_ctrl #( ...@@ -39,6 +39,9 @@ module oob_ctrl #(
output wire txcomwake, output wire txcomwake,
output wire txelecidle, output wire txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// input data stream (if any data during OOB setting => ignored) // input data stream (if any data during OOB setting => ignored)
input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in, input wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in, input wire [DATA_BYTE_WIDTH - 1:0] txcharisk_in,
...@@ -134,6 +137,9 @@ oob ...@@ -134,6 +137,9 @@ oob
.txcomwake (txcomwake), .txcomwake (txcomwake),
.txelecidle (txelecidle_inner), .txelecidle (txelecidle_inner),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// input data stream (if any data during OOB setting => ignored) // input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in), .txdata_in (txdata_in),
.txcharisk_in (txcharisk_in), .txcharisk_in (txcharisk_in),
......
...@@ -69,6 +69,8 @@ wire rxreset; ...@@ -69,6 +69,8 @@ wire rxreset;
wire rxelecidle; wire rxelecidle;
wire txelecidle; wire txelecidle;
wire rxbyteisaligned; wire rxbyteisaligned;
wire txpcsreset_req;
wire recal_tx_done;
wire gtx_ready; wire gtx_ready;
...@@ -89,6 +91,9 @@ oob_ctrl oob_ctrl( ...@@ -89,6 +91,9 @@ oob_ctrl oob_ctrl(
.txcomwake (txcomwake), .txcomwake (txcomwake),
.txelecidle (txelecidle), .txelecidle (txelecidle),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// input data stream (if any data during OOB setting => ignored) // input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in), .txdata_in (txdata_in),
.txcharisk_in (txcharisk_in), .txcharisk_in (txcharisk_in),
...@@ -115,6 +120,7 @@ wire cpllreset; ...@@ -115,6 +120,7 @@ wire cpllreset;
wire gtrefclk; wire gtrefclk;
wire rxresetdone; wire rxresetdone;
wire txresetdone; wire txresetdone;
wire txpcsreset;
wire txreset; wire txreset;
wire txuserrdy; wire txuserrdy;
wire rxuserrdy; wire rxuserrdy;
...@@ -162,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese ...@@ -162,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone; assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// 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 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;
// generate internal reset after a clock is established // generate internal reset after a clock is established
// !!!ATTENTION!!! // !!!ATTENTION!!!
// async rst block // async rst block
...@@ -271,7 +288,7 @@ GTXE2_CHANNEL #( ...@@ -271,7 +288,7 @@ GTXE2_CHANNEL #(
.SIM_VERSION ("4.0"), .SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"), .ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111), .ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (2), .ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"), .ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011), .ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"), .ALIGN_PCOMMA_DET ("TRUE"),
...@@ -330,7 +347,7 @@ GTXE2_CHANNEL #( ...@@ -330,7 +347,7 @@ GTXE2_CHANNEL #(
.ES_QUAL_MASK (80'h00000000000000000000), .ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000), .ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000), .ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20), .RX_DATA_WIDTH (40),
.OUTREFCLK_SEL_INV (2'b11), .OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480), .PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050), .PMA_RSV2 (16'h2050),
...@@ -681,7 +698,7 @@ gtx( ...@@ -681,7 +698,7 @@ gtx(
.TXHEADER (3'd0), .TXHEADER (3'd0),
.TXSEQUENCE (7'd0), .TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0), .TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0), .TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0), .TXPMARESET (1'b0),
.TXRESETDONE (txresetdone), .TXRESETDONE (txresetdone),
.TXCOMFINISH (), .TXCOMFINISH (),
...@@ -694,10 +711,10 @@ gtx( ...@@ -694,10 +711,10 @@ gtx(
.TX8B10BBYPASS (8'd0), .TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0), .TXPRBSSEL (3'd0),
.TXQPISENN (), .TXQPISENN (),
.TXQPISENP (), .TXQPISENP ()/*,
.TXSYNCMODE (1'b0), .TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0), .TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0) .TXSYNCIN (1'b0)*/
); );
/* /*
......
...@@ -18,6 +18,7 @@ then ...@@ -18,6 +18,7 @@ then
export GTX_PATH=$SATA_PATH export GTX_PATH=$SATA_PATH
fi fi
iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v -I$SATA_PATH/device -I$SATA_PATH/host -I$SATA_PATH/dma -I$SATA_PATH/tb -I$SATA_PATH -I$SATA_PATH/x393/axi -I$SATA_PATH/x393 -y$SATA_PATH/x393/util_modules -y$SATA_PATH/x393/wrap -y$UNISIMS_PATH -y$SATA_PATH/x393/memctrl -y$SATA_PATH/x393/axi -y$SATA_PATH/x393/simulation_modules $SATA_PATH/x393/simulation_modules/simul_axi_fifo_out.v -y$SATA_PATH/x393/ -D SIMULATION -D CHECKERS_ENABLED
#iverilog $SATA_PATH/neat_phy.v $SATA_PATH/x393/glbl.v $SATA_PATH/gtxe2_gpl/GTXE2_CHANNEL.v $SATA_PATH/neat_oob.v -y$UNISIMS_PATH
#iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -f opts -stb -sglbl $1 2>&1| tee $LOGFILE_PATH #iverilog $SATA_PATH/tb/tb_top.v $SATA_PATH/x393/glbl.v -f opts -stb -sglbl $1 2>&1| tee $LOGFILE_PATH
......
#!/bin/bash #!/bin/bash
LOGFILE_PATH="sim.log" LOGFILE_PATH="sim.log"
/usr/local/bin/vvp a.out -v $1 | tee $LOGFILE_PATH /usr/local/bin/vvp a.out -v $1 #|tee $LOGFILE_PATH
#2>&1 | tee $LOGFILE_PATH #2>&1 | tee $LOGFILE_PATH
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment