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 <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2022-11-30 17:42:41 -05:00
parent 52325f241b
commit 3b836d3ad0
2 changed files with 40 additions and 12 deletions

View File

@ -7,31 +7,53 @@
module nrzi_decode ( module nrzi_decode (
input clk, input clk,
input rst,
input [1:0] nrzi, input [1:0] nrzi,
input [1:0] nrzi_valid, input [1:0] nrzi_valid,
output reg [1:0] nrz, output reg [1:0] nrz,
output reg [1:0] nrz_valid output reg [1:0] nrz_valid
); );
reg [1:0] nrz_next; reg [1:0] nrz_next, nrz_valid_next;
reg nrzi_last; reg nrzi_last, nrzi_last_next, nrzi_last_valid, nrzi_last_valid_next;
reg nrzi_last_next; initial nrz_valid = 0;
initial nrzi_last_valid = 0;
always @(*) begin always @(*) begin
nrz_next[0] = nrzi[1] ^ nrzi[0]; nrz_next[0] = nrzi[1] ^ nrzi[0];
nrz_next[1] = nrzi[1] ^ nrzi_last; nrz_next[1] = nrzi[1] ^ nrzi_last;
nrzi_last_next = nrzi_last; nrzi_last_next = nrzi_last;
if (nrzi_valid != 0) nrzi_last_valid_next = 1'b1;
nrzi_last_next = nrzi[1]; if (nrzi_valid[1])
if (nrzi_valid & 2)
nrzi_last_next = nrzi[0]; 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 end
always @(posedge clk) begin always @(posedge clk) begin
nrzi_last <= nrzi_last_next; if (rst) begin
nrz_valid <= nrzi_valid; nrzi_last <= 1'bX;
nrz <= nrz_next; 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 end
endmodule endmodule

View File

@ -6,9 +6,11 @@ import random
import cocotb import cocotb
from cocotb.clock import Clock from cocotb.clock import Clock
from cocotb.regression import TestFactory 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): async def nrzi_decode(bits):
last = 1 last = 1
@ -19,8 +21,12 @@ async def nrzi_decode(bits):
@timeout(10, 'us') @timeout(10, 'us')
async def test_rx(decoder, valids): async def test_rx(decoder, valids):
decoder.nrzi_valid.value = 0 decoder.nrzi_valid.value = 0
decoder.nrzi.value = LogicArray('X', 'X')
decoder.rst.value = 1
await Timer(1) await Timer(1)
await cocotb.start(Clock(decoder.clk, 8, units='ns').start()) 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)] ins = [random.randrange(2) for _ in range(1000)]
await cocotb.start(send_recovered_bits(decoder.clk, decoder.nrzi, 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) outs.append(decoder.nrz[0].value)
# Ignore the first bit, since it is influenced by the initial 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) with_valids(globals(), test_rx)