In spite of many errors that still need fixing, this is a major advance
over the previous commit. All verilog modules are in place more or less
as intended, with various functions such as the housekeeping SPI placed
on user area pads, with the ability to switch to user control from the
configuration. The pad control bits are local to the pads and loaded
via serial shift register, so that there are not hundreds of control wires
feeding into the user space. The user has three basic controls over each
pad: in, out, and outenb. Two timer/counters and an SPI master have been
added to the SoC. The SPI master shares I/O with the housekeeping SPI, so
that all housekeeping SPI registers can be accessed from the SoC directly.
diff --git a/verilog/dv/caravel/defs.h b/verilog/dv/caravel/defs.h
index 68ef6b0..559151d 100644
--- a/verilog/dv/caravel/defs.h
+++ b/verilog/dv/caravel/defs.h
@@ -34,59 +34,67 @@
#define reg_la3_ena (*(volatile uint32_t*)0x2200001c)
// Mega Project Control (0x2300_0000)
-#define reg_mprj_io_0 (*(volatile uint32_t*)0x23000000)
-#define reg_mprj_io_1 (*(volatile uint32_t*)0x23000004)
-#define reg_mprj_io_2 (*(volatile uint32_t*)0x23000008)
-#define reg_mprj_io_3 (*(volatile uint32_t*)0x2300000c)
-#define reg_mprj_io_4 (*(volatile uint32_t*)0x23000010)
-#define reg_mprj_io_5 (*(volatile uint32_t*)0x23000014)
-#define reg_mprj_io_6 (*(volatile uint32_t*)0x23000018)
+#define reg_mprj_data (*(volatile uint32_t*)0x23000000)
+#define reg_mprj_xfer (*(volatile uint32_t*)0x23000004)
-#define reg_mprj_io_7 (*(volatile uint32_t*)0x2300001c)
-#define reg_mprj_io_8 (*(volatile uint32_t*)0x23000020)
-#define reg_mprj_io_9 (*(volatile uint32_t*)0x23000024)
-#define reg_mprj_io_10 (*(volatile uint32_t*)0x23000028)
+#define reg_mprj_io_0 (*(volatile uint32_t*)0x23000008)
+#define reg_mprj_io_1 (*(volatile uint32_t*)0x2300000c)
+#define reg_mprj_io_2 (*(volatile uint32_t*)0x23000010)
+#define reg_mprj_io_3 (*(volatile uint32_t*)0x23000014)
+#define reg_mprj_io_4 (*(volatile uint32_t*)0x23000018)
+#define reg_mprj_io_5 (*(volatile uint32_t*)0x2300001c)
+#define reg_mprj_io_6 (*(volatile uint32_t*)0x23000020)
-#define reg_mprj_io_11 (*(volatile uint32_t*)0x2300002c)
-#define reg_mprj_io_12 (*(volatile uint32_t*)0x23000030)
-#define reg_mprj_io_13 (*(volatile uint32_t*)0x23000034)
-#define reg_mprj_io_14 (*(volatile uint32_t*)0x23000038)
+#define reg_mprj_io_7 (*(volatile uint32_t*)0x23000024)
+#define reg_mprj_io_8 (*(volatile uint32_t*)0x23000028)
+#define reg_mprj_io_9 (*(volatile uint32_t*)0x2300002c)
+#define reg_mprj_io_10 (*(volatile uint32_t*)0x23000030)
-#define reg_mprj_io_15 (*(volatile uint32_t*)0x2300003c)
-#define reg_mprj_io_16 (*(volatile uint32_t*)0x23000040)
-#define reg_mprj_io_17 (*(volatile uint32_t*)0x23000044)
-#define reg_mprj_io_18 (*(volatile uint32_t*)0x23000048)
+#define reg_mprj_io_11 (*(volatile uint32_t*)0x23000034)
+#define reg_mprj_io_12 (*(volatile uint32_t*)0x23000038)
+#define reg_mprj_io_13 (*(volatile uint32_t*)0x2300003c)
+#define reg_mprj_io_14 (*(volatile uint32_t*)0x23000040)
-#define reg_mprj_io_19 (*(volatile uint32_t*)0x2300004c)
-#define reg_mprj_io_20 (*(volatile uint32_t*)0x23000050)
-#define reg_mprj_io_21 (*(volatile uint32_t*)0x23000054)
-#define reg_mprj_io_22 (*(volatile uint32_t*)0x23000058)
+#define reg_mprj_io_15 (*(volatile uint32_t*)0x23000044)
+#define reg_mprj_io_16 (*(volatile uint32_t*)0x23000048)
+#define reg_mprj_io_17 (*(volatile uint32_t*)0x2300004c)
+#define reg_mprj_io_18 (*(volatile uint32_t*)0x23000050)
-#define reg_mprj_io_23 (*(volatile uint32_t*)0x2300005c)
-#define reg_mprj_io_24 (*(volatile uint32_t*)0x23000060)
-#define reg_mprj_io_25 (*(volatile uint32_t*)0x23000064)
-#define reg_mprj_io_26 (*(volatile uint32_t*)0x23000068)
+#define reg_mprj_io_19 (*(volatile uint32_t*)0x23000054)
+#define reg_mprj_io_20 (*(volatile uint32_t*)0x23000058)
+#define reg_mprj_io_21 (*(volatile uint32_t*)0x2300005c)
+#define reg_mprj_io_22 (*(volatile uint32_t*)0x23000060)
-#define reg_mprj_io_27 (*(volatile uint32_t*)0x2300006c)
-#define reg_mprj_io_28 (*(volatile uint32_t*)0x23000070)
-#define reg_mprj_io_29 (*(volatile uint32_t*)0x23000074)
-#define reg_mprj_io_30 (*(volatile uint32_t*)0x23000078)
-#define reg_mprj_io_31 (*(volatile uint32_t*)0x2300007c)
+#define reg_mprj_io_23 (*(volatile uint32_t*)0x23000064)
+#define reg_mprj_io_24 (*(volatile uint32_t*)0x23000068)
+#define reg_mprj_io_25 (*(volatile uint32_t*)0x2300006c)
+#define reg_mprj_io_26 (*(volatile uint32_t*)0x23000070)
+
+#define reg_mprj_io_27 (*(volatile uint32_t*)0x23000074)
+#define reg_mprj_io_28 (*(volatile uint32_t*)0x23000078)
+#define reg_mprj_io_29 (*(volatile uint32_t*)0x2300007c)
+#define reg_mprj_io_30 (*(volatile uint32_t*)0x23000080)
+#define reg_mprj_io_31 (*(volatile uint32_t*)0x23000084)
// Mega Project Slaves (0x3000_0000)
#define reg_mprj_slave (*(volatile uint32_t*)0x30000000)
// Flash Control SPI Configuration (2D00_0000)
-#define reg_spictrl (*(volatile uint32_t*)0x2D000000)
+#define reg_spictrl (*(volatile uint32_t*)0x2d000000)
-// House-Keeping SPI Read-Only Registers (0x2E00_0000)
-#define reg_spi_config (*(volatile uint32_t*)0x2E000000)
-#define reg_spi_enables (*(volatile uint32_t*)0x2E000004)
-#define reg_spi_pll_config (*(volatile uint32_t*)0x2E000008)
-#define reg_spi_mfgr_id (*(volatile uint32_t*)0x2E00000c)
-#define reg_spi_prod_id (*(volatile uint32_t*)0x2E000010)
-#define reg_spi_mask_rev (*(volatile uint32_t*)0x2E000014)
-#define reg_spi_pll_bypass (*(volatile uint32_t*)0x2E000018)
+// Counter-Timer 0 Configuration
+#define reg_timer0_config (*(volatile uint32_t*)0x21100000)
+#define reg_timer0_value (*(volatile uint32_t*)0x21100004)
+#define reg_timer0_data (*(volatile uint32_t*)0x21100008)
+
+// Counter-Timer 1 Configuration
+#define reg_timer1_config (*(volatile uint32_t*)0x21200000)
+#define reg_timer1_value (*(volatile uint32_t*)0x21200004)
+#define reg_timer1_data (*(volatile uint32_t*)0x21200008)
+
+// SPI Master Configuration
+#define reg_spimaster_config (*(volatile uint32_t*)0x21300000)
+#define reg_spimaster_data (*(volatile uint32_t*)0x21300004)
// System Area (0x2F00_0000)
#define reg_pll_out_dest (*(volatile uint32_t*)0x2F00000c)
@@ -94,11 +102,22 @@
#define reg_irq7_source (*(volatile uint32_t*)0x2F000014)
#define reg_irq8_source (*(volatile uint32_t*)0x2F000018)
-// Crosbbar Slave Addresses (0x8000_0000 - 0xB000_0000)
+// Crossbar Slave Addresses (0x8000_0000 - 0xB000_0000)
#define qspi_ctrl_slave (*(volatile uint32_t*)0x80000000)
#define storage_area_slave (*(volatile uint32_t*)0x90000000)
#define mega_any_slave1 (*(volatile uint32_t*)0xA0000000)
#define mega_any_slave2 (*(volatile uint32_t*)0xB0000000)
+// Useful GPIO mode values
+#define GPIO_MODE_MGMT_STD_INPUT_NOPULL 0x0403
+#define GPIO_MODE_MGMT_STD_INPUT_PULLDOWN 0x0803
+#define GPIO_MODE_MGMT_STD_INPUT_PULLUP 0x0c03
+#define GPIO_MODE_MGMT_STD_OUTPUT 0x1801
+
+#define GPIO_MODE_USER_STD_INPUT_NOPULL 0x0402
+#define GPIO_MODE_USER_STD_INPUT_PULLDOWN 0x0802
+#define GPIO_MODE_USER_STD_INPUT_PULLUP 0x0c02
+#define GPIO_MODE_USER_STD_OUTPUT 0x1800
+
// --------------------------------------------------------
#endif
diff --git a/verilog/dv/caravel/mgmt_soc/gpio/README b/verilog/dv/caravel/mgmt_soc/gpio/README
new file mode 100644
index 0000000..f1935dd
--- /dev/null
+++ b/verilog/dv/caravel/mgmt_soc/gpio/README
@@ -0,0 +1,27 @@
+------------------------------------------------
+Caravel
+gpio testbench
+------------------------------------------------
+
+This testbench exercises the fundamental use of the Caravel
+management SoC to drive the I/O in the user area as general
+purpose I/O on startup.
+
+On startup, all GPIO are configured as input to the management
+region (so as to be high impedence to the external world) and
+decoupled from the user project area.
+
+To configure any GPIO as output, the appropriate memory-mapped
+location for the I/O must be properly configured. Since the
+I/O configuration is stored in two places, in the SoC, but
+also locally at each I/O pad, the "transfer" bit must be
+applied, which initiates a transfer of the configuration data
+around the padframe.
+
+The testbench takes 16 pins from the user area and checks
+functionality by applying input values on 8 of these pins from
+the testbench verilog, detecting them in the C program, then
+copying the values to the other 8 pins, and detecting those
+values in the testbench verilog.
+
+If any of that does not work, then the testbench will fail.
diff --git a/verilog/dv/caravel/mgmt_soc/gpio/gpio.c b/verilog/dv/caravel/mgmt_soc/gpio/gpio.c
index 4dbacc6..bd6a17c 100644
--- a/verilog/dv/caravel/mgmt_soc/gpio/gpio.c
+++ b/verilog/dv/caravel/mgmt_soc/gpio/gpio.c
@@ -3,37 +3,96 @@
// --------------------------------------------------------
/*
- GPIO Test
- Tests PU and PD on the lower 2 pins while being driven from outside
- Tests Writing to the upper 2 pins
- Tests reading from the lower 2 pins
-*/
+ * GPIO Test
+ * Tests PU and PD on the lower 8 pins while being driven from outside
+ * Tests Writing to the upper 8 pins
+ * Tests reading from the lower 8 pins
+ */
+
void main()
{
int i;
- /* Lower 2 pins are input and upper 2 pins are o/p */
- reg_gpio_data = 0;
- reg_gpio_ena = 0x0003;
+ /* Set data out to zero */
+ reg_mprj_data = 0;
+
+ /* Lower 8 pins are input and upper 8 pins are output */
+ reg_mprj_io_31 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_30 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_29 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_28 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_27 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_26 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_25 = GPIO_MODE_MGMT_STD_OUTPUT;
+ reg_mprj_io_24 = GPIO_MODE_MGMT_STD_OUTPUT;
+
+ reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+ reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_NOPULL;
+
+ /* Apply configuration */
+ reg_mprj_xfer = 1;
+ reg_mprj_xfer = 0;
// change the pull up and pull down (checked by the TB)
- reg_gpio_data = 0x0100;
- reg_gpio_pu = 0x0001;
- reg_gpio_pd = 0x0002;
+ reg_mprj_data = 0xa0000000;
- reg_gpio_data = 0x0300;
- reg_gpio_pu = 0x0002;
- reg_gpio_pd = 0x0001;
+ reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
- reg_gpio_pu = 0x0001;
- reg_gpio_pd = 0x0002;
+ reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
- // read the lower 2 pins, add 1 then o/p the result
+ /* Apply configuration */
+ reg_mprj_xfer = 1;
+ reg_mprj_xfer = 0;
+
+ reg_mprj_data = 0x0b000000;
+
+ reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+
+ reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+
+ /* Apply configuration */
+ reg_mprj_xfer = 1;
+ reg_mprj_xfer = 0;
+
+ reg_mprj_io_23 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_22 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_21 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+ reg_mprj_io_20 = GPIO_MODE_MGMT_STD_INPUT_PULLDOWN;
+
+ reg_mprj_io_19 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_18 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_17 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+ reg_mprj_io_16 = GPIO_MODE_MGMT_STD_INPUT_PULLUP;
+
+ /* Apply configuration */
+ reg_mprj_xfer = 1;
+ reg_mprj_xfer = 0;
+
+ // read the lower 8 pins, add 1 then o/p the result
// checked by the TB
- reg_gpio_data = 0x0100;
+ reg_mprj_data = 0xab000000;
+
while (1){
- int x = reg_gpio_data & 0x03;
- reg_gpio_data = (x+1) << 8;
+ int x = reg_mprj_data & 0xff0000;
+ reg_mprj_data = (x+1) << 24;
}
}
diff --git a/verilog/dv/caravel/mgmt_soc/gpio/gpio.hex b/verilog/dv/caravel/mgmt_soc/gpio/gpio.hex
index 667a214..adcdbdd 100755
--- a/verilog/dv/caravel/mgmt_soc/gpio/gpio.hex
+++ b/verilog/dv/caravel/mgmt_soc/gpio/gpio.hex
@@ -6,7 +6,7 @@
13 09 00 00 93 09 00 00 13 0A 00 00 93 0A 00 00
13 0B 00 00 93 0B 00 00 13 0C 00 00 93 0C 00 00
13 0D 00 00 93 0D 00 00 13 0E 00 00 93 0E 00 00
-13 0F 00 00 93 0F 00 00 17 05 00 00 13 05 45 16
+13 0F 00 00 93 0F 00 00 17 05 00 00 13 05 45 3E
93 05 00 00 13 06 00 00 63 D8 C5 00 14 41 94 C1
11 05 91 05 E3 CC C5 FE 13 05 00 00 93 05 00 00
63 57 B5 00 23 20 05 00 11 05 E3 4D B5 FE 71 28
@@ -20,12 +20,52 @@
23 20 75 00 11 05 83 23 05 00 FD 1F E3 96 0F FC
FD 15 F1 F1 63 04 0F 00 23 20 75 00 13 03 00 08
A3 81 62 00 82 80 01 00 00 00 01 11 22 CE 00 10
-B7 07 00 21 23 A0 07 00 B7 07 00 21 91 07 0D 47
-98 C3 B7 07 00 21 13 07 00 10 98 C3 B7 07 00 21
-A1 07 05 47 98 C3 B7 07 00 21 B1 07 09 47 98 C3
-B7 07 00 21 13 07 00 30 98 C3 B7 07 00 21 A1 07
-09 47 98 C3 B7 07 00 21 B1 07 05 47 98 C3 B7 07
-00 21 A1 07 05 47 98 C3 B7 07 00 21 B1 07 09 47
-98 C3 B7 07 00 21 13 07 00 10 98 C3 B7 07 00 21
-9C 43 8D 8B 23 26 F4 FE 83 27 C4 FE 85 07 13 97
-87 00 B7 07 00 21 98 C3 D5 B7 00 00
+B7 07 00 23 23 A0 07 00 B7 07 00 23 93 87 47 08
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 07 08
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 C7 07
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 87 07
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 47 07
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 07 07
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 C7 06
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 87 06
+09 67 13 07 17 80 98 C3 B7 07 00 23 93 87 47 06
+13 07 30 40 98 C3 B7 07 00 23 93 87 07 06 13 07
+30 40 98 C3 B7 07 00 23 93 87 C7 05 13 07 30 40
+98 C3 B7 07 00 23 93 87 87 05 13 07 30 40 98 C3
+B7 07 00 23 93 87 47 05 13 07 30 40 98 C3 B7 07
+00 23 93 87 07 05 13 07 30 40 98 C3 B7 07 00 23
+93 87 C7 04 13 07 30 40 98 C3 B7 07 00 23 93 87
+87 04 13 07 30 40 98 C3 B7 07 00 23 91 07 05 47
+98 C3 B7 07 00 23 91 07 23 A0 07 00 B7 07 00 23
+37 07 00 A0 98 C3 B7 07 00 23 93 87 47 06 05 67
+13 07 37 80 98 C3 B7 07 00 23 93 87 07 06 05 67
+13 07 37 80 98 C3 B7 07 00 23 93 87 C7 05 05 67
+13 07 37 80 98 C3 B7 07 00 23 93 87 87 05 05 67
+13 07 37 80 98 C3 B7 07 00 23 93 87 47 05 05 67
+13 07 37 C0 98 C3 B7 07 00 23 93 87 07 05 05 67
+13 07 37 C0 98 C3 B7 07 00 23 93 87 C7 04 05 67
+13 07 37 C0 98 C3 B7 07 00 23 93 87 87 04 05 67
+13 07 37 C0 98 C3 B7 07 00 23 91 07 05 47 98 C3
+B7 07 00 23 91 07 23 A0 07 00 B7 07 00 23 37 07
+00 0B 98 C3 B7 07 00 23 93 87 47 06 05 67 13 07
+37 C0 98 C3 B7 07 00 23 93 87 07 06 05 67 13 07
+37 C0 98 C3 B7 07 00 23 93 87 C7 05 05 67 13 07
+37 C0 98 C3 B7 07 00 23 93 87 87 05 05 67 13 07
+37 C0 98 C3 B7 07 00 23 93 87 47 05 05 67 13 07
+37 80 98 C3 B7 07 00 23 93 87 07 05 05 67 13 07
+37 80 98 C3 B7 07 00 23 93 87 C7 04 05 67 13 07
+37 80 98 C3 B7 07 00 23 93 87 87 04 05 67 13 07
+37 80 98 C3 B7 07 00 23 91 07 05 47 98 C3 B7 07
+00 23 91 07 23 A0 07 00 B7 07 00 23 93 87 47 06
+05 67 13 07 37 80 98 C3 B7 07 00 23 93 87 07 06
+05 67 13 07 37 80 98 C3 B7 07 00 23 93 87 C7 05
+05 67 13 07 37 80 98 C3 B7 07 00 23 93 87 87 05
+05 67 13 07 37 80 98 C3 B7 07 00 23 93 87 47 05
+05 67 13 07 37 C0 98 C3 B7 07 00 23 93 87 07 05
+05 67 13 07 37 C0 98 C3 B7 07 00 23 93 87 C7 04
+05 67 13 07 37 C0 98 C3 B7 07 00 23 93 87 87 04
+05 67 13 07 37 C0 98 C3 B7 07 00 23 91 07 05 47
+98 C3 B7 07 00 23 91 07 23 A0 07 00 B7 07 00 23
+37 07 00 AB 98 C3 B7 07 00 23 9C 43 3E 87 B7 07
+FF 00 F9 8F 23 26 F4 FE 83 27 C4 FE 85 07 13 97
+87 01 B7 07 00 23 98 C3 F9 BF 00 00
diff --git a/verilog/dv/caravel/mgmt_soc/gpio/gpio_tb.v b/verilog/dv/caravel/mgmt_soc/gpio/gpio_tb.v
index f823737..56781da 100644
--- a/verilog/dv/caravel/mgmt_soc/gpio/gpio_tb.v
+++ b/verilog/dv/caravel/mgmt_soc/gpio/gpio_tb.v
@@ -32,7 +32,7 @@
always #10 clock <= (clock === 1'b0);
initial begin
- clock = 0;
+ clock <= 0;
end
initial begin
@@ -64,7 +64,8 @@
wire flash_io1;
reg RSTB;
- wire CSB, SCK, SDI, SDO;
+ reg CSB, SCK, SDI;
+ wire SDO;
// Transactor
initial begin
@@ -99,6 +100,9 @@
end
initial begin
+ CSB <= 1'b1;
+ SCK <= 1'b0;
+ SDI <= 1'b0;
RSTB <= 1'b0;
#1000;
@@ -133,6 +137,9 @@
// apply {27'bz, SCK, CSB, SDI, SDO, 1'bz} to mprj_io (32 bits)
wire [11:0] noconnect;
+ wire [2:0] spi_sigs;
+
+ assign spi_sigs = 3'b010;
caravel uut (
.vdd3v3 (VDD3V3),
@@ -141,7 +148,8 @@
.clock (clock),
.gpio (gpio),
.mprj_io ({checkbits, noconnect[11:1],
- SCK, CSB, SDI, SDO, noconnect[0]}),
+ // SCK, CSB, SDI, SDO, noconnect[0]}),
+ spi_sigs, SDO, noconnect[0]}),
.flash_csb(flash_csb),
.flash_clk(flash_clk),
.flash_io0(flash_io0),
diff --git a/verilog/rtl/README b/verilog/rtl/README
new file mode 100644
index 0000000..ec44791
--- /dev/null
+++ b/verilog/rtl/README
@@ -0,0 +1,183 @@
+A quick documentation of the Caravel memory map and operation
+---------------------------------------------------------------
+
+Caravel pinout:
+---------------
+
+ vdd3v3
+ vdd1v8
+ vss
+ gpio 1 bit, mainly used for external LDO control of user power supply
+ clock Master clock input
+ resetb Master reset (sense inverted) input
+ flash_csb SPI flash controller chip select (sense inverted)
+ flash_clk SPI flash controller clock
+ flash_io0 SPI flash controller data out
+ flash_io1 SPI flash controller data in
+ mprj_io 32 bits general purpose programmable digital or analog I/O
+
+Special-use pins for the management SoC:
+----------------------------------------
+
+ On power-up, the "mprj_io" GPIO are under complete control of the managment
+ SoC. The first 8 user GPIO are special-purpose pads with dedicated functions
+ for the management SoC:
+
+ mprj_io[0] JTAG I/O
+ mprj_io[1] SDO, housekeeping SPI
+ mprj_io[2] SDI, housekeeping SPI
+ mprj_io[3] CSB, housekeeping SPI
+ mprj_io[4] SCK, housekeeping SPI
+ mprj_io[5] Rx, UART
+ mprj_io[6] Tx, UART
+ mrpj_io[7] IRQ
+
+ The next 4 user GPIO are designed to be used with an SPI flash controller in
+ the user space. They allow the four pins to be overridden by the housekeeping
+ SPI to access the SPI flash in pass-through mode.
+
+ mprj_io[8] user flash CSB
+ mprj_io[9] user flash SCK
+ mprj_io[10] user flash IO0
+ mprj_io[11] user flash IO1
+
+ The user may additionally use any available GPIO for the SPI flash IO2 and IO3
+ lines; the pass-through mode only uses the basic 4-pin SPI mode.
+
+ All of the special-use pins are configured through a memory-mapped region. But
+ to avoid a large number of wires in the user space to reach all of the GPIO
+ pad controls, each user GPIO pad has a corresponding local control block. The
+ control block holds the configuration data for the corresponding pad. This
+ configuration data is a mirror of the data in the memory-mapped region, and is
+ loaded by a "transfer" bit in another memory-mapped register. In addition to
+ all of the static control bits for the GPIO, each block contains a single bit
+ that specifies whether that pad is under the control of the user or the management
+ area. All pins are configured from the management area. However, the configuration
+ of static control bits leaves three dynamic signals: input, output, and output
+ enable. One set of these three signals is available to the user when the pad is
+ under user control. The other set of these three signals is available to the
+ management SoC. Again, to reduce wiring, only the two pads for JTAG and the
+ housekeeping SDO have all three pins under control of the SoC; the remaining
+ pads have a single wire to the management SoC which is either an input wire
+ or an output wire, depending on how the control signals for the pad are set.
+
+ This setup gives a simplified view of the pad to the user: For digital
+ applications, the user can treat the pad as a simple bidirectional digital
+ pad with an output enable to switch between output and input functions.
+ The user can set the output enable line high or low for a static input or
+ output function. The user will also have access to the ESD-protected
+ pad connections for analog signals, and can connect to the VDDA domain
+ input digital signal if needed.
+
+Memory map:
+-----------
+
+ The Caravel memory map is as follows:
+
+ SRAM: 0000 0000
+
+ Flash: Config: 1000 0000
+
+ UART: Clock divider: 2000 0000
+ Data: 2000 0004
+
+ GPIO: Data: 2100 0000
+ Output enable: 2100 0004
+ Pullup 2100 0008
+ Pulldown 2100 000c
+
+ Counter 1: Config: 2110 0000
+ Value: 2110 0004
+ Data: 2110 0008
+
+ Counter 2: Config: 2120 0000
+ Value: 2120 0004
+ Data: 2120 0008
+
+ SPI master: Config: 2130 0000
+ Data: 2130 0004
+
+ Logic analyzer: Data 0: 2200 0000
+ Data 1: 2200 0004
+ Data 2: 2200 0008
+ Data 3: 2200 000c
+ Enable 0: 2200 0010
+ Enable 1: 2200 0014
+ Enable 2: 2200 0018
+ Enable 3: 2200 001c
+
+ Project ctrl: Data: 2300 0000
+ Transfer: 2300 0004
+ I/O Config: 2300 0008
+ to 2300 0084
+ Power Config: 2300 0088
+ to 2300 0104
+
+ Flash ctrl: Config: 2D00 0000
+
+ System: PLL out: 2F00 0000
+ Trap out: 2F00 0004
+ IRQ7 source: 2F00 0008
+
+ User area base: 3000 0000
+
+ Crossbar: QSPI control 8000 0000
+ Storage area 9000 0000
+ Any slave 1 a000 0000
+ Any slave 2 b000 0000
+
+Project I/O Control:
+---------------------
+
+ Configuration bits per I/O (13 bits for each GPIO pad):
+ Global Default
+ Bits 12-10: digital mode (3 bits) 001
+ Bit 9: voltage trip point select 0
+ Bit 8: slow slew select 0
+ Bit 7: analog bus polarity 0
+ Bit 6: analog bus select 0
+ Bit 5: analog bus enable 0
+ Bit 4: IB mode select 0
+ Bit 3: input disable 0
+ Bit 2: holdover value 0
+ Bit 1: output disable 1
+ Bit 0: management control enable 1
+
+Default I/O modes:
+------------------
+ mprj_io[0] JTAG I/O 110 0 0 0 0 0 0 0 0 0 1
+ mprj_io[1] SDO, housekeeping SPI 110 0 0 0 0 0 0 0 0 0 1
+ all others: 001 0 0 0 0 0 0 0 0 1 1
+
+
+ Standard GPIO output configuration:
+ mprj_io[6] Tx, UART 110 0 0 0 0 0 0 0 0 0 1
+
+ Standard GPIO input configuration:
+ mprj_io[*] 001 0 0 0 0 0 0 0 0 1 1
+
+ Standard GPIO input configuration with pullup:
+ mprj_io[*] 010 0 0 0 0 0 0 0 0 1 1
+
+ Standard GPIO input configuration with pulldown:
+ mprj_io[*] 011 0 0 0 0 0 0 0 0 1 1
+
+ Specifically:
+ JTAG and SDO are set to output. The output enable configure bit
+ is a don't-care, since the output enable line is directly controlled
+ by the module (JTAG or housekeeping SPI, respectively).
+
+ All other I/O are set as input mode only, with output disabled.
+
+ Tx is set to input like the others; before enabling the UART
+ from a program in flash, the I/O must be set to an output configuration.
+
+ Note that the standard input configurations with pull-up and pull-down
+ require that "out" be set 1 or 0, respectively; since the I/O are
+ designed with minimal wiring, there is only one wire for input and
+ output, so the wire is used for input in these cases, and special
+ signal handling is done locally to set the value of "out" equal to
+ ~dm[0]. This is a (minor) restriction on the available I/O modes.
+
+ Other possible modes are open-drain (for I2C), weak drive strength
+ output (5k up + down), and analog mode (digital disabled)
diff --git a/verilog/rtl/caravel.v b/verilog/rtl/caravel.v
index abcbd8a..492712e 100644
--- a/verilog/rtl/caravel.v
+++ b/verilog/rtl/caravel.v
@@ -38,7 +38,7 @@
`include "/home/tim/projects/efabless/tech/SW/sky130A/libs.ref/sky130_fd_sc_hvl/verilog/sky130_fd_sc_hvl.v"
`include "mgmt_soc.v"
-`include "caravel_spi.v"
+`include "housekeeping_spi.v"
`include "digital_pll.v"
`include "caravel_clkrst.v"
`include "mprj_counter.v"
@@ -47,6 +47,7 @@
`include "chip_io.v"
`include "user_id_programming.v"
`include "gpio_control_block.v"
+`include "gpio_control_block2.v"
`ifdef USE_OPENRAM
`include "sram_1rw1r_32_8192_8_sky130.v"
@@ -102,10 +103,10 @@
// can be accessed through the SPI slave even when the processor is in
// reset.
- // flash_csb = mprj_io[8]
- // flash_sck = mprj_io[9]
- // flash_io0 = mprj_io[10]
- // flash_io1 = mprj_io[11]
+ // user_flash_csb = mprj_io[8]
+ // user_flash_sck = mprj_io[9]
+ // user_flash_io0 = mprj_io[10]
+ // user_flash_io1 = mprj_io[11]
// One-bit GPIO dedicated to management SoC (outside of user control)
wire gpio_out_core;
@@ -116,7 +117,6 @@
wire gpio_inenb_core;
// Mega-Project Control (pad-facing)
- wire [`MPRJ_IO_PADS-1:0] mgmt_io_data;
wire mprj_io_loader_resetn;
wire mprj_io_loader_clock;
wire mprj_io_loader_data;
@@ -124,7 +124,7 @@
wire [`MPRJ_IO_PADS-1:0] mprj_io_hldh_n;
wire [`MPRJ_IO_PADS-1:0] mprj_io_enh;
wire [`MPRJ_IO_PADS-1:0] mprj_io_inp_dis;
- wire [`MPRJ_IO_PADS-1:0] mprj_io_oeb_n;
+ wire [`MPRJ_IO_PADS-1:0] mprj_io_oeb;
wire [`MPRJ_IO_PADS-1:0] mprj_io_ib_mode_sel;
wire [`MPRJ_IO_PADS-1:0] mprj_io_vtrip_sel;
wire [`MPRJ_IO_PADS-1:0] mprj_io_slow_sel;
@@ -137,7 +137,7 @@
wire [`MPRJ_IO_PADS-1:0] mprj_io_out;
// Mega-Project Control (user-facing)
- wire [`MPRJ_IO_PADS-1:0] user_io_oeb_n;
+ wire [`MPRJ_IO_PADS-1:0] user_io_oeb;
wire [`MPRJ_IO_PADS-1:0] user_io_in;
wire [`MPRJ_IO_PADS-1:0] user_io_out;
@@ -146,6 +146,29 @@
wire mgmt_serial_clock;
wire mgmt_serial_resetn;
+ // Mega-Project Control management I/O
+ // There are two types of GPIO connections:
+ // (1) Full Bidirectional: Management connects to in, out, and oeb
+ // Uses: JTAG and SDO
+ // (2) Selectable bidirectional: Management connects to in and out,
+ // which are tied together. oeb is grounded (oeb from the
+ // configuration is used)
+
+ // SDI = mprj_io[2] (input)
+ // CSB = mprj_io[3] (input)
+ // SCK = mprj_io[4] (input)
+ // ser_rx = mprj_io[5] (input)
+ // ser_tx = mprj_io[6] (output)
+ // irq = mprj_io[7] (input)
+
+ wire [`MPRJ_IO_PADS-1:0] mgmt_io_in;
+ wire jtag_out, sdo_out;
+ wire jtag_outenb, sdo_outenb;
+
+ wire [`MPRJ_IO_PADS-3:0] mgmt_io_nc1; /* no-connects */
+ wire [`MPRJ_IO_PADS-3:0] mgmt_io_nc3; /* no-connects */
+ wire [1:0] mgmt_io_nc2; /* no-connects */
+
// Power-on-reset signal. The reset pad generates the sense-inverted
// reset at 3.3V. The 1.8V signal and the inverted 1.8V signal are
// derived.
@@ -153,6 +176,12 @@
wire porb_h;
wire porb_l;
+ // To be considered: Master hold signal on all user pads (?)
+ // For now, set holdh_n to 1 (NOTE: This is in the 3.3V domain)
+ // and setting enh to porb_h.
+ assign mprj_io_hldh_n = {`MPRJ_IO_PADS{vdd3v3}};
+ assign mprj_io_enh = {`MPRJ_IO_PADS{porb_h}};
+
chip_io padframe(
// Package Pins
.vdd3v3(vdd3v3),
@@ -189,10 +218,10 @@
.flash_io1_do_core(flash_io1_do_core),
.flash_io0_di_core(flash_io0_di_core),
.flash_io1_di_core(flash_io1_di_core),
- .pll_clk16(pll_clk16),
+ .por(~porb_l),
.mprj_io_in(mprj_io_in),
.mprj_io_out(mprj_io_out),
- .mprj_io_oeb_n(mprj_io_oeb_n),
+ .mprj_io_oeb(mprj_io_oeb),
.mprj_io_hldh_n(mprj_io_hldh_n),
.mprj_io_enh(mprj_io_enh),
.mprj_io_inp_dis(mprj_io_inp_dis),
@@ -284,7 +313,10 @@
.mprj_io_loader_resetn(mprj_io_loader_resetn),
.mprj_io_loader_clock(mprj_io_loader_clock),
.mprj_io_loader_data(mprj_io_loader_data),
- .mgmt_io_data(mgmt_io_data),
+ .mgmt_in_data(mgmt_io_in),
+ .mgmt_out_data({mgmt_io_nc1, sdo_out, jtag_out}),
+ .mgmt_outz_data({mgmt_io_in[(`MPRJ_IO_PADS-1):2], mgmt_io_nc2}),
+ .mgmt_oeb_data({mgmt_io_nc3, sdo_outenb, jtag_outenb}),
// Mega Project Slave ports (WB MI A)
.mprj_cyc_o(mprj_cyc_o_core),
.mprj_stb_o(mprj_stb_o_core),
@@ -338,13 +370,26 @@
assign gpio_serial_link_shifted = {mprj_io_loader_data, gpio_serial_link[`MPRJ_IO_PADS-1:1]};
- gpio_control_block gpio_control_inst [`MPRJ_IO_PADS-1:0] (
+ // NOTE: The intention is to replace most of gpio_control_block2
+ // (3 management wires per pad) with gpio_control_block (1 management
+ // wire per pad). However, the inout line on gpio_control_block is
+ // troublesome and so I am starting with the simpler interface. Ultimately
+ // the JTAG and SDO lines will keep the 3-pin interface and these pads will
+ // be located closest to the management area.
+
+ gpio_control_block2 #(
+ .DM_INIT(3'b010), // Test: All pads set to pull-up
+ .OENB_INIT(1'b0) // Test: All pads set to pull-up
+ ) gpio_control_inst [`MPRJ_IO_PADS-1:0] (
+
// Management Soc-facing signals
.resetn(mprj_io_loader_resetn),
.serial_clock(mprj_io_loader_clock),
- .mgmt_gpio_io(mgmt_io_data),
+ .mgmt_gpio_in(mgmt_io_in), // For gpio_control_block2 only
+ .mgmt_gpio_out({mgmt_io_in[(`MPRJ_IO_PADS-1):2], sdo_out, jtag_out}),
+ .mgmt_gpio_oeb({{(`MPRJ_IO_PADS-2){1'b1}}, sdo_outenb, jtag_outenb}),
// Serial data chain for pad configuration
.serial_data_in(gpio_serial_link_shifted),
@@ -352,7 +397,7 @@
// User-facing signals
.user_gpio_out(user_io_out),
- .user_gpio_outenb(user_io_oeb_n),
+ .user_gpio_oeb(user_io_oeb),
.user_gpio_in(user_io_in),
// Pad-facing signals (Pad GPIOv2)
@@ -365,7 +410,7 @@
.pad_gpio_ana_sel(mprj_io_analog_sel),
.pad_gpio_ana_pol(mprj_io_analog_pol),
.pad_gpio_dm(mprj_io_dm),
- .pad_gpio_outenb(mprj_io_oen_n),
+ .pad_gpio_outenb(mprj_io_oeb),
.pad_gpio_out(mprj_io_out),
.pad_gpio_in(mprj_io_in)
);
diff --git a/verilog/rtl/caravel_spi.v b/verilog/rtl/caravel_spi.v
deleted file mode 100644
index 3abd227..0000000
--- a/verilog/rtl/caravel_spi.v
+++ /dev/null
@@ -1,261 +0,0 @@
-//-------------------------------------
-// SPI controller for Caravel (PicoSoC)
-//-------------------------------------
-// Written by Tim Edwards
-// efabless, inc. September 27, 2020
-//-------------------------------------
-
-`include "caravel_spi_slave.v"
-
-//-----------------------------------------------------------
-// This is a standalone slave SPI for the caravel chip that is
-// intended to be independent of the picosoc and independent
-// of all IP blocks except the power-on-reset. This SPI has
-// register outputs controlling the functions that critically
-// affect operation of the picosoc and so cannot be accessed
-// from the picosoc itself. This includes the PLL enables
-// and trim, and the crystal oscillator enable. It also has
-// a general reset for the picosoc, an IRQ input, a bypass for
-// the entire crystal oscillator and PLL chain, the
-// manufacturer and product IDs and product revision number.
-// To be independent of the 1.8V regulator, the slave SPI is
-// synthesized with the 3V digital library and runs off of
-// the 3V supply.
-//
-// This module is designed to be decoupled from the chip
-// padframe and redirected to the wishbone bus under
-// register control from the management SoC, such that the
-// contents can be accessed from the management core via the
-// SPI master.
-//
-//-----------------------------------------------------------
-
-//------------------------------------------------------------
-// Caravel defined registers:
-// Register 0: SPI status and control (unused & reserved)
-// Register 1 and 2: Manufacturer ID (0x0456) (readonly)
-// Register 3: Product ID (= 2) (readonly)
-// Register 4-7: Mask revision (readonly) --- Externally programmed
-// with via programming. Via programmed with a script to match
-// each customer ID.
-//
-// Register 8: PLL enable (1 bit)
-// Register 9: PLL bypass (1 bit)
-// Register 10: IRQ (1 bit)
-// Register 11: reset (1 bit)
-// Register 12: trap (1 bit) (readonly)
-// Register 13-16: PLL trim (26 bits)
-// Register 17: PLL output select (3 bits)
-// Register 18: PLL divider (5 bits)
-//------------------------------------------------------------
-
-module caravel_spi(
-`ifdef LVS
- vdd, vss,
-`endif
- RSTB, SCK, SDI, CSB, SDO, sdo_enb,
- mgmt_sck, mgmt_sdi, mgmt_csb, mgmt_sdo,
- pll_dco_ena, pll_div, pll_sel,
- pll_trim, pll_bypass, irq, reset, trap,
- mask_rev_in, pass_thru_reset,
- pass_thru_mgmt_sck, pass_thru_mgmt_csb,
- pass_thru_mgmt_sdi, pass_thru_mgmt_sdo,
- pass_thru_user_sck, pass_thru_user_csb,
- pass_thru_user_sdi, pass_thru_user_sdo
-);
-
-`ifdef LVS
- inout vdd; // 3.3V supply
- inout vss; // common ground
-`endif
-
- input RSTB; // from padframe
-
- input SCK; // from padframe
- input SDI; // from padframe
- input CSB; // from padframe
- output SDO; // to padframe
- output sdo_enb; // to padframe
-
- input mgmt_sck; // from management SoC
- input mgmt_sdi; // from management SoC
- input mgmt_csb; // from management SoC
- output mgmt_sdo; // to management SoC
-
- output pll_dco_ena;
- output [4:0] pll_div;
- output [2:0] pll_sel;
- output [25:0] pll_trim;
- output pll_bypass;
- output irq;
- output reset;
- input trap;
- input [31:0] mask_rev_in; // metal programmed; 3.3V domain
-
- // Pass-through programming mode for management area SPI flash
- output pass_thru_reset;
- output pass_thru_mgmt_sck;
- output pass_thru_mgmt_csb;
- output pass_thru_mgmt_sdi;
- input pass_thru_mgmt_sdo;
-
- // Pass-through programming mode for user area SPI flash
- output pass_thru_user_sck;
- output pass_thru_user_csb;
- output pass_thru_user_sdi;
- input pass_thru_user_sdo;
-
- reg [25:0] pll_trim;
- reg [4:0] pll_div;
- reg [2:0] pll_sel;
- reg pll_dco_ena;
- reg pll_bypass;
- reg reset_reg;
- reg irq;
-
- wire [7:0] odata;
- wire [7:0] idata;
- wire [7:0] iaddr;
-
- wire trap;
- wire rdstb;
- wire wrstb;
- wire pass_thru_mgmt; // Mode detected by spi_slave
- wire pass_thru_mgmt_delay;
- wire pass_thru_user; // Mode detected by spi_slave
- wire pass_thru_user_delay;
-
- // Connect to management SoC SPI master when mgmt_csb is low
-
- wire loc_sck;
- wire loc_csb;
- wire loc_sdi;
- wire loc_sdo;
- wire loc_sdoenb;
-
- assign loc_csb = (mgmt_csb == 1'b0) ? 1'b0 : CSB;
- assign loc_sck = (mgmt_csb == 1'b0) ? mgmt_sck : SCK;
- assign loc_sdi = (mgmt_csb == 1'b0) ? mgmt_sdi : SDI;
-
- assign mgmt_sdo = (mgmt_csb == 1'b0) ? loc_sdo : 1'b0;
- assign sdo_enb = (mgmt_csb == 1'b0) ? 1'b1 : loc_sdoenb;
-
- // Pass-through mode handling
-
- assign pass_thru_mgmt_csb = ~pass_thru_mgmt_delay;
- assign pass_thru_mgmt_sck = pass_thru_mgmt ? SCK : 1'b0;
- assign pass_thru_mgmt_sdi = pass_thru_mgmt ? SDI : 1'b0;
-
- assign pass_thru_user_csb = ~pass_thru_user_delay;
- assign pass_thru_user_sck = pass_thru_user ? SCK : 1'b0;
- assign pass_thru_user_sdi = pass_thru_user ? SDI : 1'b0;
-
- assign SDO = pass_thru_mgmt ? pass_thru_mgmt_sdo :
- pass_thru_user ? pass_thru_user_sdo : loc_sdo;
- assign reset = pass_thru_reset ? 1'b1 : reset_reg;
-
- // Instantiate the SPI slave module
-
- caravel_spi_slave U1 (
- .reset(~RSTB),
- .SCK(loc_sck),
- .SDI(loc_sdi),
- .CSB(loc_csb),
- .SDO(loc_sdo),
- .sdoenb(loc_sdoenb),
- .idata(odata),
- .odata(idata),
- .oaddr(iaddr),
- .rdstb(rdstb),
- .wrstb(wrstb),
- .pass_thru_mgmt(pass_thru_mgmt),
- .pass_thru_mgmt_delay(pass_thru_mgmt_delay),
- .pass_thru_user(pass_thru_user),
- .pass_thru_user_delay(pass_thru_user_delay),
- .pass_thru_reset(pass_thru_reset)
- );
-
- wire [11:0] mfgr_id;
- wire [7:0] prod_id;
- wire [31:0] mask_rev;
-
- assign mfgr_id = 12'h456; // Hard-coded
- assign prod_id = 8'h10; // Hard-coded
- assign mask_rev = mask_rev_in; // Copy in to out.
-
- // Send register contents to odata on SPI read command
- // All values are 1-4 bits and no shadow registers are required.
-
- assign odata =
- (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed)
- (iaddr == 8'h01) ? {4'h0, mfgr_id[11:8]} : // Manufacturer ID (fixed)
- (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed)
- (iaddr == 8'h03) ? prod_id : // Product ID (fixed)
- (iaddr == 8'h04) ? mask_rev[31:24] : // Mask rev (metal programmed)
- (iaddr == 8'h05) ? mask_rev[23:16] : // Mask rev (metal programmed)
- (iaddr == 8'h06) ? mask_rev[15:8] : // Mask rev (metal programmed)
- (iaddr == 8'h07) ? mask_rev[7:0] : // Mask rev (metal programmed)
-
- (iaddr == 8'h08) ? {7'b0000000, pll_dco_ena} :
- (iaddr == 8'h09) ? {7'b0000000, pll_bypass} :
- (iaddr == 8'h0a) ? {7'b0000000, irq} :
- (iaddr == 8'h0b) ? {7'b0000000, reset} :
- (iaddr == 8'h0c) ? {7'b0000000, trap} :
- (iaddr == 8'h0d) ? pll_trim[7:0] :
- (iaddr == 8'h0e) ? pll_trim[15:8] :
- (iaddr == 8'h0f) ? pll_trim[23:16] :
- (iaddr == 8'h10) ? {6'b000000, pll_trim[25:24]} :
- (iaddr == 8'h11) ? {5'b00000, pll_sel} :
- (iaddr == 8'h12) ? {3'b000, pll_div} :
- 8'h00; // Default
-
- // Register mapping and I/O to slave module
-
- always @(posedge SCK or negedge RSTB) begin
- if (RSTB == 1'b0) begin
- // Set trim for PLL at (almost) slowest rate (~90MHz). However,
- // pll_trim[12] must be set to zero for proper startup.
- pll_trim <= 26'b11111111111110111111111111;
- pll_sel <= 3'b000;
- pll_div <= 5'b00100; // Default divide-by-8
- pll_dco_ena <= 1'b1; // Default free-running PLL
- pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL)
- irq <= 1'b0;
- reset_reg <= 1'b0;
- end else if (wrstb == 1'b1) begin
- case (iaddr)
- 8'h08: begin
- pll_dco_ena <= idata[0];
- end
- 8'h09: begin
- pll_bypass <= idata[0];
- end
- 8'h0a: begin
- irq <= idata[0];
- end
- 8'h0b: begin
- reset_reg <= idata[0];
- end
- // Register 0xc is read-only
- 8'h0d: begin
- pll_trim[7:0] <= idata;
- end
- 8'h0e: begin
- pll_trim[15:8] <= idata;
- end
- 8'h0f: begin
- pll_trim[23:16] <= idata;
- end
- 8'h10: begin
- pll_trim[25:24] <= idata[1:0];
- end
- 8'h11: begin
- pll_sel <= idata[2:0];
- end
- 8'h12: begin
- pll_div <= idata[4:0];
- end
- endcase // (iaddr)
- end
- end
-endmodule // caravel_spi
diff --git a/verilog/rtl/caravel_spi_slave.v b/verilog/rtl/caravel_spi_slave.v
deleted file mode 100644
index e8a6494..0000000
--- a/verilog/rtl/caravel_spi_slave.v
+++ /dev/null
@@ -1,221 +0,0 @@
-//------------------------------------------------------
-// caravel_spi_slave.v
-//------------------------------------------------------
-// General purpose SPI slave module for the Caravel chip
-//------------------------------------------------------
-// Written by Tim Edwards
-// efabless, inc., September 28, 2020
-//------------------------------------------------
-// This file is distributed free and open source
-//------------------------------------------------
-
-// SCK --- Clock input
-// SDI --- Data input
-// SDO --- Data output
-// CSB --- Chip select (sense negative)
-// idata --- Data from chip to transmit out, in 8 bits
-// odata --- Input data to chip, in 8 bits
-// addr --- Decoded address to upstream circuits
-// rdstb --- Read strobe, tells upstream circuit to supply next byte to idata
-// wrstb --- Write strobe, tells upstream circuit to latch odata.
-
-// Data format (general purpose):
-// 8 bit format
-// 1st byte: Command word (see below)
-// 2nd byte: Address word (register 0 to 255)
-// 3rd byte: Data word (value 0 to 255)
-
-// Command format:
-// 00000000 No operation
-// 10000000 Write until CSB raised
-// 01000000 Read until CSB raised
-// 11000000 Simultaneous read/write until CSB raised
-// 11000100 Pass-through read/write to management area flash SPI until CSB raised
-// 11000101 Pass-through read/write to user area flash SPI until CSB raised
-// wrnnn000 Read/write as above, for nnn = 1 to 7 bytes, then terminate
-
-// Lower three bits are reserved for future use.
-// All serial bytes are read and written msb first.
-
-// Fixed control and status registers
-
-// Address 0 is reserved and contains flags for SPI mode. This is
-// currently undefined and is always value 0.
-// Address 1 is reserved and contains manufacturer ID low 8 bits.
-// Address 2 is reserved and contains manufacturer ID high 4 bits.
-// Address 3 is reserved and contains product ID (8 bits).
-// Addresses 4 to 7 are reserved and contain the mask ID (32 bits).
-// Addresses 8 to 255 are available for general purpose use.
-
-`define COMMAND 3'b000
-`define ADDRESS 3'b001
-`define DATA 3'b010
-`define USERPASS 3'b100
-`define MGMTPASS 3'b101
-
-module caravel_spi_slave(reset, SCK, SDI, CSB, SDO,
- sdoenb, idata, odata, oaddr, rdstb, wrstb,
- pass_thru_mgmt, pass_thru_mgmt_delay,
- pass_thru_user, pass_thru_user_delay, pass_thru_reset);
-
- input reset;
- input SCK;
- input SDI;
- input CSB;
- output SDO;
- output sdoenb;
- input [7:0] idata;
- output [7:0] odata;
- output [7:0] oaddr;
- output rdstb;
- output wrstb;
- output pass_thru_mgmt;
- output pass_thru_mgmt_delay;
- output pass_thru_user;
- output pass_thru_user_delay;
- output pass_thru_reset;
-
- reg [7:0] addr;
- reg wrstb;
- reg rdstb;
- reg sdoenb;
- reg [2:0] state;
- reg [2:0] count;
- reg writemode;
- reg readmode;
- reg [2:0] fixed;
- wire [7:0] odata;
- reg [6:0] predata;
- wire [7:0] oaddr;
- reg [7:0] ldata;
- reg pass_thru_mgmt;
- reg pass_thru_mgmt_delay;
- reg pre_pass_thru_mgmt;
- reg pass_thru_user;
- reg pass_thru_user_delay;
- reg pre_pass_thru_user;
- wire csb_reset;
-
- assign odata = {predata, SDI};
- assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr;
- assign SDO = ldata[7];
- assign csb_reset = CSB | reset;
- assign pass_thru_reset = pass_thru_mgmt_delay | pre_pass_thru_mgmt;
-
- // Readback data is captured on the falling edge of SCK so that
- // it is guaranteed valid at the next rising edge.
- always @(negedge SCK or posedge CSB) begin
- if (CSB == 1'b1) begin
- wrstb <= 1'b0;
- ldata <= 8'b00000000;
- sdoenb <= 1'b1;
- end else begin
-
- // After CSB low, 1st SCK starts command
-
- if (state == `DATA) begin
- if (readmode == 1'b1) begin
- sdoenb <= 1'b0;
- if (count == 3'b000) begin
- ldata <= idata;
- end else begin
- ldata <= {ldata[6:0], 1'b0}; // Shift out
- end
- end else begin
- sdoenb <= 1'b1;
- end
-
- // Apply write strobe on SCK negative edge on the next-to-last
- // data bit so that it updates data on the rising edge of SCK
- // on the last data bit.
-
- if (count == 3'b111) begin
- if (writemode == 1'b1) begin
- wrstb <= 1'b1;
- end
- end else begin
- wrstb <= 1'b0;
- end
- end else if (state == `MGMTPASS || state == `USERPASS) begin
- wrstb <= 1'b0;
- sdoenb <= 1'b0;
- end else begin
- wrstb <= 1'b0;
- sdoenb <= 1'b1;
- end // ! state `DATA
- end // ! CSB
- end // always @ ~SCK
-
- always @(posedge SCK or posedge CSB) begin
- if (csb_reset == 1'b1) begin
- // Default state on reset
- addr <= 8'h00;
- rdstb <= 1'b0;
- predata <= 7'b0000000;
- state <= `COMMAND;
- count <= 3'b000;
- readmode <= 1'b0;
- writemode <= 1'b0;
- fixed <= 3'b000;
- pass_thru_mgmt <= 1'b0;
- pass_thru_mgmt_delay <= 1'b0;
- pre_pass_thru_mgmt <= 1'b0;
- pass_thru_user = 1'b0;
- pass_thru_user_delay <= 1'b0;
- pre_pass_thru_user <= 1'b0;
- end else begin
- // After CSB low, 1st SCK starts command
- if (state == `COMMAND) begin
- rdstb <= 1'b0;
- count <= count + 1;
- if (count == 3'b000) begin
- writemode <= SDI;
- end else if (count == 3'b001) begin
- readmode <= SDI;
- end else if (count < 3'b101) begin
- fixed <= {fixed[1:0], SDI};
- end else if (count < 3'b110) begin
- pass_thru_mgmt_delay <= pre_pass_thru_mgmt;
- pass_thru_user_delay <= pre_pass_thru_user;
- end else if (count == 3'b111) begin
- if (pre_pass_thru_mgmt == 1'b1) begin
- state <= `MGMTPASS;
- pre_pass_thru_mgmt <= 1'b0;
- end else if (pre_pass_thru_user == 1'b1) begin
- state <= `USERPASS;
- pre_pass_thru_user <= 1'b0;
- end else begin
- state <= `ADDRESS;
- end
- end
- end else if (state == `ADDRESS) begin
- count <= count + 1;
- addr <= {addr[6:0], SDI};
- if (count == 3'b111) begin
- if (readmode == 1'b1) begin
- rdstb <= 1'b1;
- end
- state <= `DATA;
- end else begin
- rdstb <= 1'b0;
- end
- end else if (state == `DATA) begin
- predata <= {predata[6:0], SDI};
- count <= count + 1;
- if (count == 3'b111) begin
- if (fixed == 3'b001) begin
- state <= `COMMAND;
- end else if (fixed != 3'b000) begin
- fixed <= fixed - 1;
- addr <= addr + 1; // Auto increment address (fixed)
- end else begin
- addr <= addr + 1; // Auto increment address (streaming)
- end
- end else begin
- rdstb <= 1'b0;
- end
- end // ! state `DATA
- end // ! CSB
- end // always @ SCK
-
-endmodule // caravel_spi_slave
diff --git a/verilog/rtl/chip_io.v b/verilog/rtl/chip_io.v
index 82df32d..dc46ebf 100644
--- a/verilog/rtl/chip_io.v
+++ b/verilog/rtl/chip_io.v
@@ -33,11 +33,12 @@
input flash_io1_do_core,
output flash_io0_di_core,
output flash_io1_di_core,
- input pll_clk16,
+ // porbh, returned to the I/O level shifted down and inverted
+ input por,
// Mega-project IOs
- input [`MPRJ_IO_PADS-1:0] mprj_io,
+ inout [`MPRJ_IO_PADS-1:0] mprj_io,
input [`MPRJ_IO_PADS-1:0] mprj_io_out,
- input [`MPRJ_IO_PADS-1:0] mprj_io_oeb_n,
+ input [`MPRJ_IO_PADS-1:0] mprj_io_oeb,
input [`MPRJ_IO_PADS-1:0] mprj_io_hldh_n,
input [`MPRJ_IO_PADS-1:0] mprj_io_enh,
input [`MPRJ_IO_PADS-1:0] mprj_io_inp_dis,
@@ -198,20 +199,25 @@
`endif
mprj_io mprj_pads(
- .vdd(vdd3v3),
+ .vdd3v3(vdd3v3),
.vdd1v8(vdd1v8),
.vss(vss),
.vddio_q(vddio_q),
.vssio_q(vssio_q),
.analog_a(analog_a),
.analog_b(analog_b),
+ .porb_h(porb_h),
+ .por(por),
.io(mprj_io),
.io_out(mprj_io_out),
- .oeb_n(mprj_io_oeb_n),
+ .oeb(mprj_io_oeb),
.hldh_n(mprj_io_hldh_n),
.enh(mprj_io_enh),
.inp_dis(mprj_io_inp_dis),
.ib_mode_sel(mprj_io_ib_mode_sel),
+ .vtrip_sel(mprj_io_vtrip_sel),
+ .holdover(mprj_io_holdover),
+ .slow_sel(mprj_io_slow_sel),
.analog_en(mprj_io_analog_en),
.analog_sel(mprj_io_analog_sel),
.analog_pol(mprj_io_analog_pol),
diff --git a/verilog/rtl/gpio_control_block.v b/verilog/rtl/gpio_control_block.v
index 1575841..2325b39 100644
--- a/verilog/rtl/gpio_control_block.v
+++ b/verilog/rtl/gpio_control_block.v
@@ -31,7 +31,21 @@
*/
module gpio_control_block #(
- parameter PAD_CTRL_BITS = 13
+ parameter PAD_CTRL_BITS = 13,
+ // Parameterized initial startup state of the pad.
+ // The default parameters if unspecified is for the pad to be
+ // an input with no pull-up or pull-down, so that it is disconnected
+ // from the outside world.
+ parameter HOLD_INIT = 1'b0,
+ parameter SLOW_INIT = 1'b0,
+ parameter TRIP_INIT = 1'b0,
+ parameter IB_INIT = 1'b0,
+ parameter IENB_INIT = 1'b0,
+ parameter OENB_INIT = 1'b1,
+ parameter DM_INIT = 3'b001,
+ parameter AENA_INIT = 1'b0,
+ parameter ASEL_INIT = 1'b0,
+ parameter APOL_INIT = 1'b0
) (
// Management Soc-facing signals
input resetn, // Global reset
@@ -45,7 +59,7 @@
// User-facing signals
input user_gpio_out, // User space to pad
- input user_gpio_outenb, // Output enable (user)
+ input user_gpio_oeb, // Output enable (user)
output user_gpio_in, // Pad to user space
// Pad-facing signals (Pad GPIOv2)
@@ -58,7 +72,7 @@
output pad_gpio_ana_sel,
output pad_gpio_ana_pol,
output [2:0] pad_gpio_dm,
- output pad_gpio_outenb,
+ output pad_gpio_oeb,
output pad_gpio_out,
input pad_gpio_in
);
@@ -67,15 +81,14 @@
localparam MGMT_EN = 0;
localparam OEB = 1;
localparam HLDH = 2;
- localparam ENH = 3;
- localparam INP_DIS = 4;
- localparam MOD_SEL = 5;
- localparam AN_EN = 6;
- localparam AN_SEL = 7;
- localparam AN_POL = 8;
- localparam SLOW = 9;
- localparam TRIP = 10;
- localparam DM = 11;
+ localparam INP_DIS = 2;
+ localparam MOD_SEL = 4;
+ localparam AN_EN = 5;
+ localparam AN_SEL = 6;
+ localparam AN_POL = 7;
+ localparam SLOW = 8;
+ localparam TRIP = 9;
+ localparam DM = 10;
/* Internally registered signals */
reg mgmt_ena; // Enable management SoC to access pad
@@ -129,17 +142,17 @@
always @(posedge load_data or posedge int_reset) begin
if (int_reset == 1'b1) begin
/* Initial state on reset: Pad set to management input */
- mgmt_ena <= 1'b0;
- gpio_holdover <= 1'b0; // All signals latched in hold mode
- gpio_slow_sel <= 1'b0; // Fast slew rate
- gpio_vtrip_sel <= 1'b0; // CMOS mode
- gpio_ib_mode_sel <= 1'b0; // CMOS mode
- gpio_inenb <= 1'b0; // Input enabled
- gpio_outenb <= 1'b1; // Output disabled
- gpio_dm <= 3'b001; // Configured as input only
- gpio_ana_en <= 1'b0; // Digital enabled
- gpio_ana_sel <= 1'b0; // Don't-care when gpio_ana_en = 0
- gpio_ana_pol <= 1'b0; // Don't-care when gpio_ana_en = 0
+ mgmt_ena <= 1'b1; // Management SoC has control over all I/O
+ gpio_holdover <= HOLD_INIT; // All signals latched in hold mode
+ gpio_slow_sel <= SLOW_INIT; // Fast slew rate
+ gpio_vtrip_sel <= TRIP_INIT; // CMOS mode
+ gpio_ib_mode_sel <= IB_INIT; // CMOS mode
+ gpio_inenb <= IENB_INIT; // Input enabled
+ gpio_outenb <= OENB_INIT; // Output disabled
+ gpio_dm <= DM_INIT; // Configured as input only
+ gpio_ana_en <= AENA_INIT; // Digital enabled
+ gpio_ana_sel <= ASEL_INIT; // Don't-care when gpio_ana_en = 0
+ gpio_ana_pol <= APOL_INIT; // Don't-care when gpio_ana_en = 0
end else begin
/* Load data */
mgmt_ena <= shift_register[MGMT_EN];
@@ -177,18 +190,23 @@
/* set the pullup or pulldown condition, the pad output bit must */
/* be set to the opposite state of dm[0]. */
/* dm[0] = 0 is pull-down; dm[0] = 1 is pull-up. */
- /* Otherwise, the output
+ /* */
+ /* This is done for management control only, since the management */
+ /* control has only 1 inout signal for both input and output, and */
+ /* cannot set the output and read the input simultaneously. The */
+ /* user has control over both lines and only needs to be told what */
+ /* to set the output line to, to enable a pullup or pulldown. */
- assign pad_gpio_out = (mgmt_ena) ? mgmt_gpio_io :
- (((gpio_dm[2:1] == 2'b01) && (gpio_inenb == 1'b0)) ?
- ~gpio_dm[0] : user_gpio_out);
+ assign pad_gpio_out = (mgmt_ena) ?
+ (((gpio_dm[2:1] == 2'b01) && (gpio_inenb == 1'b0)) ?
+ ~gpio_dm[0] : mgmt_gpio_io) : user_gpio_out;
/* When under user control, gpio_outenb = 1 means that the pad is */
/* configured as input, and the user outenb is unused. Otherwise, */
/* the pad outenb signal is controlled by the user. */
assign pad_gpio_outenb = (mgmt_ena) ? gpio_outenb :
- ((gpio_outenb == 1) ? 1'b1 : user_gpio_outenb);
+ ((gpio_outenb == 1) ? 1'b1 : user_gpio_oeb);
/* User gpio_in is grounded when the management controls the pad */
assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
diff --git a/verilog/rtl/gpio_control_block2.v b/verilog/rtl/gpio_control_block2.v
new file mode 100644
index 0000000..b28a02e
--- /dev/null
+++ b/verilog/rtl/gpio_control_block2.v
@@ -0,0 +1,193 @@
+/*
+ *---------------------------------------------------------------------
+ * See gpio_control_block for description. This module is like
+ * gpio_contro_block except that it has an additional two management-
+ * Soc-facing pins, which are the out_enb line and the output line.
+ * If the chip is configured for output with the oeb control
+ * register = 1, then the oeb line is controlled by the additional
+ * signal from the management SoC. If the oeb control register = 0,
+ * then the output is disabled completely. The "io" line is input
+ * only in this module.
+ *
+ *---------------------------------------------------------------------
+ */
+
+/*
+ *---------------------------------------------------------------------
+ *
+ * This module instantiates a shift register chain that passes through
+ * each gpio cell. These are connected end-to-end around the padframe
+ * periphery. The purpose is to avoid a massive number of control
+ * wires between the digital core and I/O, passing through the user area.
+ *
+ * See mprj_ctrl.v for the module that registers the data for each
+ * I/O and drives the input to the shift register.
+ *
+ *---------------------------------------------------------------------
+ */
+
+module gpio_control_block2 #(
+ parameter PAD_CTRL_BITS = 13,
+ // Parameterized initial startup state of the pad.
+ // The default parameters if unspecified is for the pad to be
+ // an input with no pull-up or pull-down, so that it is disconnected
+ // from the outside world.
+ parameter HOLD_INIT = 1'b0,
+ parameter SLOW_INIT = 1'b0,
+ parameter TRIP_INIT = 1'b0,
+ parameter IB_INIT = 1'b0,
+ parameter IENB_INIT = 1'b0,
+ parameter OENB_INIT = 1'b1,
+ parameter DM_INIT = 3'b001,
+ parameter AENA_INIT = 1'b0,
+ parameter ASEL_INIT = 1'b0,
+ parameter APOL_INIT = 1'b0
+) (
+ // Management Soc-facing signals
+ input resetn, // Global reset
+ input serial_clock,
+
+ output mgmt_gpio_in, // Management from pad (input only)
+ input mgmt_gpio_out, // Management to pad (output only)
+ input mgmt_gpio_oeb, // Management to pad (output only)
+
+ // Serial data chain for pad configuration
+ input serial_data_in,
+ output serial_data_out,
+
+ // User-facing signals
+ input user_gpio_out, // User space to pad
+ input user_gpio_oeb, // Output enable (user)
+ output user_gpio_in, // Pad to user space
+
+ // Pad-facing signals (Pad GPIOv2)
+ output pad_gpio_holdover,
+ output pad_gpio_slow_sel,
+ output pad_gpio_vtrip_sel,
+ output pad_gpio_inenb,
+ output pad_gpio_ib_mode_sel,
+ output pad_gpio_ana_en,
+ output pad_gpio_ana_sel,
+ output pad_gpio_ana_pol,
+ output [2:0] pad_gpio_dm,
+ output pad_gpio_outenb,
+ output pad_gpio_out,
+ input pad_gpio_in
+);
+
+ /* Parameters defining the bit offset of each function in the chain */
+ localparam MGMT_EN = 0;
+ localparam OEB = 1;
+ localparam HLDH = 2;
+ localparam ENH = 3;
+ localparam INP_DIS = 4;
+ localparam MOD_SEL = 5;
+ localparam AN_EN = 6;
+ localparam AN_SEL = 7;
+ localparam AN_POL = 8;
+ localparam SLOW = 9;
+ localparam TRIP = 10;
+ localparam DM = 11;
+
+ /* Internally registered signals */
+ reg mgmt_ena; // Enable management SoC to access pad
+ reg gpio_holdover;
+ reg gpio_slow_sel;
+ reg gpio_vtrip_sel;
+ reg gpio_inenb;
+ reg gpio_ib_mode_sel;
+ reg gpio_outenb;
+ reg [2:0] gpio_dm;
+ reg gpio_ana_en;
+ reg gpio_ana_sel;
+ reg gpio_ana_pol;
+
+ /* Derived output values */
+ wire pad_gpio_holdover;
+ wire pad_gpio_slow_sel;
+ wire pad_gpio_vtrip_sel;
+ wire pad_gpio_inenb;
+ wire pad_gpio_ib_mode_sel;
+ wire pad_gpio_ana_en;
+ wire pad_gpio_ana_sel;
+ wire pad_gpio_ana_pol;
+ wire [2:0] pad_gpio_dm;
+ wire pad_gpio_outenb;
+ wire pad_gpio_out;
+ wire pad_gpio_in;
+
+ /* Serial shift for the above (latched) values */
+ reg [PAD_CTRL_BITS-1:0] shift_register;
+
+ /* Utilize reset and clock to encode a load operation */
+ wire load_data;
+ wire int_reset;
+
+ /* Create internal reset and load signals from input reset and clock */
+ assign serial_data_out = shift_register[PAD_CTRL_BITS-1];
+ assign int_reset = (~resetn) & (~serial_clock);
+ assign load_data = (~resetn) & serial_clock;
+
+ always @(posedge serial_clock or posedge int_reset) begin
+ if (int_reset == 1'b1) begin
+ /* Clear shift register */
+ shift_register <= 'd0;
+ end else begin
+ /* Shift data in */
+ shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in};
+ end
+ end
+
+ always @(posedge load_data or posedge int_reset) begin
+ if (int_reset == 1'b1) begin
+ /* Initial state on reset: Pad set to management input */
+ mgmt_ena <= 1'b1; // Management SoC has control over all I/O
+ gpio_holdover <= HOLD_INIT; // All signals latched in hold mode
+ gpio_slow_sel <= SLOW_INIT; // Fast slew rate
+ gpio_vtrip_sel <= TRIP_INIT; // CMOS mode
+ gpio_ib_mode_sel <= IB_INIT; // CMOS mode
+ gpio_inenb <= IENB_INIT; // Input enabled
+ gpio_outenb <= OENB_INIT; // (unused placeholder)
+ gpio_dm <= DM_INIT; // Configured as input only
+ gpio_ana_en <= AENA_INIT; // Digital enabled
+ gpio_ana_sel <= ASEL_INIT; // Don't-care when gpio_ana_en = 0
+ gpio_ana_pol <= APOL_INIT; // Don't-care when gpio_ana_en = 0
+ end else begin
+ /* Load data */
+ mgmt_ena <= shift_register[MGMT_EN];
+ gpio_outenb <= shift_register[OEB];
+ gpio_holdover <= shift_register[HLDH];
+ gpio_inenb <= shift_register[INP_DIS];
+ gpio_ib_mode_sel <= shift_register[MOD_SEL];
+ gpio_ana_en <= shift_register[AN_EN];
+ gpio_ana_sel <= shift_register[AN_SEL];
+ gpio_ana_pol <= shift_register[AN_POL];
+ gpio_slow_sel <= shift_register[SLOW];
+ gpio_vtrip_sel <= shift_register[TRIP];
+ gpio_dm <= shift_register[DM+2:DM];
+
+ end
+ end
+
+ /* These pad configuration signals are static and do not change */
+ /* after setup. */
+
+ assign pad_gpio_holdover = gpio_holdover;
+ assign pad_gpio_slow_sel = gpio_slow_sel;
+ assign pad_gpio_vtrip_sel = gpio_vtrip_sel;
+ assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel;
+ assign pad_gpio_ana_en = gpio_ana_en;
+ assign pad_gpio_ana_sel = gpio_ana_sel;
+ assign pad_gpio_ana_pol = gpio_ana_pol;
+ assign pad_gpio_dm = gpio_dm;
+ assign pad_gpio_inenb = gpio_inenb;
+
+ /* Implement pad control behavior depending on state of mgmt_ena */
+
+ assign pad_gpio_out = (mgmt_ena) ? mgmt_gpio_out : user_gpio_out;
+ assign pad_gpio_outenb = (mgmt_ena) ? mgmt_gpio_oeb : user_gpio_oeb;
+
+ assign user_gpio_in = (mgmt_ena) ? 1'b0 : pad_gpio_in;
+ assign mgmt_gpio_in = (mgmt_ena) ? pad_gpio_in : 1'b0;
+
+endmodule
diff --git a/verilog/rtl/housekeeping_spi.v b/verilog/rtl/housekeeping_spi.v
new file mode 100644
index 0000000..97bd7a1
--- /dev/null
+++ b/verilog/rtl/housekeeping_spi.v
@@ -0,0 +1,481 @@
+//-------------------------------------
+// SPI controller for Caravel (PicoSoC)
+//-------------------------------------
+// Written by Tim Edwards
+// efabless, inc. September 27, 2020
+//-------------------------------------
+
+//-----------------------------------------------------------
+// This is a standalone slave SPI for the caravel chip that is
+// intended to be independent of the picosoc and independent
+// of all IP blocks except the power-on-reset. This SPI has
+// register outputs controlling the functions that critically
+// affect operation of the picosoc and so cannot be accessed
+// from the picosoc itself. This includes the PLL enables
+// and trim, and the crystal oscillator enable. It also has
+// a general reset for the picosoc, an IRQ input, a bypass for
+// the entire crystal oscillator and PLL chain, the
+// manufacturer and product IDs and product revision number.
+// To be independent of the 1.8V regulator, the slave SPI is
+// synthesized with the 3V digital library and runs off of
+// the 3V supply.
+//
+// This module is designed to be decoupled from the chip
+// padframe and redirected to the wishbone bus under
+// register control from the management SoC, such that the
+// contents can be accessed from the management core via the
+// SPI master.
+//
+//-----------------------------------------------------------
+
+//------------------------------------------------------------
+// Caravel defined registers:
+// Register 0: SPI status and control (unused & reserved)
+// Register 1 and 2: Manufacturer ID (0x0456) (readonly)
+// Register 3: Product ID (= 2) (readonly)
+// Register 4-7: Mask revision (readonly) --- Externally programmed
+// with via programming. Via programmed with a script to match
+// each customer ID.
+//
+// Register 8: PLL enable (1 bit)
+// Register 9: PLL bypass (1 bit)
+// Register 10: IRQ (1 bit)
+// Register 11: reset (1 bit)
+// Register 12: trap (1 bit) (readonly)
+// Register 13-16: PLL trim (26 bits)
+// Register 17: PLL output select (3 bits)
+// Register 18: PLL divider (5 bits)
+//------------------------------------------------------------
+
+module housekeeping_spi(
+`ifdef LVS
+ vdd, vss,
+`endif
+ RSTB, SCK, SDI, CSB, SDO, sdo_enb,
+ mgmt_sck, mgmt_sdi, mgmt_csb, mgmt_sdo,
+ pll_dco_ena, pll_div, pll_sel,
+ pll_trim, pll_bypass, irq, reset, trap,
+ mask_rev_in, pass_thru_reset,
+ pass_thru_mgmt_sck, pass_thru_mgmt_csb,
+ pass_thru_mgmt_sdi, pass_thru_mgmt_sdo,
+ pass_thru_user_sck, pass_thru_user_csb,
+ pass_thru_user_sdi, pass_thru_user_sdo
+);
+
+`ifdef LVS
+ inout vdd; // 3.3V supply
+ inout vss; // common ground
+`endif
+
+ input RSTB; // from padframe
+
+ input SCK; // from padframe
+ input SDI; // from padframe
+ input CSB; // from padframe
+ output SDO; // to padframe
+ output sdo_enb; // to padframe
+
+ input mgmt_sck; // from management SoC
+ input mgmt_sdi; // from management SoC
+ input mgmt_csb; // from management SoC
+ output mgmt_sdo; // to management SoC
+
+ output pll_dco_ena;
+ output [4:0] pll_div;
+ output [2:0] pll_sel;
+ output [25:0] pll_trim;
+ output pll_bypass;
+ output irq;
+ output reset;
+ input trap;
+ input [31:0] mask_rev_in; // metal programmed; 3.3V domain
+
+ // Pass-through programming mode for management area SPI flash
+ output pass_thru_reset;
+ output pass_thru_mgmt_sck;
+ output pass_thru_mgmt_csb;
+ output pass_thru_mgmt_sdi;
+ input pass_thru_mgmt_sdo;
+
+ // Pass-through programming mode for user area SPI flash
+ output pass_thru_user_sck;
+ output pass_thru_user_csb;
+ output pass_thru_user_sdi;
+ input pass_thru_user_sdo;
+
+ reg [25:0] pll_trim;
+ reg [4:0] pll_div;
+ reg [2:0] pll_sel;
+ reg pll_dco_ena;
+ reg pll_bypass;
+ reg reset_reg;
+ reg irq;
+
+ wire [7:0] odata;
+ wire [7:0] idata;
+ wire [7:0] iaddr;
+
+ wire trap;
+ wire rdstb;
+ wire wrstb;
+ wire pass_thru_mgmt; // Mode detected by spi_slave
+ wire pass_thru_mgmt_delay;
+ wire pass_thru_user; // Mode detected by spi_slave
+ wire pass_thru_user_delay;
+
+ // Connect to management SoC SPI master when mgmt_csb is low
+
+ wire loc_sck;
+ wire loc_csb;
+ wire loc_sdi;
+ wire loc_sdo;
+ wire loc_sdoenb;
+
+ assign loc_csb = (mgmt_csb == 1'b0) ? 1'b0 : CSB;
+ assign loc_sck = (mgmt_csb == 1'b0) ? mgmt_sck : SCK;
+ assign loc_sdi = (mgmt_csb == 1'b0) ? mgmt_sdi : SDI;
+
+ assign mgmt_sdo = (mgmt_csb == 1'b0) ? loc_sdo : 1'b0;
+ assign sdo_enb = (mgmt_csb == 1'b0) ? 1'b1 : loc_sdoenb;
+
+ // Pass-through mode handling
+
+ assign pass_thru_mgmt_csb = ~pass_thru_mgmt_delay;
+ assign pass_thru_mgmt_sck = pass_thru_mgmt ? SCK : 1'b0;
+ assign pass_thru_mgmt_sdi = pass_thru_mgmt ? SDI : 1'b0;
+
+ assign pass_thru_user_csb = ~pass_thru_user_delay;
+ assign pass_thru_user_sck = pass_thru_user ? SCK : 1'b0;
+ assign pass_thru_user_sdi = pass_thru_user ? SDI : 1'b0;
+
+ assign SDO = pass_thru_mgmt ? pass_thru_mgmt_sdo :
+ pass_thru_user ? pass_thru_user_sdo : loc_sdo;
+ assign reset = pass_thru_reset ? 1'b1 : reset_reg;
+
+ // Instantiate the SPI slave module
+
+ housekeeping_spi_slave U1 (
+ .reset(~RSTB),
+ .SCK(loc_sck),
+ .SDI(loc_sdi),
+ .CSB(loc_csb),
+ .SDO(loc_sdo),
+ .sdoenb(loc_sdoenb),
+ .idata(odata),
+ .odata(idata),
+ .oaddr(iaddr),
+ .rdstb(rdstb),
+ .wrstb(wrstb),
+ .pass_thru_mgmt(pass_thru_mgmt),
+ .pass_thru_mgmt_delay(pass_thru_mgmt_delay),
+ .pass_thru_user(pass_thru_user),
+ .pass_thru_user_delay(pass_thru_user_delay),
+ .pass_thru_reset(pass_thru_reset)
+ );
+
+ wire [11:0] mfgr_id;
+ wire [7:0] prod_id;
+ wire [31:0] mask_rev;
+
+ assign mfgr_id = 12'h456; // Hard-coded
+ assign prod_id = 8'h10; // Hard-coded
+ assign mask_rev = mask_rev_in; // Copy in to out.
+
+ // Send register contents to odata on SPI read command
+ // All values are 1-4 bits and no shadow registers are required.
+
+ assign odata =
+ (iaddr == 8'h00) ? 8'h00 : // SPI status (fixed)
+ (iaddr == 8'h01) ? {4'h0, mfgr_id[11:8]} : // Manufacturer ID (fixed)
+ (iaddr == 8'h02) ? mfgr_id[7:0] : // Manufacturer ID (fixed)
+ (iaddr == 8'h03) ? prod_id : // Product ID (fixed)
+ (iaddr == 8'h04) ? mask_rev[31:24] : // Mask rev (metal programmed)
+ (iaddr == 8'h05) ? mask_rev[23:16] : // Mask rev (metal programmed)
+ (iaddr == 8'h06) ? mask_rev[15:8] : // Mask rev (metal programmed)
+ (iaddr == 8'h07) ? mask_rev[7:0] : // Mask rev (metal programmed)
+
+ (iaddr == 8'h08) ? {7'b0000000, pll_dco_ena} :
+ (iaddr == 8'h09) ? {7'b0000000, pll_bypass} :
+ (iaddr == 8'h0a) ? {7'b0000000, irq} :
+ (iaddr == 8'h0b) ? {7'b0000000, reset} :
+ (iaddr == 8'h0c) ? {7'b0000000, trap} :
+ (iaddr == 8'h0d) ? pll_trim[7:0] :
+ (iaddr == 8'h0e) ? pll_trim[15:8] :
+ (iaddr == 8'h0f) ? pll_trim[23:16] :
+ (iaddr == 8'h10) ? {6'b000000, pll_trim[25:24]} :
+ (iaddr == 8'h11) ? {5'b00000, pll_sel} :
+ (iaddr == 8'h12) ? {3'b000, pll_div} :
+ 8'h00; // Default
+
+ // Register mapping and I/O to slave module
+
+ always @(posedge SCK or negedge RSTB) begin
+ if (RSTB == 1'b0) begin
+ // Set trim for PLL at (almost) slowest rate (~90MHz). However,
+ // pll_trim[12] must be set to zero for proper startup.
+ pll_trim <= 26'b11111111111110111111111111;
+ pll_sel <= 3'b000;
+ pll_div <= 5'b00100; // Default divide-by-8
+ pll_dco_ena <= 1'b1; // Default free-running PLL
+ pll_bypass <= 1'b1; // NOTE: Default bypass mode (don't use PLL)
+ irq <= 1'b0;
+ reset_reg <= 1'b0;
+ end else if (wrstb == 1'b1) begin
+ case (iaddr)
+ 8'h08: begin
+ pll_dco_ena <= idata[0];
+ end
+ 8'h09: begin
+ pll_bypass <= idata[0];
+ end
+ 8'h0a: begin
+ irq <= idata[0];
+ end
+ 8'h0b: begin
+ reset_reg <= idata[0];
+ end
+ // Register 0xc is read-only
+ 8'h0d: begin
+ pll_trim[7:0] <= idata;
+ end
+ 8'h0e: begin
+ pll_trim[15:8] <= idata;
+ end
+ 8'h0f: begin
+ pll_trim[23:16] <= idata;
+ end
+ 8'h10: begin
+ pll_trim[25:24] <= idata[1:0];
+ end
+ 8'h11: begin
+ pll_sel <= idata[2:0];
+ end
+ 8'h12: begin
+ pll_div <= idata[4:0];
+ end
+ endcase // (iaddr)
+ end
+ end
+endmodule // housekeeping_spi
+
+//------------------------------------------------------
+// housekeeping_spi_slave.v
+//------------------------------------------------------
+// General purpose SPI slave module for the Caravel chip
+//------------------------------------------------------
+// Written by Tim Edwards
+// efabless, inc., September 28, 2020
+//------------------------------------------------
+// This file is distributed free and open source
+//------------------------------------------------
+
+// SCK --- Clock input
+// SDI --- Data input
+// SDO --- Data output
+// CSB --- Chip select (sense negative)
+// idata --- Data from chip to transmit out, in 8 bits
+// odata --- Input data to chip, in 8 bits
+// addr --- Decoded address to upstream circuits
+// rdstb --- Read strobe, tells upstream circuit to supply next byte to idata
+// wrstb --- Write strobe, tells upstream circuit to latch odata.
+
+// Data format (general purpose):
+// 8 bit format
+// 1st byte: Command word (see below)
+// 2nd byte: Address word (register 0 to 255)
+// 3rd byte: Data word (value 0 to 255)
+
+// Command format:
+// 00000000 No operation
+// 10000000 Write until CSB raised
+// 01000000 Read until CSB raised
+// 11000000 Simultaneous read/write until CSB raised
+// 11000100 Pass-through read/write to management area flash SPI until CSB raised
+// 11000101 Pass-through read/write to user area flash SPI until CSB raised
+// wrnnn000 Read/write as above, for nnn = 1 to 7 bytes, then terminate
+
+// Lower three bits are reserved for future use.
+// All serial bytes are read and written msb first.
+
+// Fixed control and status registers
+
+// Address 0 is reserved and contains flags for SPI mode. This is
+// currently undefined and is always value 0.
+// Address 1 is reserved and contains manufacturer ID low 8 bits.
+// Address 2 is reserved and contains manufacturer ID high 4 bits.
+// Address 3 is reserved and contains product ID (8 bits).
+// Addresses 4 to 7 are reserved and contain the mask ID (32 bits).
+// Addresses 8 to 255 are available for general purpose use.
+
+`define COMMAND 3'b000
+`define ADDRESS 3'b001
+`define DATA 3'b010
+`define USERPASS 3'b100
+`define MGMTPASS 3'b101
+
+module housekeeping_spi_slave(reset, SCK, SDI, CSB, SDO,
+ sdoenb, idata, odata, oaddr, rdstb, wrstb,
+ pass_thru_mgmt, pass_thru_mgmt_delay,
+ pass_thru_user, pass_thru_user_delay, pass_thru_reset);
+
+ input reset;
+ input SCK;
+ input SDI;
+ input CSB;
+ output SDO;
+ output sdoenb;
+ input [7:0] idata;
+ output [7:0] odata;
+ output [7:0] oaddr;
+ output rdstb;
+ output wrstb;
+ output pass_thru_mgmt;
+ output pass_thru_mgmt_delay;
+ output pass_thru_user;
+ output pass_thru_user_delay;
+ output pass_thru_reset;
+
+ reg [7:0] addr;
+ reg wrstb;
+ reg rdstb;
+ reg sdoenb;
+ reg [2:0] state;
+ reg [2:0] count;
+ reg writemode;
+ reg readmode;
+ reg [2:0] fixed;
+ wire [7:0] odata;
+ reg [6:0] predata;
+ wire [7:0] oaddr;
+ reg [7:0] ldata;
+ reg pass_thru_mgmt;
+ reg pass_thru_mgmt_delay;
+ reg pre_pass_thru_mgmt;
+ reg pass_thru_user;
+ reg pass_thru_user_delay;
+ reg pre_pass_thru_user;
+ wire csb_reset;
+
+ assign odata = {predata, SDI};
+ assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr;
+ assign SDO = ldata[7];
+ assign csb_reset = CSB | reset;
+ assign pass_thru_reset = pass_thru_mgmt_delay | pre_pass_thru_mgmt;
+
+ // Readback data is captured on the falling edge of SCK so that
+ // it is guaranteed valid at the next rising edge.
+ always @(negedge SCK or posedge csb_reset) begin
+ if (csb_reset == 1'b1) begin
+ wrstb <= 1'b0;
+ ldata <= 8'b00000000;
+ sdoenb <= 1'b1;
+ end else begin
+
+ // After CSB low, 1st SCK starts command
+
+ if (state == `DATA) begin
+ if (readmode == 1'b1) begin
+ sdoenb <= 1'b0;
+ if (count == 3'b000) begin
+ ldata <= idata;
+ end else begin
+ ldata <= {ldata[6:0], 1'b0}; // Shift out
+ end
+ end else begin
+ sdoenb <= 1'b1;
+ end
+
+ // Apply write strobe on SCK negative edge on the next-to-last
+ // data bit so that it updates data on the rising edge of SCK
+ // on the last data bit.
+
+ if (count == 3'b111) begin
+ if (writemode == 1'b1) begin
+ wrstb <= 1'b1;
+ end
+ end else begin
+ wrstb <= 1'b0;
+ end
+ end else if (state == `MGMTPASS || state == `USERPASS) begin
+ wrstb <= 1'b0;
+ sdoenb <= 1'b0;
+ end else begin
+ wrstb <= 1'b0;
+ sdoenb <= 1'b1;
+ end // ! state `DATA
+ end // ! csb_reset
+ end // always @ ~SCK
+
+ always @(posedge SCK or posedge csb_reset) begin
+ if (csb_reset == 1'b1) begin
+ // Default state on reset
+ addr <= 8'h00;
+ rdstb <= 1'b0;
+ predata <= 7'b0000000;
+ state <= `COMMAND;
+ count <= 3'b000;
+ readmode <= 1'b0;
+ writemode <= 1'b0;
+ fixed <= 3'b000;
+ pass_thru_mgmt <= 1'b0;
+ pass_thru_mgmt_delay <= 1'b0;
+ pre_pass_thru_mgmt <= 1'b0;
+ pass_thru_user = 1'b0;
+ pass_thru_user_delay <= 1'b0;
+ pre_pass_thru_user <= 1'b0;
+ end else begin
+ // After csb_reset low, 1st SCK starts command
+ if (state == `COMMAND) begin
+ rdstb <= 1'b0;
+ count <= count + 1;
+ if (count == 3'b000) begin
+ writemode <= SDI;
+ end else if (count == 3'b001) begin
+ readmode <= SDI;
+ end else if (count < 3'b101) begin
+ fixed <= {fixed[1:0], SDI};
+ end else if (count < 3'b110) begin
+ pass_thru_mgmt_delay <= pre_pass_thru_mgmt;
+ pass_thru_user_delay <= pre_pass_thru_user;
+ end else if (count == 3'b111) begin
+ if (pre_pass_thru_mgmt == 1'b1) begin
+ state <= `MGMTPASS;
+ pre_pass_thru_mgmt <= 1'b0;
+ end else if (pre_pass_thru_user == 1'b1) begin
+ state <= `USERPASS;
+ pre_pass_thru_user <= 1'b0;
+ end else begin
+ state <= `ADDRESS;
+ end
+ end
+ end else if (state == `ADDRESS) begin
+ count <= count + 1;
+ addr <= {addr[6:0], SDI};
+ if (count == 3'b111) begin
+ if (readmode == 1'b1) begin
+ rdstb <= 1'b1;
+ end
+ state <= `DATA;
+ end else begin
+ rdstb <= 1'b0;
+ end
+ end else if (state == `DATA) begin
+ predata <= {predata[6:0], SDI};
+ count <= count + 1;
+ if (count == 3'b111) begin
+ if (fixed == 3'b001) begin
+ state <= `COMMAND;
+ end else if (fixed != 3'b000) begin
+ fixed <= fixed - 1;
+ addr <= addr + 1; // Auto increment address (fixed)
+ end else begin
+ addr <= addr + 1; // Auto increment address (streaming)
+ end
+ end else begin
+ rdstb <= 1'b0;
+ end
+ end // ! state `DATA
+ end // ! csb_reset
+ end // always @ SCK
+
+endmodule // housekeeping_spi_slave
diff --git a/verilog/rtl/mgmt_core.v b/verilog/rtl/mgmt_core.v
index 26e7e55..bd52027 100644
--- a/verilog/rtl/mgmt_core.v
+++ b/verilog/rtl/mgmt_core.v
@@ -19,8 +19,7 @@
output flash_io1_oeb,
output flash_csb_ieb,
output flash_clk_ieb,
- output flash_io0_ieb,
- output flash_io1_ieb,
+ output flash_io0_ieb, output flash_io1_ieb,
output flash_io0_do,
output flash_io1_do,
input flash_io0_di,
@@ -29,14 +28,17 @@
input porb,
// Clocking
input clock,
- input ext_clk,
output pll_clk16,
// LA signals
input [127:0] la_input, // From Mega-Project to cpu
output [127:0] la_output, // From CPU to Mega-Project
output [127:0] la_oen, // LA output enable
// Mega-Project Control Signals
- inout [`MPRJ_IO_PADS-1:0] mgmt_io_data,
+ // inout [`MPRJ_IO_PADS-1:0] mgmt_io_data,
+ input [`MPRJ_IO_PADS-1:0] mgmt_in_data,
+ output [`MPRJ_IO_PADS-1:0] mgmt_out_data,
+ output [`MPRJ_IO_PADS-1:0] mgmt_outz_data,
+ output [`MPRJ_IO_PADS-1:0] mgmt_oeb_data,
output mprj_io_loader_resetn,
output mprj_io_loader_clock,
output mprj_io_loader_data,
@@ -66,22 +68,16 @@
input [31:0] mask_rev
);
wire ext_clk_sel;
- wire ext_clk;
wire pll_clk;
wire ext_reset;
- wire spi_sck;
- wire spi_csb;
- wire spi_sdi;
- wire spi_sdo;
-
caravel_clkrst clkrst(
`ifdef LVS
.vdd1v8(vdd1v8),
.vss(vss),
`endif
.ext_clk_sel(ext_clk_sel),
- .ext_clk(ext_clk),
+ .ext_clk(clock), // Should be better handled. . .
.pll_clk(pll_clk),
.resetb(porb),
.ext_reset(ext_reset),
@@ -93,18 +89,22 @@
// area pins, when under control of the management area (during
// startup, and when not otherwise programmed for the user project).
- // JTAG = mgmt_io_data[0] (inout)
- // SDO = mgmt_io_data[1] (output) (shared with SPI master)
- // SDI = mgmt_io_data[2] (input) (shared with SPI master)
- // CSB = mgmt_io_data[3] (input) (shared with SPI master)
- // SCK = mgmt_io_data[4] (input) (shared with SPI master)
- // ser_rx = mgmt_io_data[5] (input)
- // ser_tx = mgmt_io_data[6] (output)
- // irq = mgmt_io_data[7] (input)
- // flash_csb = mgmt_io_data[8] (output) (user area flash)
- // flash_sck = mgmt_io_data[9] (output) (user area flash)
- // flash_io0 = mgmt_io_data[10] (output) (user area flash)
- // flash_io1 = mgmt_io_data[11] (input) (user area flash)
+ // JTAG = mgmt_in/out_data[0] (inout)
+ // SDO = mgmt_out_data[1] (output) (shared with SPI master)
+ // SDI = mgmt_in_data[2] (input) (shared with SPI master)
+ // CSB = mgmt_in_data[3] (input) (shared with SPI master)
+ // SCK = mgmt_in_data[4] (input) (shared with SPI master)
+ // ser_rx = mgmt_in_data[5] (input)
+ // ser_tx = mgmt_out_data[6] (output)
+ // irq = mgmt_in_data[7] (input)
+ // flash_csb = mgmt_out_data[8] (output) (user area flash)
+ // flash_sck = mgmt_out_data[9] (output) (user area flash)
+ // flash_io0 = mgmt_in/out_data[10] (input) (user area flash)
+ // flash_io1 = mgmt_in/out_data[11] (output) (user area flash)
+
+ // OEB lines for [0] and [1] are the only ones connected directly to
+ // the pad. All others have OEB controlled by the configuration bit
+ // in the control block.
mgmt_soc soc (
`ifdef LVS
@@ -112,7 +112,7 @@
.vss(vss),
`endif
.pll_clk(pll_clk),
- .ext_clk(ext_clk),
+ .ext_clk(clock),
.ext_clk_sel(ext_clk_sel),
.clk(core_clk),
.resetn(core_rstn),
@@ -125,15 +125,16 @@
.gpio_outenb_pad(gpio_outenb_pad),
.gpio_inenb_pad(gpio_inenb_pad),
// UART
- .ser_tx(mgmt_io_data[6]),
- .ser_rx(mgmt_io_data[5]),
- .irq_pin(mgmt_io_data[7]),
+ .ser_tx(mgmt_out_data[6]),
+ .ser_rx(mgmt_in_data[5]),
+ .irq_pin(mgmt_in_data[7]),
.irq_spi(irq_spi),
// SPI master
- .spi_csb(spi_csb),
- .spi_sck(spi_sck),
- .spi_sdi(spi_sdi),
- .spi_sdo(spi_sdo),
+ .spi_csb(mgmt_out_data[3]),
+ .spi_sck(mgmt_out_data[4]),
+ .spi_sdi(mgmt_in_data[1]),
+ .spi_sdo(mgmt_out_data[2]),
+ .spi_sdoenb(mgmt_oeb_data[2]),
// Flash
.flash_csb(flash_csb),
.flash_clk(flash_clk),
@@ -172,7 +173,11 @@
.mprj_io_loader_clock(mprj_io_loader_clock),
.mprj_io_loader_data(mprj_io_loader_data),
// I/O data
- .mgmt_io_data(mgmt_io_data),
+ // .mgmt_io_data(mgmt_io_data),
+ .mgmt_in_data(mgmt_in_data),
+ .mgmt_out_data(mgmt_out_data),
+ .mgmt_outz_data(mgmt_outz_data),
+ .mgmt_oeb_data(mgmt_oeb_data),
// Mega Project Slave ports (WB MI A)
.mprj_cyc_o(mprj_cyc_o),
.mprj_stb_o(mprj_stb_o),
@@ -217,28 +222,25 @@
wire [25:0] spi_pll_trim;
// Housekeeping SPI (SPI slave module)
- caravel_spi housekeeping (
+ housekeeping_spi housekeeping (
`ifdef LVS
.vdd(vdd1v8),
.vss(vss),
`endif
.RSTB(porb),
- .SCK(mgmt_io_data[4]),
- .SDI(mgmt_io_data[2]),
- .CSB(mgmt_io_data[3]),
- .SDO(mgmt_io_data[1]),
+ .SCK(mgmt_in_data[4]),
+ .SDI(mgmt_in_data[2]),
+ .CSB(mgmt_in_data[3]),
+ .SDO(mgmt_out_data[1]),
+ .sdo_enb(mgmt_oeb_data[1]),
// Note that the Soc SPI master shares pins with the housekeeping
// SPI but with SDI and SDO reversed, such that the CPU can
// access the housekeeping SPI registers directly if the
// SPI master is enabled.
- .mgmt_sck(mgmt_io_data[4]),
- .mgmt_sdi(mgmt_io_data[1]),
- .mgmt_csb(mgmt_io_data[3]),
- .mgmt_sdo(mgmt_io_data[2]),
- // NOTE: SDO enable is not accessible in the current configuration.
- // May want to have a different type of GPIO control for the several
- // pins like SPI SDO that could benefit from it.
- .sdo_enb(),
+ .mgmt_sck(mgmt_in_data[4]),
+ .mgmt_sdi(mgmt_in_data[1]),
+ .mgmt_csb(mgmt_in_data[3]),
+ .mgmt_sdo(mgmt_out_data[2]),
.pll_dco_ena(spi_pll_dco_ena),
.pll_sel(spi_pll_sel),
.pll_div(spi_pll_div),
@@ -253,10 +255,10 @@
.pass_thru_mgmt_csb(pass_thru_mgmt_csb),
.pass_thru_mgmt_sdi(pass_thru_mgmt_sdi),
.pass_thru_mgmt_sdo(pass_thru_mgmt_sdo),
- .pass_thru_user_sck(mgmt_io_data[9]),
- .pass_thru_user_csb(mgmt_io_data[8]),
- .pass_thru_user_sdi(mgmt_io_data[10]),
- .pass_thru_user_sdo(mgmt_io_data[11])
+ .pass_thru_user_sck(mgmt_out_data[9]),
+ .pass_thru_user_csb(mgmt_out_data[8]),
+ .pass_thru_user_sdi(mgmt_out_data[10]),
+ .pass_thru_user_sdo(mgmt_in_data[11])
);
endmodule
diff --git a/verilog/rtl/mgmt_soc.v b/verilog/rtl/mgmt_soc.v
index 5162a9b..ce43250 100644
--- a/verilog/rtl/mgmt_soc.v
+++ b/verilog/rtl/mgmt_soc.v
@@ -76,12 +76,17 @@
output mprj_io_loader_data,
// Mega-Project pad data (when management SoC controls the pad)
- inout [MPRJ_IO_PADS-1:0] mgmt_io_data,
+ // inout [MPRJ_IO_PADS-1:0] mgmt_io_data,
+ input [MPRJ_IO_PADS-1:0] mgmt_in_data,
+ output [MPRJ_IO_PADS-1:0] mgmt_out_data,
+ output [MPRJ_IO_PADS-1:0] mgmt_outz_data,
+ output [MPRJ_IO_PADS-1:0] mgmt_oeb_data,
// SPI master
output spi_csb,
output spi_sck,
output spi_sdo,
+ output spi_sdoenb,
input spi_sdi,
// UART
@@ -209,9 +214,9 @@
parameter MPRJ_PWR_PADS = 32;
// System Control Registers
- parameter PLL_OUT = 8'h0c;
- parameter TRAP_OUT = 8'h10;
- parameter IRQ7_SRC = 8'h14;
+ parameter PLL_OUT = 8'h00;
+ parameter TRAP_OUT = 8'h04;
+ parameter IRQ7_SRC = 8'h08;
// Wishbone Interconnect
localparam ADR_WIDTH = 32;
@@ -477,6 +482,7 @@
.sck(spi_sck),
.sdi(spi_sdi),
.sdo(spi_sdo),
+ .sdoenb(spi_sdoenb),
.irq(irq_spi_master)
);
@@ -650,7 +656,11 @@
.serial_clock(mprj_io_loader_clock),
.serial_resetn(mprj_io_loader_resetn),
.serial_data_out(mprj_io_loader_data),
- .mgmt_gpio_io(mgmt_io_data)
+ // .mgmt_gpio_io(mgmt_io_data)
+ .mgmt_gpio_in(mgmt_in_data),
+ .mgmt_gpio_out(mgmt_out_data),
+ .mgmt_gpio_outz(mgmt_outz_data),
+ .mgmt_gpio_oeb(mgmt_oeb_data)
);
// Wishbone Slave RAM
diff --git a/verilog/rtl/mprj_ctrl.v b/verilog/rtl/mprj_ctrl.v
index 8970c41..cb67ac4 100644
--- a/verilog/rtl/mprj_ctrl.v
+++ b/verilog/rtl/mprj_ctrl.v
@@ -25,7 +25,10 @@
output serial_data_out,
// Read/write data to each GPIO pad from management SoC
- inout [IO_PADS-1:0] mgmt_gpio_io
+ input [IO_PADS-1:0] mgmt_gpio_in,
+ output [IO_PADS-1:0] mgmt_gpio_out,
+ output [IO_PADS-1:0] mgmt_gpio_outz,
+ output [IO_PADS-1:0] mgmt_gpio_oeb // Only JTAG and SDO connected
);
wire resetn;
wire valid;
@@ -58,7 +61,11 @@
.serial_clock(serial_clock),
.serial_resetn(serial_resetn),
.serial_data_out(serial_data_out),
- .mgmt_gpio_io(mgmt_gpio_io)
+ // .mgmt_gpio_io(mgmt_gpio_io)
+ .mgmt_gpio_in(mgmt_gpio_in),
+ .mgmt_gpio_out(mgmt_gpio_out),
+ .mgmt_gpio_outz(mgmt_gpio_outz),
+ .mgmt_gpio_oeb(mgmt_gpio_oeb)
);
endmodule
@@ -70,7 +77,7 @@
parameter CONFIG = 8'h 08,
parameter IO_PADS = 32,
parameter PWR_PADS = 32,
- parameter IO_CTRL_BITS = 14,
+ parameter IO_CTRL_BITS = 13,
parameter PWR_CTRL_BITS = 1
)(
input clk,
@@ -86,26 +93,35 @@
output serial_clock,
output serial_resetn,
output serial_data_out,
- inout [IO_PADS-1:0] mgmt_gpio_io
+ // inout [IO_PADS-1:0] mgmt_gpio_io
+ input [IO_PADS-1:0] mgmt_gpio_in,
+ output [IO_PADS-1:0] mgmt_gpio_out,
+ output [IO_PADS-1:0] mgmt_gpio_outz,
+ output [IO_PADS-1:0] mgmt_gpio_oeb
);
-`define START 2'b00
-`define XBYTE 2'b01
-`define LOAD 2'b10
+`define IDLE 2'b00
+`define START 2'b01
+`define XBYTE 2'b10
+`define LOAD 2'b11
localparam IO_BASE_ADR = (BASE_ADR | CONFIG);
localparam PWR_BASE_ADR = (BASE_ADR | CONFIG) + IO_PADS*4;
- localparam OEB = 1; // Offset of OEB in shift register block.
+ localparam OEB = 1; // Offset of output enable in shift register.
+ localparam INP_DIS = 3; // Offset of input disable in shift register.
reg [IO_CTRL_BITS-1:0] io_ctrl [IO_PADS-1:0]; // I/O control, 1 word per gpio pad
reg [PWR_CTRL_BITS-1:0] pwr_ctrl [PWR_PADS-1:0];// Power control, 1 word per power pad
- reg [IO_PADS-1:0] mgmt_gpio_out; // I/O read/write data, 1 bit per gpio pad
+ reg [IO_PADS-1:0] mgmt_gpio_out; // I/O write data, 1 bit per gpio pad
+ wire [IO_PADS-1:0] mgmt_gpio_outz; // I/O write data output when input disabled
+ wire [IO_PADS-1:0] mgmt_gpio_oeb;
reg xfer_ctrl; // Transfer control (1 bit)
wire [IO_PADS-1:0] io_ctrl_sel; // wishbone selects
wire [PWR_PADS-1:0] pwr_ctrl_sel;
wire io_data_sel;
wire xfer_sel;
+ wire [IO_PADS-1:0] mgmt_gpio_in;
assign xfer_sel = (iomem_addr[7:0] == XFER);
assign io_data_sel = (iomem_addr[7:0] == DATA);
@@ -114,14 +130,18 @@
// if OEB = 0 then mgmt_gpio_out --> mgmt_gpio_io; if OEB = 1 then
// mgmt_gpio_io --> mgmt_gpio_in. mgmt_gpio_in is always a copy of mgmt_gpio_io.
- assign mgmt_gpio_in = mgmt_gpio_io;
+ // assign mgmt_gpio_in = mgmt_gpio_io;
genvar i;
generate
for (i=0; i<IO_PADS; i=i+1) begin
assign io_ctrl_sel[i] = (iomem_addr[7:0] == (IO_BASE_ADR[7:0] + i*4));
- assign mgmt_gpio_io[i] = (io_ctrl[0][i] + OEB == 1'b0) ?
- mgmt_gpio_out[i] : 1'bz;
+ // OEB is both tranferred by serial chain and output; that way
+ // each pad can selectively choose whether to have a dedicated
+ // signal for OEB, or to use it as a static configuration bit.
+ assign mgmt_gpio_oeb[i] = io_ctrl[OEB][i];
+ assign mgmt_gpio_outz[i] = (io_ctrl[INP_DIS][i] == 1'b1) ?
+ mgmt_gpio_out[i] : 1'bz;
end
endgenerate
@@ -145,8 +165,9 @@
if (io_data_sel) begin
iomem_rdata <= mgmt_gpio_in;
- mgmt_gpio_out <= 'd0;
- if (iomem_wstrb[0]) mgmt_gpio_out[IO_PADS-1:0] <= iomem_wdata[IO_PADS-1:0];
+ if (iomem_wstrb[0]) begin
+ mgmt_gpio_out[IO_PADS-1:0] <= iomem_wdata[IO_PADS-1:0];
+ end
end else if (xfer_sel) begin
iomem_rdata <= {31'd0, xfer_ctrl};
@@ -162,7 +183,9 @@
if (!resetn) begin
// NOTE: This needs to be set to the specific bit sequence
// that initializes every I/O pad to the appropriate state on
- // startup.
+ // startup, to match the startup state at each pad. Otherwise
+ // surprises happen if not all pad configurations are applied
+ // from the program code, and a transfer is initiated.
io_ctrl[i] <= 'd0;
end else begin
if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
@@ -213,7 +236,7 @@
always @(posedge clk or negedge resetn) begin
if (resetn == 1'b0) begin
- xfer_state <= `START;
+ xfer_state <= `IDLE;
xfer_count <= 4'd0;
pad_count <= 6'd0;
serial_resetn <= 1'b0;
@@ -222,7 +245,13 @@
end else begin
- if (xfer_state == `START) begin
+ if (xfer_state == `IDLE) begin
+ serial_resetn <= 1'b0;
+ serial_clock <= 1'b0;
+ if (xfer_ctrl == 1'b1) begin
+ xfer_state <= `START;
+ end
+ end else if (xfer_state == `START) begin
serial_resetn <= 1'b1;
serial_clock <= 1'b0;
xfer_count <= 6'd0;
@@ -266,7 +295,7 @@
end else if (xfer_count == 4'd3) begin
serial_resetn <= 1'b1;
serial_clock <= 1'b0;
- xfer_state <= `START;
+ xfer_state <= `IDLE;
end
end
end
diff --git a/verilog/rtl/mprj_ctrl.v.orig b/verilog/rtl/mprj_ctrl.v.orig
new file mode 100644
index 0000000..35fc346
--- /dev/null
+++ b/verilog/rtl/mprj_ctrl.v.orig
@@ -0,0 +1,283 @@
+module mprj_ctrl_wb #(
+ parameter BASE_ADR = 32'h 2300_0000,
+ parameter DATA = 8'h 00,
+ parameter XFER = 8'h 04,
+ parameter CONFIG = 8'h 08,
+ parameter IO_PADS = 32, // Number of IO control registers
+ parameter PWR_PADS = 32 // Number of power control registers
+)(
+ input wb_clk_i,
+ input wb_rst_i,
+
+ input [31:0] wb_dat_i,
+ input [31:0] wb_adr_i,
+ input [3:0] wb_sel_i,
+ input wb_cyc_i,
+ input wb_stb_i,
+ input wb_we_i,
+
+ output [31:0] wb_dat_o,
+ output wb_ack_o,
+
+ // Output is to serial loader
+ output serial_clock,
+ output serial_resetn,
+ output serial_data_out,
+
+ // Read/write data to each GPIO pad from management SoC
+ inout [IO_PADS-1:0] mgmt_gpio_io
+);
+ wire resetn;
+ wire valid;
+ wire ready;
+ wire [3:0] iomem_we;
+
+ assign resetn = ~wb_rst_i;
+ assign valid = wb_stb_i && wb_cyc_i;
+
+ assign iomem_we = wb_sel_i & {4{wb_we_i}};
+ assign wb_ack_o = ready;
+
+ mprj_ctrl #(
+ .BASE_ADR(BASE_ADR),
+ .DATA(DATA),
+ .CONFIG(CONFIG),
+ .XFER(XFER),
+ .IO_PADS(IO_PADS),
+ .PWR_PADS(PWR_PADS)
+ ) mprj_ctrl (
+ .clk(wb_clk_i),
+ .resetn(resetn),
+ .iomem_addr(wb_adr_i),
+ .iomem_valid(valid),
+ .iomem_wstrb(iomem_we[1:0]),
+ .iomem_wdata(wb_dat_i),
+ .iomem_rdata(wb_dat_o),
+ .iomem_ready(ready),
+
+ .serial_clock(serial_clock),
+ .serial_resetn(serial_resetn),
+ .serial_data_out(serial_data_out),
+ .mgmt_gpio_io(mgmt_gpio_io)
+ );
+
+endmodule
+
+module mprj_ctrl #(
+ parameter BASE_ADR = 32'h 2300_0000,
+ parameter DATA = 8'h 00,
+ parameter XFER = 8'h 04,
+ parameter CONFIG = 8'h 08,
+ parameter IO_PADS = 32,
+ parameter PWR_PADS = 32,
+ parameter IO_CTRL_BITS = 14,
+ parameter PWR_CTRL_BITS = 1
+)(
+ input clk,
+ input resetn,
+
+ input [31:0] iomem_addr,
+ input iomem_valid,
+ input [1:0] iomem_wstrb,
+ input [31:0] iomem_wdata,
+ output reg [31:0] iomem_rdata,
+ output reg iomem_ready,
+
+ output serial_clock,
+ output serial_resetn,
+ output serial_data_out,
+ inout [IO_PADS-1:0] mgmt_gpio_io
+);
+
+`define IDLE 2'b00
+`define START 2'b01
+`define XBYTE 2'b10
+`define LOAD 2'b11
+
+ localparam IO_BASE_ADR = (BASE_ADR | CONFIG);
+ localparam PWR_BASE_ADR = (BASE_ADR | CONFIG) + IO_PADS*4;
+ localparam OEB = 1; // Offset of OEB in shift register block.
+
+ reg [IO_CTRL_BITS-1:0] io_ctrl [IO_PADS-1:0]; // I/O control, 1 word per gpio pad
+ reg [PWR_CTRL_BITS-1:0] pwr_ctrl [PWR_PADS-1:0];// Power control, 1 word per power pad
+ reg [IO_PADS-1:0] mgmt_gpio_out; // I/O read/write data, 1 bit per gpio pad
+ reg xfer_ctrl; // Transfer control (1 bit)
+
+ wire [IO_PADS-1:0] io_ctrl_sel; // wishbone selects
+ wire [PWR_PADS-1:0] pwr_ctrl_sel;
+ wire io_data_sel;
+ wire xfer_sel;
+ wire [IO_PADS-1:0] mgmt_gpio_in;
+
+ assign xfer_sel = (iomem_addr[7:0] == XFER);
+ assign io_data_sel = (iomem_addr[7:0] == DATA);
+
+ // Direction of mgmt_gpio_io depends on the value of io_ctrl pad bit 1 (OEB)
+ // if OEB = 0 then mgmt_gpio_out --> mgmt_gpio_io; if OEB = 1 then
+ // mgmt_gpio_io --> mgmt_gpio_in. mgmt_gpio_in is always a copy of mgmt_gpio_io.
+
+ assign mgmt_gpio_in = mgmt_gpio_io;
+
+ genvar i;
+ generate
+ for (i=0; i<IO_PADS; i=i+1) begin
+ assign io_ctrl_sel[i] = (iomem_addr[7:0] == (IO_BASE_ADR[7:0] + i*4));
+ assign mgmt_gpio_io[i] = (io_ctrl[0][i] + OEB == 1'b0) ?
+ mgmt_gpio_out[i] : 1'bz;
+ end
+ endgenerate
+
+ generate
+ for (i=0; i<PWR_PADS; i=i+1) begin
+ assign pwr_ctrl_sel[i] = (iomem_addr[7:0] == (PWR_BASE_ADR[7:0] + i*4));
+ end
+ endgenerate
+
+ // I/O transfer of xfer bit and gpio data to/from user project region under
+ // management SoC control
+
+ always @(posedge clk) begin
+ if (!resetn) begin
+ xfer_ctrl <= 0;
+ mgmt_gpio_out <= 'd0;
+ end else begin
+ iomem_ready <= 0;
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ iomem_ready <= 1'b 1;
+
+ if (io_data_sel) begin
+ iomem_rdata <= mgmt_gpio_in;
+ mgmt_gpio_out <= 'd0;
+ if (iomem_wstrb[0]) mgmt_gpio_out[IO_PADS-1:0] <= iomem_wdata[IO_PADS-1:0];
+
+ end else if (xfer_sel) begin
+ iomem_rdata <= {31'd0, xfer_ctrl};
+ if (iomem_wstrb[0]) xfer_ctrl <= iomem_wdata[1:0];
+ end
+ end
+ end
+ end
+
+ generate
+ for (i=0; i<IO_PADS; i=i+1) begin
+ always @(posedge clk) begin
+ if (!resetn) begin
+ // NOTE: This needs to be set to the specific bit sequence
+ // that initializes every I/O pad to the appropriate state on
+ // startup.
+ io_ctrl[i] <= 'd0;
+ end else begin
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ if (io_ctrl_sel[i]) begin
+ iomem_rdata <= io_ctrl[i];
+ // NOTE: Byte-wide write to io_ctrl is prohibited
+ if (iomem_wstrb[0])
+ io_ctrl[i] <= iomem_wdata[IO_CTRL_BITS-1:0];
+ end
+ end
+ end
+ end
+ end
+ endgenerate
+
+ generate
+ for (i=0; i<PWR_PADS; i=i+1) begin
+ always @(posedge clk) begin
+ if (!resetn) begin
+ pwr_ctrl[i] <= 'd0;
+ end else begin
+ if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
+ if (pwr_ctrl_sel[i]) begin
+ iomem_rdata <= pwr_ctrl[i];
+ if (iomem_wstrb[0])
+ pwr_ctrl[i] <= iomem_wdata[PWR_CTRL_BITS-1:0];
+ end
+ end
+ end
+ end
+ end
+ endgenerate
+
+ reg [3:0] xfer_count;
+ reg [5:0] pad_count;
+ reg [1:0] xfer_state;
+ reg serial_clock;
+ reg serial_resetn;
+ reg serial_data_out;
+
+ // NOTE: Ignoring power control bits for now. . . need to revisit.
+ // Depends on how the power pads are arranged among the GPIO, and
+ // whether or not switching will be internal and under the control
+ // of the SoC.
+
+ reg [IO_CTRL_BITS-1:0] serial_data_staging;
+
+ always @(posedge clk or negedge resetn) begin
+ if (resetn == 1'b0) begin
+
+ xfer_state <= `IDLE;
+ xfer_count <= 4'd0;
+ pad_count <= 6'd0;
+ serial_resetn <= 1'b0;
+ serial_clock <= 1'b0;
+ serial_data_out <= 1'b0;
+
+ end else begin
+
+ if (xfer_state == `IDLE) begin
+ serial_resetn <= 1'b0;
+ serial_clock <= 1'b0;
+ if (xfer_ctrl == 1'b1) begin
+ xfer_state <= `START;
+ end
+ end else if (xfer_state == `START) begin
+ serial_resetn <= 1'b1;
+ serial_clock <= 1'b0;
+ xfer_count <= 6'd0;
+ if (pad_count == IO_PADS) begin
+ xfer_state <= `LOAD;
+ end else begin
+ pad_count <= pad_count + 1;
+ xfer_state <= `XBYTE;
+ serial_data_staging <= io_ctrl[pad_count];
+ end
+ end else if (xfer_state == `XBYTE) begin
+ serial_resetn <= 1'b1;
+ serial_clock <= ~serial_clock;
+ if (serial_clock == 1'b0) begin
+ if (xfer_count == IO_CTRL_BITS) begin
+ xfer_state <= `START;
+ end else begin
+ xfer_count <= xfer_count + 1;
+ end
+ end else begin
+ serial_data_staging <= {serial_data_staging[IO_CTRL_BITS-2:0], 1'b0};
+ serial_data_out <= serial_data_staging[IO_CTRL_BITS-1];
+ end
+ end else if (xfer_state == `LOAD) begin
+ xfer_count <= xfer_count + 1;
+
+ /* Load sequence: Raise clock for final data shift in;
+ * Pulse reset low while clock is high
+ * Set clock back to zero.
+ * Return to idle mode.
+ */
+ if (xfer_count == 4'd0) begin
+ serial_clock <= 1'b1;
+ serial_resetn <= 1'b1;
+ end else if (xfer_count == 4'd1) begin
+ serial_clock <= 1'b1;
+ serial_resetn <= 1'b0;
+ end else if (xfer_count == 4'd2) begin
+ serial_clock <= 1'b1;
+ serial_resetn <= 1'b1;
+ end else if (xfer_count == 4'd3) begin
+ serial_resetn <= 1'b1;
+ serial_clock <= 1'b0;
+ xfer_state <= `IDLE;
+ end
+ end
+ end
+ end
+
+endmodule
diff --git a/verilog/rtl/mprj_io.v b/verilog/rtl/mprj_io.v
index 0238649..32ae628 100644
--- a/verilog/rtl/mprj_io.v
+++ b/verilog/rtl/mprj_io.v
@@ -1,14 +1,16 @@
module mprj_io(
- inout vdd,
+ inout vdd3v3,
inout vdd1v8,
inout vss,
input vddio_q,
input vssio_q,
input analog_a,
input analog_b,
- input [`MPRJ_IO_PADS-1:0] io,
+ input porb_h,
+ input por,
+ inout [`MPRJ_IO_PADS-1:0] io,
input [`MPRJ_IO_PADS-1:0] io_out,
- input [`MPRJ_IO_PADS-1:0] oeb_n,
+ input [`MPRJ_IO_PADS-1:0] oeb,
input [`MPRJ_IO_PADS-1:0] hldh_n,
input [`MPRJ_IO_PADS-1:0] enh,
input [`MPRJ_IO_PADS-1:0] inp_dis,
@@ -22,10 +24,9 @@
input [`MPRJ_IO_PADS*3-1:0] dm,
output [`MPRJ_IO_PADS-1:0] io_in
);
-
- `MPRJ_IO_PAD_V(io, io_in, io_out, `MPRJ_IO_PADS,
- oeb_n, hldh_n, enh, inp_dis, ib_mode_sel,
- vtrip_sel, slow_sel, holdolver,
- analog_en, analog_sel, analog_pol, dm);
+ `MPRJ_IO_PAD_V(io, io_in, io_out, `MPRJ_IO_PADS,
+ oeb, hldh_n, enh, inp_dis, ib_mode_sel,
+ vtrip_sel, slow_sel, holdover,
+ analog_en, analog_sel, analog_pol, dm);
endmodule
diff --git a/verilog/rtl/simple_spi_master.v b/verilog/rtl/simple_spi_master.v
index de6ac2a..dad5471 100755
--- a/verilog/rtl/simple_spi_master.v
+++ b/verilog/rtl/simple_spi_master.v
@@ -82,6 +82,7 @@
output csb, // SPI chip select
output sck, // SPI clock
output sdo, // SPI output
+ output sdoenb, // SPI output enable
output irq // interrupt output
);
@@ -175,13 +176,16 @@
wire irq_out;
wire sck;
wire sdo;
+ wire sdoenb;
// Define behavior for inverted SCK and inverted CSB
- assign csb = (invcsb) ? ~icsb : icsb;
- assign sck = (invsck) ? ~isck : isck;
+ assign csb = (enable == 1'b0) ? 1'bz : (invcsb) ? ~icsb : icsb;
+ assign sck = (enable == 1'b0) ? 1'bz : (invsck) ? ~isck : isck;
// No bidirectional 3-pin mode defined, so SDO is enabled whenever CSB is low.
- assign sdo = icsb ? 1'bz : isdo;
+ assign sdoenb = icsb;
+ // assign sdo = (enable == 1'b0) ? 1'bz : icsb ? 1'bz : isdo;
+ assign sdo = isdo;
assign irq_out = irqena & done;
diff --git a/verilog/rtl/spimemio.v b/verilog/rtl/spimemio.v
index 456c2d0..2d0b6fe 100644
--- a/verilog/rtl/spimemio.v
+++ b/verilog/rtl/spimemio.v
@@ -132,7 +132,13 @@
.cfgreg_we(cfgreg_we),
.cfgreg_di(wb_dat_i),
- .cfgreg_do(spimemio_cfgreg_do)
+ .cfgreg_do(spimemio_cfgreg_do),
+
+ .pass_thru(pass_thru),
+ .pass_thru_csb(pass_thru_csb),
+ .pass_thru_sck(pass_thru_sck),
+ .pass_thru_sdi(pass_thru_sdi),
+ .pass_thru_sdo(pass_thru_sdo)
);
endmodule
@@ -176,7 +182,13 @@
input [3:0] cfgreg_we,
input [31:0] cfgreg_di,
- output [31:0] cfgreg_do
+ output [31:0] cfgreg_do,
+
+ input pass_thru,
+ input pass_thru_csb,
+ input pass_thru_sck,
+ input pass_thru_sdi,
+ output pass_thru_sdo
);
reg xfer_resetn;
reg din_valid;
diff --git a/verilog/rtl/sysctrl.v b/verilog/rtl/sysctrl.v
index 62ed4fc..86ec1e5 100644
--- a/verilog/rtl/sysctrl.v
+++ b/verilog/rtl/sysctrl.v
@@ -1,8 +1,8 @@
module sysctrl_wb #(
parameter BASE_ADR = 32'h2F00_0000,
- parameter PLL_OUT = 8'h0c,
- parameter TRAP_OUT = 8'h10,
- parameter IRQ7_SRC = 8'h14
+ parameter PLL_OUT = 8'h00,
+ parameter TRAP_OUT = 8'h04,
+ parameter IRQ7_SRC = 8'h08
) (
input wb_clk_i,
input wb_rst_i,
@@ -60,9 +60,9 @@
module sysctrl #(
parameter BASE_ADR = 32'h2300_0000,
- parameter PLL_OUT = 8'h0c,
- parameter TRAP_OUT = 8'h10,
- parameter IRQ7_SRC = 8'h14
+ parameter PLL_OUT = 8'h00,
+ parameter TRAP_OUT = 8'h04,
+ parameter IRQ7_SRC = 8'h08
) (
input clk,
input resetn,