mirror of https://github.com/efabless/caravel.git
First major update; current code passes syntax checks in iverilog
and simulates, but fails testbench (not surprising at this stage).
This commit is contained in:
parent
f1909cab52
commit
bdfa747145
|
@ -0,0 +1,110 @@
|
|||
Caravel memory map vs. SPI register map
|
||||
----------------------------------------------------------------------------------
|
||||
SPI register description signal memory map address
|
||||
----------------------------------------------------------------------------------
|
||||
00 SPI status (reserved) (undefined) 2e00_0000
|
||||
01 Manufacturer ID (high) mfgr_id[11:8] 2e00_0006
|
||||
02 Manufacturer ID (low) mfgr_id[7:0] 2e00_0005
|
||||
03 Product ID prod_id[7:0] 2e00_0004
|
||||
04 User project ID mask_rev[31:24] 2e00_000b
|
||||
05 User project ID mask_rev[23:16] 2e00_000a
|
||||
06 User project ID mask_rev[15:8] 2e00_0009
|
||||
07 User project ID mask_rev[7:0] 2e00_0008
|
||||
08 CPU trap state trap 2e00_000c
|
||||
09 Power monitor usr1/2_vcc/vdd_pwrgood 2f00_0000
|
||||
0a Output redirect clk1/clk2/trap_output_dest 2f00_0004
|
||||
0b Input redirect irq_8/7_inputsrc 2f00_000c
|
||||
0c GPIO[0] configure gpio_configure[0][12:8] 2600_0025
|
||||
0d GPIO[0] configure gpio_configure[0][7:0] 2600_0024
|
||||
0e GPIO[1] configure gpio_configure[1][12:8] 2600_0029
|
||||
0f GPIO[1] configure gpio_configure[1][7:0] 2600_0028
|
||||
10 GPIO[2] configure gpio_configure[2][12:8] 2600_002d
|
||||
11 GPIO[2] configure gpio_configure[2][7:0] 2600_002c
|
||||
12 GPIO[3] configure gpio_configure[3][12:8] 2600_0031
|
||||
13 GPIO[3] configure gpio_configure[3][7:0] 2600_0030
|
||||
14 GPIO[4] configure gpio_configure[4][12:8] 2600_0035
|
||||
15 GPIO[4] configure gpio_configure[4][7:0] 2600_0034
|
||||
16 GPIO[5] configure gpio_configure[5][12:8] 2600_0039
|
||||
17 GPIO[5] configure gpio_configure[5][7:0] 2600_0038
|
||||
18 GPIO[6] configure gpio_configure[6][12:8] 2600_003d
|
||||
19 GPIO[6] configure gpio_configure[6][7:0] 2600_003c
|
||||
1a GPIO[7] configure gpio_configure[7][12:8] 2600_0041
|
||||
1b GPIO[7] configure gpio_configure[7][7:0] 2600_0040
|
||||
1c GPIO[8] configure gpio_configure[8][12:8] 2600_0045
|
||||
1d GPIO[8] configure gpio_configure[8][7:0] 2600_0044
|
||||
1e GPIO[9] configure gpio_configure[9][12:8] 2600_0049
|
||||
1f GPIO[9] configure gpio_configure[9][7:0] 2600_0048
|
||||
20 GPIO[10] configure gpio_configure[10][12:8] 2600_004d
|
||||
21 GPIO[10] configure gpio_configure[10][7:0] 2600_004c
|
||||
22 GPIO[11] configure gpio_configure[11][12:8] 2600_0051
|
||||
23 GPIO[11] configure gpio_configure[11][7:0] 2600_0050
|
||||
24 GPIO[12] configure gpio_configure[12][12:8] 2600_0055
|
||||
25 GPIO[12] configure gpio_configure[12][7:0] 2600_0054
|
||||
26 GPIO[13] configure gpio_configure[13][12:8] 2600_0059
|
||||
27 GPIO[13] configure gpio_configure[13][7:0] 2600_0058
|
||||
28 GPIO[14] configure gpio_configure[14][12:8] 2600_005d
|
||||
29 GPIO[14] configure gpio_configure[14][7:0] 2600_005c
|
||||
2a GPIO[15] configure gpio_configure[15][12:8] 2600_0061
|
||||
2b GPIO[15] configure gpio_configure[15][7:0] 2600_0060
|
||||
2c GPIO[16] configure gpio_configure[16][12:8] 2600_0065
|
||||
2d GPIO[16] configure gpio_configure[16][7:0] 2600_0064
|
||||
2e GPIO[17] configure gpio_configure[17][12:8] 2600_0069
|
||||
2f GPIO[17] configure gpio_configure[17][7:0] 2600_0068
|
||||
30 GPIO[18] configure gpio_configure[18][12:8] 2600_006d
|
||||
31 GPIO[18] configure gpio_configure[18][7:0] 2600_006c
|
||||
32 GPIO[19] configure gpio_configure[19][12:8] 2600_0071
|
||||
33 GPIO[19] configure gpio_configure[19][7:0] 2600_0070
|
||||
34 GPIO[20] configure gpio_configure[20][12:8] 2600_0075
|
||||
35 GPIO[20] configure gpio_configure[20][7:0] 2600_0074
|
||||
36 GPIO[21] configure gpio_configure[21][12:8] 2600_0079
|
||||
37 GPIO[21] configure gpio_configure[21][7:0] 2600_0078
|
||||
38 GPIO[22] configure gpio_configure[22][12:8] 2600_007d
|
||||
39 GPIO[22] configure gpio_configure[22][7:0] 2600_007c
|
||||
3a GPIO[23] configure gpio_configure[23][12:8] 2600_0081
|
||||
3b GPIO[23] configure gpio_configure[23][7:0] 2600_0080
|
||||
3c GPIO[24] configure gpio_configure[24][12:8] 2600_0085
|
||||
3d GPIO[24] configure gpio_configure[24][7:0] 2600_0084
|
||||
3e GPIO[25] configure gpio_configure[25][12:8] 2600_0089
|
||||
3f GPIO[25] configure gpio_configure[25][7:0] 2600_0088
|
||||
40 GPIO[26] configure gpio_configure[26][12:8] 2600_008d
|
||||
41 GPIO[26] configure gpio_configure[26][7:0] 2600_008c
|
||||
42 GPIO[27] configure gpio_configure[27][12:8] 2600_0091
|
||||
43 GPIO[27] configure gpio_configure[27][7:0] 2600_0090
|
||||
44 GPIO[28] configure gpio_configure[28][12:8] 2600_0095
|
||||
45 GPIO[28] configure gpio_configure[28][7:0] 2600_0094
|
||||
46 GPIO[29] configure gpio_configure[29][12:8] 2600_0099
|
||||
47 GPIO[29] configure gpio_configure[29][7:0] 2600_0098
|
||||
48 GPIO[30] configure gpio_configure[30][12:8] 2600_009d
|
||||
49 GPIO[30] configure gpio_configure[30][7:0] 2600_009c
|
||||
4a GPIO[31] configure gpio_configure[31][12:8] 2600_00a1
|
||||
4b GPIO[31] configure gpio_configure[31][7:0] 2600_00a0
|
||||
4c GPIO[32] configure gpio_configure[32][12:8] 2600_00a5
|
||||
4d GPIO[32] configure gpio_configure[32][7:0] 2600_00a4
|
||||
4e GPIO[33] configure gpio_configure[33][12:8] 2600_00a9
|
||||
4f GPIO[33] configure gpio_configure[33][7:0] 2600_00a8
|
||||
50 GPIO[34] configure gpio_configure[34][12:8] 2600_00ad
|
||||
51 GPIO[34] configure gpio_configure[34][7:0] 2600_00ac
|
||||
52 GPIO[35] configure gpio_configure[35][12:8] 2600_00b1
|
||||
53 GPIO[35] configure gpio_configure[35][7:0] 2600_00b0
|
||||
54 GPIO[36] configure gpio_configure[36][12:8] 2600_00b5
|
||||
55 GPIO[36] configure gpio_configure[36][7:0] 2600_00b4
|
||||
56 GPIO[37] configure gpio_configure[37][12:8] 2600_00b9
|
||||
57 GPIO[37] configure gpio_configure[37][7:0] 2600_00b8
|
||||
58 GPIO data mgmt_gpio_in[37:32] 2600_0010
|
||||
59 GPIO data mgmt_gpio_in[31:24] 2600_000f
|
||||
5a GPIO data mgmt_gpio_in[23:16] 2600_000e
|
||||
5b GPIO data mgmt_gpio_in[15:8] 2600_000d
|
||||
5c GPIO data mgmt_gpio_in[7:0] 2600_000c
|
||||
5d Power control pwr_ctrl_out[3:0] 2600_0004
|
||||
5e GPIO control serial_resetn/clock/data 2600_0000
|
||||
5f PLL enables pll_dco_ena, pll_ena 2e00_000c
|
||||
60 PLL bypass pll_bypass 2e00_0010
|
||||
61 IRQ irq 2e00_0014
|
||||
62 Reset reset 2e00_0018
|
||||
63 PLL trim pll_trim[31:24] 2e00_001f
|
||||
64 PLL trim pll_trim[23:16] 2e00_001e
|
||||
65 PLL trim pll_trim[15:8] 2e00_001d
|
||||
66 PLL trim pll_trim[7:0] 2e00_001c
|
||||
67 PLL source pll90_sel[2:0], pll_sel[2:0] 2e00_0020
|
||||
68 PLL divider pll_div[4:0] 2e00_0024
|
||||
----------------------------------------------------------------------------------
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _CARAVEL_H_
|
||||
#define _CARAVEL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// a pointer to this is a null pointer, but the compiler does not
|
||||
// know that because "sram" is a linker symbol from sections.lds.
|
||||
extern uint32_t sram;
|
||||
|
||||
// Pointer to firmware flash routines
|
||||
extern uint32_t flashio_worker_begin;
|
||||
extern uint32_t flashio_worker_end;
|
||||
|
||||
// Storage area (MGMT: 0x0100_0000, User: 0x0200_0000)
|
||||
#define reg_rw_block0 (*(volatile uint32_t*)0x01000000)
|
||||
#define reg_rw_block1 (*(volatile uint32_t*)0x01100000)
|
||||
#define reg_ro_block0 (*(volatile uint32_t*)0x02000000)
|
||||
|
||||
// UART (0x2000_0000)
|
||||
#define reg_uart_clkdiv (*(volatile uint32_t*)0x20000000)
|
||||
#define reg_uart_data (*(volatile uint32_t*)0x20000004)
|
||||
#define reg_uart_enable (*(volatile uint32_t*)0x20000008)
|
||||
|
||||
// GPIO (0x2100_0000)
|
||||
#define reg_gpio_data (*(volatile uint32_t*)0x21000000)
|
||||
#define reg_gpio_ena (*(volatile uint32_t*)0x21000004)
|
||||
#define reg_gpio_pu (*(volatile uint32_t*)0x21000008)
|
||||
#define reg_gpio_pd (*(volatile uint32_t*)0x2100000c)
|
||||
|
||||
// Logic Analyzer (0x2200_0000)
|
||||
#define reg_la0_data (*(volatile uint32_t*)0x25000000)
|
||||
#define reg_la1_data (*(volatile uint32_t*)0x25000004)
|
||||
#define reg_la2_data (*(volatile uint32_t*)0x25000008)
|
||||
#define reg_la3_data (*(volatile uint32_t*)0x2500000c)
|
||||
|
||||
#define reg_la0_oenb (*(volatile uint32_t*)0x25000010)
|
||||
#define reg_la1_oenb (*(volatile uint32_t*)0x25000014)
|
||||
#define reg_la2_oenb (*(volatile uint32_t*)0x25000018)
|
||||
#define reg_la3_oenb (*(volatile uint32_t*)0x2500001c)
|
||||
|
||||
#define reg_la0_iena (*(volatile uint32_t*)0x25000020)
|
||||
#define reg_la1_iena (*(volatile uint32_t*)0x25000024)
|
||||
#define reg_la2_iena (*(volatile uint32_t*)0x25000028)
|
||||
#define reg_la3_iena (*(volatile uint32_t*)0x2500002c)
|
||||
|
||||
#define reg_la_sample (*(volatile uint32_t*)0x25000030)
|
||||
|
||||
// User Project Control (0x2300_0000)
|
||||
#define reg_mprj_xfer (*(volatile uint32_t*)0x26000000)
|
||||
#define reg_mprj_pwr (*(volatile uint32_t*)0x26000004)
|
||||
#define reg_mprj_irq (*(volatile uint32_t*)0x2e000014)
|
||||
#define reg_mprj_datal (*(volatile uint32_t*)0x2600000c)
|
||||
#define reg_mprj_datah (*(volatile uint32_t*)0x26000010)
|
||||
|
||||
#define reg_mprj_io_0 (*(volatile uint32_t*)0x26000024)
|
||||
#define reg_mprj_io_1 (*(volatile uint32_t*)0x26000028)
|
||||
#define reg_mprj_io_2 (*(volatile uint32_t*)0x2600002c)
|
||||
#define reg_mprj_io_3 (*(volatile uint32_t*)0x26000030)
|
||||
#define reg_mprj_io_4 (*(volatile uint32_t*)0x26000034)
|
||||
#define reg_mprj_io_5 (*(volatile uint32_t*)0x26000038)
|
||||
#define reg_mprj_io_6 (*(volatile uint32_t*)0x2600003c)
|
||||
|
||||
#define reg_mprj_io_7 (*(volatile uint32_t*)0x26000040)
|
||||
#define reg_mprj_io_8 (*(volatile uint32_t*)0x26000044)
|
||||
#define reg_mprj_io_9 (*(volatile uint32_t*)0x26000048)
|
||||
#define reg_mprj_io_10 (*(volatile uint32_t*)0x2600004c)
|
||||
|
||||
#define reg_mprj_io_11 (*(volatile uint32_t*)0x26000050)
|
||||
#define reg_mprj_io_12 (*(volatile uint32_t*)0x26000054)
|
||||
#define reg_mprj_io_13 (*(volatile uint32_t*)0x26000058)
|
||||
#define reg_mprj_io_14 (*(volatile uint32_t*)0x2600005c)
|
||||
|
||||
#define reg_mprj_io_15 (*(volatile uint32_t*)0x26000060)
|
||||
#define reg_mprj_io_16 (*(volatile uint32_t*)0x26000064)
|
||||
#define reg_mprj_io_17 (*(volatile uint32_t*)0x26000068)
|
||||
#define reg_mprj_io_18 (*(volatile uint32_t*)0x2600006c)
|
||||
|
||||
#define reg_mprj_io_19 (*(volatile uint32_t*)0x26000070)
|
||||
#define reg_mprj_io_20 (*(volatile uint32_t*)0x26000074)
|
||||
#define reg_mprj_io_21 (*(volatile uint32_t*)0x26000078)
|
||||
#define reg_mprj_io_22 (*(volatile uint32_t*)0x2600007c)
|
||||
|
||||
#define reg_mprj_io_23 (*(volatile uint32_t*)0x26000080)
|
||||
#define reg_mprj_io_24 (*(volatile uint32_t*)0x26000084)
|
||||
#define reg_mprj_io_25 (*(volatile uint32_t*)0x26000088)
|
||||
#define reg_mprj_io_26 (*(volatile uint32_t*)0x2600008c)
|
||||
|
||||
#define reg_mprj_io_27 (*(volatile uint32_t*)0x26000090)
|
||||
#define reg_mprj_io_28 (*(volatile uint32_t*)0x26000094)
|
||||
#define reg_mprj_io_29 (*(volatile uint32_t*)0x26000098)
|
||||
#define reg_mprj_io_30 (*(volatile uint32_t*)0x2600009c)
|
||||
#define reg_mprj_io_31 (*(volatile uint32_t*)0x260000a0)
|
||||
|
||||
#define reg_mprj_io_32 (*(volatile uint32_t*)0x260000a4)
|
||||
#define reg_mprj_io_33 (*(volatile uint32_t*)0x260000a8)
|
||||
#define reg_mprj_io_34 (*(volatile uint32_t*)0x260000ac)
|
||||
#define reg_mprj_io_35 (*(volatile uint32_t*)0x260000b0)
|
||||
#define reg_mprj_io_36 (*(volatile uint32_t*)0x260000b4)
|
||||
#define reg_mprj_io_37 (*(volatile uint32_t*)0x260000b8)
|
||||
|
||||
// User 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)
|
||||
|
||||
// Bit fields for Flash SPI control
|
||||
#define FLASH_BITBANG_IO0 0x00000001
|
||||
#define FLASH_BITBANG_IO1 0x00000002
|
||||
#define FLASH_BITBANG_CLK 0x00000010
|
||||
#define FLASH_BITBANG_CSB 0x00000020
|
||||
#define FLASH_BITBANG_OEB0 0x00000100
|
||||
#define FLASH_BITBANG_OEB1 0x00000200
|
||||
#define FLASH_ENABLE 0x80000000
|
||||
|
||||
// Counter-Timer 0 Configuration
|
||||
#define reg_timer0_config (*(volatile uint32_t*)0x22000000)
|
||||
#define reg_timer0_value (*(volatile uint32_t*)0x22000004)
|
||||
#define reg_timer0_data (*(volatile uint32_t*)0x22000008)
|
||||
|
||||
// Counter-Timer 1 Configuration
|
||||
#define reg_timer1_config (*(volatile uint32_t*)0x23000000)
|
||||
#define reg_timer1_value (*(volatile uint32_t*)0x23000004)
|
||||
#define reg_timer1_data (*(volatile uint32_t*)0x23000008)
|
||||
|
||||
// Bit fields for Counter-timer configuration
|
||||
#define TIMER_ENABLE 0x01
|
||||
#define TIMER_ONESHOT 0x02
|
||||
#define TIMER_UPCOUNT 0x04
|
||||
#define TIMER_CHAIN 0x08
|
||||
#define TIMER_IRQ_ENABLE 0x10
|
||||
|
||||
// SPI Master Configuration
|
||||
#define reg_spimaster_config (*(volatile uint32_t*)0x24000000)
|
||||
#define reg_spimaster_data (*(volatile uint32_t*)0x24000004)
|
||||
|
||||
// Bit fields for SPI master configuration
|
||||
#define SPI_MASTER_DIV_MASK 0x00ff
|
||||
#define SPI_MASTER_MLB 0x0100
|
||||
#define SPI_MASTER_INV_CSB 0x0200
|
||||
#define SPI_MASTER_INV_CLK 0x0400
|
||||
#define SPI_MASTER_MODE_1 0x0800
|
||||
#define SPI_MASTER_STREAM 0x1000
|
||||
#define SPI_MASTER_ENABLE 0x2000
|
||||
#define SPI_MASTER_IRQ_ENABLE 0x4000
|
||||
#define SPI_HOUSEKEEPING_CONN 0x8000
|
||||
|
||||
// System Area (0x2F00_0000)
|
||||
#define reg_power_good (*(volatile uint32_t*)0x2F000000)
|
||||
#define reg_clk_out_dest (*(volatile uint32_t*)0x2F000004)
|
||||
#define reg_trap_out_dest (*(volatile uint32_t*)0x2F000004)
|
||||
#define reg_irq_source (*(volatile uint32_t*)0x2F00000C)
|
||||
|
||||
// Bit fields for reg_power_good
|
||||
#define USER1_VCCD_POWER_GOOD 0x01
|
||||
#define USER2_VCCD_POWER_GOOD 0x02
|
||||
#define USER1_VDDA_POWER_GOOD 0x04
|
||||
#define USER2_VDDA_POWER_GOOD 0x08
|
||||
|
||||
// Bit fields for reg_clk_out_dest
|
||||
#define CLOCK1_MONITOR 0x01
|
||||
#define CLOCK2_MONITOR 0x02
|
||||
#define TRAP_MONITOR 0x04
|
||||
|
||||
// Bit fields for reg_irq_source
|
||||
#define IRQ7_SOURCE 0x01
|
||||
#define IRQ8_SOURCE 0x02
|
||||
|
||||
// Individual bit fields for the GPIO pad control
|
||||
#define MGMT_ENABLE 0x0001
|
||||
#define OUTPUT_DISABLE 0x0002
|
||||
#define HOLD_OVERRIDE 0x0004
|
||||
#define INPUT_DISABLE 0x0008
|
||||
#define MODE_SELECT 0x0010
|
||||
#define ANALOG_ENABLE 0x0020
|
||||
#define ANALOG_SELECT 0x0040
|
||||
#define ANALOG_POLARITY 0x0080
|
||||
#define SLOW_SLEW_MODE 0x0100
|
||||
#define TRIPPOINT_SEL 0x0200
|
||||
#define DIGITAL_MODE_MASK 0x1c00
|
||||
|
||||
// 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 0x1809
|
||||
#define GPIO_MODE_MGMT_STD_BIDIRECTIONAL 0x1801
|
||||
#define GPIO_MODE_MGMT_STD_ANALOG 0x000b
|
||||
|
||||
#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 0x1808
|
||||
#define GPIO_MODE_USER_STD_BIDIRECTIONAL 0x1800
|
||||
#define GPIO_MODE_USER_STD_OUT_MONITORED 0x1802
|
||||
#define GPIO_MODE_USER_STD_ANALOG 0x000a
|
||||
|
||||
// --------------------------------------------------------
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
# SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
PDK_PATH = $(PDK_ROOT)/sky130A
|
||||
VERILOG_PATH = ../../../..
|
||||
RTL_PATH = $(VERILOG_PATH)/rtl
|
||||
BEHAVIOURAL_MODELS = ../../
|
||||
|
||||
# Temporary: Path to management SoC wrapper repository
|
||||
MGMT_WRAPPER_PATH = ~/gits/caravel_pico/verilog/rtl
|
||||
|
||||
FIRMWARE_PATH = ../..
|
||||
GCC_PATH?=/ef/apps/bin
|
||||
GCC_PREFIX?=riscv32-unknown-elf
|
||||
|
||||
SIM_DEFINES = -DFUNCTIONAL -DSIM
|
||||
|
||||
SIM?=RTL
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
PATTERN = gpio
|
||||
|
||||
all: ${PATTERN:=.vcd}
|
||||
|
||||
hex: ${PATTERN:=.hex}
|
||||
|
||||
%.vvp: %_tb.v %.hex
|
||||
ifeq ($(SIM),RTL)
|
||||
iverilog -Ttyp $(SIM_DEFINES) -I $(BEHAVIOURAL_MODELS) \
|
||||
-I $(PDK_PATH) -I $(RTL_PATH) -I $(MGMT_WRAPPER_PATH) \
|
||||
$< -o $@
|
||||
else
|
||||
iverilog -Ttyp $(SIM_DEFINES) -DGL -I $(BEHAVIOURAL_MODELS) \
|
||||
-I $(PDK_PATH) -I $(VERILOG_PATH) -I $(RTL_PATH) \
|
||||
$< -o $@
|
||||
endif
|
||||
|
||||
%.vcd: %.vvp
|
||||
vvp $<
|
||||
|
||||
%.elf: %.c $(FIRMWARE_PATH)/sections.lds $(FIRMWARE_PATH)/start.s check-env
|
||||
${GCC_PATH}/${GCC_PREFIX}-gcc -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(FIRMWARE_PATH)/start.s $<
|
||||
|
||||
%.hex: %.elf
|
||||
${GCC_PATH}/${GCC_PREFIX}-objcopy -O verilog $< $@
|
||||
# to fix flash base address
|
||||
sed -i 's/@10000000/@00000000/g' $@
|
||||
|
||||
%.bin: %.elf
|
||||
${GCC_PATH}/${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@
|
||||
|
||||
check-env:
|
||||
ifndef PDK_ROOT
|
||||
$(error PDK_ROOT is undefined, please export it before running make)
|
||||
endif
|
||||
ifeq (,$(wildcard $(PDK_ROOT)/sky130A))
|
||||
$(error $(PDK_ROOT)/sky130A not found, please install pdk before running make)
|
||||
endif
|
||||
ifeq (,$(wildcard $(GCC_PATH)/$(GCC_PREFIX)-gcc ))
|
||||
$(error $(GCC_PATH)/$(GCC_PREFIX)-gcc is not found, please export GCC_PATH and GCC_PREFIX before running make)
|
||||
endif
|
||||
# check for efabless style installation
|
||||
ifeq (,$(wildcard $(PDK_ROOT)/sky130A/libs.ref/*/verilog))
|
||||
SIM_DEFINES := ${SIM_DEFINES} -DEF_STYLE
|
||||
endif
|
||||
# ---- Clean ----
|
||||
|
||||
clean:
|
||||
rm -f *.elf *.hex *.bin *.vvp *.vcd *.log
|
||||
|
||||
.PHONY: clean hex all
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<!---
|
||||
# SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
------------------------------------------------
|
||||
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.
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "../../defs.h"
|
||||
|
||||
// --------------------------------------------------------
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* Set data out to zero */
|
||||
reg_mprj_datal = 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;
|
||||
while (reg_mprj_xfer == 1);
|
||||
|
||||
// change the pull up and pull down (checked by the TB)
|
||||
reg_mprj_datal = 0xa0000000;
|
||||
|
||||
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;
|
||||
while (reg_mprj_xfer == 1);
|
||||
|
||||
reg_mprj_datal = 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;
|
||||
while (reg_mprj_xfer == 1);
|
||||
|
||||
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;
|
||||
while (reg_mprj_xfer == 1);
|
||||
|
||||
// read the lower 8 pins, add 1 then output the result
|
||||
// checked by the TB
|
||||
reg_mprj_datal = 0xab000000;
|
||||
|
||||
while (1){
|
||||
int x = (reg_mprj_datal & 0xff0000) >> 16;
|
||||
reg_mprj_datal = (x+1) << 24;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
`default_nettype none
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Clifford Wolf, 2018 Tim Edwards
|
||||
*
|
||||
* StriVe - A full example SoC using PicoRV32 in SkyWater s8
|
||||
*
|
||||
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
|
||||
* Copyright (C) 2018 Tim Edwards <tim@efabless.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*/
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
`include "__uprj_netlists.v"
|
||||
`include "caravel_netlists.v"
|
||||
`include "spiflash.v"
|
||||
|
||||
// NOTE: Temporary location of management SoC wrapper is a symbolic link
|
||||
// to the caravel_pico repository verilog/rtl/mgmt_core_wrapper.v
|
||||
`include "mgmt_core_wrapper.v"
|
||||
|
||||
module gpio_tb;
|
||||
|
||||
reg clock;
|
||||
reg power1;
|
||||
reg power2;
|
||||
|
||||
always #10 clock <= (clock === 1'b0);
|
||||
|
||||
initial begin
|
||||
clock <= 0;
|
||||
end
|
||||
|
||||
initial begin
|
||||
$dumpfile("gpio.vcd");
|
||||
$dumpvars(0, gpio_tb);
|
||||
|
||||
// Repeat cycles of 1000 clock edges as needed to complete testbench
|
||||
repeat (25) begin
|
||||
repeat (1000) @(posedge clock);
|
||||
$display("+1000 cycles");
|
||||
end
|
||||
$display("%c[1;31m",27);
|
||||
`ifdef GL
|
||||
$display ("Monitor: Timeout, Test GPIO (GL) Failed");
|
||||
`else
|
||||
$display ("Monitor: Timeout, Test GPIO (RTL) Failed");
|
||||
`endif
|
||||
$display("%c[0m",27);
|
||||
$finish;
|
||||
end
|
||||
|
||||
wire [37:0] mprj_io; // Most of these are no-connects
|
||||
wire [15:0] checkbits;
|
||||
reg [7:0] checkbits_lo;
|
||||
wire [7:0] checkbits_hi;
|
||||
|
||||
assign mprj_io[23:16] = checkbits_lo;
|
||||
assign checkbits = mprj_io[31:16];
|
||||
assign checkbits_hi = checkbits[15:8];
|
||||
assign mprj_io[3] = 1'b1; // Force CSB high.
|
||||
|
||||
wire flash_csb;
|
||||
wire flash_clk;
|
||||
wire flash_io0;
|
||||
wire flash_io1;
|
||||
wire gpio;
|
||||
|
||||
reg RSTB;
|
||||
|
||||
// Transactor
|
||||
initial begin
|
||||
checkbits_lo <= {8{1'bz}};
|
||||
wait(checkbits_hi == 8'hA0);
|
||||
checkbits_lo <= 8'hF0;
|
||||
wait(checkbits_hi == 8'h0B);
|
||||
checkbits_lo <= 8'h0F;
|
||||
wait(checkbits_hi == 8'hAB);
|
||||
checkbits_lo <= 8'h0;
|
||||
repeat (1000) @(posedge clock);
|
||||
checkbits_lo <= 8'h1;
|
||||
repeat (1000) @(posedge clock);
|
||||
checkbits_lo <= 8'h3;
|
||||
end
|
||||
|
||||
// Monitor
|
||||
initial begin
|
||||
wait(checkbits_hi == 8'hA0);
|
||||
wait(checkbits[7:0] == 8'hF0);
|
||||
wait(checkbits_hi == 8'h0B);
|
||||
wait(checkbits[7:0] == 8'h0F);
|
||||
wait(checkbits_hi == 8'hAB);
|
||||
wait(checkbits[7:0] == 8'h00);
|
||||
wait(checkbits_hi == 8'h01);
|
||||
wait(checkbits[7:0] == 8'h01);
|
||||
wait(checkbits_hi == 8'h02);
|
||||
wait(checkbits[7:0] == 8'h03);
|
||||
wait(checkbits_hi == 8'h04);
|
||||
`ifdef GL
|
||||
$display("Monitor: Test GPIO (GL) Passed");
|
||||
`else
|
||||
$display("Monitor: Test GPIO (RTL) Passed");
|
||||
`endif
|
||||
$finish;
|
||||
end
|
||||
|
||||
initial begin
|
||||
RSTB <= 1'b0;
|
||||
|
||||
#1000;
|
||||
RSTB <= 1'b1; // Release reset
|
||||
#2000;
|
||||
end
|
||||
|
||||
initial begin // Power-up
|
||||
power1 <= 1'b0;
|
||||
power2 <= 1'b0;
|
||||
#200;
|
||||
power1 <= 1'b1;
|
||||
#200;
|
||||
power2 <= 1'b1;
|
||||
end
|
||||
|
||||
|
||||
always @(checkbits) begin
|
||||
#1 $display("GPIO state = %b (%d - %d)", checkbits,
|
||||
checkbits_hi, checkbits_lo);
|
||||
end
|
||||
|
||||
wire VDD3V3;
|
||||
wire VDD1V8;
|
||||
wire VSS;
|
||||
|
||||
assign VDD3V3 = power1;
|
||||
assign VDD1V8 = power2;
|
||||
assign VSS = 1'b0;
|
||||
|
||||
// These are the mappings of mprj_io GPIO pads that are set to
|
||||
// specific functions on startup:
|
||||
//
|
||||
// JTAG = mgmt_gpio_io[0] (inout)
|
||||
// SDO = mgmt_gpio_io[1] (output)
|
||||
// SDI = mgmt_gpio_io[2] (input)
|
||||
// CSB = mgmt_gpio_io[3] (input)
|
||||
// SCK = mgmt_gpio_io[4] (input)
|
||||
// ser_rx = mgmt_gpio_io[5] (input)
|
||||
// ser_tx = mgmt_gpio_io[6] (output)
|
||||
// irq = mgmt_gpio_io[7] (input)
|
||||
|
||||
caravel uut (
|
||||
.vddio (VDD3V3),
|
||||
.vssio (VSS),
|
||||
.vdda (VDD3V3),
|
||||
.vssa (VSS),
|
||||
.vccd (VDD1V8),
|
||||
.vssd (VSS),
|
||||
.vdda1 (VDD3V3),
|
||||
.vdda2 (VDD3V3),
|
||||
.vssa1 (VSS),
|
||||
.vssa2 (VSS),
|
||||
.vccd1 (VDD1V8),
|
||||
.vccd2 (VDD1V8),
|
||||
.vssd1 (VSS),
|
||||
.vssd2 (VSS),
|
||||
.clock (clock),
|
||||
.gpio (gpio),
|
||||
.mprj_io (mprj_io),
|
||||
.flash_csb(flash_csb),
|
||||
.flash_clk(flash_clk),
|
||||
.flash_io0(flash_io0),
|
||||
.flash_io1(flash_io1),
|
||||
.resetb (RSTB)
|
||||
);
|
||||
|
||||
spiflash #(
|
||||
.FILENAME("gpio.hex")
|
||||
) spiflash (
|
||||
.csb(flash_csb),
|
||||
.clk(flash_clk),
|
||||
.io0(flash_io0),
|
||||
.io1(flash_io1),
|
||||
.io2(), // not used
|
||||
.io3() // not used
|
||||
);
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
# SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
MEMORY {
|
||||
FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x400000 /* 4MB */
|
||||
RAM(xrw) : ORIGIN = 0x00000000, LENGTH = 0x0400 /* 256 words (1 KB) */
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
/* The program code and other data goes into FLASH */
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
*(.srodata) /* .srodata sections (constants, strings, etc.) */
|
||||
*(.srodata*) /* .srodata*sections (constants, strings, etc.) */
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbol at end of code */
|
||||
_sidata = _etext; /* This is used by the startup to initialize data */
|
||||
} >FLASH
|
||||
|
||||
/* Initialized data section */
|
||||
.data : AT ( _sidata )
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sdata = .;
|
||||
_ram_start = .;
|
||||
. = ALIGN(4);
|
||||
*(.data)
|
||||
*(.data*)
|
||||
*(.sdata)
|
||||
*(.sdata*)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >RAM
|
||||
|
||||
/* Uninitialized data section */
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = .;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(.sbss)
|
||||
*(.sbss*)
|
||||
*(COMMON)
|
||||
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >RAM
|
||||
|
||||
/* Define the start of the heap */
|
||||
.heap :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_heap_start = .;
|
||||
} >RAM
|
||||
}
|
|
@ -0,0 +1,447 @@
|
|||
`default_nettype none
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2017 Clifford Wolf
|
||||
*
|
||||
* PicoSoC - A simple example SoC using PicoRV32
|
||||
*
|
||||
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* SPDX-License-Identifier: ISC
|
||||
*/
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
//
|
||||
// Simple SPI flash simulation model
|
||||
//
|
||||
// This model samples io input signals 1ns before the SPI clock edge and
|
||||
// updates output signals 1ns after the SPI clock edge.
|
||||
//
|
||||
// Supported commands:
|
||||
// AB, B9, FF, 03, BB, EB, ED
|
||||
//
|
||||
// Well written SPI flash data sheets:
|
||||
// Cypress S25FL064L http://www.cypress.com/file/316661/download
|
||||
// Cypress S25FL128L http://www.cypress.com/file/316171/download
|
||||
//
|
||||
|
||||
module spiflash #(
|
||||
parameter FILENAME = "firmware.hex"
|
||||
)(
|
||||
input csb,
|
||||
input clk,
|
||||
inout io0, // MOSI
|
||||
inout io1, // MISO
|
||||
inout io2,
|
||||
inout io3
|
||||
);
|
||||
localparam verbose = 0;
|
||||
localparam integer latency = 8;
|
||||
|
||||
reg [7:0] buffer;
|
||||
reg [3:0] reset_count = 0;
|
||||
reg [3:0] reset_monitor = 0;
|
||||
integer bitcount = 0;
|
||||
integer bytecount = 0;
|
||||
integer dummycount = 0;
|
||||
|
||||
reg [7:0] spi_cmd;
|
||||
reg [7:0] xip_cmd = 0;
|
||||
reg [23:0] spi_addr;
|
||||
|
||||
reg [7:0] spi_in;
|
||||
reg [7:0] spi_out;
|
||||
reg spi_io_vld;
|
||||
|
||||
reg powered_up = 0;
|
||||
|
||||
localparam [3:0] mode_spi = 1;
|
||||
localparam [3:0] mode_dspi_rd = 2;
|
||||
localparam [3:0] mode_dspi_wr = 3;
|
||||
localparam [3:0] mode_qspi_rd = 4;
|
||||
localparam [3:0] mode_qspi_wr = 5;
|
||||
localparam [3:0] mode_qspi_ddr_rd = 6;
|
||||
localparam [3:0] mode_qspi_ddr_wr = 7;
|
||||
|
||||
reg [3:0] mode = 0;
|
||||
reg [3:0] next_mode = 0;
|
||||
|
||||
reg io0_oe = 0;
|
||||
reg io1_oe = 0;
|
||||
reg io2_oe = 0;
|
||||
reg io3_oe = 0;
|
||||
|
||||
reg io0_dout = 0;
|
||||
reg io1_dout = 0;
|
||||
reg io2_dout = 0;
|
||||
reg io3_dout = 0;
|
||||
|
||||
assign #1 io0 = io0_oe ? io0_dout : 1'bz;
|
||||
assign #1 io1 = io1_oe ? io1_dout : 1'bz;
|
||||
assign #1 io2 = io2_oe ? io2_dout : 1'bz;
|
||||
assign #1 io3 = io3_oe ? io3_dout : 1'bz;
|
||||
|
||||
wire io0_delayed;
|
||||
wire io1_delayed;
|
||||
wire io2_delayed;
|
||||
wire io3_delayed;
|
||||
|
||||
assign #1 io0_delayed = io0;
|
||||
assign #1 io1_delayed = io1;
|
||||
assign #1 io2_delayed = io2;
|
||||
assign #1 io3_delayed = io3;
|
||||
|
||||
// 16 MB (128Mb) Flash
|
||||
reg [7:0] memory [0:16*1024*1024-1];
|
||||
|
||||
initial begin
|
||||
$display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
|
||||
memory[1048576], memory[1048577], memory[1048578],
|
||||
memory[1048579], memory[1048580]);
|
||||
$display("Reading %s", FILENAME);
|
||||
$readmemh(FILENAME, memory);
|
||||
$display("%s loaded into memory", FILENAME);
|
||||
$display("Memory 5 bytes = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x",
|
||||
memory[1048576], memory[1048577], memory[1048578],
|
||||
memory[1048579], memory[1048580]);
|
||||
end
|
||||
|
||||
task spi_action;
|
||||
begin
|
||||
spi_in = buffer;
|
||||
|
||||
if (bytecount == 1) begin
|
||||
spi_cmd = buffer;
|
||||
|
||||
if (spi_cmd == 8'h ab)
|
||||
powered_up = 1;
|
||||
|
||||
if (spi_cmd == 8'h b9)
|
||||
powered_up = 0;
|
||||
|
||||
if (spi_cmd == 8'h ff)
|
||||
xip_cmd = 0;
|
||||
end
|
||||
|
||||
if (powered_up && spi_cmd == 'h 03) begin
|
||||
if (bytecount == 2)
|
||||
spi_addr[23:16] = buffer;
|
||||
|
||||
if (bytecount == 3)
|
||||
spi_addr[15:8] = buffer;
|
||||
|
||||
if (bytecount == 4)
|
||||
spi_addr[7:0] = buffer;
|
||||
|
||||
if (bytecount >= 4) begin
|
||||
buffer = memory[spi_addr];
|
||||
spi_addr = spi_addr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (powered_up && spi_cmd == 'h bb) begin
|
||||
if (bytecount == 1)
|
||||
mode = mode_dspi_rd;
|
||||
|
||||
if (bytecount == 2)
|
||||
spi_addr[23:16] = buffer;
|
||||
|
||||
if (bytecount == 3)
|
||||
spi_addr[15:8] = buffer;
|
||||
|
||||
if (bytecount == 4)
|
||||
spi_addr[7:0] = buffer;
|
||||
|
||||
if (bytecount == 5) begin
|
||||
xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
|
||||
mode = mode_dspi_wr;
|
||||
dummycount = latency;
|
||||
end
|
||||
|
||||
if (bytecount >= 5) begin
|
||||
buffer = memory[spi_addr];
|
||||
spi_addr = spi_addr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (powered_up && spi_cmd == 'h eb) begin
|
||||
if (bytecount == 1)
|
||||
mode = mode_qspi_rd;
|
||||
|
||||
if (bytecount == 2)
|
||||
spi_addr[23:16] = buffer;
|
||||
|
||||
if (bytecount == 3)
|
||||
spi_addr[15:8] = buffer;
|
||||
|
||||
if (bytecount == 4)
|
||||
spi_addr[7:0] = buffer;
|
||||
|
||||
if (bytecount == 5) begin
|
||||
xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
|
||||
mode = mode_qspi_wr;
|
||||
dummycount = latency;
|
||||
end
|
||||
|
||||
if (bytecount >= 5) begin
|
||||
buffer = memory[spi_addr];
|
||||
spi_addr = spi_addr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (powered_up && spi_cmd == 'h ed) begin
|
||||
if (bytecount == 1)
|
||||
next_mode = mode_qspi_ddr_rd;
|
||||
|
||||
if (bytecount == 2)
|
||||
spi_addr[23:16] = buffer;
|
||||
|
||||
if (bytecount == 3)
|
||||
spi_addr[15:8] = buffer;
|
||||
|
||||
if (bytecount == 4)
|
||||
spi_addr[7:0] = buffer;
|
||||
|
||||
if (bytecount == 5) begin
|
||||
xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
|
||||
mode = mode_qspi_ddr_wr;
|
||||
dummycount = latency;
|
||||
end
|
||||
|
||||
if (bytecount >= 5) begin
|
||||
buffer = memory[spi_addr];
|
||||
spi_addr = spi_addr + 1;
|
||||
end
|
||||
end
|
||||
|
||||
spi_out = buffer;
|
||||
spi_io_vld = 1;
|
||||
|
||||
if (verbose) begin
|
||||
if (bytecount == 1)
|
||||
$write("<SPI-START>");
|
||||
$write("<SPI:%02x:%02x>", spi_in, spi_out);
|
||||
end
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
task ddr_rd_edge;
|
||||
begin
|
||||
buffer = {buffer, io3_delayed, io2_delayed, io1_delayed, io0_delayed};
|
||||
bitcount = bitcount + 4;
|
||||
if (bitcount == 8) begin
|
||||
bitcount = 0;
|
||||
bytecount = bytecount + 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
task ddr_wr_edge;
|
||||
begin
|
||||
io0_oe = 1;
|
||||
io1_oe = 1;
|
||||
io2_oe = 1;
|
||||
io3_oe = 1;
|
||||
|
||||
io0_dout = buffer[4];
|
||||
io1_dout = buffer[5];
|
||||
io2_dout = buffer[6];
|
||||
io3_dout = buffer[7];
|
||||
|
||||
buffer = {buffer, 4'h 0};
|
||||
bitcount = bitcount + 4;
|
||||
if (bitcount == 8) begin
|
||||
bitcount = 0;
|
||||
bytecount = bytecount + 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
endtask
|
||||
|
||||
always @(csb) begin
|
||||
if (csb) begin
|
||||
if (verbose) begin
|
||||
$display("");
|
||||
$fflush;
|
||||
end
|
||||
buffer = 0;
|
||||
bitcount = 0;
|
||||
bytecount = 0;
|
||||
mode = mode_spi;
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
|
||||
// Handle MBR. If in XIP continuous mode, the following
|
||||
// 8 clock cycles are normally not expected to be a command.
|
||||
// If followed by CSB high, however, if the address bits
|
||||
// are consistent with io0 == 1 for 8 clk cycles, then an
|
||||
// MBR has been issued and the system must exit XIP
|
||||
// continuous mode.
|
||||
if (xip_cmd == 8'hbb || xip_cmd == 8'heb
|
||||
|| xip_cmd == 8'hed) begin
|
||||
if (reset_count == 4'h8 && reset_monitor == 4'h8) begin
|
||||
xip_cmd = 8'h00;
|
||||
spi_cmd = 8'h03;
|
||||
end
|
||||
end
|
||||
end else
|
||||
if (xip_cmd) begin
|
||||
buffer = xip_cmd;
|
||||
bitcount = 0;
|
||||
bytecount = 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk or posedge csb) begin
|
||||
if (csb == 1'b1) begin
|
||||
reset_count = 0;
|
||||
reset_monitor = 0;
|
||||
end else begin
|
||||
if (reset_count < 4'h9) begin
|
||||
reset_count = reset_count + 1;
|
||||
if (io0_delayed == 1'b1) begin
|
||||
reset_monitor = reset_monitor + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(csb, clk) begin
|
||||
spi_io_vld = 0;
|
||||
if (!csb && !clk) begin
|
||||
if (dummycount > 0) begin
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
end else
|
||||
case (mode)
|
||||
mode_spi: begin
|
||||
io0_oe = 0;
|
||||
io1_oe = 1;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
io1_dout = buffer[7];
|
||||
end
|
||||
mode_dspi_rd: begin
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
end
|
||||
mode_dspi_wr: begin
|
||||
io0_oe = 1;
|
||||
io1_oe = 1;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
io0_dout = buffer[6];
|
||||
io1_dout = buffer[7];
|
||||
end
|
||||
mode_qspi_rd: begin
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
end
|
||||
mode_qspi_wr: begin
|
||||
io0_oe = 1;
|
||||
io1_oe = 1;
|
||||
io2_oe = 1;
|
||||
io3_oe = 1;
|
||||
io0_dout = buffer[4];
|
||||
io1_dout = buffer[5];
|
||||
io2_dout = buffer[6];
|
||||
io3_dout = buffer[7];
|
||||
end
|
||||
mode_qspi_ddr_rd: begin
|
||||
ddr_rd_edge;
|
||||
end
|
||||
mode_qspi_ddr_wr: begin
|
||||
ddr_wr_edge;
|
||||
end
|
||||
endcase
|
||||
if (next_mode) begin
|
||||
case (next_mode)
|
||||
mode_qspi_ddr_rd: begin
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
io2_oe = 0;
|
||||
io3_oe = 0;
|
||||
end
|
||||
mode_qspi_ddr_wr: begin
|
||||
io0_oe = 1;
|
||||
io1_oe = 1;
|
||||
io2_oe = 1;
|
||||
io3_oe = 1;
|
||||
io0_dout = buffer[4];
|
||||
io1_dout = buffer[5];
|
||||
io2_dout = buffer[6];
|
||||
io3_dout = buffer[7];
|
||||
end
|
||||
endcase
|
||||
mode = next_mode;
|
||||
next_mode = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!csb) begin
|
||||
if (dummycount > 0) begin
|
||||
dummycount = dummycount - 1;
|
||||
end else
|
||||
case (mode)
|
||||
mode_spi: begin
|
||||
buffer = {buffer, io0};
|
||||
bitcount = bitcount + 1;
|
||||
if (bitcount == 8) begin
|
||||
bitcount = 0;
|
||||
bytecount = bytecount + 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
mode_dspi_rd, mode_dspi_wr: begin
|
||||
buffer = {buffer, io1, io0};
|
||||
bitcount = bitcount + 2;
|
||||
if (bitcount == 8) begin
|
||||
bitcount = 0;
|
||||
bytecount = bytecount + 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
mode_qspi_rd, mode_qspi_wr: begin
|
||||
buffer = {buffer, io3, io2, io1, io0};
|
||||
bitcount = bitcount + 4;
|
||||
if (bitcount == 8) begin
|
||||
bitcount = 0;
|
||||
bytecount = bytecount + 1;
|
||||
spi_action;
|
||||
end
|
||||
end
|
||||
mode_qspi_ddr_rd: begin
|
||||
ddr_rd_edge;
|
||||
end
|
||||
mode_qspi_ddr_wr: begin
|
||||
ddr_wr_edge;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -0,0 +1,174 @@
|
|||
# SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.section .text
|
||||
|
||||
start:
|
||||
|
||||
# zero-initialize register file
|
||||
addi x1, zero, 0
|
||||
# x2 (sp) is initialized by reset
|
||||
addi x3, zero, 0
|
||||
addi x4, zero, 0
|
||||
addi x5, zero, 0
|
||||
addi x6, zero, 0
|
||||
addi x7, zero, 0
|
||||
addi x8, zero, 0
|
||||
addi x9, zero, 0
|
||||
addi x10, zero, 0
|
||||
addi x11, zero, 0
|
||||
addi x12, zero, 0
|
||||
addi x13, zero, 0
|
||||
addi x14, zero, 0
|
||||
addi x15, zero, 0
|
||||
addi x16, zero, 0
|
||||
addi x17, zero, 0
|
||||
addi x18, zero, 0
|
||||
addi x19, zero, 0
|
||||
addi x20, zero, 0
|
||||
addi x21, zero, 0
|
||||
addi x22, zero, 0
|
||||
addi x23, zero, 0
|
||||
addi x24, zero, 0
|
||||
addi x25, zero, 0
|
||||
addi x26, zero, 0
|
||||
addi x27, zero, 0
|
||||
addi x28, zero, 0
|
||||
addi x29, zero, 0
|
||||
addi x30, zero, 0
|
||||
addi x31, zero, 0
|
||||
|
||||
# zero initialize scratchpad memory
|
||||
# setmemloop:
|
||||
# sw zero, 0(x1)
|
||||
# addi x1, x1, 4
|
||||
# blt x1, sp, setmemloop
|
||||
|
||||
# copy data section
|
||||
la a0, _sidata
|
||||
la a1, _sdata
|
||||
la a2, _edata
|
||||
bge a1, a2, end_init_data
|
||||
loop_init_data:
|
||||
lw a3, 0(a0)
|
||||
sw a3, 0(a1)
|
||||
addi a0, a0, 4
|
||||
addi a1, a1, 4
|
||||
blt a1, a2, loop_init_data
|
||||
end_init_data:
|
||||
|
||||
# zero-init bss section
|
||||
la a0, _sbss
|
||||
la a1, _ebss
|
||||
bge a0, a1, end_init_bss
|
||||
loop_init_bss:
|
||||
sw zero, 0(a0)
|
||||
addi a0, a0, 4
|
||||
blt a0, a1, loop_init_bss
|
||||
end_init_bss:
|
||||
|
||||
# call main
|
||||
call main
|
||||
loop:
|
||||
j loop
|
||||
|
||||
.global flashio_worker_begin
|
||||
.global flashio_worker_end
|
||||
|
||||
.balign 4
|
||||
|
||||
flashio_worker_begin:
|
||||
# a0 ... data pointer
|
||||
# a1 ... data length
|
||||
# a2 ... optional WREN cmd (0 = disable)
|
||||
|
||||
# address of SPI ctrl reg
|
||||
li t0, 0x28000000
|
||||
|
||||
# Set CS high, IO0 is output
|
||||
li t1, 0x120
|
||||
sh t1, 0(t0)
|
||||
|
||||
# Enable Manual SPI Ctrl
|
||||
sb zero, 3(t0)
|
||||
|
||||
# Send optional WREN cmd
|
||||
beqz a2, flashio_worker_L1
|
||||
li t5, 8
|
||||
andi t2, a2, 0xff
|
||||
flashio_worker_L4:
|
||||
srli t4, t2, 7
|
||||
sb t4, 0(t0)
|
||||
ori t4, t4, 0x10
|
||||
sb t4, 0(t0)
|
||||
slli t2, t2, 1
|
||||
andi t2, t2, 0xff
|
||||
addi t5, t5, -1
|
||||
bnez t5, flashio_worker_L4
|
||||
sb t1, 0(t0)
|
||||
|
||||
# SPI transfer
|
||||
flashio_worker_L1:
|
||||
|
||||
# If byte count is zero, we're done
|
||||
beqz a1, flashio_worker_L3
|
||||
|
||||
# Set t5 to count down 32 bits
|
||||
li t5, 32
|
||||
# Load t2 from address a0 (4 bytes)
|
||||
lw t2, 0(a0)
|
||||
|
||||
flashio_worker_LY:
|
||||
# Set t6 to count down 8 bits
|
||||
li t6, 8
|
||||
|
||||
flashio_worker_L2:
|
||||
# Clock out the bit (msb first) on IO0 and read bit in from IO1
|
||||
srli t4, t2, 31
|
||||
sb t4, 0(t0)
|
||||
ori t4, t4, 0x10
|
||||
sb t4, 0(t0)
|
||||
lbu t4, 0(t0)
|
||||
andi t4, t4, 2
|
||||
srli t4, t4, 1
|
||||
slli t2, t2, 1
|
||||
or t2, t2, t4
|
||||
|
||||
# Decrement 32 bit count
|
||||
addi t5, t5, -1
|
||||
bnez t5, flashio_worker_LX
|
||||
|
||||
sw t2, 0(a0)
|
||||
addi a0, a0, 4
|
||||
lw t2, 0(a0)
|
||||
|
||||
flashio_worker_LX:
|
||||
addi t6, t6, -1
|
||||
bnez t6, flashio_worker_L2
|
||||
addi a1, a1, -1
|
||||
bnez a1, flashio_worker_LY
|
||||
|
||||
beqz t5, flashio_worker_L3
|
||||
sw t2, 0(a0)
|
||||
|
||||
flashio_worker_L3:
|
||||
# Back to MEMIO mode
|
||||
li t1, 0x80
|
||||
sb t1, 3(t0)
|
||||
|
||||
ret
|
||||
.balign 4
|
||||
flashio_worker_end:
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* caravel, a project harness for the Google/SkyWater sky130 */
|
||||
/* fabrication process and open source PDK */
|
||||
|
@ -22,10 +23,17 @@
|
|||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/* Updated 10/15/2021: Revised using the housekeeping module */
|
||||
/* from housekeeping.v (refactoring a number of functions from */
|
||||
/* the management SoC). */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
module caravel (
|
||||
|
||||
// All top-level I/O are package-facing pins
|
||||
|
||||
inout vddio, // Common 3.3V padframe/ESD power
|
||||
inout vddio_2, // Common 3.3V padframe/ESD power
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
|
@ -47,7 +55,6 @@ module caravel (
|
|||
|
||||
inout gpio, // Used for external LDO control
|
||||
inout [`MPRJ_IO_PADS-1:0] mprj_io,
|
||||
output [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out,
|
||||
input clock, // CMOS core clock input, not a crystal
|
||||
input resetb, // Reset input (sense inverted)
|
||||
|
||||
|
@ -159,12 +166,10 @@ module caravel (
|
|||
// 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 gpio_flash_io2_out, gpio_flash_io3_out;
|
||||
|
||||
wire [1:0] mgmt_io_nc; /* no-connects */
|
||||
wire [`MPRJ_IO_PADS-1:0] mgmt_io_in; /* one- and three-pin data */
|
||||
wire [`MPRJ_IO_PADS-5:0] mgmt_io_nc; /* no-connects */
|
||||
wire [3:0] mgmt_io_out; /* three-pin interface out */
|
||||
wire [3:0] mgmt_io_oeb; /* three-pin output enable */
|
||||
|
||||
wire clock_core;
|
||||
|
||||
|
@ -179,14 +184,28 @@ module caravel (
|
|||
wire rstb_h;
|
||||
wire rstb_l;
|
||||
|
||||
// Flash SPI communication (management SoC to housekeeping)
|
||||
wire flash_clk_core, flash_csb_core;
|
||||
wire flash_clk_oeb_core, flash_csb_oeb_core;
|
||||
wire flash_clk_ieb_core, flash_csb_ieb_core;
|
||||
wire flash_io0_oeb_core, flash_io1_oeb_core;
|
||||
wire flash_io2_oeb_core, flash_io3_oeb_core;
|
||||
wire flash_io0_ieb_core, flash_io1_ieb_core;
|
||||
wire flash_io2_ieb_core, flash_io3_ieb_core;
|
||||
wire flash_io0_do_core, flash_io1_do_core;
|
||||
wire flash_io2_do_core, flash_io3_do_core;
|
||||
wire flash_io0_di_core, flash_io1_di_core;
|
||||
wire flash_io2_di_core, flash_io3_di_core;
|
||||
|
||||
// Flash SPI communication (
|
||||
wire flash_clk_frame;
|
||||
wire flash_csb_frame;
|
||||
wire flash_clk_oeb, flash_csb_oeb;
|
||||
wire flash_clk_ieb, flash_csb_ieb;
|
||||
wire flash_io0_oeb, flash_io1_oeb;
|
||||
wire flash_io0_ieb, flash_io1_ieb;
|
||||
wire flash_io0_do, flash_io1_do;
|
||||
wire flash_io0_di, flash_io1_di;
|
||||
|
||||
chip_io padframe(
|
||||
`ifndef TOP_ROUTING
|
||||
|
@ -245,20 +264,20 @@ module caravel (
|
|||
.gpio_mode1_core(gpio_mode1_core),
|
||||
.gpio_outenb_core(gpio_outenb_core),
|
||||
.gpio_inenb_core(gpio_inenb_core),
|
||||
.flash_csb_core(flash_csb_core),
|
||||
.flash_clk_core(flash_clk_core),
|
||||
.flash_csb_oeb_core(flash_csb_oeb_core),
|
||||
.flash_clk_oeb_core(flash_clk_oeb_core),
|
||||
.flash_io0_oeb_core(flash_io0_oeb_core),
|
||||
.flash_io1_oeb_core(flash_io1_oeb_core),
|
||||
.flash_csb_ieb_core(flash_csb_ieb_core),
|
||||
.flash_clk_ieb_core(flash_clk_ieb_core),
|
||||
.flash_io0_ieb_core(flash_io0_ieb_core),
|
||||
.flash_io1_ieb_core(flash_io1_ieb_core),
|
||||
.flash_io0_do_core(flash_io0_do_core),
|
||||
.flash_io1_do_core(flash_io1_do_core),
|
||||
.flash_io0_di_core(flash_io0_di_core),
|
||||
.flash_io1_di_core(flash_io1_di_core),
|
||||
.flash_csb_core(flash_csb_frame),
|
||||
.flash_clk_core(flash_clk_frame),
|
||||
.flash_csb_oeb_core(flash_csb_oeb),
|
||||
.flash_clk_oeb_core(flash_clk_oeb),
|
||||
.flash_io0_oeb_core(flash_io0_oeb),
|
||||
.flash_io1_oeb_core(flash_io1_oeb),
|
||||
.flash_csb_ieb_core(flash_csb_ieb),
|
||||
.flash_clk_ieb_core(flash_clk_ieb),
|
||||
.flash_io0_ieb_core(flash_io0_ieb),
|
||||
.flash_io1_ieb_core(flash_io1_ieb),
|
||||
.flash_io0_do_core(flash_io0_do),
|
||||
.flash_io1_do_core(flash_io1_do),
|
||||
.flash_io0_di_core(flash_io0_di),
|
||||
.flash_io1_di_core(flash_io1_di),
|
||||
.mprj_io_in(mprj_io_in),
|
||||
.mprj_io_out(mprj_io_out),
|
||||
.mprj_io_oeb(mprj_io_oeb),
|
||||
|
@ -279,19 +298,12 @@ module caravel (
|
|||
wire caravel_clk2;
|
||||
wire caravel_rstn;
|
||||
|
||||
// LA signals
|
||||
wire [127:0] la_data_in_user; // From CPU to MPRJ
|
||||
wire [127:0] la_data_in_mprj; // From MPRJ to CPU
|
||||
wire [127:0] la_data_out_mprj; // From CPU to MPRJ
|
||||
wire [127:0] la_data_out_user; // From MPRJ to CPU
|
||||
wire [127:0] la_oenb_user; // From CPU to MPRJ
|
||||
wire [127:0] la_oenb_mprj; // From CPU to MPRJ
|
||||
wire [127:0] la_iena_mprj; // From CPU only
|
||||
wire [2:0] user_irq; // From MRPJ to CPU
|
||||
wire [2:0] user_irq; // From MRPJ to CPU
|
||||
wire [2:0] user_irq_core;
|
||||
wire [2:0] user_irq_ena;
|
||||
wire [2:0] irq_spi; // From SPI and external pins
|
||||
|
||||
// Exported Wishbone Bus
|
||||
// Exported Wishbone Bus (processor facing)
|
||||
wire mprj_cyc_o_core;
|
||||
wire mprj_stb_o_core;
|
||||
wire mprj_we_o_core;
|
||||
|
@ -301,28 +313,44 @@ module caravel (
|
|||
wire mprj_ack_i_core;
|
||||
wire [31:0] mprj_dat_i_core;
|
||||
|
||||
// Mask revision
|
||||
wire [31:0] mask_rev;
|
||||
wire [31:0] hk_dat_i;
|
||||
wire hk_ack_i;
|
||||
wire hk_stb_o;
|
||||
|
||||
wire mprj_clock;
|
||||
wire mprj_clock2;
|
||||
wire mprj_reset;
|
||||
// Exported Wishbone Bus (user area facing)
|
||||
wire mprj_cyc_o_user;
|
||||
wire mprj_stb_o_user;
|
||||
wire mprj_we_o_user;
|
||||
wire [3:0] mprj_sel_o_user;
|
||||
wire [31:0] mprj_adr_o_user;
|
||||
wire [31:0] mprj_dat_o_user;
|
||||
|
||||
// Mask revision
|
||||
wire [31:0] mask_rev;
|
||||
|
||||
wire mprj_clock;
|
||||
wire mprj_clock2;
|
||||
wire mprj_reset;
|
||||
|
||||
// Power monitoring
|
||||
wire mprj_vcc_pwrgood;
|
||||
wire mprj2_vcc_pwrgood;
|
||||
wire mprj_vdd_pwrgood;
|
||||
wire mprj2_vdd_pwrgood;
|
||||
|
||||
// Management processor (wrapper). Any management core
|
||||
// implementation must match this pinout.
|
||||
|
||||
mgmt_core_wrapper soc (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
|
||||
// Clock and reset
|
||||
.core_clk(caravel_clk),
|
||||
.core_rstn(caravel_rstn),
|
||||
|
||||
// GPIO (1 pin)
|
||||
.gpio_out_pad(gpio_out_core),
|
||||
.gpio_in_pad(gpio_in_core),
|
||||
|
@ -333,31 +361,19 @@ module caravel (
|
|||
|
||||
// Primary SPI flash controller
|
||||
.flash_csb(flash_csb_core),
|
||||
.flash_csb_ieb(flash_csb_ieb_core),
|
||||
.flash_csb_oeb(flash_csb_oeb_core),
|
||||
.flash_clk(flash_clk_core),
|
||||
.flash_clk_ieb(flash_clk_ieb_core),
|
||||
.flash_clk_oeb(flash_clk_oeb_core),
|
||||
.flash_io0_ieb(flash_io0_ieb_core),
|
||||
.flash_io0_oeb(flash_io0_oeb_core),
|
||||
.flash_io0_di(flash_io0_di_core),
|
||||
.flash_io0_do(flash_io0_do_core),
|
||||
.flash_io1_ieb(flash_io1_ieb_core),
|
||||
.flash_io1_oeb(flash_io1_oeb_core),
|
||||
.flash_io1_di(flash_io1_di_core),
|
||||
.flash_io1_do(flash_io1_do_core),
|
||||
.flash_io2_ieb(flash_io2_ieb_core),
|
||||
.flash_io2_oeb(flash_io2_oeb_core),
|
||||
.flash_io2_di(flash_io2_di_core),
|
||||
.flash_io2_do(flash_io2_do_core),
|
||||
.flash_io3_ieb(flash_io3_ieb_core),
|
||||
.flash_io3_oeb(flash_io3_oeb_core),
|
||||
.flash_io3_di(flash_io3_di_core),
|
||||
.flash_io3_do(flash_io3_do_core),
|
||||
|
||||
// Debug
|
||||
.jtag_out(jtag_out),
|
||||
.jtag_outenb(jtag_outenb),
|
||||
.flash_io0_oeb(flash_io0_oeb),
|
||||
.flash_io0_di(flash_io0_di),
|
||||
.flash_io0_do(flash_io0_do),
|
||||
.flash_io1_oeb(flash_io1_oeb),
|
||||
.flash_io1_di(flash_io1_di),
|
||||
.flash_io1_do(flash_io1_do),
|
||||
.flash_io2_oeb(flash_io2_oeb),
|
||||
.flash_io2_di(flash_io2_di),
|
||||
.flash_io2_do(flash_io2_do),
|
||||
.flash_io3_oeb(flash_io3_oeb),
|
||||
.flash_io3_di(flash_io3_di),
|
||||
.flash_io3_do(flash_io3_do),
|
||||
|
||||
// Exported Wishbone Bus
|
||||
.mprj_cyc_o(mprj_cyc_o_core),
|
||||
|
@ -369,17 +385,32 @@ module caravel (
|
|||
.mprj_ack_i(mprj_ack_i_core),
|
||||
.mprj_dat_i(mprj_dat_i_core),
|
||||
|
||||
// Clock and reset
|
||||
.core_clk(caravel_clk),
|
||||
.core_rstn(caravel_rstn),
|
||||
.hk_stb_o(hk_stb_o),
|
||||
.hk_dat_i(hk_dat_i),
|
||||
.hk_ack_i(hk_ack_i),
|
||||
|
||||
// IRQ
|
||||
.user_irq(user_irq),
|
||||
.user_irq_ena(user_irq_ena),
|
||||
.irq({irq_spi, user_irq}),
|
||||
|
||||
// Real-time status and control
|
||||
.hkspi_status(hkspi_status),
|
||||
.hkspi_control(hkspi_control)
|
||||
// Module status (these may or may not be implemented)
|
||||
.qspi_enabled(qspi_enabled),
|
||||
.uart_enabled(uart_enabled),
|
||||
.spi_enabled(spi_enabled),
|
||||
.debug_mode(debug_mode),
|
||||
|
||||
// Module I/O (these may or may not be implemented)
|
||||
.ser_tx(ser_tx),
|
||||
.ser_rx(ser_rx),
|
||||
.spi_sdi(spi_sdi),
|
||||
.spi_csb(spi_csb),
|
||||
.spi_sck(spi_sck),
|
||||
.spi_sdo(spi_sdo),
|
||||
.debug_in(debug_in),
|
||||
.debug_out(debug_out),
|
||||
.debug_oeb(debug_oeb),
|
||||
|
||||
// Trap status
|
||||
.trap(trap)
|
||||
);
|
||||
|
||||
/* Clock and reset to user space are passed through a tristate */
|
||||
|
@ -410,13 +441,6 @@ module caravel (
|
|||
.mprj_adr_o_core(mprj_adr_o_core),
|
||||
.mprj_dat_o_core(mprj_dat_o_core),
|
||||
.user_irq_core(user_irq_core),
|
||||
.la_data_out_core(la_data_out_user),
|
||||
.la_data_out_mprj(la_data_out_mprj),
|
||||
.la_data_in_core(la_data_in_user),
|
||||
.la_data_in_mprj(la_data_in_mprj),
|
||||
.la_oenb_mprj(la_oenb_mprj),
|
||||
.la_oenb_core(la_oenb_user),
|
||||
.la_iena_mprj(la_iena_mprj),
|
||||
.user_irq_ena(user_irq_ena),
|
||||
|
||||
.user_clock(mprj_clock),
|
||||
|
@ -435,7 +459,6 @@ module caravel (
|
|||
.user2_vdd_powergood(mprj2_vdd_pwrgood)
|
||||
);
|
||||
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
/* Wrapper module around the user project */
|
||||
/*--------------------------------------------------*/
|
||||
|
@ -455,7 +478,7 @@ module caravel (
|
|||
.wb_clk_i(mprj_clock),
|
||||
.wb_rst_i(mprj_reset),
|
||||
|
||||
// MGMT SoC Wishbone Slave
|
||||
// Management SoC Wishbone bus (exported)
|
||||
.wbs_cyc_i(mprj_cyc_o_user),
|
||||
.wbs_stb_i(mprj_stb_o_user),
|
||||
.wbs_we_i(mprj_we_o_user),
|
||||
|
@ -464,17 +487,16 @@ module caravel (
|
|||
.wbs_dat_i(mprj_dat_o_user),
|
||||
.wbs_ack_o(mprj_ack_i_core),
|
||||
.wbs_dat_o(mprj_dat_i_core),
|
||||
// Logic Analyzer
|
||||
.la_data_in(la_data_in_user),
|
||||
.la_data_out(la_data_out_user),
|
||||
.la_oenb(la_oenb_user),
|
||||
// IO Pads
|
||||
|
||||
// GPIO pad 3-pin interface (plus analog)
|
||||
.io_in (user_io_in),
|
||||
.io_out(user_io_out),
|
||||
.io_oeb(user_io_oeb),
|
||||
.analog_io(user_analog_io),
|
||||
|
||||
// Independent clock
|
||||
.user_clock2(mprj_clock2),
|
||||
|
||||
// IRQ
|
||||
.user_irq(user_irq_core)
|
||||
);
|
||||
|
@ -512,6 +534,11 @@ module caravel (
|
|||
assign gpio_resetn_2_shifted = {mprj_io_loader_resetn,
|
||||
gpio_resetn_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
|
||||
wire [2:0] spi_pll_sel;
|
||||
wire [2:0] spi_pll90_sel;
|
||||
wire [4:0] spi_pll_div;
|
||||
wire [25:0] spi_pll_trim;
|
||||
|
||||
// Clocking control
|
||||
|
||||
caravel_clocking clocking(
|
||||
|
@ -527,8 +554,8 @@ module caravel (
|
|||
.sel(spi_pll_sel),
|
||||
.sel2(spi_pll90_sel),
|
||||
.ext_reset(ext_reset), // From housekeeping SPI
|
||||
.core_clk(core_clk),
|
||||
.user_clk(user_clk),
|
||||
.core_clk(caravel_clk),
|
||||
.user_clk(caravel_clk2),
|
||||
.resetb_sync(core_rstn)
|
||||
);
|
||||
|
||||
|
@ -548,86 +575,107 @@ module caravel (
|
|||
.ext_trim(spi_pll_trim)
|
||||
);
|
||||
|
||||
// Housekeeping SPI interface
|
||||
// Housekeeping interface
|
||||
|
||||
housekeeping_spi housekeeping (
|
||||
housekeeping housekeeping (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd(VPWR),
|
||||
.vss(VGND),
|
||||
.vdd(VPWR),
|
||||
.vss(VGND),
|
||||
`endif
|
||||
.RSTB(porb),
|
||||
.SCK((hk_connect) ? mgmt_out_predata[4] : mgmt_in_data[4]),
|
||||
.SDI((hk_connect) ? mgmt_out_predata[2] : mgmt_in_data[2]),
|
||||
.CSB((hk_connect) ? mgmt_out_predata[3] : mgmt_in_data[3]),
|
||||
.SDO(sdo_out_pre),
|
||||
.sdo_enb(sdo_outenb_pre),
|
||||
|
||||
.wb_clk_i(mprj_clock),
|
||||
.wb_rst_i(mprj_reset),
|
||||
|
||||
.wb_adr_i(mprj_adr_o_core),
|
||||
.wb_dat_i(mprj_dat_o_core),
|
||||
.wb_sel_i(mprj_sel_o_core),
|
||||
.wb_we_i(mprj_we_o_core),
|
||||
.wb_cyc_i(mprj_cyc_o_core),
|
||||
.wb_stb_i(hk_stb_o),
|
||||
.wb_ack_o(hk_ack_i),
|
||||
.wb_dat_o(hk_dat_i),
|
||||
|
||||
.porb(porb),
|
||||
|
||||
.pll_ena(spi_pll_ena),
|
||||
.pll_dco_ena(spi_pll_dco_ena),
|
||||
.pll_div(spi_pll_div),
|
||||
.pll_sel(spi_pll_sel),
|
||||
.pll90_sel(spi_pll90_sel),
|
||||
.pll_div(spi_pll_div),
|
||||
.pll_ena(spi_pll_ena),
|
||||
.pll_trim(spi_pll_trim),
|
||||
.pll_bypass(ext_clk_sel),
|
||||
|
||||
.qspi_enabled(qspi_enabled),
|
||||
.uart_enabled(uart_enabled),
|
||||
.spi_enabled(spi_enabled),
|
||||
.debug_mode(debug_mode),
|
||||
|
||||
.ser_tx(ser_tx),
|
||||
.ser_rx(ser_rx),
|
||||
|
||||
.spi_sdi(spi_sdi),
|
||||
.spi_csb(spi_csb),
|
||||
.spi_sck(spi_sck),
|
||||
.spi_sdo(spi_sdo),
|
||||
|
||||
.debug_in(debug_in),
|
||||
.debug_out(debug_out),
|
||||
.debug_oeb(debug_oeb),
|
||||
|
||||
.irq(irq_spi),
|
||||
.reset(ext_reset),
|
||||
|
||||
.serial_clock(gpio_clock),
|
||||
.serial_resetn(gpio_resetn),
|
||||
.serial_data_1(gpio_data_1),
|
||||
.serial_data_2(gpio_data_2),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in),
|
||||
.mgmt_gpio_out({mgmt_io_out[3:2], mgmt_io_in[`MPRJ_IO_PADS-3:2],
|
||||
mgmt_io_out[1:0]}),
|
||||
.mgmt_gpio_oeb({mgmt_io_oeb[3:2], mgmt_io_nc[`MPRJ_IO_PADS-5:0],
|
||||
mgmt_io_oeb[1:0]}),
|
||||
|
||||
.pwr_ctrl_out(), /* Not used in this version */
|
||||
|
||||
.trap(trap),
|
||||
|
||||
.user_clock(user_clock),
|
||||
|
||||
.mask_rev_in(mask_rev),
|
||||
.gpio_enable(gpio_enable),
|
||||
.gpio_resetn(gpio_resetn),
|
||||
.gpio_clock(gpio_clock),
|
||||
.gpio_data_1(gpio_data_1),
|
||||
.gpio_data_2(gpio_data_2),
|
||||
.sram_clk(hkspi_sram_clk),
|
||||
.sram_csb(hkspi_sram_csb),
|
||||
.sram_addr(hkspi_sram_addr),
|
||||
.sram_rdata(hkspi_sram_rdata),
|
||||
.pass_thru_mgmt_reset(pass_thru_mgmt),
|
||||
.pass_thru_user_reset(pass_thru_user),
|
||||
.pass_thru_mgmt_sck(pass_thru_mgmt_sck),
|
||||
.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(pass_thru_user_sck),
|
||||
.pass_thru_user_csb(pass_thru_user_csb),
|
||||
.pass_thru_user_sdi(pass_thru_user_sdi),
|
||||
.pass_thru_user_sdo(mgmt_in_data[11])
|
||||
);
|
||||
|
||||
// GPIO control interface
|
||||
.spimemio_flash_csb(flash_csb_core),
|
||||
.spimemio_flash_clk(flash_clk_core),
|
||||
.spimemio_flash_io0_oeb(flash_io0_oeb_core),
|
||||
.spimemio_flash_io1_oeb(flash_io1_oeb_core),
|
||||
.spimemio_flash_io2_oeb(flash_io2_oeb_core),
|
||||
.spimemio_flash_io3_oeb(flash_io3_oeb_core),
|
||||
.spimemio_flash_io0_do(flash_io0_do_core),
|
||||
.spimemio_flash_io1_do(flash_io1_do_core),
|
||||
.spimemio_flash_io2_do(flash_io2_do_core),
|
||||
.spimemio_flash_io3_do(flash_io3_do_core),
|
||||
.spimemio_flash_io0_di(flash_io0_di_core),
|
||||
.spimemio_flash_io1_di(flash_io1_di_core),
|
||||
.spimemio_flash_io2_di(flash_io2_di_core),
|
||||
.spimemio_flash_io3_di(flash_io3_di_core),
|
||||
|
||||
mprj_ctrl_wb #(
|
||||
.BASE_ADR(MPRJ_CTRL_ADR)
|
||||
) mprj_ctrl (
|
||||
.wb_clk_i(wb_clk_i),
|
||||
.wb_rst_i(wb_rst_i),
|
||||
.pad_flash_csb(flash_csb_frame),
|
||||
.pad_flash_csb_oeb(flash_csb_oeb),
|
||||
.pad_flash_clk(flash_clk_frame),
|
||||
.pad_flash_clk_oeb(flash_clk_oeb),
|
||||
.pad_flash_io0_oeb(flash_io0_oeb),
|
||||
.pad_flash_io1_oeb(flash_io1_oeb),
|
||||
.pad_flash_io0_ieb(flash_io0_ieb),
|
||||
.pad_flash_io1_ieb(flash_io1_ieb),
|
||||
.pad_flash_io0_do(flash_io0_do),
|
||||
.pad_flash_io1_do(flash_io1_do),
|
||||
.pad_flash_io0_di(flash_io0_di),
|
||||
.pad_flash_io1_di(flash_io1_di),
|
||||
|
||||
.wb_adr_i(cpu_adr_o),
|
||||
.wb_dat_i(cpu_dat_o),
|
||||
.wb_sel_i(cpu_sel_o),
|
||||
.wb_we_i(cpu_we_o),
|
||||
.wb_cyc_i(cpu_cyc_o),
|
||||
.wb_stb_i(mprj_ctrl_stb_i),
|
||||
.wb_ack_o(mprj_ctrl_ack_o),
|
||||
.wb_dat_o(mprj_ctrl_dat_o),
|
||||
|
||||
.serial_clock(mprj_io_loader_clock),
|
||||
.serial_resetn(mprj_io_loader_resetn),
|
||||
.serial_data_out_1(mprj_io_loader_data_1),
|
||||
.serial_data_out_2(mprj_io_loader_data_2),
|
||||
.ext_enable(gpio_enable),
|
||||
.ext_resetn(gpio_resetn),
|
||||
.ext_clock(gpio_clock),
|
||||
.ext_data_1(gpio_data_1),
|
||||
.ext_data_2(gpio_data_2),
|
||||
.sdo_oenb_state(sdo_oenb_state),
|
||||
.jtag_oenb_state(jtag_oenb_state),
|
||||
.flash_io2_oenb_state(flash_io2_oenb_state),
|
||||
.flash_io3_oenb_state(flash_io3_oenb_state),
|
||||
.mgmt_gpio_out(mgmt_out_pre),
|
||||
.mgmt_gpio_oeb(mgmt_oeb_data),
|
||||
.mgmt_gpio_in(mgmt_in_data),
|
||||
.pwr_ctrl_out(pwr_ctrl_out),
|
||||
.user_irq_ena(user_irq_ena)
|
||||
.usr1_vcc_pwrgood(mprj_vcc_pwrgood),
|
||||
.usr2_vcc_pwrgood(mprj2_vcc_pwrgood),
|
||||
.usr1_vdd_pwrgood(mprj_vdd_pwrgood),
|
||||
.usr2_vdd_pwrgood(mprj2_vdd_pwrgood)
|
||||
);
|
||||
|
||||
// Each control block sits next to an I/O pad in the user area.
|
||||
|
@ -665,8 +713,8 @@ module caravel (
|
|||
.serial_clock_out(gpio_clock_1[1:0]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[1:0]),
|
||||
.mgmt_gpio_out({sdo_out, jtag_out}),
|
||||
.mgmt_gpio_oeb({sdo_outenb, jtag_outenb}),
|
||||
.mgmt_gpio_out(mgmt_io_out[1:0]),
|
||||
.mgmt_gpio_oeb(mgmt_io_oeb[1:0]),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
@ -720,9 +768,9 @@ module caravel (
|
|||
.resetn_out(gpio_resetn_1[7:2]),
|
||||
.serial_clock_out(gpio_clock_1[7:2]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[7:2]),
|
||||
.mgmt_gpio_out(mgmt_io_in[7:2]),
|
||||
.mgmt_gpio_oeb(one_loop1[7:2]),
|
||||
.mgmt_gpio_in(mgmt_io_in[7:2]),
|
||||
.mgmt_gpio_out(mgmt_io_in[7:2]),
|
||||
.mgmt_gpio_oeb(one_loop1[7:2]),
|
||||
|
||||
.one(one_loop1[7:2]),
|
||||
.zero(),
|
||||
|
@ -769,9 +817,9 @@ module caravel (
|
|||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.mgmt_gpio_oeb(one_loop1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.mgmt_gpio_oeb(one_loop1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
.one(one_loop1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.zero(),
|
||||
|
@ -822,8 +870,8 @@ module caravel (
|
|||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.mgmt_gpio_out({gpio_flash_io3_out, gpio_flash_io2_out}),
|
||||
.mgmt_gpio_oeb({flash_io3_oeb_core, flash_io2_oeb_core}),
|
||||
.mgmt_gpio_out(mgmt_io_out[3:2]),
|
||||
.mgmt_gpio_oeb(mgmt_io_oeb[3:2]),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
@ -870,9 +918,9 @@ module caravel (
|
|||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-3):0]),
|
||||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-3):0]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.mgmt_gpio_oeb(one_loop2),
|
||||
.mgmt_gpio_in(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.mgmt_gpio_out(mgmt_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.mgmt_gpio_oeb(one_loop2),
|
||||
|
||||
.one(one_loop2),
|
||||
.zero(),
|
||||
|
@ -935,28 +983,5 @@ module caravel (
|
|||
.X(rstb_l)
|
||||
);
|
||||
|
||||
// Storage area
|
||||
storage storage(
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
.mgmt_clk(caravel_clk),
|
||||
.mgmt_ena(mgmt_ena),
|
||||
.mgmt_wen(mgmt_wen),
|
||||
.mgmt_wen_mask(mgmt_wen_mask),
|
||||
.mgmt_addr(mgmt_addr),
|
||||
.mgmt_wdata(mgmt_wdata),
|
||||
.mgmt_rdata(mgmt_rdata),
|
||||
// Management RO interface
|
||||
.mgmt_ena_ro(mgmt_ena_ro),
|
||||
.mgmt_addr_ro(mgmt_addr_ro),
|
||||
.mgmt_rdata_ro(mgmt_rdata_ro),
|
||||
.hkspi_sram_clk(hkspi_sram_clk),
|
||||
.hkspi_sram_csb(hkspi_sram_csb),
|
||||
.hkspi_sram_addr(hkspi_sram_addr),
|
||||
.hkspi_sram_rdata(hkspi_sram_rdata)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// `default_nettype wire
|
||||
|
|
|
@ -61,30 +61,26 @@
|
|||
`include "gl/sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped.v"
|
||||
`include "gl/caravel.v"
|
||||
`else
|
||||
`include "mgmt_soc.v"
|
||||
`include "housekeeping_spi.v"
|
||||
`include "caravel_clocking.v"
|
||||
`include "mgmt_core.v"
|
||||
`include "digital_pll.v"
|
||||
`include "DFFRAM.v"
|
||||
`include "DFFRAMBB.v"
|
||||
`include "storage.v"
|
||||
`include "user_id_programming.v"
|
||||
`include "clock_div.v"
|
||||
`include "storage_bridge_wb.v"
|
||||
`include "mprj_io.v"
|
||||
`include "chip_io.v"
|
||||
`include "mprj_logic_high.v"
|
||||
|
||||
`include "digital_pll.v"
|
||||
`include "caravel_clocking.v"
|
||||
`include "user_id_programming.v"
|
||||
`include "clock_div.v"
|
||||
`include "mprj_io.v"
|
||||
`include "chip_io.v"
|
||||
`include "housekeeping_spi.v"
|
||||
`include "housekeeping.v"
|
||||
`include "mprj_logic_high.v"
|
||||
`include "mprj2_logic_high.v"
|
||||
`include "mgmt_protect.v"
|
||||
`include "mgmt_protect.v"
|
||||
`include "mgmt_protect_hv.v"
|
||||
`include "gpio_control_block.v"
|
||||
`include "gpio_logic_high.v"
|
||||
`include "gpio_control_block.v"
|
||||
`include "gpio_logic_high.v"
|
||||
`include "sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped.v"
|
||||
`include "mgmt_core_wrapper.v"
|
||||
`include "caravel.v"
|
||||
`endif
|
||||
|
||||
`include "simple_por.v"
|
||||
`include "sram_1rw1r_32_256_8_sky130.v"
|
||||
|
||||
`endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,320 +14,13 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
`default_nettype none
|
||||
//-------------------------------------
|
||||
// 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.
|
||||
//
|
||||
// SPI controller for Caravel
|
||||
//-----------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Caravel defined registers:
|
||||
// Register 0: SPI status and control (unused & reserved)
|
||||
// Register 1 and 2: Manufacturer ID (0x0456) (readonly)
|
||||
// Register 3: Product ID (= 16) (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 enables (2 bits)
|
||||
// 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 divider (3 bits)
|
||||
// Register 18: PLL feedback divider (5 bits)
|
||||
// Register 19: User GPIO bit-bang control (5 bits)
|
||||
// Register 20: SRAM read-only control (2 bits)
|
||||
// Register 21: SRAM read-only address (8 bits)
|
||||
// Register 22-25: SRAM read-only data (32 bits)
|
||||
//------------------------------------------------------------
|
||||
|
||||
module housekeeping_spi(
|
||||
`ifdef USE_POWER_PINS
|
||||
vdd, vss,
|
||||
`endif
|
||||
RSTB, SCK, SDI, CSB, SDO, sdo_enb,
|
||||
pll_ena, pll_dco_ena, pll_div, pll_sel,
|
||||
pll90_sel, pll_trim, pll_bypass, irq, reset,
|
||||
gpio_clock, gpio_resetn, gpio_data_1, gpio_data_2, gpio_enable,
|
||||
sram_clk, sram_csb, sram_addr, sram_rdata,
|
||||
trap, mask_rev_in,
|
||||
pass_thru_mgmt_reset, pass_thru_user_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 USE_POWER_PINS
|
||||
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
|
||||
|
||||
output pll_ena;
|
||||
output pll_dco_ena;
|
||||
output [4:0] pll_div;
|
||||
output [2:0] pll_sel;
|
||||
output [2:0] pll90_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
|
||||
|
||||
// Bit-bang control of GPIO serial loader
|
||||
output gpio_enable;
|
||||
output gpio_resetn;
|
||||
output gpio_clock;
|
||||
output gpio_data_1;
|
||||
output gpio_data_2;
|
||||
|
||||
// Bit-bang control of SRAM block 2nd read port
|
||||
output sram_clk;
|
||||
output sram_csb;
|
||||
output [7:0] sram_addr;
|
||||
input [31:0] sram_rdata;
|
||||
|
||||
// Pass-through programming mode for management area SPI flash
|
||||
output pass_thru_mgmt_reset;
|
||||
output pass_thru_user_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 [2:0] pll90_sel;
|
||||
reg pll_dco_ena;
|
||||
reg pll_ena;
|
||||
reg pll_bypass;
|
||||
reg reset_reg;
|
||||
reg irq;
|
||||
reg gpio_enable;
|
||||
reg gpio_clock;
|
||||
reg gpio_resetn;
|
||||
reg gpio_data_1;
|
||||
reg gpio_data_2;
|
||||
reg sram_clk;
|
||||
reg sram_csb;
|
||||
reg [7:0] sram_addr;
|
||||
|
||||
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;
|
||||
wire loc_sdo;
|
||||
|
||||
// Pass-through mode handling. Signals may only be applied when the
|
||||
// core processor is in reset.
|
||||
|
||||
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_delay ? 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_delay ? 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_mgmt_reset ? 1'b1 : reset_reg;
|
||||
|
||||
// Instantiate the SPI slave module
|
||||
|
||||
housekeeping_spi_slave U1 (
|
||||
.reset(~RSTB),
|
||||
.SCK(SCK),
|
||||
.SDI(SDI),
|
||||
.CSB(CSB),
|
||||
.SDO(loc_sdo),
|
||||
.sdoenb(sdo_enb),
|
||||
.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_mgmt_reset(pass_thru_mgmt_reset),
|
||||
.pass_thru_user_reset(pass_thru_user_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) ? {6'b000000, pll_dco_ena, pll_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) ? {2'b00, pll90_sel, pll_sel} :
|
||||
(iaddr == 8'h12) ? {3'b000, pll_div} :
|
||||
(iaddr == 8'h13) ? {3'b000, gpio_data_2, gpio_data_1, gpio_clock,
|
||||
gpio_resetn, gpio_enable} :
|
||||
(iaddr == 8'h14) ? {6'b000000, sram_clk, sram_csb} :
|
||||
(iaddr == 8'h15) ? sram_addr :
|
||||
(iaddr == 8'h16) ? sram_rdata[7:0] :
|
||||
(iaddr == 8'h17) ? sram_rdata[15:8] :
|
||||
(iaddr == 8'h18) ? sram_rdata[23:16] :
|
||||
(iaddr == 8'h19) ? sram_rdata[31:24] :
|
||||
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'b010; // Default output divider divide-by-2
|
||||
pll90_sel <= 3'b010; // Default secondary output divider divide-by-2
|
||||
pll_div <= 5'b00100; // Default feedback divider divide-by-8
|
||||
pll_dco_ena <= 1'b1; // Default free-running PLL
|
||||
pll_ena <= 1'b0; // Default PLL turned off
|
||||
pll_bypass <= 1'b1; // Default bypass mode (don't use PLL)
|
||||
irq <= 1'b0;
|
||||
reset_reg <= 1'b0;
|
||||
gpio_enable <= 1'b0;
|
||||
gpio_data_1 <= 1'b0;
|
||||
gpio_data_2 <= 1'b0;
|
||||
gpio_clock <= 1'b0;
|
||||
gpio_resetn <= 1'b0;
|
||||
sram_clk <= 1'b0;
|
||||
sram_csb <= 1'b1;
|
||||
sram_addr <= 8'd0;
|
||||
end else if (wrstb == 1'b1) begin
|
||||
case (iaddr)
|
||||
8'h08: begin
|
||||
pll_ena <= idata[0];
|
||||
pll_dco_ena <= idata[1];
|
||||
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];
|
||||
pll90_sel <= idata[5:3];
|
||||
end
|
||||
8'h12: begin
|
||||
pll_div <= idata[4:0];
|
||||
end
|
||||
8'h13: begin
|
||||
gpio_enable <= idata[0];
|
||||
gpio_resetn <= idata[1];
|
||||
gpio_clock <= idata[2];
|
||||
gpio_data_1 <= idata[3];
|
||||
gpio_data_2 <= idata[4];
|
||||
end
|
||||
8'h14: begin
|
||||
sram_csb <= idata[0];
|
||||
sram_clk <= idata[1];
|
||||
end
|
||||
8'h15: begin
|
||||
sram_addr <= idata;
|
||||
end
|
||||
// Registers 0x16-0x19 are read-only
|
||||
endcase // (iaddr)
|
||||
end
|
||||
end
|
||||
endmodule // housekeeping_spi
|
||||
|
||||
// housekeeping_spi.v
|
||||
//------------------------------------------------------
|
||||
// housekeeping_spi_slave.v
|
||||
//------------------------------------------------------
|
||||
// General purpose SPI slave module for the Caravel chip
|
||||
// General purpose SPI module for the Caravel chip
|
||||
//------------------------------------------------------
|
||||
// Written by Tim Edwards
|
||||
// efabless, inc., September 28, 2020
|
||||
|
@ -379,7 +72,7 @@ endmodule // housekeeping_spi
|
|||
`define USERPASS 3'b100
|
||||
`define MGMTPASS 3'b101
|
||||
|
||||
module housekeeping_spi_slave(reset, SCK, SDI, CSB, SDO,
|
||||
module housekeeping_spi(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,
|
||||
|
@ -554,5 +247,5 @@ module housekeeping_spi_slave(reset, SCK, SDI, CSB, SDO,
|
|||
end // ! csb_reset
|
||||
end // always @ SCK
|
||||
|
||||
endmodule // housekeeping_spi_slave
|
||||
endmodule // housekeeping_spi
|
||||
`default_nettype wire
|
||||
|
|
|
@ -1,305 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
`default_nettype none
|
||||
module la_wb # (
|
||||
parameter BASE_ADR = 32'h 2200_0000,
|
||||
parameter LA_DATA_0 = 8'h00,
|
||||
parameter LA_DATA_1 = 8'h04,
|
||||
parameter LA_DATA_2 = 8'h08,
|
||||
parameter LA_DATA_3 = 8'h0c,
|
||||
parameter LA_OENB_0 = 8'h10,
|
||||
parameter LA_OENB_1 = 8'h14,
|
||||
parameter LA_OENB_2 = 8'h18,
|
||||
parameter LA_OENB_3 = 8'h1c,
|
||||
parameter LA_IENA_0 = 8'h20,
|
||||
parameter LA_IENA_1 = 8'h24,
|
||||
parameter LA_IENA_2 = 8'h28,
|
||||
parameter LA_IENA_3 = 8'h2c,
|
||||
parameter LA_SAMPLE = 8'h30
|
||||
) (
|
||||
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,
|
||||
|
||||
input [127:0] la_data_in, // From MPRJ
|
||||
output [127:0] la_data,
|
||||
output [127:0] la_oenb,
|
||||
output [127:0] la_iena
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
la #(
|
||||
.BASE_ADR(BASE_ADR),
|
||||
.LA_DATA_0(LA_DATA_0),
|
||||
.LA_DATA_1(LA_DATA_1),
|
||||
.LA_DATA_2(LA_DATA_2),
|
||||
.LA_DATA_3(LA_DATA_3),
|
||||
.LA_OENB_0(LA_OENB_0),
|
||||
.LA_OENB_1(LA_OENB_1),
|
||||
.LA_OENB_2(LA_OENB_2),
|
||||
.LA_OENB_3(LA_OENB_3),
|
||||
.LA_IENA_0(LA_IENA_0),
|
||||
.LA_IENA_1(LA_IENA_1),
|
||||
.LA_IENA_2(LA_IENA_2),
|
||||
.LA_IENA_3(LA_IENA_3),
|
||||
.LA_SAMPLE(LA_SAMPLE)
|
||||
) la_ctrl (
|
||||
.clk(wb_clk_i),
|
||||
.resetn(resetn),
|
||||
.iomem_addr(wb_adr_i),
|
||||
.iomem_valid(valid),
|
||||
.iomem_wstrb(iomem_we),
|
||||
.iomem_wdata(wb_dat_i),
|
||||
.iomem_rdata(wb_dat_o),
|
||||
.iomem_ready(ready),
|
||||
.la_data_in(la_data_in),
|
||||
.la_data(la_data),
|
||||
.la_oenb(la_oenb),
|
||||
.la_iena(la_iena)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module la #(
|
||||
parameter BASE_ADR = 32'h 2200_0000,
|
||||
parameter LA_DATA_0 = 8'h00,
|
||||
parameter LA_DATA_1 = 8'h04,
|
||||
parameter LA_DATA_2 = 8'h08,
|
||||
parameter LA_DATA_3 = 8'h0c,
|
||||
parameter LA_OENB_0 = 8'h10,
|
||||
parameter LA_OENB_1 = 8'h14,
|
||||
parameter LA_OENB_2 = 8'h18,
|
||||
parameter LA_OENB_3 = 8'h1c,
|
||||
parameter LA_IENA_0 = 8'h20,
|
||||
parameter LA_IENA_1 = 8'h24,
|
||||
parameter LA_IENA_2 = 8'h28,
|
||||
parameter LA_IENA_3 = 8'h2c,
|
||||
parameter LA_SAMPLE = 8'h30
|
||||
) (
|
||||
input clk,
|
||||
input resetn,
|
||||
|
||||
input [31:0] iomem_addr,
|
||||
input iomem_valid,
|
||||
input [3:0] iomem_wstrb,
|
||||
input [31:0] iomem_wdata,
|
||||
|
||||
output reg [31:0] iomem_rdata,
|
||||
output reg iomem_ready,
|
||||
|
||||
input [127:0] la_data_in, // From MPRJ
|
||||
output [127:0] la_data, // To MPRJ
|
||||
output [127:0] la_oenb,
|
||||
output [127:0] la_iena
|
||||
);
|
||||
|
||||
reg [31:0] la_data_0;
|
||||
reg [31:0] la_data_1;
|
||||
reg [31:0] la_data_2;
|
||||
reg [31:0] la_data_3;
|
||||
|
||||
reg [31:0] la_oenb_0;
|
||||
reg [31:0] la_oenb_1;
|
||||
reg [31:0] la_oenb_2;
|
||||
reg [31:0] la_oenb_3;
|
||||
|
||||
reg [31:0] la_iena_0;
|
||||
reg [31:0] la_iena_1;
|
||||
reg [31:0] la_iena_2;
|
||||
reg [31:0] la_iena_3;
|
||||
|
||||
wire [3:0] la_data_sel;
|
||||
wire [3:0] la_oenb_sel;
|
||||
wire [3:0] la_iena_sel;
|
||||
wire la_sample_sel;
|
||||
|
||||
wire [31:0] la_sample_mask_0;
|
||||
wire [31:0] la_sample_mask_1;
|
||||
wire [31:0] la_sample_mask_2;
|
||||
wire [31:0] la_sample_mask_3;
|
||||
|
||||
assign la_data = {la_data_3, la_data_2, la_data_1, la_data_0};
|
||||
assign la_oenb = {la_oenb_3, la_oenb_2, la_oenb_1, la_oenb_0};
|
||||
assign la_iena = {la_iena_3, la_iena_2, la_iena_1, la_iena_0};
|
||||
|
||||
assign la_data_sel = {
|
||||
(iomem_addr[7:0] == LA_DATA_3),
|
||||
(iomem_addr[7:0] == LA_DATA_2),
|
||||
(iomem_addr[7:0] == LA_DATA_1),
|
||||
(iomem_addr[7:0] == LA_DATA_0)
|
||||
};
|
||||
|
||||
assign la_oenb_sel = {
|
||||
(iomem_addr[7:0] == LA_OENB_3),
|
||||
(iomem_addr[7:0] == LA_OENB_2),
|
||||
(iomem_addr[7:0] == LA_OENB_1),
|
||||
(iomem_addr[7:0] == LA_OENB_0)
|
||||
};
|
||||
|
||||
assign la_iena_sel = {
|
||||
(iomem_addr[7:0] == LA_IENA_3),
|
||||
(iomem_addr[7:0] == LA_IENA_2),
|
||||
(iomem_addr[7:0] == LA_IENA_1),
|
||||
(iomem_addr[7:0] == LA_IENA_0)
|
||||
};
|
||||
|
||||
assign la_sample_sel = (iomem_addr[7:0] == LA_SAMPLE);
|
||||
assign la_sample_mask_3 = (la_oenb_3 & la_iena_3);
|
||||
assign la_sample_mask_2 = (la_oenb_2 & la_iena_2);
|
||||
assign la_sample_mask_1 = (la_oenb_1 & la_iena_1);
|
||||
assign la_sample_mask_0 = (la_oenb_0 & la_iena_0);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
la_data_0 <= 0;
|
||||
la_data_1 <= 0;
|
||||
la_data_2 <= 0;
|
||||
la_data_3 <= 0;
|
||||
la_oenb_0 <= 32'hFFFF_FFFF; // default is tri-state buff disabled
|
||||
la_oenb_1 <= 32'hFFFF_FFFF;
|
||||
la_oenb_2 <= 32'hFFFF_FFFF;
|
||||
la_oenb_3 <= 32'hFFFF_FFFF;
|
||||
la_iena_0 <= 32'h0000_0000; // default is grounded input
|
||||
la_iena_1 <= 32'h0000_0000;
|
||||
la_iena_2 <= 32'h0000_0000;
|
||||
la_iena_3 <= 32'h0000_0000;
|
||||
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;
|
||||
|
||||
/* NOTE: Data in and out are independent channels */
|
||||
|
||||
if (la_data_sel[0]) begin
|
||||
iomem_rdata <= la_data_in[31:0];
|
||||
|
||||
if (iomem_wstrb[0]) la_data_0[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_data_0[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_data_0[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_data_0[31:24] <= iomem_wdata[31:24];
|
||||
|
||||
end else if (la_data_sel[1]) begin
|
||||
iomem_rdata <= la_data_in[63:32];
|
||||
|
||||
if (iomem_wstrb[0]) la_data_1[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_data_1[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_data_1[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_data_1[31:24] <= iomem_wdata[31:24];
|
||||
|
||||
end else if (la_data_sel[2]) begin
|
||||
iomem_rdata <= la_data_in[95:64];
|
||||
|
||||
if (iomem_wstrb[0]) la_data_2[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_data_2[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_data_2[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_data_2[31:24] <= iomem_wdata[31:24];
|
||||
|
||||
end else if (la_data_sel[3]) begin
|
||||
iomem_rdata <= la_data_in[127:96];
|
||||
|
||||
if (iomem_wstrb[0]) la_data_3[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_data_3[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_data_3[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_data_3[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_oenb_sel[0]) begin
|
||||
iomem_rdata <= la_oenb_0;
|
||||
|
||||
if (iomem_wstrb[0]) la_oenb_0[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_oenb_0[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_oenb_0[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_oenb_0[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_oenb_sel[1]) begin
|
||||
iomem_rdata <= la_oenb_1;
|
||||
|
||||
if (iomem_wstrb[0]) la_oenb_1[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_oenb_1[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_oenb_1[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_oenb_1[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_oenb_sel[2]) begin
|
||||
iomem_rdata <= la_oenb_2;
|
||||
|
||||
if (iomem_wstrb[0]) la_oenb_2[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_oenb_2[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_oenb_2[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_oenb_2[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_oenb_sel[3]) begin
|
||||
iomem_rdata <= la_oenb_3;
|
||||
|
||||
if (iomem_wstrb[0]) la_oenb_3[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_oenb_3[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_oenb_3[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_oenb_3[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_iena_sel[0]) begin
|
||||
iomem_rdata <= la_iena_0;
|
||||
|
||||
if (iomem_wstrb[0]) la_iena_0[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_iena_0[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_iena_0[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_iena_0[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_iena_sel[1]) begin
|
||||
iomem_rdata <= la_iena_1;
|
||||
|
||||
if (iomem_wstrb[0]) la_iena_1[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_iena_1[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_iena_1[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_iena_1[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_iena_sel[2]) begin
|
||||
iomem_rdata <= la_iena_2;
|
||||
|
||||
if (iomem_wstrb[0]) la_iena_2[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_iena_2[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_iena_2[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_iena_2[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_iena_sel[3]) begin
|
||||
iomem_rdata <= la_iena_3;
|
||||
|
||||
if (iomem_wstrb[0]) la_iena_3[ 7: 0] <= iomem_wdata[ 7: 0];
|
||||
if (iomem_wstrb[1]) la_iena_3[15: 8] <= iomem_wdata[15: 8];
|
||||
if (iomem_wstrb[2]) la_iena_3[23:16] <= iomem_wdata[23:16];
|
||||
if (iomem_wstrb[3]) la_iena_3[31:24] <= iomem_wdata[31:24];
|
||||
end else if (la_sample_sel) begin
|
||||
/* Simultaneous data capture: Sample all inputs */
|
||||
/* for which input is enabled and output is disabled. */
|
||||
la_data_0 <= la_data_in[31:0] & la_sample_mask_0;
|
||||
la_data_1 <= la_data_in[63:32] & la_sample_mask_1;
|
||||
la_data_2 <= la_data_in[95:64] & la_sample_mask_2;
|
||||
la_data_3 <= la_data_in[127:96] & la_sample_mask_3;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -1,462 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
`default_nettype none
|
||||
module mprj_ctrl_wb #(
|
||||
parameter BASE_ADR = 32'h 2300_0000,
|
||||
parameter XFER = 8'h 00,
|
||||
parameter PWRDATA = 8'h 04,
|
||||
parameter IRQDATA = 8'h 08,
|
||||
parameter IODATA = 8'h 0c, // One word per 32 IOs
|
||||
parameter IOCONFIG = 8'h 24
|
||||
)(
|
||||
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_1,
|
||||
output serial_data_out_2,
|
||||
|
||||
// Pass state of OEB bit on SDO and JTAG back to the core
|
||||
// so that the function can be overridden for management output
|
||||
output sdo_oenb_state,
|
||||
output jtag_oenb_state,
|
||||
output flash_io2_oenb_state,
|
||||
output flash_io3_oenb_state,
|
||||
|
||||
// Read/write data to each GPIO pad from management SoC
|
||||
input [`MPRJ_IO_PADS-1:0] mgmt_gpio_in,
|
||||
output [`MPRJ_IO_PADS-1:0] mgmt_gpio_out,
|
||||
output [`MPRJ_IO_PADS-1:0] mgmt_gpio_oeb,
|
||||
|
||||
// Write data to power controls
|
||||
output [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out,
|
||||
|
||||
// Enable user project IRQ signals to management SoC
|
||||
output [2:0] user_irq_ena,
|
||||
|
||||
// External bit-bang controls from the housekeeping SPI
|
||||
input ext_clock,
|
||||
input ext_resetn,
|
||||
input ext_data_1,
|
||||
input ext_data_2,
|
||||
input ext_enable
|
||||
);
|
||||
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),
|
||||
.XFER(XFER),
|
||||
.PWRDATA(PWRDATA),
|
||||
.IRQDATA(IRQDATA),
|
||||
.IODATA(IODATA),
|
||||
.IOCONFIG(IOCONFIG)
|
||||
) 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_1(serial_data_out_1),
|
||||
.serial_data_out_2(serial_data_out_2),
|
||||
.sdo_oenb_state(sdo_oenb_state),
|
||||
.jtag_oenb_state(jtag_oenb_state),
|
||||
.flash_io2_oenb_state(flash_io2_oenb_state),
|
||||
.flash_io3_oenb_state(flash_io3_oenb_state),
|
||||
// .mgmt_gpio_io(mgmt_gpio_io)
|
||||
.mgmt_gpio_in(mgmt_gpio_in),
|
||||
.mgmt_gpio_out(mgmt_gpio_out),
|
||||
.mgmt_gpio_oeb(mgmt_gpio_oeb),
|
||||
|
||||
// Write data to power controls
|
||||
.pwr_ctrl_out(pwr_ctrl_out),
|
||||
// Enable user project IRQ signals to management SoC
|
||||
.user_irq_ena(user_irq_ena),
|
||||
|
||||
// External bit-bang control from housekeeping SPI
|
||||
.ext_clock(ext_clock),
|
||||
.ext_resetn(ext_resetn),
|
||||
.ext_data_1(ext_data_1),
|
||||
.ext_data_2(ext_data_2),
|
||||
.ext_enable(ext_enable)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module mprj_ctrl #(
|
||||
parameter BASE_ADR = 32'h 2300_0000,
|
||||
parameter XFER = 8'h 00,
|
||||
parameter PWRDATA = 8'h 04,
|
||||
parameter IRQDATA = 8'h 08,
|
||||
parameter IODATA = 8'h 0c,
|
||||
parameter IOCONFIG = 8'h 24,
|
||||
parameter IO_CTRL_BITS = 13
|
||||
)(
|
||||
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_1,
|
||||
output serial_data_out_2,
|
||||
output sdo_oenb_state,
|
||||
output jtag_oenb_state,
|
||||
output flash_io2_oenb_state,
|
||||
output flash_io3_oenb_state,
|
||||
input [`MPRJ_IO_PADS-1:0] mgmt_gpio_in,
|
||||
output [`MPRJ_IO_PADS-1:0] mgmt_gpio_out,
|
||||
output [`MPRJ_IO_PADS-1:0] mgmt_gpio_oeb,
|
||||
output [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out,
|
||||
output [2:0] user_irq_ena,
|
||||
|
||||
input ext_clock,
|
||||
input ext_resetn,
|
||||
input ext_data_1,
|
||||
input ext_data_2,
|
||||
input ext_enable
|
||||
);
|
||||
|
||||
`define IDLE 2'b00
|
||||
`define START 2'b01
|
||||
`define XBYTE 2'b10
|
||||
`define LOAD 2'b11
|
||||
|
||||
localparam IO_WORDS = (`MPRJ_IO_PADS % 32 != 0) + (`MPRJ_IO_PADS / 32);
|
||||
|
||||
localparam IO_BASE_ADR = (BASE_ADR | IOCONFIG);
|
||||
|
||||
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[`MPRJ_IO_PADS-1:0]; // I/O control, 1 word per gpio pad
|
||||
reg [`MPRJ_IO_PADS-1:0] mgmt_gpio_out; // I/O write data, 1 bit per gpio pad
|
||||
reg [`MPRJ_PWR_PADS-1:0] pwr_ctrl_out; // Power write data, 1 bit per power pad
|
||||
reg [2:0] user_irq_ena; // Enable user to raise IRQs
|
||||
reg xfer_ctrl; // Transfer control (1 bit)
|
||||
|
||||
wire [IO_WORDS-1:0] io_data_sel; // wishbone selects
|
||||
wire pwr_data_sel;
|
||||
wire irq_data_sel;
|
||||
wire xfer_sel;
|
||||
wire busy;
|
||||
wire selected;
|
||||
wire [`MPRJ_IO_PADS-1:0] io_ctrl_sel;
|
||||
reg [31:0] iomem_rdata_pre;
|
||||
|
||||
wire [`MPRJ_IO_PADS-1:0] mgmt_gpio_in;
|
||||
|
||||
wire sdo_oenb_state, jtag_oenb_state;
|
||||
wire flash_io2_oenb_state, flash_io3_oenb_state;
|
||||
|
||||
// JTAG and housekeeping SDO are normally controlled by their respective
|
||||
// modules with OEB set to the default 1 value. If configured for an
|
||||
// additional output by setting the OEB bit low, then pass this information
|
||||
// back to the core so that the default signals can be overridden.
|
||||
|
||||
assign jtag_oenb_state = io_ctrl[0][OEB];
|
||||
assign sdo_oenb_state = io_ctrl[1][OEB];
|
||||
|
||||
// Likewise for the flash_io2 and flash_io3, although they are configured
|
||||
// as input by default.
|
||||
assign flash_io2_oenb_state = io_ctrl[(`MPRJ_IO_PADS)-2][OEB];
|
||||
assign flash_io3_oenb_state = io_ctrl[(`MPRJ_IO_PADS)-1][OEB];
|
||||
|
||||
`define wtop (((i+1)*32 > `MPRJ_IO_PADS) ? `MPRJ_IO_PADS-1 : (i+1)*32-1)
|
||||
`define wbot (i*32)
|
||||
`define rtop (`wtop - `wbot)
|
||||
|
||||
genvar i;
|
||||
|
||||
// Assign selection bits per address
|
||||
|
||||
assign xfer_sel = (iomem_addr[7:0] == XFER);
|
||||
assign pwr_data_sel = (iomem_addr[7:0] == PWRDATA);
|
||||
assign irq_data_sel = (iomem_addr[7:0] == IRQDATA);
|
||||
|
||||
generate
|
||||
for (i=0; i<IO_WORDS; i=i+1) begin
|
||||
assign io_data_sel[i] = (iomem_addr[7:0] == (IODATA + i*4));
|
||||
end
|
||||
|
||||
for (i=0; i<`MPRJ_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_oeb[i] = ~io_ctrl[i][INP_DIS];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
// Set selection and iomem_rdata_pre
|
||||
|
||||
assign selected = xfer_sel || pwr_data_sel || irq_data_sel || (|io_data_sel) || (|io_ctrl_sel);
|
||||
|
||||
wire [31:0] io_data_arr[0:IO_WORDS-1];
|
||||
wire [31:0] io_ctrl_arr[0:`MPRJ_IO_PADS-1];
|
||||
generate
|
||||
for (i=0; i<IO_WORDS; i=i+1) begin
|
||||
assign io_data_arr[i] = {{(31-`rtop){1'b0}}, mgmt_gpio_in[`wtop:`wbot]};
|
||||
|
||||
end
|
||||
for (i=0; i<`MPRJ_IO_PADS; i=i+1) begin
|
||||
assign io_ctrl_arr[i] = {{(32-IO_CTRL_BITS){1'b0}}, io_ctrl[i]};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
integer j;
|
||||
always @ * begin
|
||||
iomem_rdata_pre = 'b0;
|
||||
if (xfer_sel) begin
|
||||
iomem_rdata_pre = {31'b0, busy};
|
||||
end else if (pwr_data_sel) begin
|
||||
iomem_rdata_pre = {{(32-`MPRJ_PWR_PADS){1'b0}}, pwr_ctrl_out};
|
||||
end else if (irq_data_sel) begin
|
||||
iomem_rdata_pre = {29'b0, user_irq_ena};
|
||||
end else if (|io_data_sel) begin
|
||||
for (j=0; j<IO_WORDS; j=j+1) begin
|
||||
if (io_data_sel[j]) begin
|
||||
iomem_rdata_pre = io_data_arr[j];
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
for (j=0; j<`MPRJ_IO_PADS; j=j+1) begin
|
||||
if (io_ctrl_sel[j]) begin
|
||||
iomem_rdata_pre = io_ctrl_arr[j];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// General I/O transfer
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
iomem_rdata <= 0;
|
||||
iomem_ready <= 0;
|
||||
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 (selected) begin
|
||||
iomem_rdata <= iomem_rdata_pre;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// I/O write of xfer bit. Also handles iomem_ready signal and power data.
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
xfer_ctrl <= 0;
|
||||
pwr_ctrl_out <= 0;
|
||||
user_irq_ena <= 0;
|
||||
end else begin
|
||||
if (iomem_valid && !iomem_ready && iomem_addr[31:8] == BASE_ADR[31:8]) begin
|
||||
if (xfer_sel) begin
|
||||
if (iomem_wstrb[0]) xfer_ctrl <= iomem_wdata[0];
|
||||
end else if (pwr_data_sel) begin
|
||||
if (iomem_wstrb[0]) pwr_ctrl_out <= iomem_wdata[`MPRJ_PWR_PADS-1:0];
|
||||
end else if (irq_data_sel) begin
|
||||
if (iomem_wstrb[0]) user_irq_ena <= iomem_wdata[2:0];
|
||||
end
|
||||
end else begin
|
||||
xfer_ctrl <= 1'b0; // Immediately self-resetting
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// I/O transfer of gpio data to/from user project region under management
|
||||
// SoC control
|
||||
|
||||
generate
|
||||
for (i=0; i<IO_WORDS; i=i+1) begin
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
mgmt_gpio_out[`wtop:`wbot] <= 'd0;
|
||||
end else begin
|
||||
if (iomem_valid && !iomem_ready && iomem_addr[31:8] ==
|
||||
BASE_ADR[31:8]) begin
|
||||
if (io_data_sel[i]) begin
|
||||
if (iomem_wstrb[0]) begin
|
||||
mgmt_gpio_out[`wtop:`wbot] <= iomem_wdata[`rtop:0];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (i=0; i<`MPRJ_IO_PADS; i=i+1) begin
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
// NOTE: This initialization must match the defaults passed
|
||||
// to the control blocks. Specifically, 0x1803 is for a
|
||||
// bidirectional pad, and 0x0403 is for a simple input pad
|
||||
if ((i < 2) || (i >= `MPRJ_IO_PADS - 2)) begin
|
||||
io_ctrl[i] <= 'h1803;
|
||||
end else begin
|
||||
io_ctrl[i] <= 'h0403;
|
||||
end
|
||||
end else begin
|
||||
if (iomem_valid && !iomem_ready &&
|
||||
iomem_addr[31:8] == BASE_ADR[31:8]) begin
|
||||
if (io_ctrl_sel[i]) begin
|
||||
// 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
|
||||
|
||||
reg [3:0] xfer_count;
|
||||
reg [4:0] pad_count_1;
|
||||
reg [5:0] pad_count_2;
|
||||
reg [1:0] xfer_state;
|
||||
reg serial_clock;
|
||||
reg serial_resetn;
|
||||
|
||||
reg [IO_CTRL_BITS-1:0] serial_data_staging_1;
|
||||
reg [IO_CTRL_BITS-1:0] serial_data_staging_2;
|
||||
|
||||
wire serial_data_out_1;
|
||||
wire serial_data_out_2;
|
||||
|
||||
assign serial_data_out_1 = (ext_enable == 1'b1) ? ext_data_1 :
|
||||
serial_data_staging_1[IO_CTRL_BITS-1];
|
||||
assign serial_data_out_2 = (ext_enable == 1'b1) ? ext_data_2 :
|
||||
serial_data_staging_2[IO_CTRL_BITS-1];
|
||||
assign busy = (xfer_state != `IDLE);
|
||||
|
||||
always @(posedge clk or negedge resetn) begin
|
||||
if (resetn == 1'b0) begin
|
||||
|
||||
xfer_state <= `IDLE;
|
||||
xfer_count <= 4'd0;
|
||||
/* NOTE: This assumes that MPRJ_IO_PADS_1 and MPRJ_IO_PADS_2 are
|
||||
* equal, because they get clocked the same number of cycles by
|
||||
* the same clock signal. pad_count_2 gates the count for both.
|
||||
*/
|
||||
pad_count_1 <= `MPRJ_IO_PADS_1 - 1;
|
||||
pad_count_2 <= `MPRJ_IO_PADS_1;
|
||||
serial_resetn <= 1'b0;
|
||||
serial_clock <= 1'b0;
|
||||
serial_data_staging_1 <= 0;
|
||||
serial_data_staging_2 <= 0;
|
||||
|
||||
end else begin
|
||||
|
||||
if (ext_enable == 1'b1) begin
|
||||
serial_clock <= ext_clock;
|
||||
serial_resetn <= ext_resetn;
|
||||
end else if (xfer_state == `IDLE) begin
|
||||
pad_count_1 <= `MPRJ_IO_PADS_1 - 1;
|
||||
pad_count_2 <= `MPRJ_IO_PADS_1;
|
||||
serial_resetn <= 1'b1;
|
||||
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;
|
||||
pad_count_1 <= pad_count_1 - 1;
|
||||
pad_count_2 <= pad_count_2 + 1;
|
||||
xfer_state <= `XBYTE;
|
||||
serial_data_staging_1 <= io_ctrl[pad_count_1];
|
||||
serial_data_staging_2 <= io_ctrl[pad_count_2];
|
||||
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 - 1) begin
|
||||
if (pad_count_2 == `MPRJ_IO_PADS) begin
|
||||
xfer_state <= `LOAD;
|
||||
end else begin
|
||||
xfer_state <= `START;
|
||||
end
|
||||
end else begin
|
||||
xfer_count <= xfer_count + 1;
|
||||
end
|
||||
end else begin
|
||||
serial_data_staging_1 <= {serial_data_staging_1[IO_CTRL_BITS-2:0], 1'b0};
|
||||
serial_data_staging_2 <= {serial_data_staging_2[IO_CTRL_BITS-2:0], 1'b0};
|
||||
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
|
||||
`default_nettype wire
|
|
@ -1,180 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2020 Efabless Corporation
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
`default_nettype none
|
||||
module sysctrl_wb #(
|
||||
parameter BASE_ADR = 32'h2F00_0000,
|
||||
parameter PWRGOOD = 8'h00,
|
||||
parameter CLK_OUT = 8'h04,
|
||||
parameter TRAP_OUT = 8'h08,
|
||||
parameter IRQ_SRC = 8'h0c
|
||||
) (
|
||||
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,
|
||||
|
||||
input usr1_vcc_pwrgood,
|
||||
input usr2_vcc_pwrgood,
|
||||
input usr1_vdd_pwrgood,
|
||||
input usr2_vdd_pwrgood,
|
||||
output clk1_output_dest,
|
||||
output clk2_output_dest,
|
||||
output trap_output_dest,
|
||||
output irq_7_inputsrc,
|
||||
output irq_8_inputsrc
|
||||
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
sysctrl #(
|
||||
.BASE_ADR(BASE_ADR),
|
||||
.PWRGOOD(PWRGOOD),
|
||||
.CLK_OUT(CLK_OUT),
|
||||
.TRAP_OUT(TRAP_OUT),
|
||||
.IRQ_SRC(IRQ_SRC)
|
||||
) sysctrl (
|
||||
.clk(wb_clk_i),
|
||||
.resetn(resetn),
|
||||
|
||||
.iomem_addr(wb_adr_i),
|
||||
.iomem_valid(valid),
|
||||
.iomem_wstrb(iomem_we),
|
||||
.iomem_wdata(wb_dat_i),
|
||||
.iomem_rdata(wb_dat_o),
|
||||
.iomem_ready(ready),
|
||||
|
||||
.usr1_vcc_pwrgood(usr1_vcc_pwrgood),
|
||||
.usr2_vcc_pwrgood(usr2_vcc_pwrgood),
|
||||
.usr1_vdd_pwrgood(usr1_vdd_pwrgood),
|
||||
.usr2_vdd_pwrgood(usr2_vdd_pwrgood),
|
||||
.clk1_output_dest(clk1_output_dest),
|
||||
.clk2_output_dest(clk2_output_dest),
|
||||
.trap_output_dest(trap_output_dest),
|
||||
.irq_8_inputsrc(irq_8_inputsrc),
|
||||
.irq_7_inputsrc(irq_7_inputsrc)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module sysctrl #(
|
||||
parameter BASE_ADR = 32'h2300_0000,
|
||||
parameter PWRGOOD = 8'h00,
|
||||
parameter CLK_OUT = 8'h04,
|
||||
parameter TRAP_OUT = 8'h08,
|
||||
parameter IRQ_SRC = 8'h0c
|
||||
) (
|
||||
input clk,
|
||||
input resetn,
|
||||
|
||||
input [31:0] iomem_addr,
|
||||
input iomem_valid,
|
||||
input [3:0] iomem_wstrb,
|
||||
input [31:0] iomem_wdata,
|
||||
output reg [31:0] iomem_rdata,
|
||||
output reg iomem_ready,
|
||||
|
||||
input usr1_vcc_pwrgood,
|
||||
input usr2_vcc_pwrgood,
|
||||
input usr1_vdd_pwrgood,
|
||||
input usr2_vdd_pwrgood,
|
||||
output clk1_output_dest,
|
||||
output clk2_output_dest,
|
||||
output trap_output_dest,
|
||||
output irq_7_inputsrc,
|
||||
output irq_8_inputsrc
|
||||
);
|
||||
|
||||
reg clk1_output_dest;
|
||||
reg clk2_output_dest;
|
||||
reg trap_output_dest;
|
||||
reg irq_7_inputsrc;
|
||||
reg irq_8_inputsrc;
|
||||
|
||||
wire usr1_vcc_pwrgood;
|
||||
wire usr2_vcc_pwrgood;
|
||||
wire usr1_vdd_pwrgood;
|
||||
wire usr2_vdd_pwrgood;
|
||||
|
||||
wire pwrgood_sel;
|
||||
wire clk_out_sel;
|
||||
wire trap_out_sel;
|
||||
wire irq_sel;
|
||||
|
||||
assign pwrgood_sel = (iomem_addr[7:0] == PWRGOOD);
|
||||
assign clk_out_sel = (iomem_addr[7:0] == CLK_OUT);
|
||||
assign trap_out_sel = (iomem_addr[7:0] == TRAP_OUT);
|
||||
assign irq_sel = (iomem_addr[7:0] == IRQ_SRC);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!resetn) begin
|
||||
clk1_output_dest <= 0;
|
||||
clk2_output_dest <= 0;
|
||||
trap_output_dest <= 0;
|
||||
irq_7_inputsrc <= 0;
|
||||
irq_8_inputsrc <= 0;
|
||||
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 (pwrgood_sel) begin
|
||||
iomem_rdata <= {28'd0, usr2_vdd_pwrgood, usr1_vdd_pwrgood,
|
||||
usr2_vcc_pwrgood, usr1_vcc_pwrgood};
|
||||
// These are read-only bits; no write behavior on wstrb.
|
||||
|
||||
end else if (clk_out_sel) begin
|
||||
iomem_rdata <= {30'd0, clk2_output_dest, clk1_output_dest};
|
||||
if (iomem_wstrb[0]) begin
|
||||
clk1_output_dest <= iomem_wdata[0];
|
||||
clk2_output_dest <= iomem_wdata[1];
|
||||
end
|
||||
|
||||
end else if (trap_out_sel) begin
|
||||
iomem_rdata <= {31'd0, trap_output_dest};
|
||||
if (iomem_wstrb[0])
|
||||
trap_output_dest <= iomem_wdata[0];
|
||||
|
||||
end else if (irq_sel) begin
|
||||
iomem_rdata <= {30'd0, irq_8_inputsrc, irq_7_inputsrc};
|
||||
if (iomem_wstrb[0]) begin
|
||||
irq_7_inputsrc <= iomem_wdata[0];
|
||||
irq_8_inputsrc <= iomem_wdata[1];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
Loading…
Reference in New Issue