polynom = 0x04C11DB7
init = 0x52325032
check = 0xC704DD7B
- def __init__(self, dat_width):
+ def __init__(self):
self.d = Signal(self.width)
self.value = Signal(self.width)
self.error = Signal()
all: crc_tb scrambler_tb
clean:
- rm crc scrambler
+ rm crc scrambler *.vcd
+def seed_to_data(seed, random=True):
+ if random:
+ return (seed * 0x31415979 + 1) & 0xffffffff
+ else:
+ return seed
+
def check(ref, res):
- shift = 0
- while((ref[0] != res[0]) and (len(res)>1)):
- res.pop(0)
- shift += 1
- length = min(len(ref), len(res))
- errors = 0
- for i in range(length):
- if ref.pop(0) != res.pop(0):
- errors += 1
- return shift, length, errors
+ if isinstance(ref, int):
+ return 0, 1, int(ref != res)
+ else:
+ shift = 0
+ while((ref[0] != res[0]) and (len(res)>1)):
+ res.pop(0)
+ shift += 1
+ length = min(len(ref), len(res))
+ errors = 0
+ for i in range(length):
+ if ref.pop(0) != res.pop(0):
+ errors += 1
+ return shift, length, errors
// Adapted from SATA specification
+/****************************************************************************/
+/* */
+/* crc.c */
+/* */
+/* This sample code reads standard in for a sequence of 32 bit values */
+/* formatted in hexadecimal with a leading "0x" (e.g. 0xDEADBEEF). The */
+/* code calculates the Serial ATA CRC for the input data stream. The */
+/* generator polynomial used is: */
+/* 32 26 23 22 16 12 11 10 8 7 5 4 2 */
+/* G(x) = x + x + x + x + x + x + x + x + x + x + x + x + x + x + 1 */
+/* */
+/* This sample code uses a parallel implementation of the CRC calculation */
+/* circuit that is suitable for implementation in hardware. A block */
+/* diagram of the circuit being emulated is shown below. */
+/* */
+/* +---+ +---+ +---+ */
+/* Data_In --------->| | | | | R | */
+/* | + |--------->| * |--------->| e |----+ */
+/* +---->| | | | | g | | */
+/* | +---+ +---+ +---+ | */
+/* | | */
+/* | | */
+/* +--------------------------------------------+ */
+/* */
+/* The CRC value is initialized to 0x52325032 as defined in the Serial ATA */
+/* specification. */
+/* */
+/****************************************************************************/
+
+
+
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
unsigned char crc_bit[32];
unsigned char new_bit[32];
- data_in = 0x12345678;
crc = 0x52325032;
data_count = 0;
- while (data_count < 65536) {
+ while((scanf(" 0x%8x", &data_in) == 1) && (!scanf("exit"))) {
data_count++;
-
+ /* Add the data_in value to the current value of the CRC held in the */
+ /* "register". The addition is performed modulo two (XOR). */
crc ^= data_in;
-
+ /* Expand the value of the CRC held in the register to 32 individual */
+ /* bits for easy manipulation. */
for (i = 0; i < 32; ++i) {
crc_bit[i] = (crc >> i) & 0x01;
}
-
+ /* The following 32 assignments perform the function of the box */
+ /* labeled "*" in the block diagram above. The new_bit array is a */
+ /* temporary holding place for the new CRC value being calculated. */
+ /* Note that there are lots of shared terms in the assignments below. */
new_bit[31] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[24] ^
crc_bit[23] ^ crc_bit[15] ^ crc_bit[11] ^ crc_bit[9] ^ crc_bit[8] ^ crc_bit[5];
new_bit[30] = crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[23] ^
new_bit[0] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^
crc_bit[16] ^ crc_bit[12] ^ crc_bit[10] ^ crc_bit[9] ^ crc_bit[6] ^ crc_bit[0];
+ /* The new CRC value has been calculated as individual bits in the */
+ /* new_bit array. Re-assembled it into a 32 bit value and "clock" it */
+ /* into the "register". */
crc = 0;
for (i = 31; i >= 0; --i) {
crc = crc << 1;
crc |= new_bit[i];
}
- printf("%08x\n", crc);
}
-
+ printf("%08x\n", crc);
return 0;
}
from lib.sata.std import *
from lib.sata.link.crc import *
-from lib.sata.link.test.common import check
+from lib.sata.link.test.common import *
class TB(Module):
- def __init__(self, length):
+ def __init__(self, length, random):
self.submodules.crc = SATACRC()
self.length = length
+ self.random = random
+
+ def get_c_crc(self, datas):
+ stdin = ""
+ for data in datas:
+ stdin += "0x%08x " %data
+ stdin += "exit"
+ with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("UTF-8"))
+ out, err = process.communicate()
+ return int(out.decode("UTF-8"), 16)
def gen_simulation(self, selfp):
- # init CRC
- selfp.crc.d = 0x12345678
+ # init CRC
+ selfp.crc.d = 0
selfp.crc.ce = 1
selfp.crc.reset = 1
yield
selfp.crc.reset = 0
- # get C code results
- p = subprocess.Popen(["./crc"], stdout=subprocess.PIPE)
- out, err = p.communicate()
- ref = [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
+ # feed CRC with datas
+ datas = []
+ for i in range(self.length):
+ data = seed_to_data(i, self.random)
+ datas.append(data)
+ selfp.crc.d = data
+ yield
+ # log results
+ yield
+ sim_crc = selfp.crc.value
- # log results
- res = []
- for i in range(self.length):
- res.append(selfp.crc.value)
+ # stop
+ selfp.crc.ce = 0
+ for i in range(32):
yield
- # check results
- s, l, e = check(ref, res)
+ # get C core reference
+ c_crc = self.get_c_crc(datas)
+
+ # check results
+ s, l, e = check(c_crc, sim_crc)
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
from migen.sim.generic import run_simulation
length = 8192
- run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(length, True), ncycles=length+100, vcd_name="my.vcd")
int main(int argc, char *argv[])
{
int i, j;
+ unsigned int length;
unsigned short context;
unsigned long scrambler;
unsigned char now[16];
unsigned char next[32];
context = 0xF0F6;
- for (i = 0; i < 65536; ++i) {
+ scanf("0x%8x", &length);
+
+ for (i = 0; i < length; ++i) {
for (j = 0; j < 16; ++j) {
now[j] = (context >> j) & 0x01;
}
from lib.sata.std import *
from lib.sata.link.scrambler import *
-from lib.sata.link.test.common import check
+from lib.sata.link.test.common import *
class TB(Module):
def __init__(self, length):
self.submodules.scrambler = Scrambler()
self.length = length
+ def get_c_values(self, length):
+ stdin = "0x%08x" %length
+ with subprocess.Popen("./scrambler", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+ process.stdin.write(stdin.encode("UTF-8"))
+ out, err = process.communicate()
+ return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
+
def gen_simulation(self, selfp):
- # init CRC
+ # init CRC
selfp.scrambler.ce = 1
selfp.scrambler.reset = 1
yield
selfp.scrambler.reset = 0
- # get C code results
- p = subprocess.Popen(["./scrambler"], stdout=subprocess.PIPE)
- out, err = p.communicate()
- ref = [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
-
- # log results
+ # log results
yield
- res = []
+ sim_values = []
for i in range(self.length):
- res.append(selfp.scrambler.value)
+ sim_values.append(selfp.scrambler.value)
yield
- # check results
- s, l, e = check(ref, res)
+ # stop
+ selfp.scrambler.ce = 0
+ for i in range(32):
+ yield
+
+ # get C code reference
+ c_values = self.get_c_values(self.length)
+
+ # check results
+ s, l, e = check(c_values, sim_values)
print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
from migen.sim.generic import run_simulation
length = 8192
- run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd", keep_files=True)
+ run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd")
return 2**width-1
def phy_layout(dw):
- parameters = {
- "packetized": False
- }
layout = [
("data", dw),
("charisk", dw//8),
]
- return EndpointDescription(layout, parameters)
+ return EndpointDescription(layout, packetized=False)
def link_layout(dw):
- parameters = {
- "packetized": True
- }
layout = [
("d", dw),
("error", 1)
]
- return EndpointDescription(layout, parameters)
+ return EndpointDescription(layout, packetized=True)