--- /dev/null
+from migen.fhdl.std import *
+from migen.genlib.misc import optree
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+class SATAScrambler(Module):
+ """SATA Scrambler
+
+ Implement a SATA Scrambler
+
+ Attributes
+ ----------
+ value : out
+ Scrambled value.
+ """
+ def __init__(self):
+ self.value = Signal(32)
+
+ ###
+
+ context = Signal(16, reset=0xf0f6)
+ next_value = Signal(32)
+ self.sync += context.eq(next_value[16:32])
+
+ # from SATA specification, if possible replace it
+ # with a generic implementation using polynoms.
+ lfsr_coefs = (
+ (15, 13, 4, 0), #0
+ (15, 14, 13, 5, 4, 1, 0),
+ (14, 13, 6, 5, 4, 2,1, 0),
+ (15, 14, 7, 6, 5, 3,2, 1),
+ (13, 8, 7, 6, 3, 2, 0),
+ (14, 9, 8, 7, 4, 3, 1),
+ (15, 10, 9, 8, 5, 4, 2),
+ (15, 13, 11, 10, 9, 6, 5, 4, 3, 0),
+ (15, 14, 13, 12, 11, 10,7, 6, 5, 1, 0),
+ (14, 12, 11, 8, 7, 6, 4, 2, 1, 0),
+ (15, 13, 12, 9, 8, 7, 5, 3, 2, 1),
+ (15, 14, 10, 9, 8, 6, 3, 2, 0),
+ (13, 11, 10, 9, 7, 3, 1, 0),
+ (14, 12, 11, 10, 8, 4, 2, 1),
+ (15, 13, 12, 11, 9, 5, 3, 2),
+ (15, 14, 12, 10, 6, 3, 0),
+
+ (11, 7, 1, 0), #16
+ (12, 8, 2, 1),
+ (13, 9, 3, 2),
+ (14, 10, 4, 3),
+ (15, 11, 5, 4),
+ (15, 13, 12, 6, 5, 4, 0),
+ (15, 14, 7, 6, 5, 4, 1, 0),
+ (13, 8, 7, 6, 5, 4, 2, 1, 0),
+ (14, 9, 8,7, 6, 5, 3, 2, 1),
+ (15, 10, 9, 8, 7, 6, 4, 3, 2),
+ (15, 13, 11, 10, 9, 8, 7, 5, 3, 0),
+ (15, 14, 13, 12, 11, 10, 9, 8, 6, 1, 0),
+ (14, 12, 11, 10, 9, 7, 4, 2, 1, 0),
+ (15, 13, 12, 11, 10, 8, 5, 3, 2, 1),
+ (15, 14, 12, 11, 9, 6, 3, 2, 0),
+ (12, 10, 7, 3, 1, 0),
+ )
+
+ for n, coefs in enumerate(lfsr_coefs):
+ eq = [context[i] for i in coefs]
+ self.comb += next_value[n].eq(optree("^", eq))
+
+ self.comb += self.value.eq(next_value)
// Adapted from SATA specification
+/****************************************************************************/
+/* */
+/* scramble.c */
+/* */
+/* This sample code generates the entire sequence of 65535 Dwords produced */
+/* by the scrambler defined in the Serial ATA specification. The */
+/* specification calls for an LFSR to generate a string of bits that will */
+/* be packaged into 32 bit Dwords to be XORed with the data Dwords. The */
+/* generator polynomial specified is: */
+/* 16 15 13 4 */
+/* G(x) = x + x + x + x + 1 */
+/* */
+/* Parallelized versions of the scrambler are initialized to a value */
+/* derived from the initialization value of 0xFFFF defined in the */
+/* specification. This implementation is initialized to 0xF0F6. Other */
+/* parallel implementations will have different initial values. The */
+/* important point is that the first Dword output of any implementation */
+/* must equal 0xC2D2768D. */
+/* This code does not represent an elegant solution for a C implementation, */
+/* but it does demonstrate a method of generating the sequence that can be */
+/* easily implemented in hardware. A block diagram of the circuit emulated */
+/* by this code is shown below. */
+/* */
+/* +-----------------------------------+ */
+/* | | */
+/* | | */
+/* | +---+ +---+ | */
+/* | | R | | * | | */
+/* +---->| e |----------+---->| M |----+----> Output(31 downto 16) */
+/* | g | | | 1 | */
+/* +---+ | +---+ */
+/* | */
+/* | +---+ */
+/* | | * | */
+/* +---->| M |---------> Output(15 downto 0) */
+/* | 2 | */
+/* +---+ */
+/* */
+/* The register shown in the block diagram is a 16 bit register. The two */
+/* boxes, *M1 and *M2, each represent a multiply by a 16 by 16 binary */
+/* matrix. A 16 by 16 matrix times a 16 bit vector yields a 16 bit vector. */
+/* The two vectors are the two halves of the 32 bit scrambler value. The */
+/* upper half of the scrambler value is stored back into the context */
+/* register to be used to generate the next value in the scrambler */
+/* */
+/****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])