c47e7529a6e2d77c6e4dc3b917d1d5ede2109fc4
1 from litesata
.common
import *
3 class LiteSATAPHYDatapathRX(Module
):
5 self
.sink
= Sink(phy_description(16))
6 self
.source
= Source(phy_description(32))
10 # width convertion (16 to 32) and byte alignment
11 byte_alignment
= Signal()
12 last_charisk
= Signal(2)
13 last_data
= Signal(16)
14 self
.sync
.sata_rx
+= \
15 If(self
.sink
.stb
& self
.sink
.ack
,
16 If(self
.sink
.charisk
!= 0,
17 byte_alignment
.eq(self
.sink
.charisk
[1])
19 last_charisk
.eq(self
.sink
.charisk
),
20 last_data
.eq(self
.sink
.data
)
22 converter
= Converter(phy_description(16), phy_description(32), reverse
=False)
23 self
.converter
= InsertReset(RenameClockDomains(converter
, "sata_rx"))
25 self
.converter
.sink
.stb
.eq(self
.sink
.stb
),
27 self
.converter
.sink
.charisk
.eq(Cat(last_charisk
[1], self
.sink
.charisk
[0])),
28 self
.converter
.sink
.data
.eq(Cat(last_data
[8:], self
.sink
.data
[:8]))
30 self
.converter
.sink
.charisk
.eq(self
.sink
.charisk
),
31 self
.converter
.sink
.data
.eq(self
.sink
.data
)
33 self
.sink
.ack
.eq(self
.converter
.sink
.ack
),
34 self
.converter
.reset
.eq(self
.converter
.source
.charisk
[2:] != 0)
37 # clock domain crossing
38 # (SATA3) 300MHz sata_rx clk to sys_clk
39 # (SATA2) 150MHz sata_rx clk to sys_clk
40 # (SATA1) 75MHz sata_rx clk to sys_clk
42 # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
43 # source destination is always able to accept data (ack always 1)
44 fifo
= AsyncFIFO(phy_description(32), 4)
45 self
.fifo
= RenameClockDomains(fifo
, {"write": "sata_rx", "read": "sys"})
47 Record
.connect(self
.converter
.source
, fifo
.sink
),
48 Record
.connect(fifo
.source
, self
.source
)
51 class LiteSATAPHYDatapathTX(Module
):
53 self
.sink
= Sink(phy_description(32))
54 self
.source
= Source(phy_description(16))
58 # clock domain crossing
59 # (SATA3) sys_clk to 300MHz sata_tx clk
60 # (SATA2) sys_clk to 150MHz sata_tx clk
61 # (SATA1) sys_clk to 75MHz sata_tx clk
63 # source destination is always able to accept data (ack always 1)
64 fifo
= AsyncFIFO(phy_description(32), 4)
65 self
.fifo
= RenameClockDomains(fifo
, {"write": "sys", "read": "sata_tx"})
66 self
.comb
+= Record
.connect(self
.sink
, fifo
.sink
)
68 # width convertion (32 to 16)
69 converter
= Converter(phy_description(32), phy_description(16), reverse
=False)
70 self
.converter
= RenameClockDomains(converter
, "sata_tx")
72 Record
.connect(self
.fifo
.source
, self
.converter
.sink
),
73 Record
.connect(self
.converter
.source
, self
.source
)
76 class LiteSATAPHYAlignInserter(Module
):
77 def __init__(self
, ctrl
):
78 self
.sink
= sink
= Sink(phy_description(32))
79 self
.source
= source
= Source(phy_description(32))
83 # send 2 ALIGN every 256 DWORDs
84 # used for clock compensation between
91 ).Elif(source
.stb
& source
.ack
,
98 source
.charisk
.eq(0b0001),
99 source
.data
.eq(primitives
["ALIGN"]),
102 source
.stb
.eq(sink
.stb
),
103 source
.data
.eq(sink
.data
),
104 source
.charisk
.eq(sink
.charisk
),
105 sink
.ack
.eq(source
.ack
)
109 class LiteSATAPHYAlignRemover(Module
):
111 self
.sink
= sink
= Sink(phy_description(32))
112 self
.source
= source
= Source(phy_description(32))
116 charisk_match
= sink
.charisk
== 0b0001
117 data_match
= sink
.data
== primitives
["ALIGN"]
120 If(sink
.stb
& charisk_match
& data_match
,
123 Record
.connect(sink
, source
)
126 class LiteSATAPHYDatapath(Module
):
127 def __init__(self
, trx
, ctrl
):
128 self
.sink
= Sink(phy_description(32))
129 self
.source
= Source(phy_description(32))
134 self
.align_inserter
= LiteSATAPHYAlignInserter(ctrl
)
135 self
.mux
= Multiplexer(phy_description(32), 2)
136 self
.tx
= LiteSATAPHYDatapathTX()
138 self
.mux
.sel
.eq(ctrl
.ready
),
139 Record
.connect(self
.sink
, self
.align_inserter
.sink
),
140 Record
.connect(ctrl
.source
, self
.mux
.sink0
),
141 Record
.connect(self
.align_inserter
.source
, self
.mux
.sink1
),
142 Record
.connect(self
.mux
.source
, self
.tx
.sink
),
143 Record
.connect(self
.tx
.source
, trx
.sink
)
147 self
.rx
= LiteSATAPHYDatapathRX()
148 self
.demux
= Demultiplexer(phy_description(32), 2)
149 self
.align_remover
= LiteSATAPHYAlignRemover()
151 self
.demux
.sel
.eq(ctrl
.ready
),
152 Record
.connect(trx
.source
, self
.rx
.sink
),
153 Record
.connect(self
.rx
.source
, self
.demux
.sink
),
154 Record
.connect(self
.demux
.source0
, ctrl
.sink
),
155 Record
.connect(self
.demux
.source1
, self
.align_remover
.sink
),
156 Record
.connect(self
.align_remover
.source
, self
.source
)