From ddf01d51c3429c25a57077d93d3309ce0e5d2262 Mon Sep 17 00:00:00 2001 From: Nathan Ringo Date: Tue, 8 Oct 2024 21:33:12 -0500 Subject: Preparation to start using separate clock domains. --- fpga/src/Clock.bs | 19 ---------- fpga/src/HyperBus.bs | 15 +++++--- fpga/src/Numini.bs | 39 ++++++++++++++------ fpga/src/Top.bs | 4 -- fpga/src/TopSim.bs | 44 +++++++--------------- fpga/src/Uart.bs | 102 +++++++++++++++++++++++---------------------------- 6 files changed, 96 insertions(+), 127 deletions(-) delete mode 100644 fpga/src/Clock.bs 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 : -- cgit v1.2.3