42a91e95c3df8c021b0fadf9411cb9784a17ebd1
1 from migen
.fhdl
.std
import *
2 from migen
.genlib
.misc
import chooser
3 from migen
.actorlib
.fifo
import AsyncFIFO
4 from migen
.flow
.actor
import Sink
, Source
6 from lib
.sata
.common
import *
8 class K7SATAPHYDatapathRX(Module
):
10 self
.sink
= Sink(phy_description(16))
11 self
.source
= Source(phy_description(32))
18 data_sr
= Signal(32+8)
19 charisk_sr
= Signal(4+1)
20 data_sr_d
= Signal(32+8)
21 charisk_sr_d
= Signal(4+1)
23 data_sr
.eq(Cat(data_sr_d
[16:], self
.sink
.data
)),
24 charisk_sr
.eq(Cat(charisk_sr_d
[2:], self
.sink
.charisk
))
26 self
.sync
.sata_rx
+= [
27 data_sr_d
.eq(data_sr
),
28 charisk_sr_d
.eq(charisk_sr
)
34 self
.sync
.sata_rx
+= [
35 If(self
.sink
.charisk
!=0,
36 alignment
.eq(self
.sink
.charisk
[1]),
48 data
.eq(data_sr
[0:32]),
49 charisk
.eq(charisk_sr
[0:4])
51 data
.eq(data_sr
[8:40]),
52 charisk
.eq(charisk_sr
[1:5])
56 # clock domain crossing
57 # (SATA3) 300MHz sata_rx clk to sys_clk
58 # (SATA2) 150MHz sata_rx clk to sys_clk
59 # (SATA1) 75MHz sata_rx clk to sys_clk
61 # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
62 # source destination is always able to accept data (ack always 1)
63 fifo
= AsyncFIFO(phy_description(32), 4)
64 self
.submodules
.fifo
= RenameClockDomains(fifo
, {"write": "sata_rx", "read": "sys"})
66 fifo
.sink
.stb
.eq(valid
),
67 fifo
.sink
.data
.eq(data
),
68 fifo
.sink
.charisk
.eq(charisk
),
70 self
.comb
+= Record
.connect(fifo
.source
, self
.source
)
72 class K7SATAPHYDatapathTX(Module
):
74 self
.sink
= Sink(phy_description(32))
75 self
.source
= Source(phy_description(16))
79 # clock domain crossing
80 # (SATA3) sys_clk to 300MHz sata_tx clk
81 # (SATA2) sys_clk to 150MHz sata_tx clk
82 # (SATA1) sys_clk to 75MHz sata_tx clk
84 # source destination is always able to accept data (ack always 1)
85 fifo
= AsyncFIFO(phy_description(32), 4)
86 self
.submodules
.fifo
= RenameClockDomains(fifo
, {"write": "sys", "read": "sata_tx"})
87 self
.comb
+= Record
.connect(self
.sink
, fifo
.sink
)
94 self
.source
.stb
.eq(fifo
.source
.stb
),
95 fifo
.source
.ack
.eq(last
),
97 self
.sync
.sata_tx
+= [
107 chooser(fifo
.source
.data
, mux
, self
.source
.data
),
108 chooser(fifo
.source
.charisk
, mux
, self
.source
.charisk
)
111 class K7SATAPHYDatapath(Module
):
112 def __init__(self
, gtx
, ctrl
):
113 self
.sink
= Sink(phy_description(32))
114 self
.source
= Source(phy_description(32))
118 # change data width & cross domain crossing
119 rx
= K7SATAPHYDatapathRX()
120 tx
= K7SATAPHYDatapathTX()
121 self
.submodules
+= rx
, tx
123 rx
.sink
.data
.eq(gtx
.rxdata
),
124 rx
.sink
.charisk
.eq(gtx
.rxcharisk
),
126 gtx
.txdata
.eq(tx
.source
.data
),
127 gtx
.txcharisk
.eq(tx
.source
.charisk
),
130 # Align cnt (send 2 Align DWORDs every 256 DWORDs)
131 align_cnt
= Signal(8)
135 ).Elif(tx
.sink
.stb
& tx
.sink
.ack
,
136 align_cnt
.eq(align_cnt
+1)
138 send_align
= (align_cnt
< 2)
140 receive_align
= Signal()
141 self
.comb
+= receive_align
.eq(rx
.source
.stb
&
142 (rx
.source
.charisk
== 0b0001) &
143 (rx
.source
.data
== primitives
["ALIGN"]))
151 tx
.sink
.data
.eq(primitives
["ALIGN"]),
152 tx
.sink
.charisk
.eq(0b0001),
155 tx
.sink
.stb
.eq(self
.sink
.stb
),
156 tx
.sink
.data
.eq(self
.sink
.data
),
157 tx
.sink
.charisk
.eq(self
.sink
.charisk
),
158 self
.sink
.ack
.eq(tx
.sink
.ack
)
163 self
.source
.stb
.eq(rx
.source
.stb
),
164 self
.source
.data
.eq(rx
.source
.data
),
165 self
.source
.charisk
.eq(rx
.source
.charisk
),
170 tx
.sink
.stb
.eq(ctrl
.source
.stb
),
171 tx
.sink
.data
.eq(ctrl
.source
.data
),
172 tx
.sink
.charisk
.eq(ctrl
.source
.charisk
),
174 ctrl
.sink
.stb
.eq(rx
.source
.stb
),
175 ctrl
.sink
.data
.eq(rx
.source
.data
),