diff options
author | Nathan Ringo <nathan@remexre.com> | 2024-05-06 01:12:26 -0500 |
---|---|---|
committer | Nathan Ringo <nathan@remexre.com> | 2024-05-06 01:12:26 -0500 |
commit | d8db4d5cfa3977001181714e632d5addd7c0e4ba (patch) | |
tree | e01d034e671c0039864850fbeca319593b2468f6 /src | |
parent | f9b73dc7b93bbf60f5b2281a5056c4339e049388 (diff) |
Sending side done!
Diffstat (limited to 'src')
-rw-r--r-- | src/Top.bs | 18 | ||||
-rw-r--r-- | src/UART.bs | 101 | ||||
-rw-r--r-- | src/Uart.bs | 125 |
3 files changed, 139 insertions, 105 deletions
@@ -1,6 +1,7 @@ package Top where -import UART +import GetPut +import Uart interface Top = -- RS232 @@ -30,7 +31,14 @@ mkTop :: Module Top mkTop = module bitState :: Reg (Bit 1) <- mkReg 0 - uart <- mkUART (clockFreqHz / 9600) + + uart <- mkUart (clockFreqHz / 9600) + lastByte :: Reg (Bit 8) <- mkReg 0x21 + + tick <- mkDivider (clockFreqHz) + rules + "tick": when tick.clk ==> do + uart.send.put lastByte interface Top -- RS232 @@ -39,8 +47,8 @@ mkTop = uart.rxPin bit tx = uart.txPin -- Onboard LEDs - ledR_N = uart.txPin - ledG_N = bitState + ledR_N = bitState + ledG_N = uart.txPin -- RGB LED driver ledRed_N = 1 ledGrn_N = 1 @@ -56,3 +64,5 @@ mkTop = btn3 _ = return () {-# verilog mkTop #-} {-# properties mkTop = { RSTN = BTN_N } #-} + +-- vim: set ft=haskell : diff --git a/src/UART.bs b/src/UART.bs deleted file mode 100644 index f837949..0000000 --- a/src/UART.bs +++ /dev/null @@ -1,101 +0,0 @@ -package UART where - -import GetPut -import Util - -interface Clock = - clk :: Bool - -defaultClock :: Clock -defaultClock = - interface Clock - clk = True - -mkDivider :: Integer -> Clock -> Module Clock -mkDivider divisor clockIn = - module - count <- mkReg 0 - - rules - "increment_divider": when clockIn.clk ==> do - if count == fromInteger divisor then do - count := 0 - else - count := count + 1 - - interface Clock - clk = count == 0 - -interface ShiftRegister = - get :: Get (Bit 1) - put :: Put (Bit 1) - -mkShiftRegister :: Module ShiftRegister -mkShiftRegister = - module - reg :: Reg (Bit 8) <- mkReg 0 - - interface ShiftRegister - get = interface Get - get = return 0 - put = interface Put - put bit = do - return () - --- An 8n1 UART. -interface UART = - -- The RX pin. - rxPin :: Bit 1 -> Action - -- The TX pin. - txPin :: Bit 1 - - -- Reads a byte from the UART. - rxByte :: Get (Bit 8) - -- Writes a byte to the UART. - txByte :: Put (Bit 8) - -mkUART :: Integer -> Module UART -mkUART baudDivisor = - module - baud <- mkDivider baudDivisor defaultClock - - count :: Reg (Bit 4) <- mkReg 0 - rules - "increment_count": when baud.clk ==> do - count := count + 1 - - let start = 0 - d0 = 1 - d1 = 0 - d2 = 0 - d3 = 0 - d4 = 1 - d5 = 0 - d6 = 0 - d7 = 0 - stop = 1 - - interface UART - rxPin _bit = when_ baud.clk $ do - return () -- TODO - txPin = case count of - 0 -> start - 1 -> d0 - 2 -> d1 - 3 -> d2 - 4 -> d3 - 5 -> d4 - 6 -> d5 - 7 -> d6 - 8 -> d7 - 9 -> stop - _ -> 1 - - rxByte = interface Get - get = return 0 when False - txByte = interface Put - put _ = do - -- TODO - return () - --- vim: set ft=haskell : diff --git a/src/Uart.bs b/src/Uart.bs new file mode 100644 index 0000000..0a3e82b --- /dev/null +++ b/src/Uart.bs @@ -0,0 +1,125 @@ +package Uart where + +import FIFOF +import GetPut +import Util + +interface Clock = + clk :: Bool + +mkDivider :: Integer -> Module Clock +mkDivider divisor = + module + count :: Reg (Bit 32) <- mkReg 0 + + rules + "increment_divider": when True ==> do + if count == fromInteger (divisor - 1) then do + count := 0 + else + count := count + 1 + + interface Clock + clk = count == 0 + +-- | A shift register. +interface ShiftRegister item numItems = + -- | Shifts an item into the shift register. + put :: Put item + -- | Shifts an item out of the shift register. + get :: Get item + -- | The number of items currently in the shift register. + size :: Bit (TLog numItems) + +-- | Creates a shift register. +mkShiftRegister :: (Bits item itemSize) => Module (ShiftRegister item numItems) +mkShiftRegister = + module + size :: Reg (Bit (TLog numItems)) <- mkReg 0 + buffer :: Reg (Bit (TMul itemSize numItems)) <- mkReg 0 + + interface ShiftRegister + put = interface Put + put _ = return () + get = interface Get + get = return (unpack 0) when False + size = size + +-- | 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 + -- 'Stop' by sending the last data bit. + Data (Bit 8) (Bit 3) + | -- | The UART is about to send the stop bit. Transitions to 'Idle'. + Stop + deriving (Bits) + +-- | The TX side of the UART. +interface TxUart = + -- | The TX pin. + pin :: Bit 1 + -- Writes a byte to the UART. + send :: Put (Bit 8) + +mkTxUart :: Clock -> Integer -> Module TxUart +mkTxUart baudClock bufferSize = + module + fifo :: FIFOF (Bit 8) <- mkSizedFIFOF bufferSize + state <- mkReg Idle + rules + "uart_tx_send": when baudClock.clk ==> do + case state of + Idle -> do + b <- (toGet fifo).get + state := Start b + Start b -> do + state := Data b 7 + Data _ 0 -> do + state := Stop + Data b n -> do + state := Data (b >> 1) (n - 1) + Stop -> do + state := Idle + interface TxUart + pin = case state of + Idle -> 1 + Start _ -> 0 + Data b _ -> b[0:0] + Stop -> 1 + send = toPut fifo + +-- An 8n1 UART. +interface Uart = + -- The RX pin. + rxPin :: Bit 1 -> Action + -- The TX pin. + txPin :: Bit 1 + + -- Reads a byte from the UART. + recv :: Get (Bit 8) + -- Writes a byte to the UART. + send :: Put (Bit 8) + +mkUart :: Integer -> Module Uart +mkUart baudDivisor = + module + baudClock <- mkDivider baudDivisor + tx <- mkTxUart baudClock 1 + + interface Uart + rxPin _bit = when_ baudClock.clk $ do + return () -- TODO + txPin = tx.pin + + recv = interface Get + get = return 0 when False + send = tx.send + +-- vim: set ft=haskell : |