package UART; import Cntrs::*; import GetPut::*; import FIFOF::*; import SpecialFIFOs::*; import StmtFSM::*; import Connectable::*; import PinSync::*; import GlitchFilter::*; import Strobe::*; (* always_enabled *) interface UART_RX_PHY; (* prefix="" *) method Action rx_in((* port="rx_in" *) bit b); (* result="cts" *) method Bool stop_sending(); endinterface (* always_enabled *) interface UART_TX_PHY; (* result="tx_out" *) method bit tx_out(); (* prefix="" *) method Action can_send((* port="rts" *) Bool send); endinterface (* always_enabled *) interface UART_PHY; (* prefix="" *) method Action rx_in((* port="rx_in" *) bit b); (* result="tx_out" *) method bit tx_out(); (* result="cts" *) method Bool stop_sending(); (* prefix="" *) method Action can_send((* port="rts" *) Bool send); endinterface interface UART_RX; interface UART_RX_PHY phy; interface Get#(Bit#(8)) receive; endinterface interface UART_TX; interface UART_TX_PHY phy; interface Put#(Bit#(8)) send; endinterface interface UART; interface UART_PHY phy; interface Put#(Bit#(8)) send; interface Get#(Bit#(8)) receive; endinterface typedef enum { WaitIdle, Idle, Read, Stop, Cork } RXState deriving (Bits, Eq); module mkUARTReceiver(Integer clock_frequency, Integer uart_bitrate, UART_RX ifc); Reg#(bit) rx_sync <- mkPinSync(0); let rx_in <- mkGlitchFilter(3, 0); mkConnection(toGet(asReg(rx_sync)), toPut(asReg(rx_in))); Reg#(RXState) rx_state <- mkReg(WaitIdle); Strobe bit_16x_strobe <- mkStrobe(clock_frequency, 16*uart_bitrate); Count#(UInt#(4)) cnt <- mkCount(0); Reg#(Bit#(8)) shift_in <- mkReg(0); FIFOF#(Bit#(8)) rx <- mkBypassFIFOF(); (* no_implicit_conditions, fire_when_enabled *) rule rx_counter (bit_16x_strobe); cnt.incr(1); endrule (* no_implicit_conditions, fire_when_enabled *) rule rx_wait_idle (rx_state == WaitIdle && bit_16x_strobe && rx_in == 1); rx_state <= Idle; endrule (* no_implicit_conditions, fire_when_enabled *) rule rx_idle (rx_state == Idle && bit_16x_strobe && rx_in == 0); rx_state <= Read; cnt <= 1; shift_in <= 8'hFF; endrule (* no_implicit_conditions, fire_when_enabled *) rule rx_read (rx_state == Read && bit_16x_strobe && cnt == 7); let shifted_out = shift_in[0]; shift_in <= {rx_in, shift_in[7:1]}; if (shifted_out == 0) begin // start bit reached end of shiftreg rx_state <= Stop; end endrule (* fire_when_enabled *) rule rx_stop (rx_state == Stop); if (rx.notFull) begin rx.enq(shift_in); rx_state <= WaitIdle; end else rx_state <= Cork; endrule (* fire_when_enabled *) rule rx_cork (rx_state == Cork); rx.enq(shift_in); rx_state <= WaitIdle; endrule interface UART_RX_PHY phy; method rx_in = rx_sync._write; method Bool stop_sending(); // Signal is active low, so 1 == "stop sending" return rx_state == Cork; endmethod endinterface interface receive = toGet(rx); endmodule typedef enum { Idle, Ready, Send } TXState deriving (Bits, Eq); module mkUARTTransmitter(Integer clock_frequency, Integer uart_bitrate, UART_TX ifc); Reg#(bit) cts_sync <- mkPinSync(0); let cts_in <- mkGlitchFilter(3, 0); mkConnection(toGet(asReg(cts_sync)), toPut(asReg(cts_in))); Reg#(TXState) tx_state <- mkReg(Idle); Strobe bit_strobe <- mkStrobe(clock_frequency, uart_bitrate); Reg#(UInt#(4)) cnt <- mkReg(0); Reg#(Bit#(9)) shift_out <- mkReg(9'h1FF); FIFOF#(Bit#(8)) tx <- mkPipelineFIFOF(); (* fire_when_enabled *) rule tx_idle (tx_state == Idle && tx.notEmpty); shift_out <= {tx.first, 0}; tx.deq(); tx_state <= Ready; bit_strobe.reset(); endrule (* no_implicit_conditions, fire_when_enabled *) rule rx_ready (tx_state == Ready && bit_strobe && cts_in == 1); tx_state <= Send; cnt <= 0; endrule (* no_implicit_conditions, fire_when_enabled *) rule tx_send (tx_state == Send && bit_strobe); shift_out <= {1'b1, shift_out[8:1]}; cnt <= cnt+1; if (cnt == 9) tx_state <= Idle; endrule interface UART_TX_PHY phy; method bit tx_out(); if (tx_state == Send) return shift_out[0]; else return 1'b1; endmethod method Action can_send(b); cts_sync <= pack(b); endmethod endinterface interface Put send = toPut(tx); endmodule module mkUART(Integer clock_frequency, Integer uart_bitrate, UART ifc); let _rx <- mkUARTReceiver(clock_frequency, uart_bitrate); let _tx <- mkUARTTransmitter(clock_frequency, uart_bitrate); interface UART_PHY phy; method rx_in = _rx.phy.rx_in; method tx_out = _tx.phy.tx_out; method stop_sending = _rx.phy.stop_sending; method can_send = _tx.phy.can_send; endinterface interface send = _tx.send; interface receive = _rx.receive; endmodule typeclass FlowControlled#(type ifc); module disableFlowControl(ifc i, Empty ret); endtypeclass instance FlowControlled#(UART_RX_PHY); module disableFlowControl(UART_RX_PHY phy, Empty ifc); endmodule endinstance instance FlowControlled#(UART_TX_PHY); module disableFlowControl(UART_TX_PHY phy, Empty ifc); (* no_implicit_conditions,fire_when_enabled *) rule always_send; phy.can_send(True); endrule endmodule endinstance instance FlowControlled#(UART_PHY); module disableFlowControl(UART_PHY phy, Empty ifc); (* no_implicit_conditions,fire_when_enabled *) rule always_send; phy.can_send(True); endrule endmodule endinstance instance FlowControlled#(UART_RX); module disableFlowControl(UART_RX rx, Empty ifc); disableFlowControl(rx.phy); endmodule endinstance instance FlowControlled#(UART_TX); module disableFlowControl(UART_TX tx, Empty ifc); disableFlowControl(tx.phy); endmodule endinstance instance FlowControlled#(UART); module disableFlowControl(UART uart, Empty ifc); disableFlowControl(uart.phy); endmodule endinstance endpackage