mirror of
https://github.com/fpganinja/taxi.git
synced 2025-12-09 00:48:40 -08:00
lfsr: Add support for non-self-synchronizing scrambler, add tests for PCIe gen 1/2 scrambler
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -169,6 +169,7 @@ PRBS23 Fibonacci, inverted 23 23'h040001 any ITU
|
|||||||
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
||||||
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
||||||
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
||||||
|
pcie Galois, bit-reverse 16 16'h0039 16'hffff PCIe gen 1/2
|
||||||
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ module taxi_lfsr_descramble #
|
|||||||
// bit-reverse input and output
|
// bit-reverse input and output
|
||||||
parameter logic REVERSE = 1'b1,
|
parameter logic REVERSE = 1'b1,
|
||||||
// width of data bus
|
// width of data bus
|
||||||
parameter DATA_W = 64
|
parameter DATA_W = 64,
|
||||||
|
// self-synchronizing
|
||||||
|
parameter logic SELF_SYNC = 1'b1
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input wire logic clk,
|
input wire logic clk,
|
||||||
@@ -141,6 +143,7 @@ PRBS23 Fibonacci, inverted 23 23'h040001 any ITU
|
|||||||
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
||||||
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
||||||
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
||||||
|
pcie Galois, bit-reverse 16 16'h0039 16'hffff PCIe gen 1/2
|
||||||
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -157,14 +160,14 @@ taxi_lfsr #(
|
|||||||
.LFSR_W(LFSR_W),
|
.LFSR_W(LFSR_W),
|
||||||
.LFSR_POLY(LFSR_POLY),
|
.LFSR_POLY(LFSR_POLY),
|
||||||
.LFSR_GALOIS(LFSR_GALOIS),
|
.LFSR_GALOIS(LFSR_GALOIS),
|
||||||
.LFSR_FEED_FORWARD('1),
|
.LFSR_FEED_FORWARD(SELF_SYNC),
|
||||||
.REVERSE(REVERSE),
|
.REVERSE(REVERSE),
|
||||||
.DATA_W(DATA_W),
|
.DATA_W(DATA_W),
|
||||||
.DATA_IN_EN(1'b1),
|
.DATA_IN_EN(SELF_SYNC),
|
||||||
.DATA_OUT_EN(1'b1)
|
.DATA_OUT_EN(1'b1)
|
||||||
)
|
)
|
||||||
lfsr_inst (
|
lfsr_inst (
|
||||||
.data_in(data_in),
|
.data_in(SELF_SYNC ? data_in : '0),
|
||||||
.state_in(state_reg),
|
.state_in(state_reg),
|
||||||
.data_out(lfsr_data),
|
.data_out(lfsr_data),
|
||||||
.state_out(lfsr_state)
|
.state_out(lfsr_state)
|
||||||
@@ -173,7 +176,7 @@ lfsr_inst (
|
|||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (data_in_valid) begin
|
if (data_in_valid) begin
|
||||||
state_reg <= lfsr_state;
|
state_reg <= lfsr_state;
|
||||||
output_reg <= lfsr_data;
|
output_reg <= SELF_SYNC ? lfsr_data : (lfsr_data ^ data_in);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ module taxi_lfsr_scramble #
|
|||||||
// bit-reverse input and output
|
// bit-reverse input and output
|
||||||
parameter logic REVERSE = 1'b1,
|
parameter logic REVERSE = 1'b1,
|
||||||
// width of data bus
|
// width of data bus
|
||||||
parameter DATA_W = 64
|
parameter DATA_W = 64,
|
||||||
|
// self-synchronizing
|
||||||
|
parameter logic SELF_SYNC = 1'b1
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input wire logic clk,
|
input wire logic clk,
|
||||||
@@ -141,6 +143,7 @@ PRBS23 Fibonacci, inverted 23 23'h040001 any ITU
|
|||||||
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
PRBS29 Fibonacci, inverted 29 29'h08000001 any
|
||||||
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
PRBS31 Fibonacci, inverted 31 31'h10000001 any
|
||||||
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
|
||||||
|
pcie Galois, bit-reverse 16 16'h0039 16'hffff PCIe gen 1/2
|
||||||
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@@ -160,11 +163,11 @@ taxi_lfsr #(
|
|||||||
.LFSR_FEED_FORWARD('0),
|
.LFSR_FEED_FORWARD('0),
|
||||||
.REVERSE(REVERSE),
|
.REVERSE(REVERSE),
|
||||||
.DATA_W(DATA_W),
|
.DATA_W(DATA_W),
|
||||||
.DATA_IN_EN(1'b1),
|
.DATA_IN_EN(SELF_SYNC),
|
||||||
.DATA_OUT_EN(1'b1)
|
.DATA_OUT_EN(1'b1)
|
||||||
)
|
)
|
||||||
lfsr_inst (
|
lfsr_inst (
|
||||||
.data_in(data_in),
|
.data_in(SELF_SYNC ? data_in : '0),
|
||||||
.state_in(state_reg),
|
.state_in(state_reg),
|
||||||
.data_out(lfsr_data),
|
.data_out(lfsr_data),
|
||||||
.state_out(lfsr_state)
|
.state_out(lfsr_state)
|
||||||
@@ -173,7 +176,7 @@ lfsr_inst (
|
|||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (data_in_valid) begin
|
if (data_in_valid) begin
|
||||||
state_reg <= lfsr_state;
|
state_reg <= lfsr_state;
|
||||||
output_reg <= lfsr_data;
|
output_reg <= SELF_SYNC ? lfsr_data : (lfsr_data ^ data_in);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export PARAM_LFSR_INIT ?= "'1"
|
|||||||
export PARAM_LFSR_GALOIS ?= "1'b0"
|
export PARAM_LFSR_GALOIS ?= "1'b0"
|
||||||
export PARAM_REVERSE ?= "1'b1"
|
export PARAM_REVERSE ?= "1'b1"
|
||||||
export PARAM_DATA_W ?= 8
|
export PARAM_DATA_W ?= 8
|
||||||
|
export PARAM_SELF_SYNC ?= "1'b1"
|
||||||
|
|
||||||
ifeq ($(SIM), icarus)
|
ifeq ($(SIM), icarus)
|
||||||
PLUSARGS += -fst
|
PLUSARGS += -fst
|
||||||
|
|||||||
@@ -76,7 +76,21 @@ def descramble_64b66b(data, state=0x3ffffffffffffff):
|
|||||||
return data_out
|
return data_out
|
||||||
|
|
||||||
|
|
||||||
async def run_test_descramble(dut, ref_scramble):
|
def scramble_pcie(data, state=0xffff, poly=0x9c00):
|
||||||
|
data_out = bytearray()
|
||||||
|
for d in data:
|
||||||
|
b = 0
|
||||||
|
for i in range(8):
|
||||||
|
if state & 1:
|
||||||
|
state = (state >> 1) ^ poly
|
||||||
|
b = b | (1 << i)
|
||||||
|
else:
|
||||||
|
state = state >> 1
|
||||||
|
data_out.append(b ^ d)
|
||||||
|
return data_out
|
||||||
|
|
||||||
|
|
||||||
|
async def run_test_descramble(dut, ref_scramble, ref_descramble):
|
||||||
|
|
||||||
data_width = len(dut.data_in)
|
data_width = len(dut.data_in)
|
||||||
byte_lanes = data_width // 8
|
byte_lanes = data_width // 8
|
||||||
@@ -87,9 +101,9 @@ async def run_test_descramble(dut, ref_scramble):
|
|||||||
|
|
||||||
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
|
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
|
||||||
|
|
||||||
scr = scramble_64b66b(block)
|
scr = ref_scramble(block)
|
||||||
|
|
||||||
dscr = descramble_64b66b(scr)
|
dscr = ref_descramble(scr)
|
||||||
|
|
||||||
assert dscr == block
|
assert dscr == block
|
||||||
|
|
||||||
@@ -122,7 +136,12 @@ if cocotb.SIM_NAME:
|
|||||||
# if cocotb.top.LFSR_POLY.value == 0x8000000001:
|
# if cocotb.top.LFSR_POLY.value == 0x8000000001:
|
||||||
if int(cocotb.top.LFSR_W.value) == 58:
|
if int(cocotb.top.LFSR_W.value) == 58:
|
||||||
factory = TestFactory(run_test_descramble)
|
factory = TestFactory(run_test_descramble)
|
||||||
factory.add_option("ref_scramble", [scramble_64b66b])
|
factory.add_option(("ref_scramble", "ref_descramble"), [(scramble_64b66b, descramble_64b66b)])
|
||||||
|
factory.generate_tests()
|
||||||
|
|
||||||
|
if cocotb.top.LFSR_POLY.value == 0x0039:
|
||||||
|
factory = TestFactory(run_test_descramble)
|
||||||
|
factory.add_option(("ref_scramble", "ref_descramble"), [(scramble_pcie, scramble_pcie)])
|
||||||
factory.generate_tests()
|
factory.generate_tests()
|
||||||
|
|
||||||
|
|
||||||
@@ -145,11 +164,13 @@ def process_f_files(files):
|
|||||||
return list(lst.values())
|
return list(lst.values())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(("lfsr_w", "lfsr_poly", "lfsr_init", "lfsr_galois", "reverse", "data_w"), [
|
@pytest.mark.parametrize(("lfsr_w", "lfsr_poly", "lfsr_init", "lfsr_galois", "reverse", "data_w", "self_sync"), [
|
||||||
(58, "58'h8000000001", "'1", 0, 1, 8),
|
(58, "58'h8000000001", "'1", 0, 1, 8, 1),
|
||||||
(58, "58'h8000000001", "'1", 0, 1, 64),
|
(58, "58'h8000000001", "'1", 0, 1, 64, 1),
|
||||||
|
(16, "16'h0039", "'1", 1, 1, 8, 0),
|
||||||
|
(16, "16'h0039", "'1", 1, 1, 64, 0),
|
||||||
])
|
])
|
||||||
def test_taxi_lfsr_descramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois, reverse, data_w):
|
def test_taxi_lfsr_descramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois, reverse, data_w, self_sync):
|
||||||
dut = "taxi_lfsr_descramble"
|
dut = "taxi_lfsr_descramble"
|
||||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||||
toplevel = dut
|
toplevel = dut
|
||||||
@@ -169,6 +190,7 @@ def test_taxi_lfsr_descramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois
|
|||||||
parameters['LFSR_GALOIS'] = f"1'b{lfsr_galois}"
|
parameters['LFSR_GALOIS'] = f"1'b{lfsr_galois}"
|
||||||
parameters['REVERSE'] = f"1'b{reverse}"
|
parameters['REVERSE'] = f"1'b{reverse}"
|
||||||
parameters['DATA_W'] = data_w
|
parameters['DATA_W'] = data_w
|
||||||
|
parameters['SELF_SYNC'] = f"1'b{self_sync}"
|
||||||
|
|
||||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export PARAM_LFSR_INIT ?= "'1"
|
|||||||
export PARAM_LFSR_GALOIS ?= "1'b0"
|
export PARAM_LFSR_GALOIS ?= "1'b0"
|
||||||
export PARAM_REVERSE ?= "1'b1"
|
export PARAM_REVERSE ?= "1'b1"
|
||||||
export PARAM_DATA_W ?= 8
|
export PARAM_DATA_W ?= 8
|
||||||
|
export PARAM_SELF_SYNC ?= "1'b1"
|
||||||
|
|
||||||
ifeq ($(SIM), icarus)
|
ifeq ($(SIM), icarus)
|
||||||
PLUSARGS += -fst
|
PLUSARGS += -fst
|
||||||
|
|||||||
@@ -64,6 +64,20 @@ def scramble_64b66b(data, state=0x3ffffffffffffff):
|
|||||||
return data_out
|
return data_out
|
||||||
|
|
||||||
|
|
||||||
|
def scramble_pcie(data, state=0xffff, poly=0x9c00):
|
||||||
|
data_out = bytearray()
|
||||||
|
for d in data:
|
||||||
|
b = 0
|
||||||
|
for i in range(8):
|
||||||
|
if state & 1:
|
||||||
|
state = (state >> 1) ^ poly
|
||||||
|
b = b | (1 << i)
|
||||||
|
else:
|
||||||
|
state = state >> 1
|
||||||
|
data_out.append(b ^ d)
|
||||||
|
return data_out
|
||||||
|
|
||||||
|
|
||||||
async def run_test_scramble(dut, ref_scramble):
|
async def run_test_scramble(dut, ref_scramble):
|
||||||
|
|
||||||
data_width = len(dut.data_in)
|
data_width = len(dut.data_in)
|
||||||
@@ -75,7 +89,7 @@ async def run_test_scramble(dut, ref_scramble):
|
|||||||
|
|
||||||
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
|
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
|
||||||
|
|
||||||
scr = scramble_64b66b(block)
|
scr = ref_scramble(block)
|
||||||
scr_iter = iter(chunks(scr, byte_lanes))
|
scr_iter = iter(chunks(scr, byte_lanes))
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
@@ -108,6 +122,11 @@ if cocotb.SIM_NAME:
|
|||||||
factory.add_option("ref_scramble", [scramble_64b66b])
|
factory.add_option("ref_scramble", [scramble_64b66b])
|
||||||
factory.generate_tests()
|
factory.generate_tests()
|
||||||
|
|
||||||
|
if cocotb.top.LFSR_POLY.value == 0x0039:
|
||||||
|
factory = TestFactory(run_test_scramble)
|
||||||
|
factory.add_option("ref_scramble", [scramble_pcie])
|
||||||
|
factory.generate_tests()
|
||||||
|
|
||||||
|
|
||||||
# cocotb-test
|
# cocotb-test
|
||||||
|
|
||||||
@@ -128,11 +147,13 @@ def process_f_files(files):
|
|||||||
return list(lst.values())
|
return list(lst.values())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(("lfsr_w", "lfsr_poly", "lfsr_init", "lfsr_galois", "reverse", "data_w"), [
|
@pytest.mark.parametrize(("lfsr_w", "lfsr_poly", "lfsr_init", "lfsr_galois", "reverse", "data_w", "self_sync"), [
|
||||||
(58, "58'h8000000001", "'1", 0, 1, 8),
|
(58, "58'h8000000001", "'1", 0, 1, 8, 1),
|
||||||
(58, "58'h8000000001", "'1", 0, 1, 64),
|
(58, "58'h8000000001", "'1", 0, 1, 64, 1),
|
||||||
|
(16, "16'h0039", "'1", 1, 1, 8, 0),
|
||||||
|
(16, "16'h0039", "'1", 1, 1, 64, 0),
|
||||||
])
|
])
|
||||||
def test_taxi_lfsr_scramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois, reverse, data_w):
|
def test_taxi_lfsr_scramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois, reverse, data_w, self_sync):
|
||||||
dut = "taxi_lfsr_scramble"
|
dut = "taxi_lfsr_scramble"
|
||||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||||
toplevel = dut
|
toplevel = dut
|
||||||
@@ -152,6 +173,7 @@ def test_taxi_lfsr_scramble(request, lfsr_w, lfsr_poly, lfsr_init, lfsr_galois,
|
|||||||
parameters['LFSR_GALOIS'] = f"1'b{lfsr_galois}"
|
parameters['LFSR_GALOIS'] = f"1'b{lfsr_galois}"
|
||||||
parameters['REVERSE'] = f"1'b{reverse}"
|
parameters['REVERSE'] = f"1'b{reverse}"
|
||||||
parameters['DATA_W'] = data_w
|
parameters['DATA_W'] = data_w
|
||||||
|
parameters['SELF_SYNC'] = f"1'b{self_sync}"
|
||||||
|
|
||||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user