1 from lib
.sata
.common
import *
3 from migen
.genlib
.misc
import chooser
5 class SATAPHYDatapathRX(Module
):
7 self
.sink
= Sink(phy_description(16))
8 self
.source
= Source(phy_description(32))
15 data_sr
= Signal(32+8)
16 charisk_sr
= Signal(4+1)
17 data_sr_d
= Signal(32+8)
18 charisk_sr_d
= Signal(4+1)
20 data_sr
.eq(Cat(data_sr_d
[16:], self
.sink
.data
)),
21 charisk_sr
.eq(Cat(charisk_sr_d
[2:], self
.sink
.charisk
))
23 self
.sync
.sata_rx
+= [
24 data_sr_d
.eq(data_sr
),
25 charisk_sr_d
.eq(charisk_sr
)
31 self
.sync
.sata_rx
+= [
32 If(self
.sink
.charisk
!=0,
33 alignment
.eq(self
.sink
.charisk
[1]),
45 data
.eq(data_sr
[0:32]),
46 charisk
.eq(charisk_sr
[0:4])
48 data
.eq(data_sr
[8:40]),
49 charisk
.eq(charisk_sr
[1:5])
53 # clock domain crossing
54 # (SATA3) 300MHz sata_rx clk to sys_clk
55 # (SATA2) 150MHz sata_rx clk to sys_clk
56 # (SATA1) 75MHz sata_rx clk to sys_clk
58 # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
59 # source destination is always able to accept data (ack always 1)
60 fifo
= AsyncFIFO(phy_description(32), 4)
61 self
.submodules
.fifo
= RenameClockDomains(fifo
, {"write": "sata_rx", "read": "sys"})
63 fifo
.sink
.stb
.eq(valid
),
64 fifo
.sink
.data
.eq(data
),
65 fifo
.sink
.charisk
.eq(charisk
),
67 self
.comb
+= Record
.connect(fifo
.source
, self
.source
)
69 class SATAPHYDatapathTX(Module
):
71 self
.sink
= Sink(phy_description(32))
72 self
.source
= Source(phy_description(16))
76 # clock domain crossing
77 # (SATA3) sys_clk to 300MHz sata_tx clk
78 # (SATA2) sys_clk to 150MHz sata_tx clk
79 # (SATA1) sys_clk to 75MHz sata_tx clk
81 # source destination is always able to accept data (ack always 1)
82 fifo
= AsyncFIFO(phy_description(32), 4)
83 self
.submodules
.fifo
= RenameClockDomains(fifo
, {"write": "sys", "read": "sata_tx"})
84 self
.comb
+= Record
.connect(self
.sink
, fifo
.sink
)
91 self
.source
.stb
.eq(fifo
.source
.stb
),
92 fifo
.source
.ack
.eq(last
),
94 self
.sync
.sata_tx
+= [
104 chooser(fifo
.source
.data
, mux
, self
.source
.data
),
105 chooser(fifo
.source
.charisk
, mux
, self
.source
.charisk
)
108 class SATAPHYDatapath(Module
):
109 def __init__(self
, trx
, ctrl
):
110 self
.sink
= Sink(phy_description(32))
111 self
.source
= Source(phy_description(32))
115 # change data width & cross domain crossing
116 rx
= SATAPHYDatapathRX()
117 tx
= SATAPHYDatapathTX()
118 self
.submodules
+= rx
, tx
120 trx
.source
.connect(rx
.sink
),
121 tx
.source
.connect(trx
.sink
)
124 # Align cnt (send 2 Align DWORDs every 256 DWORDs)
125 align_cnt
= Signal(8)
129 ).Elif(tx
.sink
.stb
& tx
.sink
.ack
,
130 align_cnt
.eq(align_cnt
+1)
132 send_align
= (align_cnt
< 2)
134 receive_align
= Signal()
135 self
.comb
+= receive_align
.eq(rx
.source
.stb
&
136 (rx
.source
.charisk
== 0b0001) &
137 (rx
.source
.data
== primitives
["ALIGN"]))
145 tx
.sink
.data
.eq(primitives
["ALIGN"]),
146 tx
.sink
.charisk
.eq(0b0001),
149 tx
.sink
.stb
.eq(self
.sink
.stb
),
150 tx
.sink
.data
.eq(self
.sink
.data
),
151 tx
.sink
.charisk
.eq(self
.sink
.charisk
),
152 self
.sink
.ack
.eq(tx
.sink
.ack
)
157 self
.source
.stb
.eq(rx
.source
.stb
),
158 self
.source
.data
.eq(rx
.source
.data
),
159 self
.source
.charisk
.eq(rx
.source
.charisk
),
164 tx
.sink
.stb
.eq(ctrl
.source
.stb
),
165 tx
.sink
.data
.eq(ctrl
.source
.data
),
166 tx
.sink
.charisk
.eq(ctrl
.source
.charisk
),
168 ctrl
.sink
.stb
.eq(rx
.source
.stb
),
169 ctrl
.sink
.data
.eq(rx
.source
.data
),