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
a699d0ce
Commit
a699d0ce
authored
Aug 07, 2015
by
Alexey Grebenkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Link layer. Pre-testing rtl
parent
22d73e32
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
590 additions
and
96 deletions
+590
-96
crc.v
host/crc.v
+130
-0
link.v
host/link.v
+374
-96
scrambler.v
host/scrambler.v
+86
-0
No files found.
host/crc.v
0 → 100644
View file @
a699d0ce
/*******************************************************************************
* Module: crc
* Date: 2015-07-11
* Author: Alexey
* Description: crc calculations for the link layer
*
* Copyright (c) 2015 Elphel, Inc.
* crc.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.
*
* crc.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/> .
*******************************************************************************/
/* same as for a scrambler, @ doc p.561 */
// TODO make it parallel, make another widths support
module
crc
#(
parameter
DATA_BYTE_WIDTH
=
4
)
(
input
wire
clk
,
input
wire
rst
,
input
wire
val_in
,
input
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_in
,
output
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
crc_out
)
;
reg
[
31
:
0
]
crc
;
wire
[
31
:
0
]
crc_bit
;
reg
[
31
:
0
]
new_bit
;
always
@
(
posedge
clk
)
crc
<=
rst
?
32'h52325032
:
val_in
?
new_bit
:
crc
;
assign
crc_bit
=
crc
^
data_in
;
assign
crc_out
=
crc
;
always
@
(
*
)
begin
new_bit
[
31
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
15
]
^
crc_bit
[
11
]
^
crc_bit
[
9
]
^
crc_bit
[
8
]
^
crc_bit
[
5
]
;
new_bit
[
30
]
=
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
14
]
^
crc_bit
[
10
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
4
]
;
new_bit
[
29
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
13
]
^
crc_bit
[
9
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
3
]
;
new_bit
[
28
]
=
crc_bit
[
30
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
12
]
^
crc_bit
[
8
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
2
]
;
new_bit
[
27
]
=
crc_bit
[
29
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
11
]
^
crc_bit
[
7
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
1
]
;
new_bit
[
26
]
=
crc_bit
[
31
]
^
crc_bit
[
28
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
10
]
^
crc_bit
[
6
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
0
]
;
new_bit
[
25
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
15
]
^
crc_bit
[
11
]
^
crc_bit
[
8
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
;
new_bit
[
24
]
=
crc_bit
[
30
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
14
]
^
crc_bit
[
10
]
^
crc_bit
[
7
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
;
new_bit
[
23
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
15
]
^
crc_bit
[
13
]
^
crc_bit
[
9
]
^
crc_bit
[
6
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
22
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
16
]
^
crc_bit
[
14
]
^
crc_bit
[
12
]
^
crc_bit
[
11
]
^
crc_bit
[
9
]
^
crc_bit
[
0
]
;
new_bit
[
21
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
22
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
13
]
^
crc_bit
[
10
]
^
crc_bit
[
9
]
^
crc_bit
[
5
]
;
new_bit
[
20
]
=
crc_bit
[
30
]
^
crc_bit
[
28
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
23
]
^
crc_bit
[
21
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
12
]
^
crc_bit
[
9
]
^
crc_bit
[
8
]
^
crc_bit
[
4
]
;
new_bit
[
19
]
=
crc_bit
[
29
]
^
crc_bit
[
27
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
22
]
^
crc_bit
[
20
]
^
crc_bit
[
16
]
^
crc_bit
[
15
]
^
crc_bit
[
11
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
3
]
;
new_bit
[
18
]
=
crc_bit
[
31
]
^
crc_bit
[
28
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
21
]
^
crc_bit
[
19
]
^
crc_bit
[
15
]
^
crc_bit
[
14
]
^
crc_bit
[
10
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
2
]
;
new_bit
[
17
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
27
]
^
crc_bit
[
25
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
20
]
^
crc_bit
[
18
]
^
crc_bit
[
14
]
^
crc_bit
[
13
]
^
crc_bit
[
9
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
1
]
;
new_bit
[
16
]
=
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
19
]
^
crc_bit
[
17
]
^
crc_bit
[
13
]
^
crc_bit
[
12
]
^
crc_bit
[
8
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
0
]
;
new_bit
[
15
]
=
crc_bit
[
30
]
^
crc_bit
[
27
]
^
crc_bit
[
24
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
18
]
^
crc_bit
[
16
]
^
crc_bit
[
15
]
^
crc_bit
[
12
]
^
crc_bit
[
9
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
;
new_bit
[
14
]
=
crc_bit
[
29
]
^
crc_bit
[
26
]
^
crc_bit
[
23
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
17
]
^
crc_bit
[
15
]
^
crc_bit
[
14
]
^
crc_bit
[
11
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
;
new_bit
[
13
]
=
crc_bit
[
31
]
^
crc_bit
[
28
]
^
crc_bit
[
25
]
^
crc_bit
[
22
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
16
]
^
crc_bit
[
14
]
^
crc_bit
[
13
]
^
crc_bit
[
10
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
;
new_bit
[
12
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
27
]
^
crc_bit
[
24
]
^
crc_bit
[
21
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
15
]
^
crc_bit
[
13
]
^
crc_bit
[
12
]
^
crc_bit
[
9
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
11
]
=
crc_bit
[
31
]
^
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
20
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
15
]
^
crc_bit
[
14
]
^
crc_bit
[
12
]
^
crc_bit
[
9
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
10
]
=
crc_bit
[
31
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
26
]
^
crc_bit
[
19
]
^
crc_bit
[
16
]
^
crc_bit
[
14
]
^
crc_bit
[
13
]
^
crc_bit
[
9
]
^
crc_bit
[
5
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
^
crc_bit
[
0
]
;
new_bit
[
9
]
=
crc_bit
[
29
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
18
]
^
crc_bit
[
13
]
^
crc_bit
[
12
]
^
crc_bit
[
11
]
^
crc_bit
[
9
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
;
new_bit
[
8
]
=
crc_bit
[
31
]
^
crc_bit
[
28
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
17
]
^
crc_bit
[
12
]
^
crc_bit
[
11
]
^
crc_bit
[
10
]
^
crc_bit
[
8
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
7
]
=
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
23
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
16
]
^
crc_bit
[
15
]
^
crc_bit
[
10
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
5
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
^
crc_bit
[
0
]
;
new_bit
[
6
]
=
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
25
]
^
crc_bit
[
22
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
14
]
^
crc_bit
[
11
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
;
new_bit
[
5
]
=
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
24
]
^
crc_bit
[
21
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
13
]
^
crc_bit
[
10
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
5
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
4
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
20
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
15
]
^
crc_bit
[
12
]
^
crc_bit
[
11
]
^
crc_bit
[
8
]
^
crc_bit
[
6
]
^
crc_bit
[
4
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
^
crc_bit
[
0
]
;
new_bit
[
3
]
=
crc_bit
[
31
]
^
crc_bit
[
27
]
^
crc_bit
[
25
]
^
crc_bit
[
19
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
15
]
^
crc_bit
[
14
]
^
crc_bit
[
10
]
^
crc_bit
[
9
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
3
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
;
new_bit
[
2
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
26
]
^
crc_bit
[
24
]
^
crc_bit
[
18
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
14
]
^
crc_bit
[
13
]
^
crc_bit
[
9
]
^
crc_bit
[
8
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
2
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
1
]
=
crc_bit
[
28
]
^
crc_bit
[
27
]
^
crc_bit
[
24
]
^
crc_bit
[
17
]
^
crc_bit
[
16
]
^
crc_bit
[
13
]
^
crc_bit
[
12
]
^
crc_bit
[
11
]
^
crc_bit
[
9
]
^
crc_bit
[
7
]
^
crc_bit
[
6
]
^
crc_bit
[
1
]
^
crc_bit
[
0
]
;
new_bit
[
0
]
=
crc_bit
[
31
]
^
crc_bit
[
30
]
^
crc_bit
[
29
]
^
crc_bit
[
28
]
^
crc_bit
[
26
]
^
crc_bit
[
25
]
^
crc_bit
[
24
]
^
crc_bit
[
16
]
^
crc_bit
[
12
]
^
crc_bit
[
10
]
^
crc_bit
[
9
]
^
crc_bit
[
6
]
^
crc_bit
[
0
]
;
end
endmodule
host/link.v
View file @
a699d0ce
...
@@ -19,21 +19,20 @@
...
@@ -19,21 +19,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> .
* along with this program. If not, see <http://www.gnu.org/licenses/> .
*******************************************************************************/
*******************************************************************************/
module
link
#(
module
link
#(
//
2 = word, 4 = dword or 8 = qword
//
4 = dword. 4-bytes aligned data transfers TODO 2 = word - easy, 8 = qword - difficult
parameter
DATA_BYTE_WIDTH
=
4
parameter
DATA_BYTE_WIDTH
=
4
)
)
(
(
input
wire
rst
,
input
wire
rst
,
input
wire
clk
,
input
wire
clk
,
// inputs from transport layer
// data inputs from transport layer
// request for a new frame transition
input
wire
frame_req
,
// 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
]
data_in
,
input
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_in
,
// in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
// in case of strange data aligments and size (1st mentioned @ doc, p.310, odd number of words case)
// Actually, only last data bundle shall be masked, others are always valid.
// Actually, only last data bundle shall be masked, others are always valid.
// Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
// Mask could be encoded into 3 bits instead of 4 for qword, but encoding+decoding aren't worth the bit
// TODO, for now not supported, all mask bits are assumed to be set
input
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
data_mask_in
,
input
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
data_mask_in
,
// buffer read strobe
// buffer read strobe
output
wire
data_strobe_out
,
output
wire
data_strobe_out
,
...
@@ -42,12 +41,10 @@ module link #(
...
@@ -42,12 +41,10 @@ module link #(
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
// read data is valid (if 0 while last pulse wasn't received => need to hold the line)
input
wire
data_val_in
,
input
wire
data_val_in
,
// outputs to transport layer
// data outputs to transport layer
// tell if the transaction is done and how it was done
output
wire
frame_done_good
,
output
wire
frame_done_bad
,
// read data, same as related inputs
// read data, same as related inputs
output
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_out
,
output
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_out
,
// same thing - all 1s for now. TODO
output
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
data_mask_out
,
output
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
data_mask_out
,
// count every data bundle read by transport layer, even if busy flag is set
// count every data bundle read by transport layer, even if busy flag is set
// let the transport layer handle oveflows by himself
// let the transport layer handle oveflows by himself
...
@@ -56,31 +53,88 @@ module link #(
...
@@ -56,31 +53,88 @@ module link #(
// transport layer tells if its inner buffer is almost full
// transport layer tells if its inner buffer is almost full
input
wire
data_busy_in
,
input
wire
data_busy_in
,
// request for a new frame transition
input
wire
frame_req
,
// a little bit of overkill with the cound of response signals, think of throwing out 1 of them
// LL tells back if it cant handle the request for now
output
wire
frame_busy
,
// LL tells if the request is transmitting
output
wire
frame_ack
,
// or if it was cancelled because of simultanious incoming transmission
output
wire
frame_rej
,
// TL tell if the outcoming transaction is done and how it was done
output
wire
frame_done_good
,
output
wire
frame_done_bad
,
// if started an incoming transaction
output
wire
incom_start
,
// if incoming transition was completed
output
wire
incom_done
,
// transport layer responds on a completion of a FIS
input
wire
incom_ack_good
,
input
wire
incom_ack_bad
,
// oob sequence is reinitiated and link now is not espeblished
input
wire
link_reset
,
// TL demands to brutally cancel current transaction
input
wire
sync_escape_req
,
// acknowlegement of a successful reception
output
wire
sync_escape_ack
,
// TL demands to stop current recieving session
input
wire
incom_stop_req
,
// inputs from phy
// inputs from phy
// phy is ready - link is established
// phy is ready - link is established
input
wire
phy_ready
,
input
wire
phy_ready
,
// data-primitives stream from phy
input
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
phy_data_in
,
input
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
phy_isk_in
,
// charisk
input
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
phy_err_in
,
// disperr | notintable
// to phy
output
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
phy_data_out
,
output
wire
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
phy_isk_out
,
// charisk
)
;
)
;
wire
dec_err
;
// doc, p.311 TODO
// scrambled data
wire
[
:
0
]
rcvd_dword
;
// shows current processing primitive (or just data dword) TODO
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
scrambler_out
;
wire
dec_err
;
// doc, p.311
// while receiving session shows crc check status
wire
crc_good
;
wire
crc_bad
;
// current crc
wire
[
31
:
0
]
crc_dword
;
wire
data_txing
;
// if there are still some data to transmit and the transaction wasn't cancelled
wire
data_txing
;
// if there are still some data to transmit and the transaction wasn't cancelled
always
@
(
posedge
clk
)
always
@
(
posedge
clk
)
data_txing
<=
rst
|
(
data_last_in
&
data_strobe_out
|
dword_val
&
rcvd_dword
[
CODE_DMATP
])
?
1'b0
:
frame_req
?
1'b1
:
data_txing
;
data_txing
<=
rst
|
(
data_last_in
&
data_strobe_out
|
dword_val
&
rcvd_dword
[
CODE_DMATP
])
?
1'b0
:
frame_req
?
1'b1
:
data_txing
;
// send primitives variety count, including CRC and DATA as primitives
localparam
PRIM_NUM
=
15
;
// list of bits of rcvd_dword
// list of bits of rcvd_dword
localparam
CODE_DATA
=
0
;
wire
[
PRIM_NUM
:
0
]
rcvd_dword
;
// shows current processing primitive (or just data dword)
localparam
CODE_HOLDP
=
1
;
wire
dword_val
;
localparam
CODE_DATA
=
0
;
localparam
CODE_CRC
=
1
;
localparam
CODE_SYNCP
=
2
;
localparam
CODE_SYNCP
=
2
;
localparam
CODE_DMATP
=
3
;
localparam
CODE_ALIGNP
=
3
;
localparam
CODE_XRDYP
=
4
;
localparam
CODE_SOFP
=
5
;
localparam
CODE_HOLDAP
=
6
;
localparam
CODE_HOLDP
=
7
;
localparam
CODE_EOFP
=
8
;
localparam
CODE_WTRMP
=
9
;
localparam
CODE_RRDYP
=
10
;
localparam
CODE_IPP
=
11
;
localparam
CODE_DMATP
=
12
;
localparam
CODE_OKP
=
13
;
localparam
CODE_ERRP
=
14
;
// form a response to transport layer
// form a response to transport layer
wire
frame_done
;
wire
frame_done
;
assign
frame_done
=
frame_done_good
|
frame_done_bad
;
assign
frame_done
=
frame_done_good
|
frame_done_bad
;
assign
frame_done_good
=
dword_val
&
rcvd_dword
[
CODE_OKP
]
;
assign
frame_done_good
=
status_send_wait
&
dword_val
&
rcvd_dword
[
CODE_OKP
]
;
assign
frame_done_bad
=
dword_val
&
rcvd_dword
[
CODE_ERRP
]
;
assign
frame_done_bad
=
status_send_wait
&
dword_val
&
rcvd_dword
[
CODE_ERRP
]
;
// fsm
// fsm
// states and transitions are taken from the doc, "Link Layer State Machine" chapter
// states and transitions are taken from the doc, "Link Layer State Machine" chapter
...
@@ -185,13 +239,34 @@ assign state_idle = ~state_sync_esc
...
@@ -185,13 +239,34 @@ assign state_idle = ~state_sync_esc
|
~
state_rcvr_badend
;
|
~
state_rcvr_badend
;
assign
set_sync_esc
=
// got an escaping primitive = request to cancel the transmission
assign
set_nocommerr
=
wire
alignes_pair
;
// pauses every state go give a chance to insert 2 align primitives on a line at least every 256 dwords due to spec
assign
set_nocomm
=
wire
alignes_pair_0
;
// time for 1st align primitive
assign
set_align
=
wire
alignes_pair_1
;
// time for 2nd align primitive
assign
set_reset
=
reg
[
8
:
0
]
alignes_timer
;
assign
alignes_pair_0
=
alignes_timer
==
9'd252
;
assign
alignes_pair_1
=
alignes_timer
==
9'd253
;
assign
alignes_pair
=
alignes_pair_0
|
alignes_pair_1
;
always
@
(
posedge
clk
)
alignes_timer
<=
rst
|
alignes_pause_1
|
state_reset
?
9'h0
:
alignes_timer
+
1'b1
;
wire
got_escape
;
assign
got_escape
=
dword_val
&
rcvd_dword
[
CODE_SYNCP
]
;
// escaping is done
assign
sync_escape_ack
=
state_sync_esc
;
// Whole transitions table, literally from doc pages 311-328
assign
set_sync_esc
=
sync_escape_req
;
assign
set_nocommerr
=
~
phy_ready
&
~
state_nocomm
&
~
state_reset
;
assign
set_nocomm
=
state_nocommerr
;
assign
set_align
=
state_reset
&
~
link_reset
;
assign
set_reset
=
link_reset
;
assign
set_send_rdy
=
state_idle
&
frame_req
;
assign
set_send_rdy
=
state_idle
&
frame_req
;
assign
set_send_sof
=
state_send_rdy
&
phy_ready
;
assign
set_send_sof
=
state_send_rdy
&
phy_ready
&
dword_val
&
rcvd_dword
[
CODE_RRDYP
]
;
assign
set_send_data
=
state_send_sof
&
phy_ready
assign
set_send_data
=
state_send_sof
&
phy_ready
|
state_send_rhold
&
data_txing
&
~
dec_err
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
&
~
rcvd_dword
[
CODE_DMATP
]
|
state_send_rhold
&
data_txing
&
~
dec_err
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
&
~
rcvd_dword
[
CODE_DMATP
]
|
state_send_shold
&
data_txing
&
data_val_in
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
;
|
state_send_shold
&
data_txing
&
data_val_in
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
;
...
@@ -203,92 +278,294 @@ assign set_send_crc = state_send_data & data_txing & data_val_in & d
...
@@ -203,92 +278,294 @@ assign set_send_crc = state_send_data & data_txing & data_val_in & d
assign
set_send_eof
=
state_send_crc
&
phy_ready
&
dword_val
&
~
rcvd_dword
[
CODE_SYNCP
]
;
assign
set_send_eof
=
state_send_crc
&
phy_ready
&
dword_val
&
~
rcvd_dword
[
CODE_SYNCP
]
;
assign
set_wait
=
state_send_eof
&
phy_ready
&
dword_val
&
~
rcvd_dword
[
CODE_SYNCP
]
;
assign
set_wait
=
state_send_eof
&
phy_ready
&
dword_val
&
~
rcvd_dword
[
CODE_SYNCP
]
;
// receiver's branch
// receiver's branch
assign
set_rcvr_wait
=
state_idle
&
dword_val
&
rcvd_dword
[
CODE_
RDYP
]
;
assign
set_rcvr_wait
=
state_idle
&
dword_val
&
rcvd_dword
[
CODE_
XRDYP
]
|
state_send_rdy
&
dword_val
&
rcvd_dword
[
CODE_RDYP
]
;
|
state_send_rdy
&
dword_val
&
rcvd_dword
[
CODE_
X
RDYP
]
;
assign
set_rcvr_rdy
=
state_rcv_wait
&
dword_val
&
rcvd_dword
[
CODE_RDYP
]
&
~
data_busy_in
;
assign
set_rcvr_rdy
=
state_rcv_wait
&
dword_val
&
rcvd_dword
[
CODE_
X
RDYP
]
&
~
data_busy_in
;
assign
set_rcvr_data
=
state_rcvr_rdy
&
dword_val
&
rcvd_dword
[
CODE_SOFP
]
;
assign
set_rcvr_data
=
state_rcvr_rdy
&
dword_val
&
rcvd_dword
[
CODE_SOFP
]
;
|
state_rcvr_rhold
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_EOFP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
&
~
data_busy_in
;
|
state_rcvr_rhold
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_EOFP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
&
~
data_busy_in
|
state_rcvr_shold
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_EOFP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
;
|
state_rcvr_shold
&
dword_val
&
~
rcvd_dword
[
CODE_HOLDP
]
&
~
rcvd_dword
[
CODE_EOFP
]
&
~
rcvd_dword
[
CODE_SYNCP
]
;
assign
set_rcvr_rhold
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_DATA
]
&
data_busy_in
;
assign
set_rcvr_rhold
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_DATA
]
&
data_busy_in
;
assign
set_rcvr_shold
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_HOLDP
]
;
assign
set_rcvr_shold
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_HOLDP
]
|
state_rcvr_rhold
&
dword_val
&
rcvd_dword
[
CODE_HOLDP
]
&
~
data_busy_in
;
|
state_rcvr_rhold
&
dword_val
&
rcvd_dword
[
CODE_HOLDP
]
&
~
data_busy_in
;
assign
set_rcvr_eof
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
;
assign
set_rcvr_eof
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
|
state_rcvr_rhold
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
;
|
state_rcvr_rhold
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
|
state_rcvr_shold
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
;
|
state_rcvr_shold
&
dword_val
&
rcvd_dword
[
CODE_EOFP
]
;
assign
set_rcvr_goodcrc
=
state_rcvr_eof
&
crc_good
;
assign
set_rcvr_goodcrc
=
state_rcvr_eof
&
crc_good
;
assign
set_rcvr_goodend
=
state_rcvr_goodcrc
&
assign
set_rcvr_goodend
=
state_rcvr_goodcrc
&
incom_ack_good
;
assign
set_rcvr_badend
=
state_rcvr_data
&
assign
set_rcvr_badend
=
state_rcvr_data
&
dword_val
&
rcvd_dword
[
CODE_WTRM
]
|
state_rcvr_eof
&
crc_bad
;
|
state_rcvr_eof
&
crc_bad
|
state_rcvr_goodcrc
&
|
state_rcvr_goodcrc
&
incom_ack_bad
;
assign
clr_sync_esc
=
assign
clr_sync_esc
=
set_nocomerr
|
set_reset
|
dword_val
&
(
rcvd_dword
[
CODE_RDYP
]
|
rcvd_dword
[
CODE_SYNCP
])
;
assign
clr_nocommerr
=
assign
clr_nocommerr
=
set_reset
|
set_nocomm
;
assign
clr_nocomm
=
assign
clr_nocomm
=
set_reset
|
set_align
;
assign
clr_align
=
assign
clr_align
=
set_nocomerr
|
set_reset
|
phy_ready
;
assign
clr_reset
=
assign
clr_reset
=
~
link_reset
;
assign
clr_send_rdy
=
assign
clr_send_rdy
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_sof
|
set_rcvr_wait
;
assign
clr_send_sof
=
assign
clr_send_sof
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_data
|
got_escape
;
assign
clr_send_data
=
assign
clr_send_data
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_rhold
|
set_send_shold
|
set_send_crc
|
got_escape
;
assign
clr_send_rhold
=
assign
clr_send_rhold
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_data
|
set_send_crc
|
got_escape
;
assign
clr_send_shold
=
assign
clr_send_shold
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_data
|
set_send_rhold
|
set_send_crc
|
got_escape
;
assign
clr_send_crc
=
assign
clr_send_crc
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_eof
|
got_escape
;
assign
clr_send_eof
=
assign
clr_send_eof
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_send_wait
|
got_escape
;
assign
clr_wait
=
frame_done
;
assign
clr_wait
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
frame_done
|
got_escape
;
assign
clr_rcvr_wait
=
assign
clr_rcvr_wait
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_rdy
|
dword_val
&
~
rcvd_dword
[
CODE_RDYP
]
;
assign
clr_rcvr_rdy
=
assign
clr_rcvr_rdy
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_data
|
dword_val
&
~
rcvd_dword
[
CODE_RDYP
]
&
~
rcvd_dword
[
CODE_SOFP
]
;
assign
clr_rcvr_data
=
assign
clr_rcvr_data
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_rhold
|
set_rcvr_shold
|
set_rcvr_eof
|
set_rcvr_badend
|
got_escape
;
assign
clr_rcvr_rhold
=
assign
clr_rcvr_rhold
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_data
|
set_rcvr_eof
|
set_rcvr_shold
|
got_escape
;
assign
clr_rcvr_shold
=
assign
clr_rcvr_shold
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_data
|
set_rcvr_eof
|
got_escape
;
assign
clr_rcvr_eof
=
assign
clr_rcvr_eof
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_eof
|
set_rcvr_goodcrc
|
set_rcvr_badcrc
;
assign
clr_rcvr_goodcrc
=
assign
clr_rcvr_goodcrc
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
set_rcvr_goodend
|
set_rcvr_badend
|
set_rcvr_goodcrc
|
got_escape
;
assign
clr_rcvr_goodend
=
assign
clr_rcvr_goodend
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
got_escape
;
assign
clr_rcvr_badend
=
assign
clr_rcvr_badend
=
set_nocomerr
|
set_reset
|
set_sync_esc
|
got_escape
;
// the only truely asynchronous transaction between states is -> state_ reset. It shall not be delayed by sending alignes
// Luckily, while in that state, the line is off, so we dont need to care about merging alignes and state-bounded primitives
// Others transitions are straightforward
always
@
(
posedge
clk
)
always
@
(
posedge
clk
)
state_sync_esc
<=
(
state_sync_esc
|
set_sync_esc
)
&
~
clr_sync_esc
&
~
rst
;
begin
state_nocommerr
<=
(
state_nocommerr
|
set_nocommerr
)
&
~
clr_nocommerr
&
~
rst
;
state_sync_esc
<=
(
state_sync_esc
|
set_sync_esc
&
~
alignes_pair
)
&
~
clr_sync_esc
&
~
rst
;
state_nocomm
<=
(
state_nocomm
|
set_nocomm
)
&
~
clr_nocomm
&
~
rst
;
state_nocommerr
<=
(
state_nocommerr
|
set_nocommerr
&
~
alignes_pair
)
&
~
clr_nocommerr
&
~
rst
;
state_align
<=
(
state_align
|
set_align
)
&
~
clr_align
&
~
rst
;
state_nocomm
<=
(
state_nocomm
|
set_nocomm
&
~
alignes_pair
)
&
~
clr_nocomm
&
~
rst
;
state_reset
<=
(
state_reset
|
set_reset
)
&
~
clr_reset
&
~
rst
;
state_align
<=
(
state_align
|
set_align
&
~
alignes_pair
)
&
~
clr_align
&
~
rst
;
state_send_rdy
<=
(
state_send_rdy
|
set_send_rdy
)
&
~
clr_send_rdy
&
~
rst
;
state_reset
<=
(
state_reset
|
set_reset
)
&
~
clr_reset
&
~
rst
;
state_send_sof
<=
(
state_send_sof
|
set_send_sof
)
&
~
clr_send_sof
&
~
rst
;
state_send_rdy
<=
(
state_send_rdy
|
set_send_rdy
&
~
alignes_pair
)
&
~
clr_send_rdy
&
~
rst
;
state_send_data
<=
(
state_send_data
|
set_send_data
)
&
~
clr_send_data
&
~
rst
;
state_send_sof
<=
(
state_send_sof
|
set_send_sof
&
~
alignes_pair
)
&
~
clr_send_sof
&
~
rst
;
state_send_rhold
<=
(
state_send_rhold
|
set_send_rhold
)
&
~
clr_send_rhold
&
~
rst
;
state_send_data
<=
(
state_send_data
|
set_send_data
&
~
alignes_pair
)
&
~
clr_send_data
&
~
rst
;
state_send_shold
<=
(
state_send_shold
|
set_send_shold
)
&
~
clr_send_shold
&
~
rst
;
state_send_rhold
<=
(
state_send_rhold
|
set_send_rhold
&
~
alignes_pair
)
&
~
clr_send_rhold
&
~
rst
;
state_send_crc
<=
(
state_send_crc
|
set_send_crc
)
&
~
clr_send_crc
&
~
rst
;
state_send_shold
<=
(
state_send_shold
|
set_send_shold
&
~
alignes_pair
)
&
~
clr_send_shold
&
~
rst
;
state_send_eof
<=
(
state_send_eof
|
set_send_eof
)
&
~
clr_send_eof
&
~
rst
;
state_send_crc
<=
(
state_send_crc
|
set_send_crc
&
~
alignes_pair
)
&
~
clr_send_crc
&
~
rst
;
state_wait
<=
(
state_wait
|
set_wait
)
&
~
clr_wait
&
~
rst
;
state_send_eof
<=
(
state_send_eof
|
set_send_eof
&
~
alignes_pair
)
&
~
clr_send_eof
&
~
rst
;
state_rcvr_wait
<=
(
state_rcvr_wait
|
set_rcvr_wait
)
&
~
clr_rcvr_wait
&
~
rst
;
state_wait
<=
(
state_wait
|
set_wait
&
~
alignes_pair
)
&
~
clr_wait
&
~
rst
;
state_rcvr_rdy
<=
(
state_rcvr_rdy
|
set_rcvr_rdy
)
&
~
clr_rcvr_rdy
&
~
rst
;
state_rcvr_wait
<=
(
state_rcvr_wait
|
set_rcvr_wait
&
~
alignes_pair
)
&
~
clr_rcvr_wait
&
~
rst
;
state_rcvr_data
<=
(
state_rcvr_data
|
set_rcvr_data
)
&
~
clr_rcvr_data
&
~
rst
;
state_rcvr_rdy
<=
(
state_rcvr_rdy
|
set_rcvr_rdy
&
~
alignes_pair
)
&
~
clr_rcvr_rdy
&
~
rst
;
state_rcvr_rhold
<=
(
state_rcvr_rhold
|
set_rcvr_rhold
)
&
~
clr_rcvr_rhold
&
~
rst
;
state_rcvr_data
<=
(
state_rcvr_data
|
set_rcvr_data
&
~
alignes_pair
)
&
~
clr_rcvr_data
&
~
rst
;
state_rcvr_shold
<=
(
state_rcvr_shold
|
set_rcvr_shold
)
&
~
clr_rcvr_shold
&
~
rst
;
state_rcvr_rhold
<=
(
state_rcvr_rhold
|
set_rcvr_rhold
&
~
alignes_pair
)
&
~
clr_rcvr_rhold
&
~
rst
;
state_rcvr_eof
<=
(
state_rcvr_eof
|
set_rcvr_eof
)
&
~
clr_rcvr_eof
&
~
rst
;
state_rcvr_shold
<=
(
state_rcvr_shold
|
set_rcvr_shold
&
~
alignes_pair
)
&
~
clr_rcvr_shold
&
~
rst
;
state_rcvr_goodcrc
<=
(
state_rcvr_goodcrc
|
set_rcvr_goodcrc
)
&
~
clr_rcvr_goodcrc
&
~
rst
;
state_rcvr_eof
<=
(
state_rcvr_eof
|
set_rcvr_eof
&
~
alignes_pair
)
&
~
clr_rcvr_eof
&
~
rst
;
state_rcvr_goodend
<=
(
state_rcvr_goodend
|
set_rcvr_goodend
)
&
~
clr_rcvr_goodend
&
~
rst
;
state_rcvr_goodcrc
<=
(
state_rcvr_goodcrc
|
set_rcvr_goodcrc
&
~
alignes_pair
)
&
~
clr_rcvr_goodcrc
&
~
rst
;
state_rcvr_badend
<=
(
state_rcvr_badend
|
set_rcvr_badend
)
&
~
clr_rcvr_badend
&
~
rst
;
state_rcvr_goodend
<=
(
state_rcvr_goodend
|
set_rcvr_goodend
&
~
alignes_pair
)
&
~
clr_rcvr_goodend
&
~
rst
;
state_rcvr_badend
<=
(
state_rcvr_badend
|
set_rcvr_badend
&
~
alignes_pair
)
&
~
clr_rcvr_badend
&
~
rst
;
end
// flag if incoming request to terminate current transaction came from TL
reg
incom_stop_f
;
always
@
(
posedge
clk
)
incom_stop_f
<=
rst
|
incom_done
|
~
frame_busy
?
1'b0
:
incom_stop_req
?
1'b1
:
incom_stop_f
;
// form data to phy
reg
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
to_phy_data
;
reg
[
DATA_BYTE_WIDTH
/
2
-
1
:
0
]
to_phy_isk
;
// TODO implement CONTP
localparam
[
15
:
0
]
PRIM_SYNCP_HI
=
{
3'd5
,
5'd21
,
3'd5
,
5'd21
};
localparam
[
15
:
0
]
PRIM_SYNCP_LO
=
{
3'd4
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_ALIGNP_HI
=
{
3'd3
,
5'd27
,
3'd2
,
5'd10
};
localparam
[
15
:
0
]
PRIM_ALIGNP_LO
=
{
3'd2
,
5'd10
,
3'd5
,
5'd28
};
localparam
[
15
:
0
]
PRIM_XRDYP_HI
=
{
3'd2
,
5'd23
,
3'd2
,
5'd23
};
localparam
[
15
:
0
]
PRIM_XRDYP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_SOFP_HI
=
{
3'd1
,
5'd23
,
3'd1
,
5'd23
};
localparam
[
15
:
0
]
PRIM_SOFP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_HOLDAP_HI
=
{
3'd4
,
5'd21
,
3'd4
,
5'd21
};
localparam
[
15
:
0
]
PRIM_HOLDAP_LO
=
{
3'd5
,
5'd10
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_HOLDP_HI
=
{
3'd6
,
5'd21
,
3'd6
,
5'd21
};
localparam
[
15
:
0
]
PRIM_HOLDP_LO
=
{
3'd5
,
5'd10
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_EOFP_HI
=
{
3'd6
,
5'd21
,
3'd6
,
5'd21
};
localparam
[
15
:
0
]
PRIM_EOFP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_WTRMP_HI
=
{
3'd2
,
5'd24
,
3'd2
,
5'd24
};
localparam
[
15
:
0
]
PRIM_WTRMP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_RRDYP_HI
=
{
3'd2
,
5'd10
,
3'd2
,
5'd10
};
localparam
[
15
:
0
]
PRIM_RRDYP_LO
=
{
3'd4
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_IPP_HI
=
{
3'd2
,
5'd21
,
3'd2
,
5'd21
};
localparam
[
15
:
0
]
PRIM_IPP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_DMATP_HI
=
{
3'd1
,
5'd22
,
3'd1
,
5'd22
};
localparam
[
15
:
0
]
PRIM_DMATP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_OKP_HI
=
{
3'd1
,
5'd21
,
3'd1
,
5'd21
};
localparam
[
15
:
0
]
PRIM_OKP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
localparam
[
15
:
0
]
PRIM_ERRP_HI
=
{
3'd2
,
5'd22
,
3'd2
,
5'd22
};
localparam
[
15
:
0
]
PRIM_ERRP_LO
=
{
3'd5
,
5'd21
,
3'd3
,
5'd28
};
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
prim_data
[
PRIM_NUM
-
1
:
0
]
;
// fill all possible output primitives to choose from them after
generate
if
(
DATA_BYTE_WIDTH
==
2
)
begin
reg
prim_word
;
// word counter in a primitive TODO logic
assign
prim_data
[
CODE_SYNCP
]
=
prim_word
?
PRIM_SYNCP_HI
:
PRIM_SYNCP_LO
;
assign
prim_data
[
CODE_ALIGNP
]
=
prim_word
?
PRIM_ALIGNP_HI
:
PRIM_ALIGNP_LO
;
assign
prim_data
[
CODE_XRDYP
]
=
prim_word
?
PRIM_XRDYP_HI
:
PRIM_XRDYP_LO
;
assign
prim_data
[
CODE_SOFP
]
=
prim_word
?
PRIM_SOFP_HI
:
PRIM_SOFP_LO
;
assign
prim_data
[
CODE_DATA
]
=
scrambler_out
;
assign
prim_data
[
CODE_HOLDAP
]
=
prim_word
?
PRIM_HOLDAP_HI
:
PRIM_HOLDAP_LO
;
assign
prim_data
[
CODE_HOLDP
]
=
prim_word
?
PRIM_HOLDP_HI
:
PRIM_HOLDP_LO
;
assign
prim_data
[
CODE_CRC
]
=
scrambler_out
;
assign
prim_data
[
CODE_EOFP
]
=
prim_word
?
PRIM_EOFP_HI
:
PRIM_EOFP_LO
;
assign
prim_data
[
CODE_WTRMP
]
=
prim_word
?
PRIM_WTRMP_HI
:
PRIM_WTRMP_LO
;
assign
prim_data
[
CODE_RRDYP
]
=
prim_word
?
PRIM_RRDYP_HI
:
PRIM_RRDYP_LO
;
assign
prim_data
[
CODE_IPP
]
=
prim_word
?
PRIM_IPP_HI
:
PRIM_IPP_LO
;
assign
prim_data
[
CODE_DMATP
]
=
prim_word
?
PRIM_DMATP_HI
:
PRIM_DMATP_LO
;
assign
prim_data
[
CODE_OKP
]
=
prim_word
?
PRIM_OKP_HI
:
PRIM_OKP_LO
;
assign
prim_data
[
CODE_ERRP
]
=
prim_word
?
PRIM_ERRP_HI
:
PRIM_ERRP_LO
;
always
@
(
posedge
clk
)
begin
$
display
(
"%m: unsupported data width"
)
;
$
finish
;
end
end
else
if
(
DATA_BYTE_WIDTH
==
4
)
begin
assign
prim_data
[
CODE_SYNCP
]
=
{
PRIM_SYNCP_HI
,
PRIM_SYNCP_LO
};
assign
prim_data
[
CODE_ALIGNP
]
=
{
PRIM_ALIGNP_HI
,
PRIM_ALIGNP_LO
};
assign
prim_data
[
CODE_XRDYP
]
=
{
PRIM_XRDYP_HI
,
PRIM_XRDYP_LO
};
assign
prim_data
[
CODE_SOFP
]
=
{
PRIM_SOFP_HI
,
PRIM_SOFP_LO
};
assign
prim_data
[
CODE_DATA
]
=
scrambler_out
;
assign
prim_data
[
CODE_HOLDAP
]
=
{
PRIM_HOLDAP_HI
,
PRIM_HOLDAP_LO
};
assign
prim_data
[
CODE_HOLDP
]
=
{
PRIM_HOLDP_HI
,
PRIM_HOLDP_LO
};
assign
prim_data
[
CODE_CRC
]
=
scrambler_out
;
assign
prim_data
[
CODE_EOFP
]
=
{
PRIM_EOFP_HI
,
PRIM_EOFP_LO
};
assign
prim_data
[
CODE_WTRMP
]
=
{
PRIM_WTRMP_HI
,
PRIM_WTRMP_LO
};
assign
prim_data
[
CODE_RRDYP
]
=
{
PRIM_RRDYP_HI
,
PRIM_RRDYP_LO
};
assign
prim_data
[
CODE_IPP
]
=
{
PRIM_IPP_HI
,
PRIM_IPP_LO
};
assign
prim_data
[
CODE_DMATP
]
=
{
PRIM_DMATP_HI
,
PRIM_DMATP_LO
};
assign
prim_data
[
CODE_OKP
]
=
{
PRIM_OKP_HI
,
PRIM_OKP_LO
};
assign
prim_data
[
CODE_ERRP
]
=
{
PRIM_ERRP_HI
,
PRIM_ERRP_LO
};
end
else
begin
always
@
(
posedge
clk
)
begin
$
display
(
"%m: unsupported data width"
)
;
$
finish
;
end
end
endgenerate
// select which primitive shall be sent
wire
[
PRIM_NUM
-
1
:
0
]
select_prim
;
assign
select_prim
[
CODE_SYNCP
]
=
~
alignes_pair
&
(
state_idle
|
state_sync_esc
|
state_rcvr_wait
|
state_reset
)
;
assign
select_prim
[
CODE_ALIGNP
]
=
alignes_pair
|
(
state_nocomm
|
state_nocomm_err
|
state_align
)
;
assign
select_prim
[
CODE_XRDYP
]
=
~
alignes_pair
&
(
state_send_rdy
)
;
assign
select_prim
[
CODE_SOFP
]
=
~
alignes_pair
&
(
state_send_sof
)
;
assign
select_prim
[
CODE_DATA
]
=
~
alignes_pair
&
(
state_send_data
&
~
set_send_shold
)
;
// if there's no data availible for a transmission, fsm still = state_send_data. Need to explicitly count this case.
assign
select_prim
[
CODE_HOLDAP
]
=
~
alignes_pair
&
(
state_send_rhold
|
state_rcvr_shold
&
~
incom_stop_f
)
;
assign
select_prim
[
CODE_HOLDP
]
=
~
alignes_pair
&
(
state_send_shold
|
state_rcvr_rhold
|
state_send_data
&
set_send_shold
)
;
// the case mentioned 2 lines upper
assign
select_prim
[
CODE_CRC
]
=
~
alignes_pair
&
(
state_send_crc
)
;
assign
select_prim
[
CODE_EOFP
]
=
~
alignes_pair
&
(
state_send_eof
)
;
assign
select_prim
[
CODE_WTRMP
]
=
~
alignes_pair
&
(
state_send_wait
)
;
assign
select_prim
[
CODE_RRDYP
]
=
~
alignes_pair
&
(
state_rcvr_rdy
)
;
assign
select_prim
[
CODE_IPP
]
=
~
alignes_pair
&
(
state_rcvr_data
&
~
incom_stop_f
|
state_rcvr_eof
|
state_rcvr_goodcrc
)
;
assign
select_prim
[
CODE_DMATP
]
=
~
alignes_pair
&
(
state_rcvr_data
&
incom_stop_f
|
state_rcvr_shold
&
incom_stop_f
)
;
assign
select_prim
[
CODE_OKP
]
=
~
alignes_pair
&
(
state_rcvr_goodend
)
;
assign
select_prim
[
CODE_ERRP
]
=
~
alignes_pair
&
(
state_rcvr_badend
)
;
// primitive selector MUX
always
@
(
posedge
clk
)
to_phy_data
<=
rst
?
{
DATA_BYTE_WIDTH
*
8
{
1'b0
}}:
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_SYNCP
]
}}
&
prim_data
[
CODE_SYNCP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_ALIGNP
]
}}
&
prim_data
[
CODE_ALIGNP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_RRDYP
]
}}
&
prim_data
[
CODE_RRDYP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_SOFP
]
}}
&
prim_data
[
CODE_SOFP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_HOLDAP
]
}}
&
prim_data
[
CODE_HOLDAP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_HOLDP
]
}}
&
prim_data
[
CODE_HOLDP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_EOFP
]
}}
&
prim_data
[
CODE_EOFP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_WTRMP
]
}}
&
prim_data
[
CODE_WTRMP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_XRDYP
]
}}
&
prim_data
[
CODE_XRDYP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_IPP
]
}}
&
prim_data
[
CODE_IPP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_DMATP
]
}}
&
prim_data
[
CODE_DMATP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_OKP
]
}}
&
prim_data
[
CODE_OKP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_ERRP
]
}}
&
prim_data
[
CODE_ERRP
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_CRC
]
}}
&
prim_data
[
CODE_CRC
]
|
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_DATA
]
}}
&
prim_data
[
CODE_DATA
]
;
always
@
(
posedge
clk
)
to_phy_isk
<=
rst
|
~
select_prim
[
CODE_DATA
]
&
~
select_prim
[
CODE_CRC
]
?
{{
(
DATA_BYTE_WIDTH
/
2
-
1
)
{
1'b0
}},
1'b1
}
:
{
DATA_BYTE_WIDTH
/
2
{
1'b0
}}
;
// 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
;
/*
* Scrambler can work both as a scrambler and a descramler, because data stream could be
* one direction at a time
*/
scrambler
scrambler
(
.
rst
(
select_prim
[
CODE_SOFP
]
|
dword_val
&
rcvd_dword
[
CODE_SOFP
])
,
.
clk
(
clk
)
,
.
val
(
select_prim
[
CODE_DATA
]
|
inc_is_data
)
,
.
data_in
(
crc_dword
&
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_CRC
]
}}
|
data_in
&
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_DATA
]
}}
|
phy_data_in
&
{
DATA_BYTE_WIDTH
*
8
{
inc_is_data
}}
)
,
.
data_out
(
scrambler_out
)
)
;
/*
* Same as for scrambler, crc computation for both directions
*/
crc
crc
(
.
clk
(
clk
)
,
.
rst
(
select_prim
[
CODE_SOFP
]
|
dword_val
&
rcvd_dword
[
CODE_SOFP
])
,
.
val_in
(
select_prim
[
CODE_DATA
]
|
inc_is_data
)
,
.
data_in
(
data_in
&
{
DATA_BYTE_WIDTH
*
8
{
select_prim
[
CODE_DATA
]
}}
|
phy_data_in
&
{
DATA_BYTE_WIDTH
*
8
{
inc_is_data
}}
)
,
.
crc_out
(
crc_dword
)
)
;
// the output of crc module shall be 0 if 1 tick later reciever got a crc checksum and no errors occured
assign
crc_good
=
~|
crc_dword
&
state_rcvr_eof
;
assign
crc_bad
=
|
crc_dword
&
state_rcvr_eof
;
// to TL data outputs assigment
assign
data_out
=
scrambler_out
;
assign
data_mask_out
=
2'b11
;
//{DATA_BYTE_WIDTH/2{1'b1}};
assign
data_val_out
=
select_prim
[
CODE_DATA
]
;
// from TL data
// gives a strobe everytime data is present and we're at a corresponding state.
assign
data_strobe_out
=
select_prim
[
CODE_DATA
]
;
// assign phy data outputs
assign
phy_data_out
=
to_phy_data
;
assign
phy_isk_out
=
to_phy_isk
;
assign
frame_busy
=
~
state_idle
;
assign
frame_ack
=
state_send_sof
;
assign
frame_rej
=
set_rcvr_wait
&
state_send_rdy
&
~
alignes_pair
;
// incoming fises detected
assign
incom_start
=
set_rcvr_wait
&
~
alignes_pair
;
// ... and processed
assign
incom_done
=
set_rcvr_goodcrc
&
~
alignes_pair
;
// shows that incoming primitive or data is ready to be processed // TODO somehow move alignes_pair into dword_val
assign
dword_val
=
|
rcvd_dword
&
phy_ready
;
// determine imcoming primitive type
assign
rcvd_dword
[
CODE_DATA
]
=
~|
phy_isk_in
;
assign
rcvd_dword
[
CODE_CRC
]
=
1'b0
;
assign
rcvd_dword
[
CODE_SYNCP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_SYNCP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_ALIGNP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_ALIGNP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_XRDYP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_XRDYP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_SOFP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_SOFP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_HOLDAP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_HOLDAP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_HOLDP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_HOLDP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_EOFP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_EOFP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_WTRMP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_WTRMP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_RRDYP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_RRDYP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_IPP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_IPP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_DMATP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_DMATP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_OKP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_OKP
]
==
phy_data_in
;
assign
rcvd_dword
[
CODE_ERRP
]
=
phy_isk_in
[
0
]
==
1'b1
&
~|
phy_isk_in
[
DATA_BYTE_WIDTH
/
2
-
1
:
1
]
&
prim_data
[
CODE_ERRP
]
==
phy_data_in
;
// phy level errors handling TODO
assign
dec_err
=
|
phy_err_in
;
`ifdef
CHECKERS_ENABLED
`ifdef
CHECKERS_ENABLED
// incoming primitives
always
@
(
posedge
clk
)
if
(
~|
rcvd_dword
&
phy_ready
)
begin
$
display
(
"%m: invalid primitive recieved : %h, conrol : %h, err : %h"
,
phy_data_in
,
phy_isk_in
,
phy_err_in
)
;
$
finish
;
end
// States checker
// States checker
reg
[
STATES_COUNT
-
1
:
0
]
sim_states_concat
;
reg
[
STATES_COUNT
-
1
:
0
]
sim_states_concat
;
always
@
(
posedge
clk
)
always
@
(
posedge
clk
)
...
@@ -344,6 +621,7 @@ always @ (posedge clk)
...
@@ -344,6 +621,7 @@ always @ (posedge clk)
,
state_rcvr_badend
,
state_rcvr_badend
};
};
$
display
(
"%m: invalid states: %b"
,
sim_state_concat
)
;
$
display
(
"%m: invalid states: %b"
,
sim_state_concat
)
;
$
finish
;
end
end
`endif
`endif
...
...
host/scrambler.v
0 → 100644
View file @
a699d0ce
/*******************************************************************************
* Module: scrambler
* Date: 2015-07-11
* Author: Alexey
* Description: a scrambler for the link layer
*
* Copyright (c) 2015 Elphel, Inc.
* scrambler.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.
*
* scrambler.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/> .
*******************************************************************************/
/*
* Algorithm is taken from the doc, p.565. TODO make it parallel
*/
// TODO another widths support
module
scrambler
#(
parameter
DATA_BYTE_WIDTH
=
4
)
(
input
wire
clk
,
input
wire
rst
,
input
wire
val_in
,
input
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_in
,
output
wire
[
DATA_BYTE_WIDTH
*
8
-
1
:
0
]
data_out
)
;
reg
[
15
:
0
]
now
;
reg
[
31
:
0
]
next
;
always
@
(
posedge
clk
)
now
<=
rst
?
16'hf0f6
:
val_in
?
next
:
now
;
assign
data_out
=
val_in
?
data_in
^
next
:
data_in
;
always
@
(
*
)
/* if (rst)
next = 32'h0;
else*/
begin
next
[
31
]
=
now
[
12
]
^
now
[
10
]
^
now
[
7
]
^
now
[
3
]
^
now
[
1
]
^
now
[
0
]
;
next
[
30
]
=
now
[
15
]
^
now
[
14
]
^
now
[
12
]
^
now
[
11
]
^
now
[
9
]
^
now
[
6
]
^
now
[
3
]
^
now
[
2
]
^
now
[
0
]
;
next
[
29
]
=
now
[
15
]
^
now
[
13
]
^
now
[
12
]
^
now
[
11
]
^
now
[
10
]
^
now
[
8
]
^
now
[
5
]
^
now
[
3
]
^
now
[
2
]
^
now
[
1
]
;
next
[
28
]
=
now
[
14
]
^
now
[
12
]
^
now
[
11
]
^
now
[
10
]
^
now
[
9
]
^
now
[
7
]
^
now
[
4
]
^
now
[
2
]
^
now
[
1
]
^
now
[
0
]
;
next
[
27
]
=
now
[
15
]
^
now
[
14
]
^
now
[
13
]
^
now
[
12
]
^
now
[
11
]
^
now
[
10
]
^
now
[
9
]
^
now
[
8
]
^
now
[
6
]
^
now
[
1
]
^
now
[
0
]
;
next
[
26
]
=
now
[
15
]
^
now
[
13
]
^
now
[
11
]
^
now
[
10
]
^
now
[
9
]
^
now
[
8
]
^
now
[
7
]
^
now
[
5
]
^
now
[
3
]
^
now
[
0
]
;
next
[
25
]
=
now
[
15
]
^
now
[
10
]
^
now
[
9
]
^
now
[
8
]
^
now
[
7
]
^
now
[
6
]
^
now
[
4
]
^
now
[
3
]
^
now
[
2
]
;
next
[
24
]
=
now
[
14
]
^
now
[
9
]
^
now
[
8
]
^
now
[
7
]
^
now
[
6
]
^
now
[
5
]
^
now
[
3
]
^
now
[
2
]
^
now
[
1
]
;
next
[
23
]
=
now
[
13
]
^
now
[
8
]
^
now
[
7
]
^
now
[
6
]
^
now
[
5
]
^
now
[
4
]
^
now
[
2
]
^
now
[
1
]
^
now
[
0
]
;
next
[
22
]
=
now
[
15
]
^
now
[
14
]
^
now
[
7
]
^
now
[
6
]
^
now
[
5
]
^
now
[
4
]
^
now
[
1
]
^
now
[
0
]
;
next
[
21
]
=
now
[
15
]
^
now
[
13
]
^
now
[
12
]
^
now
[
6
]
^
now
[
5
]
^
now
[
4
]
^
now
[
0
]
;
next
[
20
]
=
now
[
15
]
^
now
[
11
]
^
now
[
5
]
^
now
[
4
]
;
next
[
19
]
=
now
[
14
]
^
now
[
10
]
^
now
[
4
]
^
now
[
3
]
;
next
[
18
]
=
now
[
13
]
^
now
[
9
]
^
now
[
3
]
^
now
[
2
]
;
next
[
17
]
=
now
[
12
]
^
now
[
8
]
^
now
[
2
]
^
now
[
1
]
;
next
[
16
]
=
now
[
11
]
^
now
[
7
]
^
now
[
1
]
^
now
[
0
]
;
next
[
15
]
=
now
[
15
]
^
now
[
14
]
^
now
[
12
]
^
now
[
10
]
^
now
[
6
]
^
now
[
3
]
^
now
[
0
]
;
next
[
14
]
=
now
[
15
]
^
now
[
13
]
^
now
[
12
]
^
now
[
11
]
^
now
[
9
]
^
now
[
5
]
^
now
[
3
]
^
now
[
2
]
;
next
[
13
]
=
now
[
14
]
^
now
[
12
]
^
now
[
11
]
^
now
[
10
]
^
now
[
8
]
^
now
[
4
]
^
now
[
2
]
^
now
[
1
]
;
next
[
12
]
=
now
[
13
]
^
now
[
11
]
^
now
[
10
]
^
now
[
9
]
^
now
[
7
]
^
now
[
3
]
^
now
[
1
]
^
now
[
0
]
;
next
[
11
]
=
now
[
15
]
^
now
[
14
]
^
now
[
10
]
^
now
[
9
]
^
now
[
8
]
^
now
[
6
]
^
now
[
3
]
^
now
[
2
]
^
now
[
0
]
;
next
[
10
]
=
now
[
15
]
^
now
[
13
]
^
now
[
12
]
^
now
[
9
]
^
now
[
8
]
^
now
[
7
]
^
now
[
5
]
^
now
[
3
]
^
now
[
2
]
^
now
[
1
]
;
next
[
9
]
=
now
[
14
]
^
now
[
12
]
^
now
[
11
]
^
now
[
8
]
^
now
[
7
]
^
now
[
6
]
^
now
[
4
]
^
now
[
2
]
^
now
[
1
]
^
now
[
0
]
;
next
[
8
]
=
now
[
15
]
^
now
[
14
]
^
now
[
13
]
^
now
[
12
]
^
now
[
11
]
^
now
[
10
]
^
now
[
7
]
^
now
[
6
]
^
now
[
5
]
^
now
[
1
]
^
now
[
0
]
;
next
[
7
]
=
now
[
15
]
^
now
[
13
]
^
now
[
11
]
^
now
[
10
]
^
now
[
9
]
^
now
[
6
]
^
now
[
5
]
^
now
[
4
]
^
now
[
3
]
^
now
[
0
]
;
next
[
6
]
=
now
[
15
]
^
now
[
10
]
^
now
[
9
]
^
now
[
8
]
^
now
[
5
]
^
now
[
4
]
^
now
[
2
]
;
next
[
5
]
=
now
[
14
]
^
now
[
9
]
^
now
[
8
]
^
now
[
7
]
^
now
[
4
]
^
now
[
3
]
^
now
[
1
]
;
next
[
4
]
=
now
[
13
]
^
now
[
8
]
^
now
[
7
]
^
now
[
6
]
^
now
[
3
]
^
now
[
2
]
^
now
[
0
]
;
next
[
3
]
=
now
[
15
]
^
now
[
14
]
^
now
[
7
]
^
now
[
6
]
^
now
[
5
]
^
now
[
3
]
^
now
[
2
]
^
now
[
1
]
;
next
[
2
]
=
now
[
14
]
^
now
[
13
]
^
now
[
6
]
^
now
[
5
]
^
now
[
4
]
^
now
[
2
]
^
now
[
1
]
^
now
[
0
]
;
next
[
1
]
=
now
[
15
]
^
now
[
14
]
^
now
[
13
]
^
now
[
5
]
^
now
[
4
]
^
now
[
1
]
^
now
[
0
]
;
next
[
0
]
=
now
[
15
]
^
now
[
13
]
^
now
[
4
]
^
now
[
0
]
;
end
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