From 2a506c1476c55d9ecf990bd4878169278038f6ff Mon Sep 17 00:00:00 2001 From: Nathan Ringo Date: Sat, 2 Nov 2024 00:08:29 -0500 Subject: ... --- fpga/src/Top.bs | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) (limited to 'fpga/src/Top.bs') 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. @@ -47,6 +48,157 @@ interface Top = clockFreqHz :: Integer clockFreqHz = 12_000_000 +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 + + -- 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 @@ -162,5 +314,6 @@ mkTop = module i2c_sda = i2c_sda.io {-# verilog mkTop #-} {-# properties mkTop = { RSTN = BTN_N } #-} +-} -- vim: set ft=haskell : -- cgit v1.2.3