Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
x393_sata
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
x393_sata
Commits
b7d39322
Commit
b7d39322
authored
Aug 05, 2015
by
Alexey Grebenkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
OOB unit added. Pre-testing rtl
parent
0e25833e
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
307 additions
and
0 deletions
+307
-0
oob.v
host/oob.v
+307
-0
No files found.
host/oob.v
0 → 100644
View file @
b7d39322
/*******************************************************************************
* Module: oob
* Date: 2015-07-11
* Author: Alexey
* Description: sata oob unit implementation
*
* Copyright (c) 2015 Elphel, Inc.
* oob.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.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/> .
*******************************************************************************/
/*
* For now both device and host shall be set up to SATA2 speeds.
* Need to think how to change speed grades on fly (either to broaden
* data iface width or to change RXRATE/TXRATE)
*/
// All references to doc = to SerialATA_Revision_2_6_Gold.pdf
module
oob
#(
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 TODO move it to control oobstart/status control block
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
,
// oob sequence needs to be issued
input
wire
oob_start
,
// connection established, all further data is valid
output
wire
oob_done
,
// doc p265, link is established after 3back-to-back non-ALIGNp
output
wire
link_up
,
// the device itself sends cominit
output
wire
cominit_req
,
// allow to respond to cominit
input
wire
cominit_allow
,
// status information to handle by a control block if any exists
// incompatible host-device speed grades (host cannot lock to alignp)
output
wire
oob_incompatible
,
// timeout in an unexpected place
output
wire
oob_error
,
// noone responds to our cominits
output
wire
oob_silence
`ifdef
OOB_MULTISPEED
//TODO
// !!Implement it later on, ref to gen.adjustment fsm in the notebook!!
// speed grade control
,
// current speed grade, dynamic instead of static parameter
input
wire
[
2
:
0
]
speed_grade
,
// clock to be adjusted to best speed
input
wire
adj_clk
,
// ask for slower protocol clock
output
wire
speed_down_req
,
input
wire
speed_down_ack
,
// reset speedgrade to the fastest one
output
wire
speed_rst_req
,
input
wire
speed_rst_ack
`endif
OOB_MULTISPEED
)
;
// 873.8 us error timer
// = 2621400 SATA2 serial ticks (period = 0.000333 us)
// = 131070 ticks @ 150Mhz
// = 65535 ticks @ 75Mhz
localparam
[
19
:
0
]
CLK_TO_TIMER_CONTRIB
=
CLK_SPEED_GRADE
==
1
?
20'h4
:
CLK_SPEED_GRADE
==
2
?
20'h2
:
CLK_SPEED_GRADE
==
4
?
20'h1
:
20'h1
;
localparam
[
19
:
0
]
TIMER_LIMIT
=
19'd262140
;
reg
[
19
:
0
]
timer
;
wire
timer_clr
;
wire
timer_fin
;
// latching inputs from gtx
reg
rxcominitdet
;
reg
rxcomwakedet
;
reg
rxelecidle
;
reg
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
rxdata
;
reg
[
DATA_BYTE_WIDTH
-
1
:
0
]
rxcharisk
;
// primitives detection
wire
detected_alignp
;
wire
detected_synp
;
// fsm, doc p265,266
wire
state_idle
;
reg
state_wait_cominit
;
reg
state_wait_comwake
;
reg
state_wait_align
;
reg
state_wait_synp
;
reg
state_wait_linkup
;
reg
state_error
;
wire
set_wait_cominit
;
wire
set_wait_comwake
;
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_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
;
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_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
;
state_error
<=
(
state_error
|
set_error
)
&
~
clr_error
&
~
rst
;
end
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_align
=
state_wait_comwake
&
rxcomwakedet
;
assign
set_wait_synp
=
state_wait_align
&
detected_alignp
;
assign
set_wait_linkup
=
state_wait_synp
&
detected_synp
;
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_align
=
set_wait_synp
|
set_error
;
assign
clr_wait_synp
=
set_wait_linkup
|
set_error
;
assign
clr_wait_linkup
=
state_linkup
;
//TODO not so important, but still have to trace 3 back-to-back non alignp primitives
assign
clr_error
=
state_error
;
// waiting timeout timer
assign
timer_fin
=
timer
==
TIMER_LIMIT
;
assign
timer_clr
=
set_error
|
state_idle
;
always
@
(
posedge
clk
)
timer
<=
rst
?
20'h0
:
timer
+
CLK_TO_TIMER_CONTRIB
;
// something is wrong with speed grades if the host cannot lock to device's alignp stream
assign
oob_incompatible
=
state_wait_align
&
set_error
;
// oob sequence is done, everything is okay
assign
oob_done
=
set_wait_linkup
;
// noone responds to cominits
assign
oob_silince
=
set_error
&
state_wait_cominit
;
// other timeouts
assign
oob_error
=
set_error
&
~
oob_silence
&
~
oob_incompatible
;
// set gtx controls
reg
txelecidle_r
;
always
@
(
posedge
clk
)
txelecidle_r
<=
rst
?
1'b0
:
clr_wait_cominit
?
1'b0
:
set_wait_cominit
?
1'b1
:
txelecidle_r
;
assign
txcominit
=
set_wait_cominit
;
assign
txcomwake
=
set_wait_comwake
;
assign
txelecidle
=
set_wait_cominit
|
txelecidle_r
;
// indicate if link up condition was made
assign
link_up
=
clr_wait_linkup
;
// indicate that device is requesting for oob
reg
cominit_req_r
;
wire
cominit_req_set
;
assign
cominit_req_set
=
state_idle
&
rxcominitdet
;
always
@
(
posedge
clk
)
cominit_req_r
<=
(
cominit_req_r
|
cominit_req_set
)
&
~
(
cominit_allow
&
cominit_req
)
&
~
rst
;
assign
cominit_req
=
cominit_req_set
|
cominit_req_r
;
// detect which primitives sends the device after comwake was done
generate
if
(
DATA_BYTE_WIDTH
==
16
)
begin
reg
detected_alignp_f
;
always
@
(
posedge
clk
)
detected_alignp_f
<=
rst
|
~
state_wait_align
?
1'b0
:
~|
(
rxdata
^
{
8'b01001010
,
8'b10111100
}
)
&
~|
(
rxchaisk
^
2'b01
)
;
// {D10.2, K28.5}
assign
detected_alignp
=
detected_aligp_f
&
~|
(
rxdata
^
{
8'b01111011
,
8'b01001010
}
)
&
~|
(
rxchaisk
^
2'b00
)
;
// {D27.3, D10.2}
reg
detected_syncp_f
;
always
@
(
posedge
clk
)
detected_syncp_f
<=
rst
|
~
state_wait_sync
?
1'b0
:
~|
(
rxdata
^
{
8'b10010101
,
8'b01111100
}
)
&
~|
(
rxchaisk
^
2'b01
)
;
// {D21.4, K28.3}
assign
detected_syncp
=
detected_syncp_f
&
~|
(
rxdata
^
{
8'b10110101
,
8'b10110101
}
)
&
~|
(
rxchaisk
^
2'b00
)
;
// {D21.5, D21.5}
end
else
if
(
DATA_BYTE_WIDTH
==
32
)
begin
assign
detected_alignp
=
detected_aligp_f
&
~|
(
rxdata
^
{
8'b01111011
,
8'b01001010
,
8'b01001010
,
8'b10111100
}
)
&
~|
(
rxchaisk
^
4'h1
)
;
// {D27.3, D10.2, D10.2, K28.5}
assign
detected_syncp
=
detected_syncp_f
&
~|
(
rxdata
^
{
8'b10110101
,
8'b10110101
,
8'b10010101
,
8'b01111100
}
)
&
~|
(
rxchaisk
^
4'h1
)
;
// {D21.5, D21.5, D21.4, K28.3}
end
else
if
(
DATA_BYTE_WIDTH
==
64
)
begin
assign
detected_alignp
=
detected_aligp_f
&
~|
(
rxdata
^
{
2
{
8'b01111011
,
8'b01001010
,
8'b01001010
,
8'b10111100
}}
)
&
~|
(
rxchaisk
^
8'h11
)
;
// {D27.3, D10.2, D10.2, K28.5}
assign
detected_syncp
=
detected_syncp_f
&
~|
(
rxdata
^
{
2
{
8'b10110101
,
8'b10110101
,
8'b10010101
,
8'b01111100
}}
)
&
~|
(
rxchaisk
^
8'h11
)
;
// {D21.5, D21.5, D21.4, K28.3}
end
else
$
display
(
"%m oob module works only with 16/32/64 gtx input data width"
)
;
endgenerate
// buf inputs from gtx
always
@
(
posedge
clk
)
begin
rxcominitdet
<=
rxcominitdet_in
;
rxcomwakedet
<=
rxcomwakedet_in
;
rxelecidle
<=
rxelecidle_in
;
rxdata
<=
rxdata_in
;
rxcharisk
<=
rxcharisk_in
;
end
// set data outputs to upper levels
assign
rxdata_out
=
rxdata
;
assign
rxcharisk_out
=
rxcharisk
;
// as depicted @ doc, p264, figure 163, have to insert D10.2 and align primitives after
// getting comwake from device
reg
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
txdata
;
reg
[
DATA_BYTE_WIDTH
-
1
:
0
]
txcharisk
;
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
txdata_d102
;
wire
[
DATA_BYTE_WIDTH
-
1
:
0
]
txcharisk_d102
;
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
txdata_align
;
wire
[
DATA_BYTE_WIDTH
-
1
:
0
]
txcharisk_align
;
always
@
(
posedge
clk
)
begin
txdata
<=
state_wait_align
?
txdata_d102
:
state_wait_sync
?
txdata_align
:
txdata_in
;
txchaisk
<=
state_wait_align
?
txcharisk_d102
:
state_wait_sync
?
txcharisk_align
:
txcharisk_in
;
end
// Continious D10.2 primitive
assign
txcharisk_d102
=
{
DATA_BYTE_WIDTH
{
1'b0
}};
assign
txdata_d102
=
{
DATA_BYTE_WIDTH
{
8'b01001010
}};
// Align primitive: K28.5 + D10.2 + D10.2 + D27.3
generate
if
(
DATA_BYTE_WIDTH
==
16
)
begin
reg
align_odd
;
always
@
(
posedge
clk
)
align_odd
<=
rst
|
~
state_wait_sync
?
1'b0
:
~
align_odd
;
assign
txcharisk_align
=
align_odd
?
2'b01
:
2'b00
;
assign
txdata_align
=
align_odd
?
{
8'b01001010
,
8'b10111100
}
:
// {D10.2, K28.5}
{
8'b01111011
,
8'b01001010
)
;
// {D27.3, D10.2}
end
else
if
(
DATA_BYTE_WIDTH
==
32
)
begin
assign
txcharisk_align
=
4'h1
;
assign
txdata_align
=
{
8'b01111011
,
8'b01001010
,
8'b01001010
,
8'b10111100
};
// {D27.3, D10.2, D10.2, K28.5}
end
else
if
(
DATA_BYTE_WIDTH
==
64
)
begin
assign
txcharisk_align
=
8'h11
;
assign
txdata_align
=
{
2
{
8'b01111011
,
8'b01001010
,
8'b01001010
,
8'b10111100
}};
// 2x{D27.3, D10.2, D10.2, K28.5}
end
else
$
display
(
"%m oob module works only with 16/32/64 gtx input data width"
)
;
endgenerate
// set data outputs to gtx
assign
txdata_out
=
txdata
;
assign
txcharisk_out
=
txcharisk
;
endmodule
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment