From 3b836d3ad0ab8fbf1eacc782e494915aaf39762c Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 30 Nov 2022 17:42:41 -0500 Subject: [PATCH] nrzi_decode: Add reset input Most other modules in the recieve path are reset when signal_status goes low. This one didn't, and it was difficult to test because of this. In particular, we need to ensure that this module behaves correctly when switching between different bitstreams (such as for loopback). While implementing this, I found some bugs in the way that nrzi_valid was handled: it wasn't saved from when the transfer actually happened, and the data wasn't qualified properly. Signed-off-by: Sean Anderson --- rtl/nrzi_decode.v | 40 +++++++++++++++++++++++++++++++--------- tb/nrzi_decode.py | 12 +++++++++--- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/rtl/nrzi_decode.v b/rtl/nrzi_decode.v index ece1326..065cfd6 100644 --- a/rtl/nrzi_decode.v +++ b/rtl/nrzi_decode.v @@ -7,31 +7,53 @@ module nrzi_decode ( input clk, + input rst, input [1:0] nrzi, input [1:0] nrzi_valid, output reg [1:0] nrz, output reg [1:0] nrz_valid ); - reg [1:0] nrz_next; - reg nrzi_last; - reg nrzi_last_next; + reg [1:0] nrz_next, nrz_valid_next; + reg nrzi_last, nrzi_last_next, nrzi_last_valid, nrzi_last_valid_next; + initial nrz_valid = 0; + initial nrzi_last_valid = 0; always @(*) begin nrz_next[0] = nrzi[1] ^ nrzi[0]; nrz_next[1] = nrzi[1] ^ nrzi_last; nrzi_last_next = nrzi_last; - if (nrzi_valid != 0) - nrzi_last_next = nrzi[1]; - if (nrzi_valid & 2) + nrzi_last_valid_next = 1'b1; + if (nrzi_valid[1]) nrzi_last_next = nrzi[0]; + else if (nrzi_valid[0]) + nrzi_last_next = nrzi[1]; + else + nrzi_last_valid_next = nrzi_last_valid; + + nrz_valid_next = nrzi_valid; + if (!nrzi_last_valid) begin + nrz_valid_next = 0; + if (nrzi_valid[1]) begin + nrz_valid_next = 2'b1; + nrz_next[1] = nrz_next[0]; + end + end end always @(posedge clk) begin - nrzi_last <= nrzi_last_next; - nrz_valid <= nrzi_valid; - nrz <= nrz_next; + if (rst) begin + nrzi_last <= 1'bX; + nrzi_last_valid <= 1'b0; + nrz_valid <= 2'b0; + nrz <= 2'b0; + end else begin + nrzi_last <= nrzi_last_next; + nrzi_last_valid = nrzi_last_valid_next; + nrz_valid <= nrz_valid_next; + nrz <= nrz_next; + end end endmodule diff --git a/tb/nrzi_decode.py b/tb/nrzi_decode.py index 46a760b..0447236 100644 --- a/tb/nrzi_decode.py +++ b/tb/nrzi_decode.py @@ -6,9 +6,11 @@ import random import cocotb from cocotb.clock import Clock from cocotb.regression import TestFactory -from cocotb.triggers import FallingEdge, RisingEdge, Timer +from cocotb.triggers import ClockCycles, FallingEdge, RisingEdge, Timer +from cocotb.types import LogicArray -from .util import alist, async_iter, compare_lists, timeout, send_recovered_bits, with_valids +from .nrzi_encode import nrzi_encode +from .util import alist, async_iter, compare_lists, timeout, send_recovered_bits, with_valids, print_list_at async def nrzi_decode(bits): last = 1 @@ -19,8 +21,12 @@ async def nrzi_decode(bits): @timeout(10, 'us') async def test_rx(decoder, valids): decoder.nrzi_valid.value = 0 + decoder.nrzi.value = LogicArray('X', 'X') + decoder.rst.value = 1 await Timer(1) await cocotb.start(Clock(decoder.clk, 8, units='ns').start()) + await ClockCycles(decoder.clk, 1) + decoder.rst.value = 0 ins = [random.randrange(2) for _ in range(1000)] await cocotb.start(send_recovered_bits(decoder.clk, decoder.nrzi, @@ -40,6 +46,6 @@ async def test_rx(decoder, valids): outs.append(decoder.nrz[0].value) # Ignore the first bit, since it is influenced by the initial value - compare_lists((await alist(nrzi_decode(async_iter(ins))))[1:], outs[1:]) + compare_lists((await alist(nrzi_decode(async_iter(ins))))[1:], outs) with_valids(globals(), test_rx)