Commit e4a8fdeb authored by Alexey Grebenkin's avatar Alexey Grebenkin

Major update

parent 740156c0
...@@ -3,7 +3,13 @@ SATA controller for x393 camera ...@@ -3,7 +3,13 @@ SATA controller for x393 camera
Board: Zynq 7z30 Board: Zynq 7z30
FPGA: Kintex-7 FPGA: Kintex-7
# Current step: # Current step:
Connecting Ashwin's core (slow interface to the system is almost done, have to completely rewrite phy-level). Feels like making the phy works is going to require a lot of effort Testing basic functionallity of a host.
Trying out pio access.
Fullfilling device-side drivers and monitors via tasks.
Tests are mostly manual, relied on a common sense and waveforms instpection. Still, complatible both with gtx-gpl and unisims/gtx
# Going to do afterwards: # Going to do afterwards:
Complete and test the 'current step'. Write host controller with ~same functionallity, check if it works with previously verified higher-level code. Test dma functionallity of the host.
And then to spin out the full-compatible functionallity (ideally somewhere to the level of ahci) Make cocotb testbench - gtx-gpl only - random payload high-level verification testing purposes.
Create a base of regression tests, containing lower-level tests - both gtx-gpl and unisims/gtx.
Improve an implementation of DMA control module.
Finally decide what to do with a driver and modify application level (actally, write it from scrap) correspodning to driver's interfaces.
This diff is collapsed.
wire [31:0] phy2dev_data;
wire [3:0] phy2dev_charisk;
wire [3:0] phy2dev_err;
wire dev_clk;
wire dev_rst;
reg [31:0] dev2phy_data;
reg [3:0] dev2phy_charisk;
force dev.dev2phy_data =
force dev.dev2phy_charisk =
task
/*******************************************************************************
* Module: oob_ctrl
* Date: 2015-07-11
* Author: Alexey
* Description: module to start oob sequences and to handle errors
*
* Copyright (c) 2015 Elphel, Inc.
* oob_ctrl.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.
*
* oob_ctrl.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 "oob.v"
module oob_ctrl_dev #(
parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
)
(
// sata clk = usrclk2
input wire clk,
// reset oob
input wire rst,
// gtx is ready = all resets are done
input wire gtx_ready,
// oob responces
input wire rxcominitdet_in,
input wire rxcomwakedet_in,
input wire rxelecidle_in,
// oob issues
output wire txcominit,
output wire txcomwake,
output wire txelecidle,
// 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,
// output data stream to gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] txdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] txcharisk_out,
// input data from gtx
input wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_in,
input wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_in,
// bypassed data from gtx
output wire [DATA_BYTE_WIDTH*8 - 1:0] rxdata_out,
output wire [DATA_BYTE_WIDTH - 1:0] rxcharisk_out,
// obvious
input wire rxbyteisaligned,
// shows if channel is ready
output wire phy_ready
);
// oob sequence needs to be issued
wire oob_start;
// connection established, all further data is valid
wire oob_done;
// doc p265, link is established after 3back-to-back non-ALIGNp
wire link_up;
wire link_down;
// the device itself sends cominit
wire cominit_req;
// allow to respond to cominit
wire cominit_allow;
// status information to handle by a control block if any exists
// incompatible host-device speed grades (host cannot lock to alignp)
wire oob_incompatible; // TODO
// timeout in an unexpected place
wire oob_error;
// noone responds to our cominits
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;
always @ (posedge clk)
link_state <= (link_state | link_up) & ~link_down & ~rst;
always @ (posedge clk)
oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & link_down & ~rst;
// decide when to issue oob: always when gtx is ready
assign oob_start = gtx_ready & ~oob_state & ~oob_busy;
// set line to idle state before if we're waiting for a device to answer AND while oob sequence
wire txelecidle_inner;
assign txelecidle = ~oob_state | txelecidle_inner;
// let devices always begin oob sequence, if only it's not a glitch
assign cominit_allow = cominit_req & link_state;
oob_dev #(
.DATA_BYTE_WIDTH (DATA_BYTE_WIDTH),
.CLK_SPEED_GRADE (CLK_SPEED_GRADE)
)
oob_dev
(
// sata clk = usrclk2
.clk (clk),
// reset oob
.rst (rst),
// oob responces
.rxcominitdet_in (rxcominitdet_in),
.rxcomwakedet_in (rxcomwakedet_in),
.rxelecidle_in (rxelecidle_in),
// oob issues
.txcominit (txcominit),
.txcomwake (txcomwake),
.txelecidle (txelecidle_inner),
// input data stream (if any data during OOB setting => ignored)
.txdata_in (txdata_in),
.txcharisk_in (txcharisk_in),
// output data stream to gtx
.txdata_out (txdata_out),
.txcharisk_out (txcharisk_out),
// input data from gtx
.rxdata_in (rxdata_in),
.rxcharisk_in (rxcharisk_in),
// bypassed data from gtx
.rxdata_out (rxdata_out),
.rxcharisk_out (rxcharisk_out),
// oob sequence needs to be issued
.oob_start (oob_start),
// connection established, all further data is valid
.oob_done (oob_done),
// doc p265, link is established after 3back-to-back non-ALIGNp
.link_up (link_up),
.link_down (link_down),
// the device itself sends cominit
.cominit_req (cominit_req),
// allow to respond to cominit
.cominit_allow (cominit_allow),
// status information to handle by a control block if any exists
// incompatible host-device speed grades (host cannot lock to alignp)
.oob_incompatible (oob_incompatible),
// timeout in an unexpected place
.oob_error (oob_error),
// noone responds to our cominits
.oob_silence (oob_silence),
// oob can't handle new start request
.oob_busy (oob_busy)
);
endmodule
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -204,7 +204,7 @@ assign wr_cnt_to_push = 7'hf; ...@@ -204,7 +204,7 @@ assign wr_cnt_to_push = 7'hf;
assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push; assign wr_stop = wr_val_in & wr_data_count == wr_cnt_to_push;
assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA; assign wr_ack_out = wr_val_in & rdwr_state == WRITE_DATA;
assign wr_data_in = wr_data; //assign wr_data_in = wr_data;
// assuming for now we write only pre-defined 16 64-bit words // assuming for now we write only pre-defined 16 64-bit words
......
...@@ -63,7 +63,7 @@ module dma_regs #( ...@@ -63,7 +63,7 @@ module dma_regs #(
output wire sh_dev_val, output wire sh_dev_val,
output wire [7:0] sh_control, output wire [7:0] sh_control,
output wire sh_control_val, output wire sh_control_val,
output wire [31:0] sh_dma_id_lo output wire [31:0] sh_dma_id_lo,
output wire sh_dma_id_lo_val, output wire sh_dma_id_lo_val,
output wire [31:0] sh_dma_id_hi, output wire [31:0] sh_dma_id_hi,
output wire sh_dma_id_hi_val, output wire sh_dma_id_hi_val,
...@@ -71,7 +71,7 @@ module dma_regs #( ...@@ -71,7 +71,7 @@ module dma_regs #(
output wire sh_buf_off_val, output wire sh_buf_off_val,
output wire [31:0] sh_dma_cnt, output wire [31:0] sh_dma_cnt,
output wire sh_dma_cnt_val, output wire sh_dma_cnt_val,
output wire [31:0] sh_tran_cnt, output wire [15:0] sh_tran_cnt,
output wire sh_tran_cnt_val, output wire sh_tran_cnt_val,
output wire sh_autoact, output wire sh_autoact,
output wire sh_autoact_val, output wire sh_autoact_val,
...@@ -104,7 +104,7 @@ module dma_regs #( ...@@ -104,7 +104,7 @@ module dma_regs #(
input wire [31:0] sh_dma_cnt_in, input wire [31:0] sh_dma_cnt_in,
input wire [15:0] sh_tran_cnt_in, // Transfer Count input wire [15:0] sh_tran_cnt_in, // Transfer Count
input wire sh_notif_in, input wire sh_notif_in,
input wire sh_autoact_in input wire sh_autoact_in,
// inputs from cmd control // inputs from cmd control
input wire [31:0] cmd_in input wire [31:0] cmd_in
); );
......
This diff is collapsed.
This diff is collapsed.
...@@ -35,8 +35,8 @@ module top #( ...@@ -35,8 +35,8 @@ module top #(
output wire TXN, output wire TXN,
output wire TXP, output wire TXP,
// sata clocking iface // sata clocking iface
input wire REFCLK_PAD_P_IN, input wire EXTCLK_P,
input wire REFCLK_PAD_N_IN input wire EXTCLK_N
); );
parameter REGISTERS_CNT = 20; parameter REGISTERS_CNT = 20;
wire [32*REGISTERS_CNT - 1:0] outmem; wire [32*REGISTERS_CNT - 1:0] outmem;
...@@ -285,8 +285,8 @@ sata_top sata_top( ...@@ -285,8 +285,8 @@ sata_top sata_top(
.RXN (RXN), .RXN (RXN),
.RXP (RXP), .RXP (RXP),
.REFCLK_PAD_P_IN (REFCLK_PAD_P_IN), .EXTCLK_P (EXTCLK_P),
.REFCLK_PAD_N_IN (REFCLK_PAD_N_IN) .EXTCLK_N (EXTCLK_N)
); );
PS7 ps7_i ( PS7 ps7_i (
......
...@@ -74,7 +74,7 @@ module command( ...@@ -74,7 +74,7 @@ module command(
input wire al_sh_dma_id_hi_val_in, input wire al_sh_dma_id_hi_val_in,
input wire [31:0] al_sh_buf_off_in, input wire [31:0] al_sh_buf_off_in,
input wire al_sh_buf_off_val_in, input wire al_sh_buf_off_val_in,
input wire [31:0] al_sh_tran_cnt_in, input wire [15:0] al_sh_tran_cnt_in,
input wire al_sh_tran_cnt_val_in, input wire al_sh_tran_cnt_val_in,
input wire al_sh_autoact_in, input wire al_sh_autoact_in,
input wire al_sh_autoact_val_in, input wire al_sh_autoact_val_in,
...@@ -188,7 +188,7 @@ begin ...@@ -188,7 +188,7 @@ begin
sh_dma_id[63:32] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_hi_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[63:32] : sh_dma_id[63:32]; sh_dma_id[63:32] <= rst ? 32'h0 : al_sh_dma_id_lo_val_in ? al_sh_dma_id_hi_in : tl_sh_dma_id_val_in ? tl_sh_dma_id_in[63:32] : sh_dma_id[63:32];
sh_dma_off <= rst ? 32'h0 : al_sh_buf_off_val_in ? al_sh_buf_off_in : tl_sh_dma_off_val_in ? tl_sh_dma_off_in : sh_dma_off; sh_dma_off <= rst ? 32'h0 : al_sh_buf_off_val_in ? al_sh_buf_off_in : tl_sh_dma_off_val_in ? tl_sh_dma_off_in : sh_dma_off;
sh_dma_cnt <= rst ? 32'h0 : al_sh_dma_cnt_val_in ? al_sh_dma_cnt_in : tl_sh_dma_cnt_val_in ? tl_sh_dma_cnt_in : sh_dma_cnt; sh_dma_cnt <= rst ? 32'h0 : al_sh_dma_cnt_val_in ? al_sh_dma_cnt_in : tl_sh_dma_cnt_val_in ? tl_sh_dma_cnt_in : sh_dma_cnt;
sh_tran_cnt <= rst ? 32'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt; sh_tran_cnt <= rst ? 16'h0 : al_sh_tran_cnt_val_in ? al_sh_tran_cnt_in : tl_sh_tran_cnt_val_in ? tl_sh_tran_cnt_in : sh_tran_cnt;
sh_notif <= rst ? 1'h0 : al_sh_notif_val_in ? al_sh_notif_in : tl_sh_notif_val_in ? tl_sh_notif_in : sh_notif; sh_notif <= rst ? 1'h0 : al_sh_notif_val_in ? al_sh_notif_in : tl_sh_notif_val_in ? tl_sh_notif_in : sh_notif;
sh_autoact <= rst ? 1'h0 : al_sh_autoact_val_in ? al_sh_autoact_in : tl_sh_autoact_val_in ? tl_sh_autoact_in : sh_autoact; sh_autoact <= rst ? 1'h0 : al_sh_autoact_val_in ? al_sh_autoact_in : tl_sh_autoact_val_in ? tl_sh_autoact_in : sh_autoact;
end end
...@@ -220,10 +220,10 @@ reg [31:0] cmd; ...@@ -220,10 +220,10 @@ reg [31:0] cmd;
assign al_cmd_out = cmd; assign al_cmd_out = cmd;
always @ (posedge clk) always @ (posedge clk)
begin begin
cmd[31:4] <= rst ? 28'h0 : al_cmd_val_in ? al_cmd_in : cmd; cmd[31:4] <= rst ? 28'h0 : al_cmd_val_in ? al_cmd_in[31:4] : cmd[31:4];
cmd[3] <= rst ? 1'b0 : al_cmd_val_in ? al_cmd_in[3] : cmd_val ? 1'b0 : cmd[3]; cmd[3] <= rst ? 1'b0 : al_cmd_val_in ? al_cmd_in[3] : cmd_val ? 1'b0 : cmd[3];
cmd[2] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_bad ? 1'b1 : cmd[2]; cmd[2] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_bad ? 1'b1 : cmd[2];
cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[2]; cmd[1] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_done_good ? 1'b1 : cmd[1];
cmd[0] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_busy; cmd[0] <= rst ? 1'b0 : al_cmd_val_in ? 1'b0 : cmd_busy;
end end
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
// All references to doc = to SerialATA_Revision_2_6_Gold.pdf // All references to doc = to SerialATA_Revision_2_6_Gold.pdf
module oob #( module oob #(
parameter DATA_BYTE_WIDTH = 4, parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz parameter CLK_SPEED_GRADE = 1 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
) )
( (
// sata clk = usrclk2 // sata clk = usrclk2
...@@ -59,6 +59,8 @@ module oob #( ...@@ -59,6 +59,8 @@ module oob #(
input wire oob_start, input wire oob_start,
// connection established, all further data is valid // connection established, all further data is valid
output wire oob_done, output wire oob_done,
// oob can't handle new start request
output wire oob_busy,
// doc p265, link is established after 3back-to-back non-ALIGNp // doc p265, link is established after 3back-to-back non-ALIGNp
output wire link_up, output wire link_up,
...@@ -104,7 +106,11 @@ module oob #( ...@@ -104,7 +106,11 @@ module oob #(
localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 : localparam [19:0] CLK_TO_TIMER_CONTRIB = CLK_SPEED_GRADE == 1 ? 20'h4 :
CLK_SPEED_GRADE == 2 ? 20'h2 : CLK_SPEED_GRADE == 2 ? 20'h2 :
CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1; CLK_SPEED_GRADE == 4 ? 20'h1 : 20'h1;
`ifdef SIMULATION
localparam [19:0] TIMER_LIMIT = 19'd20000;
`else
localparam [19:0] TIMER_LIMIT = 19'd262140; localparam [19:0] TIMER_LIMIT = 19'd262140;
`endif
reg [19:0] timer; reg [19:0] timer;
wire timer_clr; wire timer_clr;
wire timer_fin; wire timer_fin;
...@@ -120,6 +126,25 @@ reg [DATA_BYTE_WIDTH - 1:0] rxcharisk; ...@@ -120,6 +126,25 @@ reg [DATA_BYTE_WIDTH - 1:0] rxcharisk;
wire detected_alignp; wire detected_alignp;
wire detected_syncp; wire detected_syncp;
// wait until device's cominit is done
reg cominit_req_l;
reg rxcominitdet_l;
reg rxcomwakedet_l;
wire rxcominit_done;
wire rxcomwake_done;
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 // fsm, doc p265,266
wire state_idle; wire state_idle;
reg state_wait_cominit; reg state_wait_cominit;
...@@ -154,8 +179,8 @@ begin ...@@ -154,8 +179,8 @@ begin
end 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 & cominit_allow | state_wait_cominit & rxcominitdet; 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; assign set_wait_align = state_wait_comwake & rxcomwakedet_l & rxcomwake_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*/);
...@@ -168,9 +193,9 @@ assign clr_error = state_error; ...@@ -168,9 +193,9 @@ assign clr_error = state_error;
// waiting timeout timer // waiting timeout timer
assign timer_fin = timer == TIMER_LIMIT; assign timer_fin = timer == TIMER_LIMIT;
assign timer_clr = set_error | state_idle; assign timer_clr = set_error | state_error | state_idle;
always @ (posedge clk) always @ (posedge clk)
timer <= rst ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB; timer <= rst | timer_clr ? 20'h0 : timer + CLK_TO_TIMER_CONTRIB;
// something is wrong with speed grades if the host cannot lock to device's alignp stream // something is wrong with speed grades if the host cannot lock to device's alignp stream
assign oob_incompatible = state_wait_align & set_error; assign oob_incompatible = state_wait_align & set_error;
...@@ -184,10 +209,13 @@ assign oob_silence = set_error & state_wait_cominit; ...@@ -184,10 +209,13 @@ assign oob_silence = set_error & state_wait_cominit;
// other timeouts // other timeouts
assign oob_error = set_error & ~oob_silence & ~oob_incompatible; assign oob_error = set_error & ~oob_silence & ~oob_incompatible;
// obvioud
assign oob_busy = ~state_idle;
// set gtx controls // set gtx controls
reg txelecidle_r; reg txelecidle_r;
always @ (posedge clk) always @ (posedge clk)
txelecidle_r <= rst ? 1'b0 : clr_wait_cominit ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r; txelecidle_r <= rst ? 1'b1 : /*clr_wait_cominit */ clr_wait_comwake ? 1'b0 : set_wait_cominit ? 1'b1 : txelecidle_r;
assign txcominit = set_wait_cominit; assign txcominit = set_wait_cominit;
assign txcomwake = set_wait_comwake; assign txcomwake = set_wait_comwake;
...@@ -321,6 +349,9 @@ generate ...@@ -321,6 +349,9 @@ generate
end end
endgenerate endgenerate
always @ (posedge clk)
rxcom_timer <= rst | rxcominit_done & state_wait_cominit | rxcomwake_done & state_wait_comwake | rxcominitdet & state_wait_cominit | rxcomwakedet & state_wait_comwake ? 10'h0 : cominit_req_l & state_idle | rxcominitdet_l & state_wait_cominit | rxcomwakedet_l & state_wait_comwake ? rxcom_timer + CLK_TO_TIMER_CONTRIB : 10'h0;
// set data outputs to gtx // set data outputs to gtx
assign txdata_out = txdata; assign txdata_out = txdata;
assign txcharisk_out = txcharisk; assign txcharisk_out = txcharisk;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
`include "oob.v" `include "oob.v"
module oob_ctrl #( module oob_ctrl #(
parameter DATA_BYTE_WIDTH = 4, parameter DATA_BYTE_WIDTH = 4,
parameter CLK_SPEED_GRADE = 2 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz parameter CLK_SPEED_GRADE = 1 // 1 - 75 Mhz, 2 - 150Mhz, 4 - 300Mhz
) )
( (
// sata clk = usrclk2 // sata clk = usrclk2
...@@ -80,6 +80,8 @@ wire oob_incompatible; // TODO ...@@ -80,6 +80,8 @@ wire oob_incompatible; // TODO
wire oob_error; wire oob_error;
// noone responds to our cominits // noone responds to our cominits
wire oob_silence; wire oob_silence;
// obvious
wire oob_busy;
// for the resync sake // for the resync sake
reg rxbyteisaligned_r; reg rxbyteisaligned_r;
...@@ -87,12 +89,12 @@ reg rxbyteisaligned_rr; ...@@ -87,12 +89,12 @@ reg rxbyteisaligned_rr;
always @ (posedge clk) always @ (posedge clk)
begin begin
rxbyteisaligned_rr <= rxbyteisaligned_r; rxbyteisaligned_rr <= rxbyteisaligned_r;
rxbyteisaligned <= rxbyteisaligned; rxbyteisaligned_r <= rxbyteisaligned;
end end
// 1 - link is up and running, 0 - probably not // 1 - link is up and running, 0 - probably not
reg link_state; reg link_state;
// 1 - connection is being established, 0 - is not // 1 - connection is being established OR already established, 0 - is not
reg oob_state; reg oob_state;
assign phy_ready = link_state & gtx_ready & rxbyteisaligned_rr; assign phy_ready = link_state & gtx_ready & rxbyteisaligned_rr;
...@@ -101,11 +103,14 @@ always @ (posedge clk) ...@@ -101,11 +103,14 @@ always @ (posedge clk)
link_state <= (link_state | link_up) & ~link_down & ~rst; link_state <= (link_state | link_up) & ~link_down & ~rst;
always @ (posedge clk) always @ (posedge clk)
oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & ~link_up & ~rst; oob_state <= (oob_state | oob_start | cominit_req & cominit_allow) & ~oob_error & ~oob_silence & ~(link_down & ~oob_busy & ~oob_start) & ~rst;
// decide when to issue oob: always when gtx is ready // decide when to issue oob: always when gtx is ready
assign oob_start = gtx_ready & ~oob_state; assign oob_start = gtx_ready & ~oob_state & ~oob_busy;
// set line to idle state before if we're waiting for a device to answer AND while oob sequence
wire txelecidle_inner;
assign txelecidle = /*~oob_state |*/ txelecidle_inner;
// let devices always begin oob sequence, if only it's not a glitch // let devices always begin oob sequence, if only it's not a glitch
assign cominit_allow = cominit_req & link_state; assign cominit_allow = cominit_req & link_state;
...@@ -127,7 +132,7 @@ oob ...@@ -127,7 +132,7 @@ oob
// oob issues // oob issues
.txcominit (txcominit), .txcominit (txcominit),
.txcomwake (txcomwake), .txcomwake (txcomwake),
.txelecidle (txelecidle), .txelecidle (txelecidle_inner),
// 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),
...@@ -162,7 +167,9 @@ oob ...@@ -162,7 +167,9 @@ oob
// timeout in an unexpected place // timeout in an unexpected place
.oob_error (oob_error), .oob_error (oob_error),
// noone responds to our cominits // noone responds to our cominits
.oob_silence (oob_silence) .oob_silence (oob_silence),
// oob can't handle new start request
.oob_busy (oob_busy)
); );
......
This diff is collapsed.
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
*******************************************************************************/ *******************************************************************************/
`include "oob_ctrl.v" `include "oob_ctrl.v"
module sata_phy( module sata_phy(
input wire rst, // initial reset, resets PLL. After pll is locked, an internal sata reset is generated.
input wire extrst,
// sata clk, generated in pll as usrclk2 // sata clk, generated in pll as usrclk2
output wire clk, output wire clk,
output wire rst,
// state // state
output wire phy_ready, output wire phy_ready,
...@@ -52,7 +54,7 @@ parameter CHIPSCOPE = "FALSE"; ...@@ -52,7 +54,7 @@ parameter CHIPSCOPE = "FALSE";
wire [31:0] txdata; wire [31:0] txdata;
wire [3:0] txcharisk; wire [3:0] txcharisk;
wire [63:0] rxdata; wire [63:0] rxdata;
wire [3:0] rxcharisk; wire [7:0] rxcharisk;
wire [31:0] rxdata_out; wire [31:0] rxdata_out;
wire [31:0] txdata_in; wire [31:0] txdata_in;
wire [3:0] txcharisk_in; wire [3:0] txcharisk_in;
...@@ -68,6 +70,8 @@ wire rxelecidle; ...@@ -68,6 +70,8 @@ wire rxelecidle;
wire txelecidle; wire txelecidle;
wire rxbyteisaligned; wire rxbyteisaligned;
wire gtx_ready;
oob_ctrl oob_ctrl( oob_ctrl oob_ctrl(
// sata clk = usrclk2 // sata clk = usrclk2
...@@ -89,11 +93,11 @@ oob_ctrl oob_ctrl( ...@@ -89,11 +93,11 @@ oob_ctrl oob_ctrl(
.txdata_in (txdata_in), .txdata_in (txdata_in),
.txcharisk_in (txcharisk_in), .txcharisk_in (txcharisk_in),
// output data stream to gtx // output data stream to gtx
.txdata_out (txdata_out), .txdata_out (txdata),
.txcharisk_out (txcharisk_out), .txcharisk_out (txcharisk),
// input data from gtx // input data from gtx
.rxdata_in (rxdata_in), .rxdata_in (rxdata[31:0]),
.rxcharisk_in (rxcharisk_in), .rxcharisk_in (rxcharisk[3:0]),
// bypassed data from gtx // bypassed data from gtx
.rxdata_out (rxdata_out), .rxdata_out (rxdata_out),
.rxcharisk_out (rxcharisk_out), .rxcharisk_out (rxcharisk_out),
...@@ -150,12 +154,27 @@ always @ (posedge gtrefclk) ...@@ -150,12 +154,27 @@ always @ (posedge gtrefclk)
*/ */
wire usrpll_locked; wire usrpll_locked;
assign cpllreset = rst; assign cpllreset = extrst;
assign rxreset = ~cplllock | cpllreset; assign rxreset = ~cplllock | cpllreset;
assign txreset = ~cplllock | cpllreset; assign txreset = ~cplllock | cpllreset;
assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done; assign rxuserrdy = usrpll_locked & cplllock & ~cpllreset & ~rxreset & rxeyereset_done;
assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done; assign txuserrdy = usrpll_locked & cplllock & ~cpllreset & ~txreset & txpmareset_done;
assign gtx_ready = rxuserrdy & txuserrdy & rxresetdone & txresetdone;
// generate internal reset after a clock is established
// !!!ATTENTION!!!
// async rst block
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;
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 * 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
...@@ -252,7 +271,7 @@ GTXE2_CHANNEL #( ...@@ -252,7 +271,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 (1), .ALIGN_COMMA_WORD (2),
.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"),
...@@ -372,7 +391,7 @@ GTXE2_CHANNEL #( ...@@ -372,7 +391,7 @@ GTXE2_CHANNEL #(
.PD_TRANS_TIME_TO_P2 (8'h64), .PD_TRANS_TIME_TO_P2 (8'h64),
.SAS_MAX_COM (64), .SAS_MAX_COM (64),
.SAS_MIN_COM (36), .SAS_MIN_COM (36),
.SATA_BURST_SEQ_LEN (4'b0111), .SATA_BURST_SEQ_LEN (4'b0110),
.SATA_BURST_VAL (3'b110), .SATA_BURST_VAL (3'b110),
.SATA_EIDLE_VAL (3'b110), .SATA_EIDLE_VAL (3'b110),
.SATA_MAX_BURST (8), .SATA_MAX_BURST (8),
...@@ -445,7 +464,7 @@ GTXE2_CHANNEL #( ...@@ -445,7 +464,7 @@ GTXE2_CHANNEL #(
.RX_DFE_XYD_CFG (13'b0000000000000), .RX_DFE_XYD_CFG (13'b0000000000000),
.TX_PREDRIVER_MODE (1'b0) .TX_PREDRIVER_MODE (1'b0)
) )
dut( gtx(
.CPLLFBCLKLOST (), .CPLLFBCLKLOST (),
.CPLLLOCK (cplllock), .CPLLLOCK (cplllock),
.CPLLLOCKDETCLK (cplllockdetclk), .CPLLLOCKDETCLK (cplllockdetclk),
...@@ -675,22 +694,22 @@ dut( ...@@ -675,22 +694,22 @@ dut(
.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)
); );
/* /*
* Interfaces * Interfaces
*/ */
assign cplllockdetclk = CLKIN_150; assign cplllockdetclk = gtrefclk; //TODO
assign drpclk = CLKIN_150; assign drpclk = gtrefclk;
assign clk = usrclk2; assign clk = usrclk2;
assign rxn = rxn_in; assign rxn = rxn_in;
assign rxp = rxp_in; assign rxp = rxp_in;
assign txp_out = txn; assign txn_out = txn;
assign txp_out = txp; assign txp_out = txp;
assign ll_data_out = rxdata_out; assign ll_data_out = rxdata_out;
assign ll_charisk_out = rxcharisk_out; assign ll_charisk_out = rxcharisk_out;
......
...@@ -38,7 +38,7 @@ reg [15:0] now; ...@@ -38,7 +38,7 @@ reg [15:0] now;
reg [31:0] next; reg [31:0] next;
always @ (posedge clk) always @ (posedge clk)
now <= rst ? 16'hf0f6 : val_in ? next : now; now <= rst ? 16'hf0f6 : val_in ? next[31:16] : now;
assign data_out = val_in ? data_in ^ next : data_in; assign data_out = val_in ? data_in ^ next : data_in;
......
This diff is collapsed.
//--------------------------------------------------------------------------------
// Entity mux_21
// Version: 1.0
// Author: Ashwin Mendon
// Description: 2 bit 2:1 Multiplexer
//--------------------------------------------------------------------------------
// Copyright (C) 2012
// Ashwin A. Mendon
//
// This file is part of SATA2 core.
//
// This program 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.
//
// This program 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 mux_21
(
input wire [1:0] a,
input wire [1:0] b,
input wire sel,
output reg [1:0] o
);
always @ (a or b or sel)
begin
case (sel)
1'b0:
o = a;
1'b1:
o = b;
endcase
end
endmodule
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
TIMESCALE = 1000; # in ps
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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