aboutsummaryrefslogtreecommitdiff
path: root/fpga/src/Top.bs
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-11-02 00:08:29 -0500
committerNathan Ringo <nathan@remexre.com>2024-11-02 00:08:29 -0500
commit2a506c1476c55d9ecf990bd4878169278038f6ff (patch)
tree2d618474d89d0b90fe0166e30ba96268e94a2d1e /fpga/src/Top.bs
parentd3bcde4eedd2dd3dcf5cbc4302821f38ff553498 (diff)
...
Diffstat (limited to 'fpga/src/Top.bs')
-rw-r--r--fpga/src/Top.bs155
1 files changed, 154 insertions, 1 deletions
diff --git a/fpga/src/Top.bs b/fpga/src/Top.bs
index 65baf8a..df5098f 100644
--- a/fpga/src/Top.bs
+++ b/fpga/src/Top.bs
@@ -1,7 +1,8 @@
-- | The top-level module, for the iCEBreaker.
package Top where
-import Numini
+import I2C
+-- import Numini
import TriState
-- | The interface to the iCEBreaker.
@@ -81,6 +82,157 @@ mkTop = module
i2c_scl_in :: Wire (Bit 1) <- mkWire
i2c_sda_in :: Wire (Bit 1) <- mkWire
+ -- i2c <- mkDividedI2C (clockFreqHz / 400_000) i2c_scl_in i2c_sda_in
+ i2c <- mkI2C i2c_scl_in i2c_sda_in
+
+ -- Provide commands.
+ state :: Reg (Bit 4) <- mkReg 0
+ rules
+ when state == 0, i2c.statusRegGet.ready ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0x00
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 1
+ when state == 1 ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0x00
+ state := 2
+ when state == 2, i2c.statusRegGet.ready ==> do
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 3
+ when state == 3 ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0x00
+ state := 4
+ when state == 4, i2c.statusRegGet.ready ==> do
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 5
+ when state == 5 ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0x12
+ state := 6
+ when state == 6, i2c.statusRegGet.busIdle ==> do
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 7
+ when state == 7 ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0xaa
+ state := 8
+ when state == 8, i2c.statusRegGet.ready ==> do
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 9
+ when state == 9 ==> do
+ i2c.addrRegPut (0x20 ++ (0 :: Bit 1))
+ i2c.dataRegPut 0xaa
+ state := 10
+ when state == 10, i2c.statusRegGet.ready ==> do
+ i2c.statusRegPut (i2c.statusRegGet { ready = False })
+ state := 11
+
+ -- Wire up the tristates.
+ rules
+ "update_hyperbus_rwds_out": when True ==> do
+ hyperbus_rwds_enable := False
+ hyperbus_rwds_out := 0
+ "update_hyperbus_rwds_in": when True ==> do
+ hyperbus_rwds_in := hyperbus_rwds._read
+ "update_hyperbus_dq_out": when True ==> do
+ hyperbus_dq_enable := False
+ hyperbus_dq_out := 0
+ "update_hyperbus_dq_in": when True ==> do
+ hyperbus_dq_in := hyperbus_dq7._read
+ ++ hyperbus_dq6._read
+ ++ hyperbus_dq5._read
+ ++ hyperbus_dq4._read
+ ++ hyperbus_dq3._read
+ ++ hyperbus_dq2._read
+ ++ hyperbus_dq1._read
+ ++ hyperbus_dq0._read
+ "update_i2c_scl_out": when True ==> do
+ i2c_scl_enable := unpack i2c.txSCL
+ "update_i2c_scl_in": when True ==> do
+ i2c_scl_in := i2c_scl._read
+ "update_i2c_sda_out": when True ==> do
+ i2c_sda_enable := unpack i2c.txSDA
+ "update_i2c_sda_in": when True ==> do
+ i2c_sda_in := i2c_sda._read
+
+ interface Top
+ -- RS232
+ usb_uart_rx bit = usb_uart_rx := bit
+ usb_uart_tx = 0
+ -- Onboard LEDs
+ led_r_n = 1
+ led_g_n = 1
+ -- RGB LED driver
+ rgb_r_n = 1
+ rgb_g_n = 1
+ rgb_b_n = 1
+ -- HyperBus 1 (PMOD 1A)
+ hyperbus_cs2_n = 1
+ hyperbus_cs0_n = 1
+ hyperbus_ck = 0
+ hyperbus_ck_n = 1
+ hyperbus_cs3_n = 1
+ hyperbus_cs1_n = 1
+ hyperbus_reset_n = 1
+ hyperbus_rwds = hyperbus_rwds.io
+ -- HyperBus 2 (PMOD 1B)
+ hyperbus_dq0 = hyperbus_dq0.io
+ hyperbus_dq1 = hyperbus_dq1.io
+ hyperbus_dq2 = hyperbus_dq2.io
+ hyperbus_dq3 = hyperbus_dq3.io
+ hyperbus_dq4 = hyperbus_dq4.io
+ hyperbus_dq5 = hyperbus_dq5.io
+ hyperbus_dq6 = hyperbus_dq6.io
+ hyperbus_dq7 = hyperbus_dq7.io
+ -- LEDs and buttons (PMOD 2)
+ ch559_uart_rx bit = ch559_uart_rx := bit
+ ch559_uart_tx = 0
+ inkplate_uart_rx bit = inkplate_uart_rx := bit
+ inkplate_uart_tx = 0
+ todo_btn _ = noAction
+ todo_led = 0
+ i2c_scl = i2c_scl.io
+ i2c_sda = i2c_sda.io
+{-# verilog mkTop #-}
+{-# properties mkTop = { RSTN = BTN_N } #-}
+
+{-
+mkTop :: Module Top
+mkTop = module
+ ch559_uart_rx <- mkWire
+ inkplate_uart_rx <- mkWire
+ usb_uart_rx <- mkWire
+
+ -- Make tristates for the HyperBus inouts.
+ hyperbus_rwds_enable :: Reg Bool <- mkReg False
+ hyperbus_rwds_out :: Reg (Bit 1) <- mkReg 0
+ hyperbus_dq_enable :: Reg Bool <- mkReg False
+ hyperbus_dq_out :: Reg (Bit 8) <- mkReg 0
+ hyperbus_rwds <- mkTriState hyperbus_rwds_enable hyperbus_rwds_out
+ hyperbus_dq0 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[0:0]
+ hyperbus_dq1 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[1:1]
+ hyperbus_dq2 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[2:2]
+ hyperbus_dq3 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[3:3]
+ hyperbus_dq4 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[4:4]
+ hyperbus_dq5 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[5:5]
+ hyperbus_dq6 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[6:6]
+ hyperbus_dq7 <- mkTriState hyperbus_dq_enable hyperbus_dq_out[7:7]
+
+ -- Make a tristate for the I2C inouts. Note that we never drive the line
+ -- high -- I2C uses a high-impedance state instead of high.
+ i2c_scl_enable <- mkReg False
+ i2c_scl <- mkTriState i2c_scl_enable 0
+ i2c_sda_enable <- mkReg False
+ i2c_sda <- mkTriState i2c_sda_enable 0
+
+ -- Make wires for all the inout inputs.
+ hyperbus_rwds_in :: Wire (Bit 1) <- mkWire
+ hyperbus_dq_in :: Wire (Bit 8) <- mkWire
+ i2c_scl_in :: Wire (Bit 1) <- mkWire
+ i2c_sda_in :: Wire (Bit 1) <- mkWire
+
numini <- mkNumini ch559_uart_rx inkplate_uart_rx usb_uart_rx
hyperbus_rwds_in hyperbus_dq_in i2c_scl_in i2c_sda_in
@@ -162,5 +314,6 @@ mkTop = module
i2c_sda = i2c_sda.io
{-# verilog mkTop #-}
{-# properties mkTop = { RSTN = BTN_N } #-}
+-}
-- vim: set ft=haskell :