aboutsummaryrefslogtreecommitdiff
path: root/fpga/src/Uart.bs
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-10-20 17:49:23 -0500
committerNathan Ringo <nathan@remexre.com>2024-10-20 17:49:23 -0500
commit5c89c77fcf7493778732c12e2b141b5e9fa1f4a3 (patch)
tree943e0a339d28f8ef3a7aa7aaf8ad09f94ba63186 /fpga/src/Uart.bs
parentddf01d51c3429c25a57077d93d3309ce0e5d2262 (diff)
Maybe repaired UART, I2C, and HyperBus (but now getting a weird error)...
Diffstat (limited to 'fpga/src/Uart.bs')
-rw-r--r--fpga/src/Uart.bs117
1 files changed, 70 insertions, 47 deletions
diff --git a/fpga/src/Uart.bs b/fpga/src/Uart.bs
index 82f8e06..954f96e 100644
--- a/fpga/src/Uart.bs
+++ b/fpga/src/Uart.bs
@@ -1,56 +1,39 @@
package Uart where
-import FIFOF
+import Clocks
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'.
+ = -- | The UART is not currently sending anything. Transitions to 'Data b 0'
+ -- after sending the start bit once.
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 b (n + 1)' by sending a data bit. 'Data b 7' 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
+-- | Runs the TX side of the UART, receiving bytes from the 'Get' and writing
+-- output bits to the 'Put'.
+mkTxUart :: RWire (Bit 8) -> Wire (Bit 1) -> Module ()
+mkTxUart fifo tx = module
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_idle": when Idle <- state ==> do
+ case fifo.wget of
+ Just b -> do
+ state := Data b 7
+ tx._write 0
+ Nothing ->
+ tx._write 1
"uart_tx_data": when Data b n <- state ==> do
- pin := b[0:0]
- if n == 0 then
+ tx._write b[n:n]
+ if n == 7 then
state := Idle
else
- state := Data (b >> 1) (n - 1)
-
- interface TxUart
- pin = pin
- send = toPut fifo
+ state := Data b (n + 1)
-- | The state of the RX side of the UART.
data RxState
@@ -68,11 +51,17 @@ data RxState
Stop (Bit 8)
deriving (Bits, FShow)
+-- | Runs the RX side of the UART, receiving input bits from the 'Get' and
+-- writing bytes to the 'Put'.
+mkRxUart :: Wire (Bit 8) -> Bit 1 -> Module ()
+mkRxUart fifo rxBit = module
+ rules
+
+{-
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
@@ -83,26 +72,60 @@ mkRxUart rx bufferSize = module
"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
+-- | Returns a UART that does _not_ have FIFOs.
+mkUart' :: Bit 1 -> Module Uart
+mkUart' rx = module
+ recvFIFO :: Wire (Bit 8) <- mkWire
+ sendFIFO :: RWire (Bit 8) <- mkRWireSBR
+ tx :: Wire (Bit 1) <- mkWire
+
+ mkRxUart recvFIFO rx
+ mkTxUart sendFIFO tx
+
+ interface Uart
+ tx = tx._read
+ recv = toGet recvFIFO
+ send = toPut sendFIFO
+
+mkDividedUart :: Integer -> Bit 1 -> Module Uart
+mkDividedUart divisor rx = module
+ clock <- mkClockDivider divisor
+ reset <- mkAsyncResetFromCR divisor clock.slowClock
+
+ rxSync :: SyncBitIfc (Bit 1) <- mkSyncBitFromCC clock.slowClock
+ txSync :: Reg (Bit 1) <- mkSyncRegToCC 1 clock.slowClock reset
+ recvFIFO :: SyncFIFOIfc (Bit 8) <- mkSyncFIFOToCC 16 clock.slowClock reset
+ sendFIFO :: SyncFIFOIfc (Bit 8) <- mkSyncFIFOFromCC 16 clock.slowClock
+ rules
+ when True ==> rxSync.send rx
+
+ changeSpecialWires (Just clock.slowClock) (Just reset) Nothing $ module
+ uart <- mkUart' rxSync.read
+ rules
+ when True ==> txSync._write uart.tx
+ when True ==> do
+ byte <- uart.recv.get
+ recvFIFO.enq byte
+ when True ==> do
+ uart.send.put sendFIFO.first
+ sendFIFO.deq
+ return ()
+
interface Uart
- tx = uart_tx.pin
- recv = recv
- send = uart_tx.send
+ tx = txSync._read
+ recv = toGet recvFIFO
+ send = toPut sendFIFO
-- vim: set ft=haskell :