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