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 #(
output reg txcomwake,
output reg txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// output data stream to gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
......@@ -60,6 +63,7 @@ localparam STATE_AWAITCOMWAKE = 2;
localparam STATE_AWAITNOCOMWAKE = 3;
localparam STATE_CALIBRATE = 4;
localparam STATE_COMWAKE = 5;
localparam STATE_RECAL = 55;
localparam STATE_SENDALIGN = 6;
localparam STATE_READY = 7;
localparam STATE_PARTIAL = 8;
......@@ -115,26 +119,33 @@ begin
rxcharisk <= rxcharisk_in;
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 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)
if (rst | ~gtx_ready)
if (rst | (~gtx_ready & ~(state == STATE_RECAL)))
begin
state <= STATE_RESET;
txelecidle <= 1'b1;
txcominit <= 1'b0;
txcomwake <= 1'b0;
txelecidle_cnt <= 10'h0;
end
else
case (state)
STATE_RESET:
begin
if (rxcominitdet_in)
if (rxcominitdet) begin
txelecidle_cnt <= 10'h0;
state <= STATE_COMINIT;
txelecidle <= 1'b1;
txcominit <= 1'b0;
txcomwake <= 1'b0;
end
end
STATE_COMINIT:
begin
......@@ -144,7 +155,7 @@ always @ (posedge clk)
STATE_AWAITCOMWAKE:
begin
txcominit <= 1'b0;
if (rxcomwakedet_in)
if (rxcomwakedet)
state <= STATE_AWAITNOCOMWAKE;
else
if (retry_interval_elapsed)
......@@ -166,12 +177,27 @@ always @ (posedge clk)
STATE_COMWAKE:
begin
txcomwake <= 1'b1;
state <= STATE_SENDALIGN;
state <= STATE_RECAL;
txelecidle_cnt <= 10'h0;
end
STATE_SENDALIGN:
STATE_RECAL:
begin
data <= align;
isk <= 4'h1;
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;
isk <= 4'h1;
if (aligndet)
......@@ -184,6 +210,7 @@ always @ (posedge clk)
end
STATE_READY:
begin
txelecidle <= 1'b0;
data <= sync;
isk <= 4'h1;
if (rxelecidle_in)
......@@ -191,6 +218,7 @@ always @ (posedge clk)
end
STATE_ERROR:
begin
txelecidle <= 1'b0;
state <= STATE_RESET;
end
endcase
......
......@@ -51,6 +51,7 @@ module sata_phy_dev(
parameter CHIPSCOPE = "FALSE";
wire txcomfinish;
wire [31:0] txdata;
wire [31:0] txdata_oob;
wire [3:0] txcharisk;
......@@ -71,6 +72,8 @@ wire rxreset;
wire rxelecidle;
wire txelecidle;
wire rxbyteisaligned;
wire txpcsreset_req;
wire recal_tx_done;
wire gtx_ready;
......@@ -97,6 +100,9 @@ oob_dev oob_dev(
.txcomwake (txcomwake),
.txelecidle (txelecidle),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// output data stream to gtx
.txdata_out (txdata_oob),
.txcharisk_out (txcharisk_oob),
......@@ -114,6 +120,7 @@ wire cpllreset;
wire gtrefclk;
wire rxresetdone;
wire txresetdone;
wire txpcsreset;
wire txreset;
wire txuserrdy;
wire rxuserrdy;
......@@ -161,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese
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
// !!!ATTENTION!!!
// async rst block
......@@ -174,6 +192,8 @@ assign rst = rst_r;
always @ (posedge clk or posedge extrst)
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
* It's recommended to use MMCM instead of PLL, whatever
......@@ -329,7 +349,7 @@ GTXE2_CHANNEL #(
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20),
.RX_DATA_WIDTH (40),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
......@@ -680,10 +700,10 @@ gtx(
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0),
.TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone),
.TXCOMFINISH (),
.TXCOMFINISH (txcomfinish),
.TXCOMINIT (txcominit),
.TXCOMSAS (1'b0),
.TXCOMWAKE (txcomwake),
......
......@@ -71,6 +71,7 @@ module dma_adapter(
// additinal wire to indicate if membridge recieved a packet
input wire rdata_done // = membridge.is_last_in_page & membridge.afi_rready;
);
reg [2:0] membr_state;
// cmd handling
// if not busy and got cmd with val => cmd recieved, assert busy, start a respective algorithm
wire wr_start;
......@@ -299,7 +300,6 @@ reg [32:0] membr_data;
reg [15:0] membr_addr;
reg membr_start;
reg membr_done;
reg [2:0] membr_state;
reg membr_setup; // indicates the first tick of the state
wire membr_inprocess;
......
......@@ -109,40 +109,6 @@ wire adp_val_sclk;
reg [31:7] current_addr;
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
wire state_idle;
......@@ -216,6 +182,40 @@ pulse_cross_clock adp_busy_clr_pulse(
.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
......
......@@ -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_rst_i (.O(axi_rst),.I(axi_rst_pre));
axi_hp_clk #(
.CLKIN_PERIOD(20),
.CLKFBOUT_MULT_AXIHP(18),
.CLKIN_PERIOD(6.666),
.CLKFBOUT_MULT_AXIHP(6),
.CLKFBOUT_DIV_AXIHP(6)
) axi_hp_clk_i (
.rst (axi_rst), // input
......
......@@ -483,7 +483,7 @@ always @ (posedge clk)
// incoming data 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
* one direction at a time
......
......@@ -42,6 +42,9 @@ module oob #(
output wire txcomwake,
output wire txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// 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 - 1:0] txcharisk_in,
......@@ -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
localparam COMINIT_DONE_TIME = 896; // 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
wire state_idle;
reg state_wait_cominit;
reg state_wait_comwake;
reg state_recal_tx;
reg state_wait_align;
reg state_wait_synp;
reg state_wait_linkup;
......@@ -156,22 +152,25 @@ reg state_error;
wire set_wait_cominit;
wire set_wait_comwake;
wire set_recal_tx;
wire set_wait_align;
wire set_wait_synp;
wire set_wait_linkup;
wire set_error;
wire clr_wait_cominit;
wire clr_wait_comwake;
wire clr_recal_tx;
wire clr_wait_align;
wire clr_wait_synp;
wire clr_wait_linkup;
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)
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_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,12 +179,14 @@ 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_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_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 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_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
......@@ -212,6 +213,9 @@ assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
// obvioud
assign oob_busy = ~state_idle;
// ask for recalibration
assign txpcsreset_req = state_recal_tx;
// set gtx controls
reg txelecidle_r;
always @ (posedge clk)
......@@ -282,6 +286,16 @@ generate
end
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
always @ (posedge clk)
begin
......@@ -308,8 +322,10 @@ wire [DATA_BYTE_WIDTH - 1:0] txcharisk_align;
always @ (posedge clk)
begin
txdata <= state_wait_align ? txdata_d102 :
state_wait_rxrst ? txdata_d102 :
state_wait_synp ? txdata_align : txdata_in;
txcharisk <= state_wait_align ? txcharisk_d102 :
state_wait_rxrst ? txcharisk_d102 :
state_wait_synp ? txcharisk_align : txcharisk_in;
end
......
......@@ -39,6 +39,9 @@ module oob_ctrl #(
output wire txcomwake,
output wire txelecidle,
output wire txpcsreset_req,
input wire recal_tx_done,
// 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 - 1:0] txcharisk_in,
......@@ -134,6 +137,9 @@ oob
.txcomwake (txcomwake),
.txelecidle (txelecidle_inner),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
......
......@@ -69,6 +69,8 @@ wire rxreset;
wire rxelecidle;
wire txelecidle;
wire rxbyteisaligned;
wire txpcsreset_req;
wire recal_tx_done;
wire gtx_ready;
......@@ -89,6 +91,9 @@ oob_ctrl oob_ctrl(
.txcomwake (txcomwake),
.txelecidle (txelecidle),
.txpcsreset_req (txpcsreset_req),
.recal_tx_done (recal_tx_done),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
......@@ -115,6 +120,7 @@ wire cpllreset;
wire gtrefclk;
wire rxresetdone;
wire txresetdone;
wire txpcsreset;
wire txreset;
wire txuserrdy;
wire rxuserrdy;
......@@ -162,6 +168,17 @@ assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmarese
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
// !!!ATTENTION!!!
// async rst block
......@@ -271,7 +288,7 @@ GTXE2_CHANNEL #(
.SIM_VERSION ("4.0"),
.ALIGN_COMMA_DOUBLE ("FALSE"),
.ALIGN_COMMA_ENABLE (10'b1111111111),
.ALIGN_COMMA_WORD (2),
.ALIGN_COMMA_WORD (1),
.ALIGN_MCOMMA_DET ("TRUE"),
.ALIGN_MCOMMA_VALUE (10'b1010000011),
.ALIGN_PCOMMA_DET ("TRUE"),
......@@ -330,7 +347,7 @@ GTXE2_CHANNEL #(
.ES_QUAL_MASK (80'h00000000000000000000),
.ES_SDATA_MASK (80'h00000000000000000000),
.ES_VERT_OFFSET (9'b000000000),
.RX_DATA_WIDTH (20),
.RX_DATA_WIDTH (40),
.OUTREFCLK_SEL_INV (2'b11),
.PMA_RSV (32'h00018480),
.PMA_RSV2 (16'h2050),
......@@ -681,7 +698,7 @@ gtx(
.TXHEADER (3'd0),
.TXSEQUENCE (7'd0),
.TXSTARTSEQ (1'b0),
.TXPCSRESET (1'b0),
.TXPCSRESET (txpcsreset),
.TXPMARESET (1'b0),
.TXRESETDONE (txresetdone),
.TXCOMFINISH (),
......@@ -694,10 +711,10 @@ gtx(
.TX8B10BBYPASS (8'd0),
.TXPRBSSEL (3'd0),
.TXQPISENN (),
.TXQPISENP (),
.TXQPISENP ()/*,
.TXSYNCMODE (1'b0),
.TXSYNCALLIN (1'b0),
.TXSYNCIN (1'b0)
.TXSYNCIN (1'b0)*/
);
/*
......
......@@ -18,6 +18,7 @@ then
export GTX_PATH=$SATA_PATH
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/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
......
#!/bin/bash
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
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