gary/lib/UART_Test.bsv

266 lines
8.4 KiB
Plaintext
Raw Permalink Normal View History

package UART_Test;
import Assert::*;
import StmtFSM::*;
import Connectable::*;
import GetPut::*;
import Probe::*;
import UART::*;
import Testing::*;
import Strobe::*;
interface Test;
method Action start();
method Bool done();
endinterface
module mkTestReceiver(Test);
Reg#(Bool) running <- mkReg(False);
let testflags <- mkTestFlags();
let cycles <- mkCycleCounter();
let dut <- mkUARTReceiver(25_000_000, 115_200);
Reg#(bit) tx <- mkReg(1);
mkConnection(toGet(asReg(tx)), toPut(dut.phy.rx_in));
Probe#(Bit#(8)) read_probe <- mkProbe();
Probe#(Bool) cork_probe <- mkProbe();
rule record_cork;
cork_probe <= dut.phy.stop_sending();
endrule
Reg#(Bit#(40)) shift[2] <- mkCReg(2, 40'hFFFFFFFFFF);
let shift_in_strobe <- mkStrobe(25_000_000, 115_200);
(* no_implicit_conditions, fire_when_enabled *)
rule shift_in (running && shift_in_strobe && (tx == 0 || !dut.phy.stop_sending));
if (testflags.verbose)
$display("%0d (%0d): to UART: %0d", cycles.all, cycles, shift[0][0]);
tx <= shift[0][0];
shift[0] <= {1'b1, shift[0][39:1]};
endrule
function Action start_tx(Bit#(40) val);
return action
shift[1] <= val;
endaction;
endfunction
function Bool tx_idle();
return shift[0] == 40'hFFFFFFFFFF;
endfunction
function Bool tx_is(Bit#(40) val);
return shift[0] == val;
endfunction
let fsm <- mkFSM(seq
running <= True;
// Let UART initialize and settle
repeat (61) noAction;
// desynchronize sender and receiver strobes, to emulate a
// real setup.
shift_in_strobe.reset();
action
dynamicAssert(tx_idle(), "transmitter not idle");
dynamicAssert(!dut.phy.stop_sending(), "receiver not ready to receive");
endaction
// Single byte transmission
action
start_tx({10'h3FF, 10'h3FF, 10'h3FF, 1'b1, 8'd77, 1'b0});
cycles.reset();
endaction
// Read received byte
action
let got <- dut.receive.get();
read_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): UART.rx = %0d, want %0d", cycles.all, cycles, got, 77);
dynamicAssert(got == 77, "wrong byte received");
dynamicAssert(cycles < 2100, "byte not received during stop bit");
endaction
dynamicAssert(!dut.phy.stop_sending(), "receiver not ready to receive");
await(shift_in_strobe);
action
dynamicAssert(tx_idle(), "transmitter not idle");
dynamicAssert(!dut.phy.stop_sending(), "receiver not ready to receive");
endaction
await(shift_in_strobe);
// Send 4 bytes back to back, to check flow control
action
start_tx({
1'b1, 8'd25, 1'b0,
1'b1, 8'd14, 1'b0,
1'b1, 8'd59, 1'b0,
1'b1, 8'd42, 1'b0});
cycles.reset();
endaction
// Once two bytes are sent, the receiver should cork.
await(tx_is({10'h3FF, 10'h3FF, 1'b1, 8'd25, 1'b0, 1'b1, 8'd14, 1'b0}));
repeat (1000) noAction;
dynamicAssert(dut.phy.stop_sending(), "receiver did not cork sender");
// Read out one byte, verify that one more byte can transmit.
action
let got <- dut.receive.get();
read_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): UART.rx = %0d, want %0d", cycles.all, cycles, got, 42);
dynamicAssert(got == 42, "wrong byte received");
dynamicAssert(cycles < 5400, "byte not received during stop bit");
endaction
await(tx_is({10'h3FF, 10'h3FF, 10'h3FF, 1'b1, 8'd25, 1'b0}));
dynamicAssert(dut.phy.stop_sending(), "receiver did not cork sender");
// Read out one more byte, check the final byte transmits.
action
let got <- dut.receive.get();
read_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): UART.rx = %0d, want %0d", cycles.all, cycles, got, 59);
dynamicAssert(got == 59, "wrong byte received");
dynamicAssert(cycles < 7600, "byte not received during stop bit");
endaction
await(tx_is(40'hFFFFFFFFFF));
repeat (1000) noAction;
dynamicAssert(dut.phy.stop_sending(), "receiver did not cork sender");
// Read the final two bytes from the receiver.
action
let got <- dut.receive.get();
read_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): UART.rx = %0d, want %0d", cycles.all, cycles, got, 14);
dynamicAssert(got == 14, "wrong byte received");
dynamicAssert(cycles < 10500, "byte not received during stop bit");
endaction
repeat (1000) noAction;
dynamicAssert(!dut.phy.stop_sending(), "receiver did not uncork sender");
action
let got <- dut.receive.get();
read_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): UART.rx = %0d, want %0d", cycles.all, cycles, got, 25);
dynamicAssert(got == 25, "wrong byte received");
dynamicAssert(cycles < 11500, "byte not received during stop bit");
endaction
repeat (1000) noAction;
dynamicAssert(!dut.phy.stop_sending(), "receiver did not uncork sender");
running <= False;
endseq);
method start = fsm.start;
method done = fsm.done;
endmodule
module mkTestTransmitter(Test);
let testflags <- mkTestFlags();
let cycles <- mkCycleCounter();
let receiver <- mkUARTReceiver(25_000_000, 115_200);
let dut <- mkUARTTransmitter(25_000_000, 115_200);
mkConnection(toGet(dut.phy.tx_out), toPut(receiver.phy.rx_in));
mkConnection(toGet(True), toPut(dut.phy.can_send));
Probe#(bit) tx_probe <- mkProbe();
Probe#(Bit#(8)) recv_probe <- mkProbe();
rule record_tx;
tx_probe <= dut.phy.tx_out;
endrule
let fsm <- mkFSM(seq
// Let UART initialize and settle
repeat (61) noAction;
action
dut.send.put(42);
cycles.reset();
if (testflags.verbose)
$display("%0d: send", cycles.all);
endaction
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 42, "wrong value received");
dynamicAssert(cycles < 2000, "value received too late");
endaction
repeat(1000) noAction;
par
seq
dut.send.put(1);
dut.send.put(2);
dut.send.put(5);
dut.send.put(3);
dut.send.put(4);
endseq
seq
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 1, "wrong byte received");
endaction
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 2, "wrong byte received");
endaction
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 5, "wrong byte received");
endaction
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 3, "wrong byte received");
endaction
action
let got <- receiver.receive.get();
recv_probe <= got;
if (testflags.verbose)
$display("%0d (%0d): received %0d", cycles.all, cycles, got);
dynamicAssert(got == 4, "wrong byte received");
endaction
endseq
endpar
endseq);
method start = fsm.start;
method done = fsm.done;
endmodule
module mkTB();
let rx_test <- mkTestReceiver();
let tx_test <- mkTestTransmitter();
runTest(30000,
mkTest("UART", seq
rx_test.start();
await(rx_test.done);
tx_test.start();
await(tx_test.done);
endseq));
endmodule
endpackage