-- | The top-level module, for the iCEBreaker. package Top where import I2C -- import Numini import TriState -- | The interface to the iCEBreaker. interface Top = -- RS232 usb_uart_rx :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [RX] #-} usb_uart_tx :: Bit 1 {-# always_ready, result = TX #-} -- Onboard LEDs led_r_n :: Bit 1 {-# always_ready, result = LEDR_N #-} led_g_n :: Bit 1 {-# always_ready, result = LEDG_N #-} -- RGB LED driver rgb_r_n :: Bit 1 {-# always_ready, result = LED_RED_N #-} rgb_g_n :: Bit 1 {-# always_ready, result = LED_GRN_N #-} rgb_b_n :: Bit 1 {-# always_ready, result = LED_BLU_N #-} -- HyperBus 1 (PMOD 1A) hyperbus_cs2_n :: Bit 1 {-# always_ready, result = P1A1 #-} hyperbus_cs0_n :: Bit 1 {-# always_ready, result = P1A2 #-} hyperbus_ck :: Bit 1 {-# always_ready, result = P1A3 #-} hyperbus_ck_n :: Bit 1 {-# always_ready, result = P1A4 #-} hyperbus_cs3_n :: Bit 1 {-# always_ready, result = P1A7 #-} hyperbus_cs1_n :: Bit 1 {-# always_ready, result = P1A8 #-} hyperbus_reset_n :: Bit 1 {-# always_ready, result = P1A9 #-} hyperbus_rwds :: Inout (Bit 1) {-# prefix = P1A10 #-} -- HyperBus 2 (PMOD 1B) hyperbus_dq0 :: Inout (Bit 1) {-# prefix = P1B1 #-} hyperbus_dq1 :: Inout (Bit 1) {-# prefix = P1B2 #-} hyperbus_dq2 :: Inout (Bit 1) {-# prefix = P1B3 #-} hyperbus_dq3 :: Inout (Bit 1) {-# prefix = P1B4 #-} hyperbus_dq7 :: Inout (Bit 1) {-# prefix = P1B7 #-} hyperbus_dq6 :: Inout (Bit 1) {-# prefix = P1B8 #-} hyperbus_dq5 :: Inout (Bit 1) {-# prefix = P1B9 #-} hyperbus_dq4 :: Inout (Bit 1) {-# prefix = P1B10 #-} -- Serial buses (PMOD 2) ch559_uart_rx :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [P2_1] #-} ch559_uart_tx :: Bit 1 {-# always_ready, result = P2_2 #-} inkplate_uart_rx :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [P2_3] #-} inkplate_uart_tx :: Bit 1 {-# always_ready, result = P2_4 #-} todo_btn :: Bit 1 -> Action {-# always_enabled, always_ready, prefix = "", arg_names = [P2_7] #-} todo_led :: Bit 1 {-# always_ready, result = P2_8 #-} i2c_scl :: Inout (Bit 1) {-# prefix = P2_9 #-} i2c_sda :: Inout (Bit 1) {-# prefix = P2_10 #-} 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 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 -- Wire up the tristates. rules "update_hyperbus_rwds_out": when True ==> do case numini.hyperbus_rwds_out of Just bits -> do hyperbus_rwds_enable := True hyperbus_rwds_out := bits Nothing -> 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 case numini.hyperbus_dq_out of Just bits -> do hyperbus_dq_enable := True hyperbus_dq_out := bits Nothing -> 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 numini.i2c_scl_out "update_i2c_scl_in": when True ==> do i2c_scl_in := i2c_scl._read "update_i2c_sda_out": when True ==> do i2c_sda_enable := unpack numini.i2c_sda_out "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 = numini.usb_uart_tx -- Onboard LEDs led_r_n = numini.led_r_n led_g_n = numini.led_g_n -- RGB LED driver rgb_r_n = numini.rgb_r_n rgb_g_n = numini.rgb_g_n rgb_b_n = numini.rgb_b_n -- HyperBus 1 (PMOD 1A) hyperbus_cs2_n = numini.hyperbus_cs2_n hyperbus_cs0_n = numini.hyperbus_cs0_n hyperbus_ck = numini.hyperbus_ck hyperbus_ck_n = numini.hyperbus_ck_n hyperbus_cs3_n = numini.hyperbus_cs3_n hyperbus_cs1_n = numini.hyperbus_cs1_n hyperbus_reset_n = numini.hyperbus_reset_n 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 = numini.ch559_uart_tx inkplate_uart_rx bit = inkplate_uart_rx := bit inkplate_uart_tx = numini.inkplate_uart_tx todo_btn _ = noAction todo_led = 0 i2c_scl = i2c_scl.io i2c_sda = i2c_sda.io {-# verilog mkTop #-} {-# properties mkTop = { RSTN = BTN_N } #-} -} -- vim: set ft=haskell :