package Uart where import FIFOF import GetPut -- | The state of the TX side of the UART. data TxState = -- | The UART is not currently sending anything. May transition to -- 'Start b' when ready to send 'b'. Idle | -- | The UART is about to send the start bit. 'Start b' transitions to -- 'Data b 7' by sending the start bit. Start (Bit 8) | -- | The UART is about to send a data bit. 'Data b n' transitions to -- 'Data (b >> 1) (n - 1)' by sending a data bit. 'Data b 0' transitions to -- 'Idle' by sending the last data bit. Being in the 'Idle' state for a -- clock transmits the stop bit. Data (Bit 8) (Bit 3) deriving (Bits) -- | The TX side of the UART. interface TxUart = -- | The TX pin. pin :: Bit 1 -- | Writes a byte to the UART's transmit buffer. send :: Put (Bit 8) mkTxUart :: Integer -> Module TxUart mkTxUart bufferSize = module fifo :: FIFOF (Bit 8) <- mkSizedFIFOF bufferSize state :: Reg TxState <- mkReg Idle pin :: Reg (Bit 1) <- mkReg 1 rules "uart_tx_idle": when Idle <- state, not fifo.notEmpty ==> do pin := 1 "uart_tx_idle_to_start": when Idle <- state, fifo.notEmpty ==> do pin := 1 b <- (toGet fifo).get state := Start b "uart_tx_start": when Start b <- state ==> do pin := 0 state := Data b 7 "uart_tx_data": when Data b n <- state ==> do pin := b[0:0] if n == 0 then state := Idle else state := Data (b >> 1) (n - 1) interface TxUart pin = pin send = toPut fifo -- | The state of the RX side of the UART. data RxState = -- | The initial state of the UART, and the state after receiving the stop -- bit. May transition to 'Data 0 0' when the start bit is received. Idle | -- | In the 'Data _ n' state, the UART has received the start bit and 'n' -- data bits, and is about to receive more data bits. 'Data _ n' -- transitions to 'Data _ (n + 1)' by receiving a data bit. 'Data b 7' -- transitions to 'Stop' by receving the last data bit. Data (Bit 8) (Bit 3) | -- | In the 'Stop' state, the UART has received the start and data bits, -- and is waiting for the stop bit (which is ignored). Transitions to -- 'Idle'. Stop (Bit 8) deriving (Bits, FShow) mkRxUart :: Wire (Bit 1) -> Integer -> Module (Get (Bit 8)) mkRxUart rx bufferSize = module fifo :: FIFOF (Bit 8) <- mkGSizedFIFOF True False bufferSize state :: Reg RxState <- mkReg Idle rules "uart_rx_idle_to_start": when Idle <- state, rx == 0 ==> do state := Data 0 0 "uart_rx_data_to_data": when Data bits n <- state, n < 7 ==> do state := Data (rx ++ bits[7:1]) (n + 1) "uart_rx_data_to_stop": when Data bits 7 <- state ==> do state := Stop (rx ++ bits[7:1]) "uart_rx_stop_to_idle": when Stop bits <- state, rx == 1 ==> do fifo.enq bits state := Idle return (toGet fifo) -- | An 8n1 UART. interface Uart = -- | The TX pin. tx :: Bit 1 -- | Reads a byte from the UART's receive buffer. recv :: Get (Bit 8) -- | Writes a byte to the UART's transmit buffer. send :: Put (Bit 8) mkUart :: Wire (Bit 1) -> Module Uart mkUart rx = module recv <- mkRxUart rx 8 uart_tx <- mkTxUart 8 interface Uart tx = uart_tx.pin recv = recv send = uart_tx.send -- vim: set ft=haskell :