blob: d95f507033bbf0766b8d15e65544c4b153c0b311 [file] [log] [blame]
Charlie7d7207a2022-05-21 18:43:37 +01001/*
2 * SPDX-FileCopyrightText: 2020 Efabless Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * SPDX-License-Identifier: Apache-2.0
16 */
17
18// This include is relative to $CARAVEL_PATH (see Makefile)
19#include <defs.h>
20#include <stub.c>
21
22/*
23 IO Test:
24 - Configures MPRJ lower 8-IO pins as outputs
25 - Observes counter value through the MPRJ lower 8 IO pins (in the testbench)
26*/
27
Charlie7e131522022-05-24 23:56:27 +010028#define GPIO0_OE_WRITE_ADDR ((uint32_t*)0x33031000)
29#define GPIO0_OE_SET_ADDR ((uint32_t*)0x33031004)
30#define GPIO0_OE_CLEAR_ADDR ((uint32_t*)0x33031008)
31#define GPIO0_OE_TOGGLE_ADDR ((uint32_t*)0x3303100C)
32#define GPIO0_OUTPUT_WRITE_ADDR ((uint32_t*)0x33031010)
33#define GPIO0_OUTPUT_SET_ADDR ((uint32_t*)0x33031014)
34#define GPIO0_OUTPUT_CLEAR_ADDR ((uint32_t*)0x33031018)
35#define GPIO0_OUTPUT_TOGGLE_ADDR ((uint32_t*)0x3303101C)
36#define GPIO0_INPUT_ADDR ((uint32_t*)0x33031020)
37#define GPIO1_OE_WRITE_ADDR ((uint32_t*)0x33032000)
38#define GPIO1_OE_SET_ADDR ((uint32_t*)0x33032004)
39#define GPIO1_OE_CLEAR_ADDR ((uint32_t*)0x33032008)
40#define GPIO1_OE_TOGGLE_ADDR ((uint32_t*)0x3303200C)
41#define GPIO1_OUTPUT_WRITE_ADDR ((uint32_t*)0x33032010)
42#define GPIO1_OUTPUT_SET_ADDR ((uint32_t*)0x33032014)
43#define GPIO1_OUTPUT_CLEAR_ADDR ((uint32_t*)0x33032018)
44#define GPIO1_OUTPUT_TOGGLE_ADDR ((uint32_t*)0x3303201C)
45#define GPIO1_INPUT_ADDR ((uint32_t*)0x33032020)
Charlie7d7207a2022-05-21 18:43:37 +010046
47#define MPRJ_WB_ADDRESS (*(volatile uint32_t*)0x30000000)
48#define MPRJ_WB_DATA_LOCATION 0x30008000
49
50void wbWrite (uint32_t* location, uint32_t value)
51{
52 // Write the address
53 uint32_t locationData = (uint32_t)location;
54 MPRJ_WB_ADDRESS = locationData & 0xFFFF8000;
55
56 // Write the data
57 uint32_t writeAddress = (locationData & 0x00007FFF) | MPRJ_WB_DATA_LOCATION;
58 *((volatile uint32_t*)writeAddress) = value;
59}
60
61uint32_t wbRead (uint32_t* location)
62{
63 // Write the address
64 uint32_t locationData = (uint32_t)location;
65 MPRJ_WB_ADDRESS = locationData & 0xFFFF8000;
66
67 // Write the data
68 uint32_t writeAddress = (locationData & 0x00007FFF) | MPRJ_WB_DATA_LOCATION;
69 return *((volatile uint32_t*)writeAddress);
70}
71
72void nextTest (bool testPassing)
73{
Charlie7e131522022-05-24 23:56:27 +010074 uint32_t testPassingOutput = testPassing ? 0x01000 : 0;
75 wbWrite (GPIO0_OUTPUT_SET_ADDR, testPassingOutput | 0x02000);
76 wbWrite (GPIO0_OUTPUT_CLEAR_ADDR, 0x02000);
Charlie7d7207a2022-05-21 18:43:37 +010077}
78
79void main ()
80{
81 /*
82 IO Control Registers
83 | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
84 | 3-bits | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit | 1-bit |
85
86 Output: 0000_0110_0000_1110 (0x1808) = GPIO_MODE_USER_STD_OUTPUT
87 | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
88 | 110 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
89
90
91 Input: 0000_0001_0000_1111 (0x0402) = GPIO_MODE_USER_STD_INPUT_NOPULL
92 | DM | VTRIP | SLOW | AN_POL | AN_SEL | AN_EN | MOD_SEL | INP_DIS | HOLDH | OEB_N | MGMT_EN |
93 | 001 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
94
95 */
96
97 /* Set up the housekeeping SPI to be connected internally so */
98 /* that external pin changes don't affect it. */
99
100 // Connect the housekeeping SPI to the SPI master
101 // so that the CSB line is not left floating. This allows
102 // all of the GPIO pins to be used for user functions.
103
104 // https://github.com/efabless/caravel/blob/main/docs/other/gpio.txt
105
106 // Enable the wishbone bus
107 reg_wb_enable = 1;
108
109 // Enable GPIO
110 reg_mprj_io_12 = GPIO_MODE_USER_STD_OUTPUT;
111 reg_mprj_io_13 = GPIO_MODE_USER_STD_OUTPUT;
112 reg_mprj_io_14 = GPIO_MODE_USER_STD_OUTPUT;
113 reg_mprj_io_15 = GPIO_MODE_USER_STD_OUTPUT;
114 reg_mprj_io_16 = GPIO_MODE_USER_STD_OUTPUT;
115 reg_mprj_io_17 = GPIO_MODE_USER_STD_OUTPUT;
116 reg_mprj_io_18 = GPIO_MODE_USER_STD_INPUT_NOPULL;
117 reg_mprj_io_19 = GPIO_MODE_USER_STD_INPUT_NOPULL;
118
119 /* Apply configuration */
120 reg_mprj_xfer = 1;
121 while (reg_mprj_xfer == 1) {}
122
Charliee3126002022-05-21 18:51:44 +0100123 // Setup test output
124 bool testPass = true;
Charlie7e131522022-05-24 23:56:27 +0100125 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, 0x01000);
Charliee3126002022-05-21 18:51:44 +0100126
Charlie7e131522022-05-24 23:56:27 +0100127 wbWrite (GPIO0_OE_WRITE_ADDR, ~0x3F000);
128 wbWrite (GPIO0_OUTPUT_SET_ADDR, 0x04000);
129 wbWrite (GPIO0_OUTPUT_SET_ADDR, 0x08000);
130 wbWrite (GPIO0_OUTPUT_SET_ADDR, 0x10000);
131 wbWrite (GPIO0_OUTPUT_SET_ADDR, 0x20000);
132 wbWrite (GPIO0_OUTPUT_TOGGLE_ADDR, 0x3C000);
133 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, 0x3C000);
134 wbWrite (GPIO0_OUTPUT_CLEAR_ADDR, 0x04000);
135 wbWrite (GPIO0_OUTPUT_CLEAR_ADDR, 0x08000);
136 wbWrite (GPIO0_OUTPUT_CLEAR_ADDR, 0x10000);
137 wbWrite (GPIO0_OUTPUT_CLEAR_ADDR, 0x20000);
Charliee3126002022-05-21 18:51:44 +0100138 nextTest (testPass);
Charlie7e131522022-05-24 23:56:27 +0100139
140 wbWrite (GPIO1_OE_WRITE_ADDR, ~0x00000);
Charlie7d7207a2022-05-21 18:43:37 +0100141 uint32_t ioData = wbRead (GPIO1_INPUT_ADDR);
Charlie7e131522022-05-24 23:56:27 +0100142 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, (testPass ? 0x01000 : 0) | (ioData << 15));
Charliee3126002022-05-21 18:51:44 +0100143 if (ioData != 0x2) testPass = false; // input = 2'b10
Charlie7d7207a2022-05-21 18:43:37 +0100144
Charliee3126002022-05-21 18:51:44 +0100145 nextTest (testPass);
Charlie7d7207a2022-05-21 18:43:37 +0100146 ioData = wbRead (GPIO1_INPUT_ADDR);
Charlie7e131522022-05-24 23:56:27 +0100147 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, (testPass ? 0x01000 : 0) | (ioData << 15));
Charliee3126002022-05-21 18:51:44 +0100148 if (ioData != 0x1) testPass = false; // input = 2'b01
Charlie7d7207a2022-05-21 18:43:37 +0100149
Charliee3126002022-05-21 18:51:44 +0100150 nextTest (testPass);
Charlie7d7207a2022-05-21 18:43:37 +0100151 ioData = wbRead (GPIO1_INPUT_ADDR);
Charlie7e131522022-05-24 23:56:27 +0100152 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, (testPass ? 0x01000 : 0) | (ioData << 15));
Charliee3126002022-05-21 18:51:44 +0100153 if (ioData != 0x3) testPass = false; // input = 2'b11
Charlie7d7207a2022-05-21 18:43:37 +0100154
Charliee3126002022-05-21 18:51:44 +0100155 nextTest (testPass);
Charlie7d7207a2022-05-21 18:43:37 +0100156 ioData = wbRead (GPIO1_INPUT_ADDR);
Charlie7e131522022-05-24 23:56:27 +0100157 wbWrite (GPIO0_OUTPUT_WRITE_ADDR, (testPass ? 0x01000 : 0) | (ioData << 15));
Charliee3126002022-05-21 18:51:44 +0100158 if (ioData != 0) testPass = false; // input = 2'b00
Charlie7d7207a2022-05-21 18:43:37 +0100159
160 // Finish test
Charliee3126002022-05-21 18:51:44 +0100161 nextTest (testPass);
Charlie7d7207a2022-05-21 18:43:37 +0100162}