aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile3
-rw-r--r--flake.nix1
-rw-r--r--src/Top.bs18
-rw-r--r--src/UART.bs101
-rw-r--r--src/Uart.bs125
5 files changed, 142 insertions, 106 deletions
diff --git a/Makefile b/Makefile
index 5157357..269cf32 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
BSC_COMP_FLAGS = -aggressive-conditions -bdir tmp -check-assert -keep-fires \
-p src:+ -vdir tmp
BSC_LINK_FLAGS = -keep-fires
+BSC_SOURCES = FIFO1.v
TOPFILE = Top
TOPMODULE = mkTop
SRCS = $(shell find src -name '*.bs')
@@ -21,7 +22,7 @@ tmp/%.bin: tmp/%.asc
tmp/%.asc: tmp/%.json src/icebreaker.pcf
nextpnr-ice40 -ql tmp/$*.nplog --up5k --package sg48 --freq 12 \
--asc $@ --pcf src/icebreaker.pcf --json $<
-tmp/$(TOPMODULE).json: tmp/$(TOPMODULE).v
+tmp/$(TOPMODULE).json: tmp/$(TOPMODULE).v $(addprefix $(BSC)/lib/Verilog/,$(BSC_SOURCES))
yosys -ql tmp/$(TOPMODULE).yslog -p 'synth_ice40 -top mkTop -json $@' $^
tmp/$(TOPMODULE).v: tmp/$(TOPFILE).bo
bsc -g $(TOPMODULE) -verilog $(BSC_COMP_FLAGS) src/$(TOPFILE).bs
diff --git a/flake.nix b/flake.nix
index ef36aef..bc12844 100644
--- a/flake.nix
+++ b/flake.nix
@@ -14,6 +14,7 @@
pkgs.picocom
pkgs.yosys
];
+ env.BSC = pkgs.bluespec;
};
packages = { };
diff --git a/src/Top.bs b/src/Top.bs
index 2a056ac..d5cb7e3 100644
--- a/src/Top.bs
+++ b/src/Top.bs
@@ -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 :