4b5b9960a848874d18802f32b0d8045f0c9e2600
[litex.git] / litesata / core / link / scrambler.py
1 from litesata.common import *
2
3 @DecorateModule(InsertCE)
4 class Scrambler(Module):
5 """SATA Scrambler
6
7 Implement a SATA Scrambler
8
9 Attributes
10 ----------
11 value : out
12 Scrambled value.
13 """
14 def __init__(self):
15 self.value = Signal(32)
16
17 ###
18
19 context = Signal(16, reset=0xf0f6)
20 next_value = Signal(32)
21 self.sync += context.eq(next_value[16:32])
22
23 # XXX: from SATA specification, replace it with
24 # a generic implementation using polynoms.
25 lfsr_coefs = (
26 (15, 13, 4, 0), #0
27 (15, 14, 13, 5, 4, 1, 0),
28 (14, 13, 6, 5, 4, 2,1, 0),
29 (15, 14, 7, 6, 5, 3,2, 1),
30 (13, 8, 7, 6, 3, 2, 0),
31 (14, 9, 8, 7, 4, 3, 1),
32 (15, 10, 9, 8, 5, 4, 2),
33 (15, 13, 11, 10, 9, 6, 5, 4, 3, 0),
34 (15, 14, 13, 12, 11, 10,7, 6, 5, 1, 0),
35 (14, 12, 11, 8, 7, 6, 4, 2, 1, 0),
36 (15, 13, 12, 9, 8, 7, 5, 3, 2, 1),
37 (15, 14, 10, 9, 8, 6, 3, 2, 0),
38 (13, 11, 10, 9, 7, 3, 1, 0),
39 (14, 12, 11, 10, 8, 4, 2, 1),
40 (15, 13, 12, 11, 9, 5, 3, 2),
41 (15, 14, 12, 10, 6, 3, 0),
42
43 (11, 7, 1, 0), #16
44 (12, 8, 2, 1),
45 (13, 9, 3, 2),
46 (14, 10, 4, 3),
47 (15, 11, 5, 4),
48 (15, 13, 12, 6, 5, 4, 0),
49 (15, 14, 7, 6, 5, 4, 1, 0),
50 (13, 8, 7, 6, 5, 4, 2, 1, 0),
51 (14, 9, 8,7, 6, 5, 3, 2, 1),
52 (15, 10, 9, 8, 7, 6, 4, 3, 2),
53 (15, 13, 11, 10, 9, 8, 7, 5, 3, 0),
54 (15, 14, 13, 12, 11, 10, 9, 8, 6, 1, 0),
55 (14, 12, 11, 10, 9, 7, 4, 2, 1, 0),
56 (15, 13, 12, 11, 10, 8, 5, 3, 2, 1),
57 (15, 14, 12, 11, 9, 6, 3, 2, 0),
58 (12, 10, 7, 3, 1, 0),
59 )
60
61 for n, coefs in enumerate(lfsr_coefs):
62 eq = [context[i] for i in coefs]
63 self.comb += next_value[n].eq(optree("^", eq))
64
65 self.comb += self.value.eq(next_value)
66
67 @DecorateModule(InsertReset)
68 class LiteSATAScrambler(Module):
69 def __init__(self, description):
70 self.sink = sink = Sink(description)
71 self.source = source = Source(description)
72
73 ###
74
75 self.scrambler = Scrambler()
76 self.comb += [
77 self.scrambler.ce.eq(sink.stb & sink.ack),
78 Record.connect(sink, source),
79 source.d.eq(sink.d ^ self.scrambler.value)
80 ]