aboutsummaryrefslogtreecommitdiff
path: root/fpga
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-10-08 21:33:12 -0500
committerNathan Ringo <nathan@remexre.com>2024-10-08 21:33:12 -0500
commitddf01d51c3429c25a57077d93d3309ce0e5d2262 (patch)
treeba8fa87bd190adfd02ff54092dbb57791bb7218e /fpga
parent08d727e9886cde6a367906999e96a33f7ba37f33 (diff)
Preparation to start using separate clock domains.
Diffstat (limited to 'fpga')
-rw-r--r--fpga/src/Clock.bs19
-rw-r--r--fpga/src/HyperBus.bs15
-rw-r--r--fpga/src/Numini.bs39
-rw-r--r--fpga/src/Top.bs4
-rw-r--r--fpga/src/TopSim.bs44
-rw-r--r--fpga/src/Uart.bs102
6 files changed, 96 insertions, 127 deletions
diff --git a/fpga/src/Clock.bs b/fpga/src/Clock.bs
deleted file mode 100644
index c908502..0000000
--- a/fpga/src/Clock.bs
+++ /dev/null
@@ -1,19 +0,0 @@
--- | A simple clock package.
-package Clock where
-
-interface Clock =
- clk :: Bool
-
--- TODO: Make a multiclock that uses one count for all the sub-clocks in the
--- design.
-
-mkClock :: Bit n -> Module Clock
-mkClock divisor =
- module
- count :: Reg (Bit n) <- mkReg 0
- rules
- when True ==> count := if count == divisor - 1 then 0 else count + 1
- interface Clock
- clk = count == 0
-
--- vim: set ft=haskell :
diff --git a/fpga/src/HyperBus.bs b/fpga/src/HyperBus.bs
index 41d1703..2b75b6e 100644
--- a/fpga/src/HyperBus.bs
+++ b/fpga/src/HyperBus.bs
@@ -1,8 +1,6 @@
-- | A controller for a HyperBus interface, allowing for I/O to four chips.
package HyperBus where
-import Clock
-
-- | The HyperBus output pins.
interface HyperBusOut =
ck :: Bit 1
@@ -15,11 +13,16 @@ interface HyperBusOut =
rwds_out :: Maybe (Bit 1)
dq_out :: Maybe (Bit 8)
-mkHyperBus :: Wire (Bit 1) -> Wire (Bit 8) -> Clock -> Module HyperBusOut
-mkHyperBus rwds_in dq_in clock = module
+mkHyperBus :: Wire (Bit 1) -> Wire (Bit 8) -> Module HyperBusOut
+mkHyperBus rwds_in dq_in = module
+ clockPin :: Reg (Bit 1) <- mkReg 0
+ rules
+ "update_clock_pin": when True ==> do
+ clockPin := invert clockPin
+
interface HyperBusOut
- ck = if clock.clk then 1 else 0
- ck_n = if clock.clk then 0 else 1
+ ck = clockPin
+ ck_n = invert clockPin
cs0_n = 1
cs1_n = 1
cs2_n = 1
diff --git a/fpga/src/Numini.bs b/fpga/src/Numini.bs
index 58c2c38..39990fc 100644
--- a/fpga/src/Numini.bs
+++ b/fpga/src/Numini.bs
@@ -2,7 +2,8 @@
-- the simulator's. This insulates us from Bluesim's lack of Inout support.
package Numini where
-import Clock
+import Clocks
+import Connectable
import HyperBus
import Uart
@@ -32,22 +33,38 @@ interface NuminiOut =
i2c_scl :: Bit 1
i2c_sda_out :: Maybe (Bit 1)
-clockFreqHz :: Bit 24
+clockFreqHz :: Integer
clockFreqHz = 12_000_000
mkNumini :: Wire (Bit 1) -> Wire (Bit 1) -> Wire (Bit 1) -> Wire (Bit 1) ->
Wire (Bit 8) -> Wire (Bit 1) -> Module NuminiOut
mkNumini ch559_uart_rx inkplate_uart_rx usb_uart_rx hyperbus_rwds_in
hyperbus_dq_in i2c_sda_in = module
- clk9600 <- mkClock (clockFreqHz / 9600)
- clk2M <- mkClock (clockFreqHz / 2_000_000)
- clk3M <- mkClock (clockFreqHz / 3_000_000)
-
- ch559_uart <- mkUart ch559_uart_rx clk9600
- inkplate_uart <- mkUart inkplate_uart_rx clk2M
- usb_uart <- mkUart usb_uart_rx clk9600
-
- hyperbus <- mkHyperBus hyperbus_rwds_in hyperbus_dq_in clk3M
+ {-
+ -- Make derived clocks and resets.
+ clk9600 <- mkClockDivider (clockFreqHz / 9600)
+ clk2M <- mkClockDivider (clockFreqHz / 2_000_000)
+ clk3M <- mkClockDivider (clockFreqHz / 3_000_000)
+ reset9600 <- mkReset (clockFreqHz / 9600) True clk9600.slowClock
+ reset2M <- mkReset (clockFreqHz / 2_000_000) True clk2M.slowClock
+ reset3M <- mkReset (clockFreqHz / 3_000_000) True clk3M.slowClock
+
+ -- Make the peripherals.
+ ch559_uart <- changeSpecialWires (Just clk9600.slowClock)
+ (Just reset9600.new_rst) Nothing (mkUart ch559_uart_rx)
+ inkplate_uart <- changeSpecialWires (Just clk2M.slowClock)
+ (Just reset2M.new_rst) Nothing (mkUart inkplate_uart_rx)
+ usb_uart <- changeSpecialWires (Just clk9600.slowClock)
+ (Just reset9600.new_rst) Nothing (mkUart usb_uart_rx)
+ hyperbus <- changeSpecialWires (Just clk3M.slowClock)
+ (Just reset3M.new_rst) Nothing (mkHyperBus hyperbus_rwds_in hyperbus_dq_in)
+ -}
+ ch559_uart <- (mkUart ch559_uart_rx)
+ inkplate_uart <- (mkUart inkplate_uart_rx)
+ usb_uart <- (mkUart usb_uart_rx)
+ hyperbus <- (mkHyperBus hyperbus_rwds_in hyperbus_dq_in)
+
+ mkConnection usb_uart.send usb_uart.recv
interface NuminiOut
ch559_uart_tx = ch559_uart.tx
diff --git a/fpga/src/Top.bs b/fpga/src/Top.bs
index df79387..67449bd 100644
--- a/fpga/src/Top.bs
+++ b/fpga/src/Top.bs
@@ -1,12 +1,8 @@
-- | The top-level module, for the iCEBreaker.
package Top where
-import Connectable
-import CPU
-import GetPut
import Numini
import TriState
-import Uart
-- | The interface to the iCEBreaker.
interface Top =
diff --git a/fpga/src/TopSim.bs b/fpga/src/TopSim.bs
index ca92fe1..bf5d59c 100644
--- a/fpga/src/TopSim.bs
+++ b/fpga/src/TopSim.bs
@@ -1,38 +1,22 @@
-- | The top-level module for simulation.
package TopSim where
-import Connectable
-import CPU
-import GetPut
-import TriState
-import Uart
+import Numini
mkTopSim :: Module Empty
-mkTopSim =
- module
- cpu <- mkCPU
+mkTopSim = module
+ ch559_uart_rx <- mkWire
+ inkplate_uart_rx <- mkWire
+ usb_uart_rx <- mkWire
+ hyperbus_rwds_in <- mkWire
+ hyperbus_dq_in <- mkWire
+ i2c_sda_in <- mkWire
+ numini <- mkNumini ch559_uart_rx inkplate_uart_rx usb_uart_rx
+ hyperbus_rwds_in hyperbus_dq_in i2c_sda_in
- uart <- mkUart 1
- mkConnection cpu.uart_tx uart.send
- mkConnection cpu.uart_rx uart.recv
-
- fakeUart <- mkUart 1
- rules
- when True ==> uart.rxPin fakeUart.txPin
-
- timer :: Reg (Bit 8) <- mkReg 0
- rules
- when True ==> timer := timer + 1
- when (timer == 0x00) ==> fakeUart.send.put 0x30
- when (timer == 0x01) ==> fakeUart.send.put 0x30
- when (timer == 0x02) ==> fakeUart.send.put 0x77
- when (timer == 0x03) ==> fakeUart.send.put 0x31
- when (timer == 0x04) ==> fakeUart.send.put 0x32
- when (timer == 0x05) ==> fakeUart.send.put 0x33
- when (timer == 0x06) ==> fakeUart.send.put 0x34
- when (timer == 0x10) ==> fakeUart.send.put 0x30
- when (timer == 0x11) ==> fakeUart.send.put 0x30
- when (timer == 0x12) ==> fakeUart.send.put 0x72
- when (timer == 0xff) ==> $finish
+ timer :: Reg (Bit 8) <- mkReg 0
+ rules
+ when True ==> timer := timer + 1
+ when (timer == 0xff) ==> $finish
-- vim: set ft=haskell :
diff --git a/fpga/src/Uart.bs b/fpga/src/Uart.bs
index 7298083..82f8e06 100644
--- a/fpga/src/Uart.bs
+++ b/fpga/src/Uart.bs
@@ -1,6 +1,5 @@
package Uart where
-import Clock
import FIFOF
import GetPut
@@ -26,34 +25,32 @@ interface TxUart =
-- | Writes a byte to the UART's transmit buffer.
send :: Put (Bit 8)
-mkTxUart :: Clock -> Integer -> Module TxUart
-mkTxUart clock bufferSize =
- module
- fifo :: FIFOF (Bit 8) <- mkSizedFIFOF bufferSize
- state :: Reg TxState <- mkReg Idle
- pin :: Reg (Bit 1) <- mkReg 1
+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": when clock.clk
- 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
+ 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
@@ -71,32 +68,23 @@ data RxState
Stop (Bit 8)
deriving (Bits, FShow)
--- | The RX side of the UART.
-interface RxUart =
- -- | Reads a byte from the UART's receive buffer.
- recv :: Get (Bit 8)
-
-mkRxUart :: Wire (Bit 1) -> Clock -> Integer -> Module RxUart
-mkRxUart rx clock bufferSize =
- module
- fifo :: FIFOF (Bit 8) <- mkGSizedFIFOF True False bufferSize
- state :: Reg RxState <- mkReg Idle
+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": when clock.clk
- 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
+ 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
- interface RxUart
- recv = toGet fifo
+ return (toGet fifo)
-- | An 8n1 UART.
interface Uart =
@@ -108,13 +96,13 @@ interface Uart =
-- | Writes a byte to the UART's transmit buffer.
send :: Put (Bit 8)
-mkUart :: Wire (Bit 1) -> Clock -> Module Uart
-mkUart rx clock = module
- uart_rx <- mkRxUart rx clock 8
- uart_tx <- mkTxUart clock 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 = uart_rx.recv
+ recv = recv
send = uart_tx.send
-- vim: set ft=haskell :