0666137af4a7e43f05caa3b24a03810c4c59300c
[litex.git] / lib / sata / link / cont.py
1 from migen.fhdl.std import *
2 from migen.genlib.misc import optree
3
4 from lib.sata.common import *
5 from lib.sata.link.scrambler import Scrambler
6
7 class SATACONTInserter(Module):
8 def __init__(self, description):
9 self.sink = sink = Sink(description)
10 self.source = source = Source(description)
11
12 ###
13
14 # Detect consecutive primitives
15 # tn insert CONT
16 counter = Counter(max=4)
17 self.submodules += counter
18
19 is_primitive = Signal()
20 last_was_primitive = Signal()
21 last_primitive = Signal(32)
22 change = Signal()
23
24 cont_insert = Signal()
25 scrambler_insert = Signal()
26 last_primitive_insert = Signal()
27 last_primitive_insert_d = Signal()
28
29 self.comb += [
30 is_primitive.eq(sink.charisk != 0),
31 change.eq((sink.data != last_primitive) | ~is_primitive),
32 cont_insert.eq(~change & (counter.value == 1)),
33 scrambler_insert.eq(~change & (counter.value == 2)),
34 last_primitive_insert.eq((counter.value == 2) & (
35 (~is_primitive & last_was_primitive) |
36 (is_primitive & (last_primitive == primitives["HOLD"]) & (last_primitive != sink.data))))
37 ]
38
39 self.sync += \
40 If(sink.stb & source.ack,
41 last_primitive_insert_d.eq(last_primitive_insert),
42 If(is_primitive,
43 last_primitive.eq(sink.data),
44 last_was_primitive.eq(1)
45 ).Else(
46 last_was_primitive.eq(0)
47 )
48 )
49 self.comb += \
50 If(sink.stb & source.ack,
51 If(change | last_primitive_insert_d,
52 counter.reset.eq(1)
53 ).Else(
54 counter.ce.eq(~scrambler_insert)
55 )
56 )
57
58 # scrambler (between CONT and next primitive)
59 scrambler = InsertReset(Scrambler())
60 self.submodules += scrambler
61 self.comb += [
62 scrambler.reset.eq(ResetSignal()), #XXX: should be reseted on COMINIT / COMRESET
63 scrambler.ce.eq(scrambler_insert & source.stb & source.ack)
64 ]
65
66 # Datapath
67 self.comb += [
68 Record.connect(sink, source),
69 If(sink.stb,
70 If(cont_insert,
71 source.charisk.eq(0b0001),
72 source.data.eq(primitives["CONT"])
73 ).Elif(scrambler_insert,
74 source.charisk.eq(0b0000),
75 source.data.eq(scrambler.value)
76 ).Elif(last_primitive_insert,
77 source.stb.eq(1),
78 sink.ack.eq(0),
79 source.charisk.eq(0b0001),
80 source.data.eq(last_primitive)
81 )
82 )
83 ]
84
85 class SATACONTRemover(Module):
86 def __init__(self, description):
87 self.sink = sink = Sink(description)
88 self.source = source = Source(description)
89
90 ###
91
92 # Detect CONT
93 is_primitive = Signal()
94 is_cont = Signal()
95 in_cont = Signal()
96 cont_ongoing = Signal()
97
98 self.comb += [
99 is_primitive.eq(sink.charisk != 0),
100 is_cont.eq(is_primitive & (sink.data == primitives["CONT"]))
101 ]
102 self.sync += \
103 If(is_cont,
104 in_cont.eq(1)
105 ).Elif(is_primitive,
106 in_cont.eq(0)
107 )
108 self.comb += cont_ongoing.eq(is_cont | (in_cont & ~is_primitive))
109
110 # Datapath
111 last_primitive = Signal()
112 self.sync += [
113 If(is_primitive & ~is_cont,
114 last_primitive.eq(sink.data)
115 )
116 ]
117 self.comb += [
118 Record.connect(sink, source),
119 If(cont_ongoing,
120 source.charisk.eq(0b0001),
121 source.data.eq(last_primitive)
122 )
123 ]