mirror of https://github.com/efabless/caravel.git
Seeding with documentation of pinout and verilog RTL (mostly unchanged
from original except to remove blocks that are not supposed to be in this repository like the processor core and the storage).
This commit is contained in:
parent
271f978bc8
commit
332f9ec2e7
|
@ -0,0 +1,320 @@
|
|||
Definitions:
|
||||
caravel_openframe: Version with one wrapper for user
|
||||
project only.
|
||||
|
||||
caravel_harness: Version with wrappers for user project
|
||||
area and management core.
|
||||
|
||||
caravel_pico: PicoRV32, as a drop-in module for caravel_harness
|
||||
|
||||
Harness definition:
|
||||
Management SoC and User Project are both wrappers for drop-in
|
||||
modules.
|
||||
|
||||
The harness itself contains the clocking module, DLL, user ID,
|
||||
housekeeping SPI, POR, and GPIO control.
|
||||
|
||||
GPIO handling moved out of management SoC and into SPI. SPI
|
||||
gets a wishbone interface; the management SoC talks to the SPI
|
||||
through wishbone, not by taking over the 4-pin SPI interface.
|
||||
|
||||
(Maybe) New block like the ID has the mode at power-up for
|
||||
each GPIO. Can be configured with a text file. SPI pins are
|
||||
fixed for operation on startup.
|
||||
|
||||
On power-up, the SPI automatically configures the GPIO. Manual
|
||||
load is possible from both the SPI and from the wishbone bus.
|
||||
|
||||
Openframe definition:
|
||||
There is only one area which is the User Project, with a wrapper
|
||||
to take a drop-in module.
|
||||
|
||||
The openframe module contains clocking, DLL, user ID, housekeeping
|
||||
SPI, POR, and GPIO control. Operation is essentially the same as
|
||||
the above (harness definition).
|
||||
|
||||
MPW-one compatibility:
|
||||
Looks like the harness, but the logic analyzer and management-
|
||||
protect is part of the harness and the user area wrapper matches
|
||||
that for MPW-one.
|
||||
|
||||
MPW-two compatibility:
|
||||
Looks like the harness, but the logic analyzer and management-
|
||||
protect is part of the harness and the user area wrapper matches
|
||||
that for MPW-two.
|
||||
|
||||
Caravel-pico definition:
|
||||
Caravel-pico is a version of the PicoRV32 Management SoC from
|
||||
MPW-two, but without the GPIO control, clocking control, DLL,
|
||||
housekeeping SPI, and logic analyzer. It mainly just exports
|
||||
the Wishbone bus interface to the user project area.
|
||||
|
||||
Pinouts for Caravel (any version)
|
||||
----------------------------------------------
|
||||
Power supplies:
|
||||
vddio, vssio, vdda, vssa, vccd, vssd,
|
||||
vdda1, vdda2, vssa1, vssa2,
|
||||
vccd1, vccd2, vssd1, vssd2
|
||||
|
||||
Management SoC signals:
|
||||
debug (or JTAG, management)
|
||||
gpio
|
||||
clock
|
||||
resetb
|
||||
flash_csb
|
||||
flash_clk
|
||||
flash_io0
|
||||
flash_io1
|
||||
|
||||
User area signals:
|
||||
mprj_io[37:0]
|
||||
|
||||
User project area pinout (openframe)
|
||||
----------------------------------------------
|
||||
Power supplies:
|
||||
vddio, vssio, vdda, vssa, vccd, vssd,
|
||||
vdda1, vdda2, vssa1, vssa2,
|
||||
vccd1, vccd2, vssd1, vssd2
|
||||
|
||||
Wishbone bus (exported to SPI):
|
||||
wb_clk_i
|
||||
wb_rst_i
|
||||
wbs_stb_i
|
||||
wbs_cyc_i
|
||||
wbs_we_i
|
||||
wbs_sel_i[3:0]
|
||||
wbs_dat_i[31:0]
|
||||
wbs_adr_i[31:0]
|
||||
wbs_ack_o
|
||||
wbs_dat_o[31:0]
|
||||
|
||||
GPIO:
|
||||
io_in[37:0]
|
||||
io_out[37:0]
|
||||
io_oeb[37:0]
|
||||
|
||||
GPIO (single):
|
||||
gpio_out
|
||||
gpio_in
|
||||
gpio_oeb
|
||||
gpio_ieb
|
||||
|
||||
Flash controller:
|
||||
flash_clk
|
||||
flash_clk_oeb
|
||||
flash_csb
|
||||
flash_csb_oeb
|
||||
flash_io0_do
|
||||
flash_io1_do
|
||||
flash_io2_do
|
||||
flash_io3_do
|
||||
flash_io0_di
|
||||
flash_io1_di
|
||||
flash_io2_di
|
||||
flash_io3_di
|
||||
flash_io0_oeb
|
||||
flash_io1_oeb
|
||||
flash_io2_oeb
|
||||
flash_io3_oeb
|
||||
flash_io0_ieb
|
||||
flash_io1_ieb
|
||||
flash_io2_ieb
|
||||
flash_io3_ieb
|
||||
|
||||
Essentials:
|
||||
resetb
|
||||
core_clk
|
||||
|
||||
Miscellaneous:
|
||||
user_clock2
|
||||
user_irq[2:0]
|
||||
|
||||
|
||||
User project area pinout (harness)
|
||||
----------------------------------------------
|
||||
Power supplies:
|
||||
vdda1, vdda2, vssa1, vssa2,
|
||||
vccd1, vccd2, vssd1, vssd2
|
||||
|
||||
Wishbone bus:
|
||||
wb_clk_i
|
||||
wb_rst_i
|
||||
wbs_stb_i
|
||||
wbs_cyc_i
|
||||
wbs_we_i
|
||||
wbs_sel_i[3:0]
|
||||
wbs_dat_i[31:0]
|
||||
wbs_adr_i[31:0]
|
||||
wbs_ack_o
|
||||
wbs_dat_o[31:0]
|
||||
|
||||
GPIO:
|
||||
io_in[37:0]
|
||||
io_out[37:0]
|
||||
io_oeb[37:0]
|
||||
|
||||
Miscellaneous:
|
||||
user_clock2
|
||||
user_irq[2:0]
|
||||
|
||||
Management SoC pinout
|
||||
----------------------------------------------
|
||||
GPIO:
|
||||
gpio_out
|
||||
gpio_in
|
||||
gpio_oeb
|
||||
gpio_ieb
|
||||
|
||||
Flash controller:
|
||||
flash_clk
|
||||
flash_csb
|
||||
flash_io0_do
|
||||
flash_io1_do
|
||||
flash_io2_do
|
||||
flash_io3_do
|
||||
flash_io0_di
|
||||
flash_io1_di
|
||||
flash_io2_di
|
||||
flash_io3_di
|
||||
flash_io0_oeb
|
||||
flash_io1_oeb
|
||||
flash_io2_oeb
|
||||
flash_io3_oeb
|
||||
|
||||
Essentials:
|
||||
resetb
|
||||
core_clk
|
||||
|
||||
Wishbone bus:
|
||||
mprj_ack_i
|
||||
mprj_dat_i[31:0]
|
||||
mprj_dat_o[31:0]
|
||||
mprj_cyc_o
|
||||
mprj_stb_o
|
||||
mprj_we_o
|
||||
mprj_sel_o[3:0]
|
||||
mprj_adr_o[31:0]
|
||||
|
||||
Interface pinout (standard = pass-through)
|
||||
----------------------------------------------
|
||||
Clocking (DLL)
|
||||
clock
|
||||
porb
|
||||
resetb
|
||||
core_clk
|
||||
|
||||
Housekeeping SPI
|
||||
SCK
|
||||
CSB
|
||||
SDI
|
||||
SDO
|
||||
sdo_enb
|
||||
|
||||
Flash pass-through:
|
||||
flash_clk_oeb
|
||||
flash_csb_oeb
|
||||
flash_io0_ieb
|
||||
flash_io1_ieb
|
||||
flash_io2_ieb
|
||||
flash_io3_ieb
|
||||
|
||||
(plus management flash signals in from SoC/out to pads)
|
||||
|
||||
Wishbone bus:
|
||||
mprj_ack_i
|
||||
mprj_dat_i[31:0]
|
||||
mprj_dat_o[31:0]
|
||||
mprj_cyc_o
|
||||
mprj_stb_o
|
||||
mprj_we_o
|
||||
mprj_sel_o[3:0]
|
||||
mprj_adr_o[31:0]
|
||||
|
||||
User ID programming
|
||||
mask_rev[31:0]
|
||||
|
||||
Interface pinout (MPW-one compatibility level)
|
||||
----------------------------------------------
|
||||
Clocking (DLL)
|
||||
clock
|
||||
porb
|
||||
resetb
|
||||
core_clk
|
||||
|
||||
GPIO controller
|
||||
serial_data
|
||||
serial_clock
|
||||
serial_reset
|
||||
|
||||
Housekeeping SPI
|
||||
SCK
|
||||
CSB
|
||||
SDI
|
||||
SDO
|
||||
sdo_enb
|
||||
|
||||
Flash pass-through:
|
||||
flash_clk_oeb
|
||||
flash_csb_oeb
|
||||
flash_io0_ieb
|
||||
flash_io1_ieb
|
||||
flash_io2_ieb
|
||||
flash_io3_ieb
|
||||
|
||||
(plus management flash signals in from SoC/out to pads)
|
||||
|
||||
Wishbone bus:
|
||||
mprj_ack_i
|
||||
mprj_dat_i[31:0]
|
||||
mprj_dat_o[31:0]
|
||||
mprj_cyc_o
|
||||
mprj_stb_o
|
||||
mprj_we_o
|
||||
mprj_sel_o[3:0]
|
||||
mprj_adr_o[31:0]
|
||||
|
||||
User ID programming
|
||||
mask_rev[31:0]
|
||||
|
||||
Logic Analyzer
|
||||
la_io[127:0]
|
||||
la_oenb[127:0]
|
||||
|
||||
Interface pinout (MPW-two compatibility level)
|
||||
----------------------------------------------
|
||||
Clocking (DLL)
|
||||
clock
|
||||
porb
|
||||
resetb
|
||||
core_clk
|
||||
|
||||
GPIO controller
|
||||
serial_data
|
||||
serial_clock
|
||||
serial_reset
|
||||
|
||||
Housekeeping SPI
|
||||
SCK
|
||||
CSB
|
||||
SDI
|
||||
SDO
|
||||
sdo_enb
|
||||
|
||||
Wishbone bus:
|
||||
mprj_ack_i
|
||||
mprj_dat_i[31:0]
|
||||
mprj_dat_o[31:0]
|
||||
mprj_cyc_o
|
||||
mprj_stb_o
|
||||
mprj_we_o
|
||||
mprj_sel_o[3:0]
|
||||
mprj_adr_o[31:0]
|
||||
|
||||
User ID programming
|
||||
mask_rev[31:0]
|
||||
|
||||
Logic Analyzer
|
||||
la_input[127:0]
|
||||
la_output[127:0]
|
||||
la_oenb[127:0]
|
||||
la_iena[127:0]
|
|
@ -0,0 +1,35 @@
|
|||
// 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, a project harness for the Google/SkyWater sky130 */
|
||||
/* fabrication process and open source PDK */
|
||||
/* */
|
||||
/* Copyright 2020 efabless, Inc. */
|
||||
/* Written by Tim Edwards, December 2019 */
|
||||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
`define USE_POWER_PINS
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
`ifdef GL
|
||||
`include "gl/__user_analog_project_wrapper.v"
|
||||
`else
|
||||
`include "__user_analog_project_wrapper.v"
|
||||
`endif
|
|
@ -0,0 +1,35 @@
|
|||
// 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, a project harness for the Google/SkyWater sky130 */
|
||||
/* fabrication process and open source PDK */
|
||||
/* */
|
||||
/* Copyright 2020 efabless, Inc. */
|
||||
/* Written by Tim Edwards, December 2019 */
|
||||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
`define USE_POWER_PINS
|
||||
|
||||
`include "defines.v"
|
||||
|
||||
`ifdef GL
|
||||
`include "gl/__user_project_wrapper.v"
|
||||
`else
|
||||
`include "__user_project_wrapper.v"
|
||||
`endif
|
|
@ -0,0 +1,124 @@
|
|||
// 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
|
||||
/*
|
||||
*-------------------------------------------------------------
|
||||
*
|
||||
* user_analog_project_wrapper
|
||||
*
|
||||
* This wrapper enumerates all of the pins available to the
|
||||
* user for the user analog project.
|
||||
*
|
||||
*-------------------------------------------------------------
|
||||
*/
|
||||
|
||||
module user_analog_project_wrapper (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vdda1, // User area 1 3.3V supply
|
||||
inout vdda2, // User area 2 3.3V supply
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V supply
|
||||
inout vccd2, // User area 2 1.8v supply
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
`endif
|
||||
|
||||
// Wishbone Slave ports (WB MI A)
|
||||
input wb_clk_i,
|
||||
input wb_rst_i,
|
||||
input wbs_stb_i,
|
||||
input wbs_cyc_i,
|
||||
input wbs_we_i,
|
||||
input [3:0] wbs_sel_i,
|
||||
input [31:0] wbs_dat_i,
|
||||
input [31:0] wbs_adr_i,
|
||||
output wbs_ack_o,
|
||||
output [31:0] wbs_dat_o,
|
||||
|
||||
// Logic Analyzer Signals
|
||||
input [127:0] la_data_in,
|
||||
output [127:0] la_data_out,
|
||||
input [127:0] la_oenb,
|
||||
|
||||
/* GPIOs. There are 27 GPIOs, on either side of the analog.
|
||||
* These have the following mapping to the GPIO padframe pins
|
||||
* and memory-mapped registers, since the numbering remains the
|
||||
* same as caravel but skips over the analog I/O:
|
||||
*
|
||||
* io_in/out/oeb/in_3v3 [26:14] <---> mprj_io[37:25]
|
||||
* io_in/out/oeb/in_3v3 [13:0] <---> mprj_io[13:0]
|
||||
*
|
||||
* When the GPIOs are configured by the Management SoC for
|
||||
* user use, they have three basic bidirectional controls:
|
||||
* in, out, and oeb (output enable, sense inverted). For
|
||||
* analog projects, a 3.3V copy of the signal input is
|
||||
* available. out and oeb must be 1.8V signals.
|
||||
*/
|
||||
|
||||
input [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] io_in,
|
||||
input [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] io_in_3v3,
|
||||
output [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] io_out,
|
||||
output [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] io_oeb,
|
||||
|
||||
/* Analog (direct connection to GPIO pad---not for high voltage or
|
||||
* high frequency use). The management SoC must turn off both
|
||||
* input and output buffers on these GPIOs to allow analog access.
|
||||
* These signals may drive a voltage up to the value of VDDIO
|
||||
* (3.3V typical, 5.5V maximum).
|
||||
*
|
||||
* Note that analog I/O is not available on the 7 lowest-numbered
|
||||
* GPIO pads, and so the analog_io indexing is offset from the
|
||||
* GPIO indexing by 7, as follows:
|
||||
*
|
||||
* gpio_analog/noesd [17:7] <---> mprj_io[35:25]
|
||||
* gpio_analog/noesd [6:0] <---> mprj_io[13:7]
|
||||
*
|
||||
*/
|
||||
|
||||
inout [`MPRJ_IO_PADS-`ANALOG_PADS-10:0] gpio_analog,
|
||||
inout [`MPRJ_IO_PADS-`ANALOG_PADS-10:0] gpio_noesd,
|
||||
|
||||
/* Analog signals, direct through to pad. These have no ESD at all,
|
||||
* so ESD protection is the responsibility of the designer.
|
||||
*
|
||||
* user_analog[10:0] <---> mprj_io[24:14]
|
||||
*
|
||||
*/
|
||||
inout [`ANALOG_PADS-1:0] io_analog,
|
||||
|
||||
/* Additional power supply ESD clamps, one per analog pad. The
|
||||
* high side should be connected to a 3.3-5.5V power supply.
|
||||
* The low side should be connected to ground.
|
||||
*
|
||||
* clamp_high[2:0] <---> mprj_io[20:18]
|
||||
* clamp_low[2:0] <---> mprj_io[20:18]
|
||||
*
|
||||
*/
|
||||
inout [2:0] io_clamp_high,
|
||||
inout [2:0] io_clamp_low,
|
||||
|
||||
// Independent clock (on independent integer divider)
|
||||
input user_clock2,
|
||||
|
||||
// User maskable interrupt signals
|
||||
output [2:0] user_irq
|
||||
);
|
||||
|
||||
// Dummy assignment so that we can take it through the openlane flow
|
||||
assign io_out = io_in;
|
||||
|
||||
endmodule // user_analog_project_wrapper
|
|
@ -0,0 +1,90 @@
|
|||
// 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
|
||||
/*
|
||||
*-------------------------------------------------------------
|
||||
*
|
||||
* user_project_wrapper
|
||||
*
|
||||
* This wrapper enumerates all of the pins available to the
|
||||
* user for the user project.
|
||||
*
|
||||
* An example user project is provided in this wrapper. The
|
||||
* example should be removed and replaced with the actual
|
||||
* user project.
|
||||
*
|
||||
*-------------------------------------------------------------
|
||||
*/
|
||||
|
||||
module user_project_wrapper #(
|
||||
parameter BITS = 32
|
||||
)(
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vdda1, // User area 1 3.3V supply
|
||||
inout vdda2, // User area 2 3.3V supply
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V supply
|
||||
inout vccd2, // User area 2 1.8v supply
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
`endif
|
||||
|
||||
// Wishbone Slave ports (WB MI A)
|
||||
input wb_clk_i,
|
||||
input wb_rst_i,
|
||||
input wbs_stb_i,
|
||||
input wbs_cyc_i,
|
||||
input wbs_we_i,
|
||||
input [3:0] wbs_sel_i,
|
||||
input [31:0] wbs_dat_i,
|
||||
input [31:0] wbs_adr_i,
|
||||
output wbs_ack_o,
|
||||
output [31:0] wbs_dat_o,
|
||||
|
||||
// Logic Analyzer Signals
|
||||
input [127:0] la_data_in,
|
||||
output [127:0] la_data_out,
|
||||
input [127:0] la_oenb,
|
||||
|
||||
// IOs
|
||||
input [`MPRJ_IO_PADS-1:0] io_in,
|
||||
output [`MPRJ_IO_PADS-1:0] io_out,
|
||||
output [`MPRJ_IO_PADS-1:0] io_oeb,
|
||||
|
||||
// Analog (direct connection to GPIO pad---use with caution)
|
||||
// Note that analog I/O is not available on the 7 lowest-numbered
|
||||
// GPIO pads, and so the analog_io indexing is offset from the
|
||||
// GPIO indexing by 7 (also upper 2 GPIOs do not have analog_io).
|
||||
inout [`MPRJ_IO_PADS-10:0] analog_io,
|
||||
|
||||
// Independent clock (on independent integer divider)
|
||||
input user_clock2,
|
||||
|
||||
// User maskable interrupt signals
|
||||
output [2:0] user_irq
|
||||
);
|
||||
|
||||
// Dummy assignments so that we can take it through the openlane flow
|
||||
`ifdef SIM
|
||||
// Needed for running GL simulation
|
||||
assign io_out = 0;
|
||||
assign io_oeb = 0;
|
||||
`else
|
||||
assign io_out = io_in;
|
||||
`endif
|
||||
|
||||
endmodule // user_project_wrapper
|
|
@ -0,0 +1,942 @@
|
|||
// `default_nettype none
|
||||
// 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
|
||||
/*--------------------------------------------------------------*/
|
||||
/* caravan, a project harness for the Google/SkyWater sky130 */
|
||||
/* fabrication process and open source PDK. caravan is an */
|
||||
/* alternative architecture to caravel that has simple straight */
|
||||
/* through connections replacing the GPIO pads on the top side */
|
||||
/* of the padframe. A total of 11 pads are converted from GPIO */
|
||||
/* to analog, leaving 27 GPIO. */
|
||||
/* */
|
||||
/* Copyright 2021 efabless, Inc. */
|
||||
/* Written by Tim Edwards, December 2019 */
|
||||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Derived types for the array bounds on the two digital and */
|
||||
/* two analog pad arrays. As defined above, the sections have */
|
||||
/* the number of pads as follows: */
|
||||
/* */
|
||||
/* DIG2 : 13 GPIO pads */
|
||||
/* ANA2 : 6 analog pads */
|
||||
/* ANA1 : 5 analog pads */
|
||||
/* DIG1 : 14 GPIO pads */
|
||||
/* */
|
||||
/* This makes a total of 38 pads = `MPRJ_IO_PADS */
|
||||
/* The pads are still designated as mprj_io[37:0] around the */
|
||||
/* padframe. The SoC core remains the same, so the programming */
|
||||
/* of the digital signals remains the same, but the values for */
|
||||
/* GPIO 15-25 are not used. */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
`define DIG2_TOP (`MPRJ_IO_PADS - 1)
|
||||
`define DIG2_BOT (`MPRJ_IO_PADS_1 + `ANALOG_PADS_2)
|
||||
`define ANA2_TOP (`MPRJ_IO_PADS_1 + `ANALOG_PADS_2 - 1)
|
||||
`define ANA2_BOT (`MPRJ_IO_PADS_1)
|
||||
`define ANA1_TOP (`MPRJ_IO_PADS_1 - 1)
|
||||
`define ANA1_BOT (`MPRJ_IO_PADS_1 - `ANALOG_PADS_1)
|
||||
`define DIG1_TOP (`MPRJ_IO_PADS_1 - `ANALOG_PADS_1 - 1)
|
||||
`define DIG1_BOT (0)
|
||||
|
||||
`define MPRJ_DIG_PADS (`MPRJ_IO_PADS - `ANALOG_PADS)
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
module caravan (
|
||||
inout vddio, // Common 3.3V padframe/ESD power
|
||||
inout vddio_2, // Common 3.3V padframe/ESD power
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
inout vssio_2, // Common padframe/ESD ground
|
||||
inout vdda, // Management 3.3V power
|
||||
inout vssa, // Common analog ground
|
||||
inout vccd, // Management/Common 1.8V power
|
||||
inout vssd, // Common digital ground
|
||||
inout vdda1, // User area 1 3.3V power
|
||||
inout vdda1_2, // User area 1 3.3V power
|
||||
inout vdda2, // User area 2 3.3V power
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa1_2, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V power
|
||||
inout vccd2, // User area 2 1.8V power
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
|
||||
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,
|
||||
|
||||
// Note that only two pins are available on the flash so dual and
|
||||
// quad flash modes are not available.
|
||||
|
||||
output flash_csb,
|
||||
output flash_clk,
|
||||
output flash_io0,
|
||||
output flash_io1
|
||||
);
|
||||
|
||||
//------------------------------------------------------------
|
||||
// This value is uniquely defined for each user project.
|
||||
//------------------------------------------------------------
|
||||
parameter USER_PROJECT_ID = 32'h00000000;
|
||||
|
||||
// These pins are overlaid on mprj_io space. They have the function
|
||||
// below when the management processor is in reset, or in the default
|
||||
// configuration. They are assigned to uses in the user space by the
|
||||
// configuration program running off of the SPI flash. Note that even
|
||||
// when the user has taken control of these pins, they can be restored
|
||||
// to the original use by setting the resetb pin low. The SPI pins and
|
||||
// UART pins can be connected directly to an FTDI chip as long as the
|
||||
// FTDI chip sets these lines to high impedence (input function) at
|
||||
// all times except when holding the chip in reset.
|
||||
|
||||
// JTAG = mprj_io[0] (inout)
|
||||
// SDO = mprj_io[1] (output)
|
||||
// SDI = mprj_io[2] (input)
|
||||
// CSB = mprj_io[3] (input)
|
||||
// SCK = mprj_io[4] (input)
|
||||
// ser_rx = mprj_io[5] (input)
|
||||
// ser_tx = mprj_io[6] (output)
|
||||
// irq = mprj_io[7] (input)
|
||||
|
||||
// These pins are reserved for any project that wants to incorporate
|
||||
// its own processor and flash controller. While a user project can
|
||||
// technically use any available I/O pins for the purpose, these
|
||||
// four pins connect to a pass-through mode from the SPI slave (pins
|
||||
// 1-4 above) so that any SPI flash connected to these specific pins
|
||||
// can be accessed through the SPI slave even when the processor is in
|
||||
// reset.
|
||||
|
||||
// user_flash_csb = mprj_io[8]
|
||||
// user_flash_sck = mprj_io[9]
|
||||
// user_flash_io0 = mprj_io[10]
|
||||
// user_flash_io1 = mprj_io[11]
|
||||
|
||||
// One-bit GPIO dedicated to management SoC (outside of user control)
|
||||
wire gpio_out_core;
|
||||
wire gpio_in_core;
|
||||
wire gpio_mode0_core;
|
||||
wire gpio_mode1_core;
|
||||
wire gpio_outenb_core;
|
||||
wire gpio_inenb_core;
|
||||
|
||||
// 27 GPIO pads with full controls
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_inp_dis;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_ib_mode_sel;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_vtrip_sel;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_slow_sel;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_holdover;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_analog_en;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_analog_sel;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_analog_pol;
|
||||
wire [(`MPRJ_IO_PADS-`ANALOG_PADS)*3-1:0] mprj_io_dm;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_in;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_in_3v3;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_out;
|
||||
|
||||
// User Project Control (user-facing)
|
||||
// 27 GPIO bidirectional with in/out/oeb and a 3.3V copy of the input
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] user_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] user_io_in;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] user_io_out;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] user_io_in_3v3;
|
||||
|
||||
// 18 direct connections to GPIO for low-frequency, low-voltage analog
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-10:0] user_gpio_analog;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-10:0] user_gpio_noesd;
|
||||
|
||||
// 3 power supply ESD clamps for user applications
|
||||
wire [2:0] user_clamp_high;
|
||||
wire [2:0] user_clamp_low;
|
||||
|
||||
// 11 core connections to the analog pads
|
||||
wire [`ANALOG_PADS-1:0] user_analog;
|
||||
|
||||
/* Padframe control signals */
|
||||
wire [`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1:0] gpio_serial_link_1;
|
||||
wire [`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1:0] gpio_serial_link_2;
|
||||
wire mprj_io_loader_resetn;
|
||||
wire mprj_io_loader_clock;
|
||||
wire mprj_io_loader_data_1; /* user1 side serial loader */
|
||||
wire mprj_io_loader_data_2; /* user2 side serial loader */
|
||||
|
||||
// User Project Control management I/O
|
||||
// There are two types of GPIO connections:
|
||||
// (1) Full Bidirectional: Management connects to in, out, and oeb
|
||||
// Uses: JTAG and SDO
|
||||
// (2) Selectable bidirectional: Management connects to in and out,
|
||||
// which are tied together. oeb is grounded (oeb from the
|
||||
// configuration is used)
|
||||
|
||||
// SDI = mprj_io[2] (input)
|
||||
// CSB = mprj_io[3] (input)
|
||||
// SCK = mprj_io[4] (input)
|
||||
// ser_rx = mprj_io[5] (input)
|
||||
// ser_tx = mprj_io[6] (output)
|
||||
// irq = mprj_io[7] (input)
|
||||
|
||||
wire [`MPRJ_IO_PADS-1:0] mgmt_io_in;
|
||||
wire jtag_out, sdo_out;
|
||||
wire jtag_outenb, sdo_outenb;
|
||||
wire gpio_flash_io2_out, gpio_flash_io3_out;
|
||||
|
||||
wire [1:0] mgmt_io_nc; /* no-connects */
|
||||
|
||||
wire clock_core;
|
||||
|
||||
// Power-on-reset signal. The reset pad generates the sense-inverted
|
||||
// reset at 3.3V. The 1.8V signal and the inverted 1.8V signal are
|
||||
// derived.
|
||||
|
||||
wire porb_h;
|
||||
wire porb_l;
|
||||
wire por_l;
|
||||
|
||||
wire rstb_h;
|
||||
wire rstb_l;
|
||||
|
||||
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_io0_do_core, flash_io1_do_core;
|
||||
wire flash_io0_di_core, flash_io1_di_core;
|
||||
|
||||
chip_io_alt #(
|
||||
.ANALOG_PADS_1(`ANALOG_PADS_1),
|
||||
.ANALOG_PADS_2(`ANALOG_PADS_2)
|
||||
) padframe (
|
||||
`ifndef TOP_ROUTING
|
||||
// Package Pins
|
||||
.vddio_pad (vddio), // Common padframe/ESD supply
|
||||
.vddio_pad2 (vddio_2),
|
||||
.vssio_pad (vssio), // Common padframe/ESD ground
|
||||
.vssio_pad2 (vssio_2),
|
||||
.vccd_pad (vccd), // Common 1.8V supply
|
||||
.vssd_pad (vssd), // Common digital ground
|
||||
.vdda_pad (vdda), // Management analog 3.3V supply
|
||||
.vssa_pad (vssa), // Management analog ground
|
||||
.vdda1_pad (vdda1), // User area 1 3.3V supply
|
||||
.vdda1_pad2 (vdda1_2),
|
||||
.vdda2_pad (vdda2), // User area 2 3.3V supply
|
||||
.vssa1_pad (vssa1), // User area 1 analog ground
|
||||
.vssa1_pad2 (vssa1_2),
|
||||
.vssa2_pad (vssa2), // User area 2 analog ground
|
||||
.vccd1_pad (vccd1), // User area 1 1.8V supply
|
||||
.vccd2_pad (vccd2), // User area 2 1.8V supply
|
||||
.vssd1_pad (vssd1), // User area 1 digital ground
|
||||
.vssd2_pad (vssd2), // User area 2 digital ground
|
||||
`endif
|
||||
|
||||
// Core Side Pins
|
||||
.vddio (vddio_core),
|
||||
.vssio (vssio_core),
|
||||
.vdda (vdda_core),
|
||||
.vssa (vssa_core),
|
||||
.vccd (vccd_core),
|
||||
.vssd (vssd_core),
|
||||
.vdda1 (vdda1_core),
|
||||
.vdda2 (vdda2_core),
|
||||
.vssa1 (vssa1_core),
|
||||
.vssa2 (vssa2_core),
|
||||
.vccd1 (vccd1_core),
|
||||
.vccd2 (vccd2_core),
|
||||
.vssd1 (vssd1_core),
|
||||
.vssd2 (vssd2_core),
|
||||
|
||||
.gpio(gpio),
|
||||
.mprj_io(mprj_io),
|
||||
.clock(clock),
|
||||
.resetb(resetb),
|
||||
.flash_csb(flash_csb),
|
||||
.flash_clk(flash_clk),
|
||||
.flash_io0(flash_io0),
|
||||
.flash_io1(flash_io1),
|
||||
// SoC Core Interface
|
||||
.porb_h(porb_h),
|
||||
.por(por_l),
|
||||
.resetb_core_h(rstb_h),
|
||||
.clock_core(clock_core),
|
||||
.gpio_out_core(gpio_out_core),
|
||||
.gpio_in_core(gpio_in_core),
|
||||
.gpio_mode0_core(gpio_mode0_core),
|
||||
.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),
|
||||
.mprj_io_in(mprj_io_in),
|
||||
.mprj_io_in_3v3(mprj_io_in_3v3),
|
||||
.mprj_io_out(mprj_io_out),
|
||||
.mprj_io_oeb(mprj_io_oeb),
|
||||
.mprj_io_inp_dis(mprj_io_inp_dis),
|
||||
.mprj_io_ib_mode_sel(mprj_io_ib_mode_sel),
|
||||
.mprj_io_vtrip_sel(mprj_io_vtrip_sel),
|
||||
.mprj_io_slow_sel(mprj_io_slow_sel),
|
||||
.mprj_io_holdover(mprj_io_holdover),
|
||||
.mprj_io_analog_en(mprj_io_analog_en),
|
||||
.mprj_io_analog_sel(mprj_io_analog_sel),
|
||||
.mprj_io_analog_pol(mprj_io_analog_pol),
|
||||
.mprj_io_dm(mprj_io_dm),
|
||||
.mprj_gpio_analog(user_gpio_analog),
|
||||
.mprj_gpio_noesd(user_gpio_noesd),
|
||||
.mprj_analog(user_analog),
|
||||
.mprj_clamp_high(user_clamp_high),
|
||||
.mprj_clamp_low(user_clamp_low)
|
||||
);
|
||||
|
||||
// SoC core
|
||||
wire caravel_clk;
|
||||
wire caravel_clk2;
|
||||
wire caravel_rstn;
|
||||
|
||||
wire [7:0] spi_ro_config_core;
|
||||
|
||||
// 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 MPRJ to CPU
|
||||
wire [2:0] user_irq_core;
|
||||
wire [2:0] user_irq_ena;
|
||||
|
||||
// WB MI A (User Project)
|
||||
wire mprj_cyc_o_core;
|
||||
wire mprj_stb_o_core;
|
||||
wire mprj_we_o_core;
|
||||
wire [3:0] mprj_sel_o_core;
|
||||
wire [31:0] mprj_adr_o_core;
|
||||
wire [31:0] mprj_dat_o_core;
|
||||
wire mprj_ack_i_core;
|
||||
wire [31:0] mprj_dat_i_core;
|
||||
|
||||
// Mask revision
|
||||
wire [31:0] mask_rev;
|
||||
|
||||
wire mprj_clock;
|
||||
wire mprj_clock2;
|
||||
wire mprj_reset;
|
||||
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;
|
||||
wire mprj_vcc_pwrgood;
|
||||
wire mprj2_vcc_pwrgood;
|
||||
wire mprj_vdd_pwrgood;
|
||||
wire mprj2_vdd_pwrgood;
|
||||
|
||||
// Storage area
|
||||
// Management R/W interface
|
||||
wire [`RAM_BLOCKS-1:0] mgmt_ena;
|
||||
wire [`RAM_BLOCKS-1:0] mgmt_wen;
|
||||
wire [(`RAM_BLOCKS*4)-1:0] mgmt_wen_mask;
|
||||
wire [7:0] mgmt_addr;
|
||||
wire [31:0] mgmt_wdata;
|
||||
wire [(`RAM_BLOCKS*32)-1:0] mgmt_rdata;
|
||||
// Management RO interface
|
||||
wire mgmt_ena_ro;
|
||||
wire [7:0] mgmt_addr_ro;
|
||||
wire [31:0] mgmt_rdata_ro;
|
||||
wire [31:0] hkspi_sram_rdata;
|
||||
wire [7:0] hkspi_sram_addr;
|
||||
wire hkspi_sram_clk;
|
||||
wire hkspi_sram_csb;
|
||||
|
||||
mgmt_core soc (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
// GPIO (1 pin)
|
||||
.gpio_out_pad(gpio_out_core),
|
||||
.gpio_in_pad(gpio_in_core),
|
||||
.gpio_mode0_pad(gpio_mode0_core),
|
||||
.gpio_mode1_pad(gpio_mode1_core),
|
||||
.gpio_outenb_pad(gpio_outenb_core),
|
||||
.gpio_inenb_pad(gpio_inenb_core),
|
||||
// Primary SPI flash controller
|
||||
.flash_csb(flash_csb_core),
|
||||
.flash_clk(flash_clk_core),
|
||||
.flash_csb_oeb(flash_csb_oeb_core),
|
||||
.flash_clk_oeb(flash_clk_oeb_core),
|
||||
.flash_io0_oeb(flash_io0_oeb_core),
|
||||
.flash_io1_oeb(flash_io1_oeb_core),
|
||||
.flash_csb_ieb(flash_csb_ieb_core),
|
||||
.flash_clk_ieb(flash_clk_ieb_core),
|
||||
.flash_io0_ieb(flash_io0_ieb_core),
|
||||
.flash_io1_ieb(flash_io1_ieb_core),
|
||||
.flash_io0_do(flash_io0_do_core),
|
||||
.flash_io1_do(flash_io1_do_core),
|
||||
.flash_io0_di(flash_io0_di_core),
|
||||
.flash_io1_di(flash_io1_di_core),
|
||||
// Master Reset
|
||||
.resetb(rstb_l),
|
||||
.porb(porb_l),
|
||||
// Clocks and reset
|
||||
.clock(clock_core),
|
||||
.core_clk(caravel_clk),
|
||||
.user_clk(caravel_clk2),
|
||||
.core_rstn(caravel_rstn),
|
||||
// IRQ
|
||||
.user_irq(user_irq),
|
||||
.user_irq_ena(user_irq_ena),
|
||||
// Logic Analyzer
|
||||
.la_input(la_data_in_mprj),
|
||||
.la_output(la_data_out_mprj),
|
||||
.la_oenb(la_oenb_mprj),
|
||||
.la_iena(la_iena_mprj),
|
||||
// User Project IO Control
|
||||
.mprj_vcc_pwrgood(mprj_vcc_pwrgood),
|
||||
.mprj2_vcc_pwrgood(mprj2_vcc_pwrgood),
|
||||
.mprj_vdd_pwrgood(mprj_vdd_pwrgood),
|
||||
.mprj2_vdd_pwrgood(mprj2_vdd_pwrgood),
|
||||
.mprj_io_loader_resetn(mprj_io_loader_resetn),
|
||||
.mprj_io_loader_clock(mprj_io_loader_clock),
|
||||
.mprj_io_loader_data_1(mprj_io_loader_data_1),
|
||||
.mprj_io_loader_data_2(mprj_io_loader_data_2),
|
||||
.mgmt_in_data(mgmt_io_in),
|
||||
.mgmt_out_data({gpio_flash_io3_out, gpio_flash_io2_out,
|
||||
mgmt_io_in[(`MPRJ_IO_PADS-3):2],
|
||||
mgmt_io_nc}),
|
||||
.pwr_ctrl_out(pwr_ctrl_out),
|
||||
.sdo_out(sdo_out),
|
||||
.sdo_outenb(sdo_outenb),
|
||||
.jtag_out(jtag_out),
|
||||
.jtag_outenb(jtag_outenb),
|
||||
.flash_io2_oeb(flash_io2_oeb_core),
|
||||
.flash_io3_oeb(flash_io3_oeb_core),
|
||||
// User Project Slave ports (WB MI A)
|
||||
.mprj_cyc_o(mprj_cyc_o_core),
|
||||
.mprj_stb_o(mprj_stb_o_core),
|
||||
.mprj_we_o(mprj_we_o_core),
|
||||
.mprj_sel_o(mprj_sel_o_core),
|
||||
.mprj_adr_o(mprj_adr_o_core),
|
||||
.mprj_dat_o(mprj_dat_o_core),
|
||||
.mprj_ack_i(mprj_ack_i_core),
|
||||
.mprj_dat_i(mprj_dat_i_core),
|
||||
// mask data
|
||||
.mask_rev(mask_rev),
|
||||
// MGMT area R/W interface
|
||||
.mgmt_ena(mgmt_ena),
|
||||
.mgmt_wen_mask(mgmt_wen_mask),
|
||||
.mgmt_wen(mgmt_wen),
|
||||
.mgmt_addr(mgmt_addr),
|
||||
.mgmt_wdata(mgmt_wdata),
|
||||
.mgmt_rdata(mgmt_rdata),
|
||||
// MGMT area RO interface
|
||||
.mgmt_ena_ro(mgmt_ena_ro),
|
||||
.mgmt_addr_ro(mgmt_addr_ro),
|
||||
.mgmt_rdata_ro(mgmt_rdata_ro),
|
||||
// HKSPI RO interface
|
||||
.hkspi_sram_clk(hkspi_sram_clk),
|
||||
.hkspi_sram_csb(hkspi_sram_csb),
|
||||
.hkspi_sram_addr(hkspi_sram_addr),
|
||||
.hkspi_sram_rdata(hkspi_sram_rdata)
|
||||
);
|
||||
|
||||
/* Clock and reset to user space are passed through a tristate */
|
||||
/* buffer like the above, but since they are intended to be */
|
||||
/* always active, connect the enable to the logic-1 output from */
|
||||
/* the vccd1 domain. */
|
||||
|
||||
mgmt_protect mgmt_buffers (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
.vccd2(vccd2_core),
|
||||
.vssd2(vssd2_core),
|
||||
.vdda1(vdda1_core),
|
||||
.vssa1(vssa1_core),
|
||||
.vdda2(vdda2_core),
|
||||
.vssa2(vssa2_core),
|
||||
`endif
|
||||
|
||||
.caravel_clk(caravel_clk),
|
||||
.caravel_clk2(caravel_clk2),
|
||||
.caravel_rstn(caravel_rstn),
|
||||
.mprj_cyc_o_core(mprj_cyc_o_core),
|
||||
.mprj_stb_o_core(mprj_stb_o_core),
|
||||
.mprj_we_o_core(mprj_we_o_core),
|
||||
.mprj_sel_o_core(mprj_sel_o_core),
|
||||
.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),
|
||||
.user_clock2(mprj_clock2),
|
||||
.user_reset(mprj_reset),
|
||||
.mprj_cyc_o_user(mprj_cyc_o_user),
|
||||
.mprj_stb_o_user(mprj_stb_o_user),
|
||||
.mprj_we_o_user(mprj_we_o_user),
|
||||
.mprj_sel_o_user(mprj_sel_o_user),
|
||||
.mprj_adr_o_user(mprj_adr_o_user),
|
||||
.mprj_dat_o_user(mprj_dat_o_user),
|
||||
.user_irq(user_irq),
|
||||
.user1_vcc_powergood(mprj_vcc_pwrgood),
|
||||
.user2_vcc_powergood(mprj2_vcc_pwrgood),
|
||||
.user1_vdd_powergood(mprj_vdd_pwrgood),
|
||||
.user2_vdd_powergood(mprj2_vdd_pwrgood)
|
||||
);
|
||||
|
||||
|
||||
/*----------------------------------------------*/
|
||||
/* Wrapper module around the user project */
|
||||
/*----------------------------------------------*/
|
||||
|
||||
assign user_io_in_3v3 = mprj_io_in_3v3;
|
||||
|
||||
user_analog_project_wrapper mprj (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdda1(vdda1_core), // User area 1 3.3V power
|
||||
.vdda2(vdda2_core), // User area 2 3.3V power
|
||||
.vssa1(vssa1_core), // User area 1 analog ground
|
||||
.vssa2(vssa2_core), // User area 2 analog ground
|
||||
.vccd1(vccd1_core), // User area 1 1.8V power
|
||||
.vccd2(vccd2_core), // User area 2 1.8V power
|
||||
.vssd1(vssd1_core), // User area 1 digital ground
|
||||
.vssd2(vssd2_core), // User area 2 digital ground
|
||||
`endif
|
||||
|
||||
.wb_clk_i(mprj_clock),
|
||||
.wb_rst_i(mprj_reset),
|
||||
// MGMT SoC Wishbone Slave
|
||||
.wbs_cyc_i(mprj_cyc_o_user),
|
||||
.wbs_stb_i(mprj_stb_o_user),
|
||||
.wbs_we_i(mprj_we_o_user),
|
||||
.wbs_sel_i(mprj_sel_o_user),
|
||||
.wbs_adr_i(mprj_adr_o_user),
|
||||
.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
|
||||
.io_in (user_io_in),
|
||||
.io_in_3v3 (user_io_in_3v3),
|
||||
.io_out(user_io_out),
|
||||
.io_oeb(user_io_oeb),
|
||||
.gpio_analog(user_gpio_analog),
|
||||
.gpio_noesd(user_gpio_noesd),
|
||||
.io_clamp_high(user_clamp_high),
|
||||
.io_clamp_low(user_clamp_low),
|
||||
.io_analog(user_analog),
|
||||
// Independent clock
|
||||
.user_clock2(mprj_clock2),
|
||||
// IRQ
|
||||
.user_irq(user_irq_core)
|
||||
);
|
||||
|
||||
/*--------------------------------------*/
|
||||
/* End user project instantiation */
|
||||
/*--------------------------------------*/
|
||||
|
||||
wire [`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1:0] gpio_serial_link_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1:0] gpio_serial_link_2_shifted;
|
||||
|
||||
assign gpio_serial_link_1_shifted = {gpio_serial_link_1[`MPRJ_IO_PADS_1-`ANALOG_PADS_1-2:0],
|
||||
mprj_io_loader_data_1};
|
||||
// Note that serial_link_2 is backwards compared to serial_link_1, so it
|
||||
// shifts in the other direction.
|
||||
assign gpio_serial_link_2_shifted = {mprj_io_loader_data_2,
|
||||
gpio_serial_link_2[`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1:1]};
|
||||
|
||||
// Propagating clock and reset to mitigate timing and fanout issues
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_clock_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_clock_2;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_resetn_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_resetn_2;
|
||||
wire [`MPRJ_IO_PADS_1-6:0] gpio_clock_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-7:0] gpio_clock_2_shifted;
|
||||
wire [`MPRJ_IO_PADS_1-6:0] gpio_resetn_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-7:0] gpio_resetn_2_shifted;
|
||||
|
||||
assign gpio_clock_1_shifted = {gpio_clock_1[`MPRJ_IO_PADS_1-`ANALOG_PADS_1-2:0],
|
||||
mprj_io_loader_clock};
|
||||
assign gpio_clock_2_shifted = {mprj_io_loader_clock,
|
||||
gpio_clock_2[`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1:1]};
|
||||
assign gpio_resetn_1_shifted = {gpio_resetn_1[`MPRJ_IO_PADS_1-`ANALOG_PADS_1-2:0],
|
||||
mprj_io_loader_resetn};
|
||||
assign gpio_resetn_2_shifted = {mprj_io_loader_resetn,
|
||||
gpio_resetn_2[`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1:1]};
|
||||
|
||||
// Each control block sits next to an I/O pad in the user area.
|
||||
// It gets input through a serial chain from the previous control
|
||||
// block and passes it to the next control block. Due to the nature
|
||||
// of the shift register, bits are presented in reverse, as the first
|
||||
// bit in ends up as the last bit of the last I/O pad control block.
|
||||
|
||||
// There are two types of block; the first two and the last two
|
||||
// are configured to be full bidirectional under control of the
|
||||
// management Soc (JTAG and SDO for the first two; flash_io2 and
|
||||
// flash_io3 for the last two). The rest are configured to be default
|
||||
// (input). Note that the first two and last two are the ones closest
|
||||
// to the management SoC on either side, which minimizes the wire length
|
||||
// of the extra signals those pads need.
|
||||
|
||||
/* First two GPIOs (JTAG and SDO) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Under management control
|
||||
.OENB_INIT(1'b1) // Enable output signaling from wire
|
||||
) gpio_control_bidir_1 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[1:0]),
|
||||
.serial_clock(gpio_clock_1_shifted[1:0]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[1:0]),
|
||||
.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}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[1:0]),
|
||||
.serial_data_out(gpio_serial_link_1[1:0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[1:0]),
|
||||
.user_gpio_oeb(user_io_oeb[1:0]),
|
||||
.user_gpio_in(user_io_in[1:0]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[1:0]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[1:0]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[1:0]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[1:0]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[1:0]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[1:0]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[1:0]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[1:0]),
|
||||
.pad_gpio_dm(mprj_io_dm[5:0]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[1:0]),
|
||||
.pad_gpio_out(mprj_io_out[1:0]),
|
||||
.pad_gpio_in(mprj_io_in[1:0])
|
||||
);
|
||||
|
||||
/* Section 1 GPIOs (GPIO 0 to 18) */
|
||||
wire [`MPRJ_IO_PADS_1-`ANALOG_PADS_1-3:0] one_loop1;
|
||||
|
||||
/* Section 1 GPIOs (GPIO 8 to 18) */
|
||||
gpio_control_block gpio_control_in_1 [`MPRJ_IO_PADS_1-`ANALOG_PADS_1-3:6] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[`DIG1_TOP:8]),
|
||||
.mgmt_gpio_out(mgmt_io_in[`DIG1_TOP:8]),
|
||||
.mgmt_gpio_oeb(one_loop1[`MPRJ_IO_PADS_1-`ANALOG_PADS_1-3:6]),
|
||||
|
||||
.one(one_loop1[`MPRJ_IO_PADS_1-`ANALOG_PADS_1-3:6]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.serial_data_out(gpio_serial_link_1[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)*3-1:24]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS_1-`ANALOG_PADS_1-1):8])
|
||||
);
|
||||
|
||||
|
||||
/* Section 1 GPIOs (GPIO 2 to 7) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), /* Under management control */
|
||||
.DM_INIT(3'b001), /* Set as type input */
|
||||
.OENB_INIT(1'b1) /* Output is disabled */
|
||||
) gpio_control_in_1a [5:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[7:2]),
|
||||
.serial_clock(gpio_clock_1_shifted[7:2]),
|
||||
|
||||
.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[5:0]),
|
||||
|
||||
.one(one_loop1[5:0]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[7:2]),
|
||||
.serial_data_out(gpio_serial_link_1[7:2]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[7:2]),
|
||||
.user_gpio_oeb(user_io_oeb[7:2]),
|
||||
.user_gpio_in(user_io_in[7:2]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[7:2]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[7:2]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[7:2]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[7:2]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[7:2]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[7:2]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[7:2]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[7:2]),
|
||||
.pad_gpio_dm(mprj_io_dm[23:6]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[7:2]),
|
||||
.pad_gpio_out(mprj_io_out[7:2]),
|
||||
.pad_gpio_in(mprj_io_in[7:2])
|
||||
);
|
||||
|
||||
/* Last two GPIOs (flash_io2 and flash_io3) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Under management control
|
||||
.OENB_INIT(1'b1) // Enable output signaling from wire
|
||||
) gpio_control_bidir_2 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[(`DIG2_TOP):(`DIG2_TOP-1)]),
|
||||
.mgmt_gpio_out({gpio_flash_io3_out, gpio_flash_io2_out}),
|
||||
.mgmt_gpio_oeb({flash_io3_oeb_core, flash_io2_oeb_core}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-1):(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-2)]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_DIG_PADS*3-1):(`MPRJ_DIG_PADS*3-6)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_DIG_PADS-1):(`MPRJ_DIG_PADS-2)])
|
||||
);
|
||||
|
||||
/* Section 2 GPIOs (GPIO 19 to 37) */
|
||||
wire [`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3:0] one_loop2;
|
||||
gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
.serial_clock_out(gpio_clock_1[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
|
||||
.mgmt_gpio_in(mgmt_io_in[(`DIG2_TOP-2):`DIG2_BOT]),
|
||||
.mgmt_gpio_out(mgmt_io_in[(`DIG2_TOP-2):`DIG2_BOT]),
|
||||
.mgmt_gpio_oeb(one_loop2),
|
||||
|
||||
.one(one_loop2),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-`ANALOG_PADS_2-3):0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_dm(mprj_io_dm[((`MPRJ_DIG_PADS)*3-7):((`MPRJ_IO_PADS_1-`ANALOG_PADS_1)*3)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_DIG_PADS-3):(`MPRJ_IO_PADS_1-`ANALOG_PADS_1)])
|
||||
);
|
||||
|
||||
user_id_programming #(
|
||||
.USER_PROJECT_ID(USER_PROJECT_ID)
|
||||
) user_id_value (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
.mask_rev(mask_rev)
|
||||
);
|
||||
|
||||
// Power-on-reset circuit
|
||||
simple_por por (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd3v3(vddio_core),
|
||||
.vdd1v8(vccd_core),
|
||||
.vss(vssio_core),
|
||||
`endif
|
||||
.porb_h(porb_h),
|
||||
.porb_l(porb_l),
|
||||
.por_l(por_l)
|
||||
);
|
||||
|
||||
// XRES (chip input pin reset) reset level converter
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped rstb_level (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vddio_core),
|
||||
.LVPWR(vccd_core),
|
||||
.VGND(vssio_core),
|
||||
`endif
|
||||
.A(rstb_h),
|
||||
.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
|
|
@ -0,0 +1,93 @@
|
|||
// 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
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
`define UNIT_DELAY #1
|
||||
`define USE_POWER_PINS
|
||||
|
||||
`ifdef SIM
|
||||
|
||||
`include "defines.v"
|
||||
`include "pads.v"
|
||||
|
||||
/* NOTE: Need to pass the PDK root directory to iverilog with option -I */
|
||||
`ifdef EF_STYLE // efabless style pdk installation; mainly for open galaxy users
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_fd_io.v"
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_ef_io.v"
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_ef_io__gpiov2_pad_wrapped.v"
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_ef_io__analog_pad.v"
|
||||
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hd/primitives.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hd/sky130_fd_sc_hd.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hvl/primitives.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hvl/sky130_fd_sc_hvl.v"
|
||||
`else
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_fd_io.v"
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_ef_io.v"
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_ef_io__gpiov2_pad_wrapped.v"
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_ef_io__analog_pad.v"
|
||||
|
||||
`include "libs.ref/sky130_fd_sc_hd/verilog/primitives.v"
|
||||
`include "libs.ref/sky130_fd_sc_hd/verilog/sky130_fd_sc_hd.v"
|
||||
`include "libs.ref/sky130_fd_sc_hvl/verilog/primitives.v"
|
||||
`include "libs.ref/sky130_fd_sc_hvl/verilog/sky130_fd_sc_hvl.v"
|
||||
`endif
|
||||
|
||||
`ifdef GL
|
||||
// Assume default net type to be wire because GL netlists don't have the wire definitions
|
||||
`default_nettype wire
|
||||
`include "gl/mgmt_core.v"
|
||||
`include "gl/digital_pll.v"
|
||||
`include "gl/DFFRAM.v"
|
||||
`include "gl/storage.v"
|
||||
`include "gl/user_id_programming.v"
|
||||
`include "gl/chip_io_alt.v"
|
||||
`include "gl/mprj_logic_high.v"
|
||||
`include "gl/mprj2_logic_high.v"
|
||||
`include "gl/mgmt_protect.v"
|
||||
`include "gl/mgmt_protect_hv.v"
|
||||
`include "gl/gpio_logic_high.v"
|
||||
`include "gl/gpio_control_block.v"
|
||||
`include "gl/sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped.v"
|
||||
`include "gl/caravan.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_alt.v"
|
||||
`include "mprj_logic_high.v"
|
||||
`include "mprj2_logic_high.v"
|
||||
`include "mgmt_protect.v"
|
||||
`include "mgmt_protect_hv.v"
|
||||
`include "gpio_control_block.v"
|
||||
`include "gpio_logic_high.v"
|
||||
`include "sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped.v"
|
||||
`include "caravan.v"
|
||||
`endif
|
||||
|
||||
`include "simple_por.v"
|
||||
`include "sram_1rw1r_32_256_8_sky130.v"
|
||||
|
||||
`endif
|
|
@ -0,0 +1,962 @@
|
|||
// `default_nettype none
|
||||
// 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, a project harness for the Google/SkyWater sky130 */
|
||||
/* fabrication process and open source PDK */
|
||||
/* */
|
||||
/* Copyright 2020 efabless, Inc. */
|
||||
/* Written by Tim Edwards, December 2019 */
|
||||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
module caravel (
|
||||
inout vddio, // Common 3.3V padframe/ESD power
|
||||
inout vddio_2, // Common 3.3V padframe/ESD power
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
inout vssio_2, // Common padframe/ESD ground
|
||||
inout vdda, // Management 3.3V power
|
||||
inout vssa, // Common analog ground
|
||||
inout vccd, // Management/Common 1.8V power
|
||||
inout vssd, // Common digital ground
|
||||
inout vdda1, // User area 1 3.3V power
|
||||
inout vdda1_2, // User area 1 3.3V power
|
||||
inout vdda2, // User area 2 3.3V power
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa1_2, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V power
|
||||
inout vccd2, // User area 2 1.8V power
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
|
||||
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)
|
||||
|
||||
// Note that only two flash data pins are dedicated to the
|
||||
// management SoC wrapper. The management SoC exports the
|
||||
// quad SPI mode status to make use of the top two mprj_io
|
||||
// pins for io2 and io3.
|
||||
|
||||
output flash_csb,
|
||||
output flash_clk,
|
||||
output flash_io0,
|
||||
output flash_io1
|
||||
);
|
||||
|
||||
//------------------------------------------------------------
|
||||
// This value is uniquely defined for each user project.
|
||||
//------------------------------------------------------------
|
||||
parameter USER_PROJECT_ID = 32'h00000000;
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------
|
||||
*
|
||||
* These pins are overlaid on mprj_io space. They have the function
|
||||
* below when the management processor is in reset, or in the default
|
||||
* configuration. They are assigned to uses in the user space by the
|
||||
* configuration program running off of the SPI flash. Note that even
|
||||
* when the user has taken control of these pins, they can be restored
|
||||
* to the original use by setting the resetb pin low. The SPI pins and
|
||||
* UART pins can be connected directly to an FTDI chip as long as the
|
||||
* FTDI chip sets these lines to high impedence (input function) at
|
||||
* all times except when holding the chip in reset.
|
||||
*
|
||||
* JTAG = mprj_io[0] (inout)
|
||||
* SDO = mprj_io[1] (output)
|
||||
* SDI = mprj_io[2] (input)
|
||||
* CSB = mprj_io[3] (input)
|
||||
* SCK = mprj_io[4] (input)
|
||||
* ser_rx = mprj_io[5] (input)
|
||||
* ser_tx = mprj_io[6] (output)
|
||||
* irq = mprj_io[7] (input)
|
||||
*
|
||||
* flash_io2 = mprj_io[36] (inout)
|
||||
* flash_io3 = mprj_io[37] (inout)
|
||||
*
|
||||
* These pins are reserved for any project that wants to incorporate
|
||||
* its own processor and flash controller. While a user project can
|
||||
* technically use any available I/O pins for the purpose, these
|
||||
* four pins connect to a pass-through mode from the SPI slave (pins
|
||||
* 1-4 above) so that any SPI flash connected to these specific pins
|
||||
* can be accessed through the SPI slave even when the processor is in
|
||||
* reset.
|
||||
*
|
||||
* user_flash_csb = mprj_io[8]
|
||||
* user_flash_sck = mprj_io[9]
|
||||
* user_flash_io0 = mprj_io[10]
|
||||
* user_flash_io1 = mprj_io[11]
|
||||
*
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// One-bit GPIO dedicated to management SoC (outside of user control)
|
||||
wire gpio_out_core;
|
||||
wire gpio_in_core;
|
||||
wire gpio_mode0_core;
|
||||
wire gpio_mode1_core;
|
||||
wire gpio_outenb_core;
|
||||
wire gpio_inenb_core;
|
||||
|
||||
// User Project Control (pad-facing)
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_inp_dis;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_ib_mode_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_vtrip_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_slow_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_holdover;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_en;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_pol;
|
||||
wire [`MPRJ_IO_PADS*3-1:0] mprj_io_dm;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_in;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_out;
|
||||
|
||||
// User Project Control (user-facing)
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_in;
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_out;
|
||||
wire [`MPRJ_IO_PADS-10:0] user_analog_io;
|
||||
|
||||
/* Padframe control signals */
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_serial_link_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_serial_link_2;
|
||||
wire mprj_io_loader_resetn;
|
||||
wire mprj_io_loader_clock;
|
||||
wire mprj_io_loader_data_1; /* user1 side serial loader */
|
||||
wire mprj_io_loader_data_2; /* user2 side serial loader */
|
||||
|
||||
// User Project Control management I/O
|
||||
// There are two types of GPIO connections:
|
||||
// (1) Full Bidirectional: Management connects to in, out, and oeb
|
||||
// Uses: JTAG and SDO
|
||||
// (2) Selectable bidirectional: Management connects to in and out,
|
||||
// which are tied together. oeb is grounded (oeb from the
|
||||
// configuration is used)
|
||||
|
||||
// SDI = mprj_io[2] (input)
|
||||
// CSB = mprj_io[3] (input)
|
||||
// SCK = mprj_io[4] (input)
|
||||
// ser_rx = mprj_io[5] (input)
|
||||
// ser_tx = mprj_io[6] (output)
|
||||
// irq = mprj_io[7] (input)
|
||||
|
||||
wire [`MPRJ_IO_PADS-1:0] mgmt_io_in;
|
||||
wire jtag_out, sdo_out;
|
||||
wire jtag_outenb, sdo_outenb;
|
||||
wire gpio_flash_io2_out, gpio_flash_io3_out;
|
||||
|
||||
wire [1:0] mgmt_io_nc; /* no-connects */
|
||||
|
||||
wire clock_core;
|
||||
|
||||
// Power-on-reset signal. The reset pad generates the sense-inverted
|
||||
// reset at 3.3V. The 1.8V signal and the inverted 1.8V signal are
|
||||
// derived.
|
||||
|
||||
wire porb_h;
|
||||
wire porb_l;
|
||||
wire por_l;
|
||||
|
||||
wire rstb_h;
|
||||
wire rstb_l;
|
||||
|
||||
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_io0_do_core, flash_io1_do_core;
|
||||
wire flash_io0_di_core, flash_io1_di_core;
|
||||
|
||||
chip_io padframe(
|
||||
`ifndef TOP_ROUTING
|
||||
// Package Pins
|
||||
.vddio_pad (vddio), // Common padframe/ESD supply
|
||||
.vddio_pad2 (vddio_2),
|
||||
.vssio_pad (vssio), // Common padframe/ESD ground
|
||||
.vssio_pad2 (vssio_2),
|
||||
.vccd_pad (vccd), // Common 1.8V supply
|
||||
.vssd_pad (vssd), // Common digital ground
|
||||
.vdda_pad (vdda), // Management analog 3.3V supply
|
||||
.vssa_pad (vssa), // Management analog ground
|
||||
.vdda1_pad (vdda1), // User area 1 3.3V supply
|
||||
.vdda1_pad2 (vdda1_2),
|
||||
.vdda2_pad (vdda2), // User area 2 3.3V supply
|
||||
.vssa1_pad (vssa1), // User area 1 analog ground
|
||||
.vssa1_pad2 (vssa1_2),
|
||||
.vssa2_pad (vssa2), // User area 2 analog ground
|
||||
.vccd1_pad (vccd1), // User area 1 1.8V supply
|
||||
.vccd2_pad (vccd2), // User area 2 1.8V supply
|
||||
.vssd1_pad (vssd1), // User area 1 digital ground
|
||||
.vssd2_pad (vssd2), // User area 2 digital ground
|
||||
`endif
|
||||
// Core Side Pins
|
||||
.vddio (vddio_core),
|
||||
.vssio (vssio_core),
|
||||
.vdda (vdda_core),
|
||||
.vssa (vssa_core),
|
||||
.vccd (vccd_core),
|
||||
.vssd (vssd_core),
|
||||
.vdda1 (vdda1_core),
|
||||
.vdda2 (vdda2_core),
|
||||
.vssa1 (vssa1_core),
|
||||
.vssa2 (vssa2_core),
|
||||
.vccd1 (vccd1_core),
|
||||
.vccd2 (vccd2_core),
|
||||
.vssd1 (vssd1_core),
|
||||
.vssd2 (vssd2_core),
|
||||
|
||||
.gpio(gpio),
|
||||
.mprj_io(mprj_io),
|
||||
.clock(clock),
|
||||
.resetb(resetb),
|
||||
.flash_csb(flash_csb),
|
||||
.flash_clk(flash_clk),
|
||||
.flash_io0(flash_io0),
|
||||
.flash_io1(flash_io1),
|
||||
// SoC Core Interface
|
||||
.porb_h(porb_h),
|
||||
.por(por_l),
|
||||
.resetb_core_h(rstb_h),
|
||||
.clock_core(clock_core),
|
||||
.gpio_out_core(gpio_out_core),
|
||||
.gpio_in_core(gpio_in_core),
|
||||
.gpio_mode0_core(gpio_mode0_core),
|
||||
.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),
|
||||
.mprj_io_in(mprj_io_in),
|
||||
.mprj_io_out(mprj_io_out),
|
||||
.mprj_io_oeb(mprj_io_oeb),
|
||||
.mprj_io_inp_dis(mprj_io_inp_dis),
|
||||
.mprj_io_ib_mode_sel(mprj_io_ib_mode_sel),
|
||||
.mprj_io_vtrip_sel(mprj_io_vtrip_sel),
|
||||
.mprj_io_slow_sel(mprj_io_slow_sel),
|
||||
.mprj_io_holdover(mprj_io_holdover),
|
||||
.mprj_io_analog_en(mprj_io_analog_en),
|
||||
.mprj_io_analog_sel(mprj_io_analog_sel),
|
||||
.mprj_io_analog_pol(mprj_io_analog_pol),
|
||||
.mprj_io_dm(mprj_io_dm),
|
||||
.mprj_analog_io(user_analog_io)
|
||||
);
|
||||
|
||||
// SoC core
|
||||
wire caravel_clk;
|
||||
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_core;
|
||||
wire [2:0] user_irq_ena;
|
||||
|
||||
// Exported Wishbone Bus
|
||||
wire mprj_cyc_o_core;
|
||||
wire mprj_stb_o_core;
|
||||
wire mprj_we_o_core;
|
||||
wire [3:0] mprj_sel_o_core;
|
||||
wire [31:0] mprj_adr_o_core;
|
||||
wire [31:0] mprj_dat_o_core;
|
||||
wire mprj_ack_i_core;
|
||||
wire [31:0] mprj_dat_i_core;
|
||||
|
||||
// Mask revision
|
||||
wire [31:0] mask_rev;
|
||||
|
||||
wire mprj_clock;
|
||||
wire mprj_clock2;
|
||||
wire mprj_reset;
|
||||
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;
|
||||
wire mprj_vcc_pwrgood;
|
||||
wire mprj2_vcc_pwrgood;
|
||||
wire mprj_vdd_pwrgood;
|
||||
wire mprj2_vdd_pwrgood;
|
||||
|
||||
mgmt_core_wrapper soc (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
// GPIO (1 pin)
|
||||
.gpio_out_pad(gpio_out_core),
|
||||
.gpio_in_pad(gpio_in_core),
|
||||
.gpio_mode0_pad(gpio_mode0_core),
|
||||
.gpio_mode1_pad(gpio_mode1_core),
|
||||
.gpio_outenb_pad(gpio_outenb_core),
|
||||
.gpio_inenb_pad(gpio_inenb_core),
|
||||
|
||||
// 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),
|
||||
|
||||
// Exported Wishbone Bus
|
||||
.mprj_cyc_o(mprj_cyc_o_core),
|
||||
.mprj_stb_o(mprj_stb_o_core),
|
||||
.mprj_we_o(mprj_we_o_core),
|
||||
.mprj_sel_o(mprj_sel_o_core),
|
||||
.mprj_adr_o(mprj_adr_o_core),
|
||||
.mprj_dat_o(mprj_dat_o_core),
|
||||
.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),
|
||||
|
||||
// IRQ
|
||||
.user_irq(user_irq),
|
||||
.user_irq_ena(user_irq_ena),
|
||||
|
||||
// Real-time status and control
|
||||
.hkspi_status(hkspi_status),
|
||||
.hkspi_control(hkspi_control)
|
||||
);
|
||||
|
||||
/* Clock and reset to user space are passed through a tristate */
|
||||
/* buffer like the above, but since they are intended to be */
|
||||
/* always active, connect the enable to the logic-1 output from */
|
||||
/* the vccd1 domain. */
|
||||
|
||||
mgmt_protect mgmt_buffers (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
.vccd2(vccd2_core),
|
||||
.vssd2(vssd2_core),
|
||||
.vdda1(vdda1_core),
|
||||
.vssa1(vssa1_core),
|
||||
.vdda2(vdda2_core),
|
||||
.vssa2(vssa2_core),
|
||||
`endif
|
||||
.caravel_clk(caravel_clk),
|
||||
.caravel_clk2(caravel_clk2),
|
||||
.caravel_rstn(caravel_rstn),
|
||||
.mprj_cyc_o_core(mprj_cyc_o_core),
|
||||
.mprj_stb_o_core(mprj_stb_o_core),
|
||||
.mprj_we_o_core(mprj_we_o_core),
|
||||
.mprj_sel_o_core(mprj_sel_o_core),
|
||||
.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),
|
||||
.user_clock2(mprj_clock2),
|
||||
.user_reset(mprj_reset),
|
||||
.mprj_cyc_o_user(mprj_cyc_o_user),
|
||||
.mprj_stb_o_user(mprj_stb_o_user),
|
||||
.mprj_we_o_user(mprj_we_o_user),
|
||||
.mprj_sel_o_user(mprj_sel_o_user),
|
||||
.mprj_adr_o_user(mprj_adr_o_user),
|
||||
.mprj_dat_o_user(mprj_dat_o_user),
|
||||
.user_irq(user_irq),
|
||||
.user1_vcc_powergood(mprj_vcc_pwrgood),
|
||||
.user2_vcc_powergood(mprj2_vcc_pwrgood),
|
||||
.user1_vdd_powergood(mprj_vdd_pwrgood),
|
||||
.user2_vdd_powergood(mprj2_vdd_pwrgood)
|
||||
);
|
||||
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
/* Wrapper module around the user project */
|
||||
/*--------------------------------------------------*/
|
||||
|
||||
user_project_wrapper mprj (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdda1(vdda1_core), // User area 1 3.3V power
|
||||
.vdda2(vdda2_core), // User area 2 3.3V power
|
||||
.vssa1(vssa1_core), // User area 1 analog ground
|
||||
.vssa2(vssa2_core), // User area 2 analog ground
|
||||
.vccd1(vccd1_core), // User area 1 1.8V power
|
||||
.vccd2(vccd2_core), // User area 2 1.8V power
|
||||
.vssd1(vssd1_core), // User area 1 digital ground
|
||||
.vssd2(vssd2_core), // User area 2 digital ground
|
||||
`endif
|
||||
|
||||
.wb_clk_i(mprj_clock),
|
||||
.wb_rst_i(mprj_reset),
|
||||
|
||||
// MGMT SoC Wishbone Slave
|
||||
.wbs_cyc_i(mprj_cyc_o_user),
|
||||
.wbs_stb_i(mprj_stb_o_user),
|
||||
.wbs_we_i(mprj_we_o_user),
|
||||
.wbs_sel_i(mprj_sel_o_user),
|
||||
.wbs_adr_i(mprj_adr_o_user),
|
||||
.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
|
||||
.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)
|
||||
);
|
||||
|
||||
/*------------------------------------------*/
|
||||
/* End user project instantiation */
|
||||
/*------------------------------------------*/
|
||||
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_serial_link_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_serial_link_2_shifted;
|
||||
|
||||
assign gpio_serial_link_1_shifted = {gpio_serial_link_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_data_1};
|
||||
// Note that serial_link_2 is backwards compared to serial_link_1, so it
|
||||
// shifts in the other direction.
|
||||
assign gpio_serial_link_2_shifted = {mprj_io_loader_data_2,
|
||||
gpio_serial_link_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
|
||||
// Propagating clock and reset to mitigate timing and fanout issues
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_clock_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_clock_2;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_resetn_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_resetn_2;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_clock_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_clock_2_shifted;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_resetn_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_resetn_2_shifted;
|
||||
|
||||
assign gpio_clock_1_shifted = {gpio_clock_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_clock};
|
||||
assign gpio_clock_2_shifted = {mprj_io_loader_clock,
|
||||
gpio_clock_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
assign gpio_resetn_1_shifted = {gpio_resetn_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_resetn};
|
||||
assign gpio_resetn_2_shifted = {mprj_io_loader_resetn,
|
||||
gpio_resetn_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
|
||||
// Clocking control
|
||||
|
||||
caravel_clocking clocking(
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd1v8(VPWR),
|
||||
.vss(VGND),
|
||||
`endif
|
||||
.ext_clk_sel(ext_clk_sel),
|
||||
.ext_clk(clock),
|
||||
.pll_clk(pll_clk),
|
||||
.pll_clk90(pll_clk90),
|
||||
.resetb(resetb),
|
||||
.sel(spi_pll_sel),
|
||||
.sel2(spi_pll90_sel),
|
||||
.ext_reset(ext_reset), // From housekeeping SPI
|
||||
.core_clk(core_clk),
|
||||
.user_clk(user_clk),
|
||||
.resetb_sync(core_rstn)
|
||||
);
|
||||
|
||||
// DCO/Digital Locked Loop
|
||||
|
||||
digital_pll pll (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(VPWR),
|
||||
.VGND(VGND),
|
||||
`endif
|
||||
.resetb(resetb),
|
||||
.enable(spi_pll_ena),
|
||||
.osc(clock),
|
||||
.clockp({pll_clk, pll_clk90}),
|
||||
.div(spi_pll_div),
|
||||
.dco(spi_pll_dco_ena),
|
||||
.ext_trim(spi_pll_trim)
|
||||
);
|
||||
|
||||
// Housekeeping SPI interface
|
||||
|
||||
housekeeping_spi housekeeping (
|
||||
`ifdef USE_POWER_PINS
|
||||
.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),
|
||||
.pll_dco_ena(spi_pll_dco_ena),
|
||||
.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),
|
||||
.irq(irq_spi),
|
||||
.reset(ext_reset),
|
||||
.trap(trap),
|
||||
.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
|
||||
|
||||
mprj_ctrl_wb #(
|
||||
.BASE_ADR(MPRJ_CTRL_ADR)
|
||||
) mprj_ctrl (
|
||||
.wb_clk_i(wb_clk_i),
|
||||
.wb_rst_i(wb_rst_i),
|
||||
|
||||
.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)
|
||||
);
|
||||
|
||||
// Each control block sits next to an I/O pad in the user area.
|
||||
// It gets input through a serial chain from the previous control
|
||||
// block and passes it to the next control block. Due to the nature
|
||||
// of the shift register, bits are presented in reverse, as the first
|
||||
// bit in ends up as the last bit of the last I/O pad control block.
|
||||
|
||||
// There are two types of block; the first two and the last two
|
||||
// are configured to be full bidirectional under control of the
|
||||
// management Soc (JTAG and SDO for the first two; flash_io2 and
|
||||
// flash_io3 for the last two). The rest are configured to be default
|
||||
// (input). Note that the first two and last two are the ones closest
|
||||
// to the management SoC on either side, which minimizes the wire length
|
||||
// of the extra signals those pads need.
|
||||
|
||||
/* First two GPIOs (JTAG and SDO) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
|
||||
) gpio_control_bidir_1 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[1:0]),
|
||||
.serial_clock(gpio_clock_1_shifted[1:0]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[1:0]),
|
||||
.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}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[1:0]),
|
||||
.serial_data_out(gpio_serial_link_1[1:0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[1:0]),
|
||||
.user_gpio_oeb(user_io_oeb[1:0]),
|
||||
.user_gpio_in(user_io_in[1:0]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[1:0]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[1:0]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[1:0]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[1:0]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[1:0]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[1:0]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[1:0]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[1:0]),
|
||||
.pad_gpio_dm(mprj_io_dm[5:0]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[1:0]),
|
||||
.pad_gpio_out(mprj_io_out[1:0]),
|
||||
.pad_gpio_in(mprj_io_in[1:0])
|
||||
);
|
||||
|
||||
/* Section 1 GPIOs (GPIO 0 to 18) */
|
||||
wire [`MPRJ_IO_PADS_1-1:2] one_loop1;
|
||||
|
||||
/* Section 1 GPIOs (GPIO 3 to 7) that start up under management control */
|
||||
|
||||
gpio_control_block #(
|
||||
.DM_INIT(3'b001), // Configured as inputs
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output disabled
|
||||
) gpio_control_in_1a [5:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[7:2]),
|
||||
.serial_clock(gpio_clock_1_shifted[7:2]),
|
||||
|
||||
.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]),
|
||||
|
||||
.one(one_loop1[7:2]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[7:2]),
|
||||
.serial_data_out(gpio_serial_link_1[7:2]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[7:2]),
|
||||
.user_gpio_oeb(user_io_oeb[7:2]),
|
||||
.user_gpio_in(user_io_in[7:2]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[7:2]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[7:2]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[7:2]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[7:2]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[7:2]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[7:2]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[7:2]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[7:2]),
|
||||
.pad_gpio_dm(mprj_io_dm[23:6]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[7:2]),
|
||||
.pad_gpio_out(mprj_io_out[7:2]),
|
||||
.pad_gpio_in(mprj_io_in[7:2])
|
||||
);
|
||||
|
||||
/* Section 1 GPIOs (GPIO 8 to 18) */
|
||||
|
||||
gpio_control_block gpio_control_in_1 [`MPRJ_IO_PADS_1-9:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
.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]),
|
||||
|
||||
.one(one_loop1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.serial_data_out(gpio_serial_link_1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS_1*3-1):24]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS_1-1):8])
|
||||
);
|
||||
|
||||
|
||||
/* Last two GPIOs (flash_io2 and flash_io3) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
|
||||
) gpio_control_bidir_2 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.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}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-1):(`MPRJ_IO_PADS*3-6)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)])
|
||||
);
|
||||
|
||||
/* Section 2 GPIOs (GPIO 19 to 37) */
|
||||
wire [`MPRJ_IO_PADS_2-3:0] one_loop2;
|
||||
gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-3:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
|
||||
.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),
|
||||
|
||||
.one(one_loop2),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-3):0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-7):(`MPRJ_IO_PADS_1*3)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)])
|
||||
);
|
||||
|
||||
user_id_programming #(
|
||||
.USER_PROJECT_ID(USER_PROJECT_ID)
|
||||
) user_id_value (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
.mask_rev(mask_rev)
|
||||
);
|
||||
|
||||
// Power-on-reset circuit
|
||||
simple_por por (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd3v3(vddio_core),
|
||||
.vdd1v8(vccd_core),
|
||||
.vss(vssio_core),
|
||||
`endif
|
||||
.porb_h(porb_h),
|
||||
.porb_l(porb_l),
|
||||
.por_l(por_l)
|
||||
);
|
||||
|
||||
// XRES (chip input pin reset) reset level converter
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped rstb_level (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vddio_core),
|
||||
.LVPWR(vccd_core),
|
||||
.LVGND(vssd_core),
|
||||
.VGND(vssio_core),
|
||||
`endif
|
||||
.A(rstb_h),
|
||||
.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
|
|
@ -0,0 +1,111 @@
|
|||
// 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
|
||||
// This routine synchronizes the
|
||||
|
||||
module caravel_clocking(
|
||||
`ifdef USE_POWER_PINS
|
||||
input vdd1v8,
|
||||
input vss,
|
||||
`endif
|
||||
input resetb, // Master (negative sense) reset
|
||||
input ext_clk_sel, // 0=use PLL clock, 1=use external (pad) clock
|
||||
input ext_clk, // External pad (slow) clock
|
||||
input pll_clk, // Internal PLL (fast) clock
|
||||
input pll_clk90, // Internal PLL (fast) clock, 90 degree phase
|
||||
input [2:0] sel, // Select clock divider value (0=thru, 1=divide-by-2, etc.)
|
||||
input [2:0] sel2, // Select clock divider value for 90 degree phase divided clock
|
||||
input ext_reset, // Positive sense reset from housekeeping SPI.
|
||||
output core_clk, // Output core clock
|
||||
output user_clk, // Output user (secondary) clock
|
||||
output resetb_sync // Output propagated and buffered reset
|
||||
);
|
||||
|
||||
wire pll_clk_sel;
|
||||
wire pll_clk_divided;
|
||||
wire pll_clk90_divided;
|
||||
wire core_ext_clk;
|
||||
reg use_pll_first;
|
||||
reg use_pll_second;
|
||||
reg ext_clk_syncd_pre;
|
||||
reg ext_clk_syncd;
|
||||
|
||||
assign pll_clk_sel = ~ext_clk_sel;
|
||||
|
||||
// Note that this implementation does not guard against switching to
|
||||
// the PLL clock if the PLL clock is not present.
|
||||
|
||||
always @(posedge pll_clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
use_pll_first <= 1'b0;
|
||||
use_pll_second <= 1'b0;
|
||||
ext_clk_syncd <= 1'b0;
|
||||
end else begin
|
||||
use_pll_first <= pll_clk_sel;
|
||||
use_pll_second <= use_pll_first;
|
||||
ext_clk_syncd_pre <= ext_clk; // Sync ext_clk to pll_clk
|
||||
ext_clk_syncd <= ext_clk_syncd_pre; // Do this twice (resolve metastability)
|
||||
end
|
||||
end
|
||||
|
||||
// Apply PLL clock divider
|
||||
|
||||
clock_div #(
|
||||
.SIZE(3)
|
||||
) divider (
|
||||
.in(pll_clk),
|
||||
.out(pll_clk_divided),
|
||||
.N(sel),
|
||||
.resetb(resetb)
|
||||
);
|
||||
|
||||
// Secondary PLL clock divider for user space access
|
||||
|
||||
clock_div #(
|
||||
.SIZE(3)
|
||||
) divider2 (
|
||||
.in(pll_clk90),
|
||||
.out(pll_clk90_divided),
|
||||
.N(sel2),
|
||||
.resetb(resetb)
|
||||
);
|
||||
|
||||
|
||||
// Multiplex the clock output
|
||||
|
||||
assign core_ext_clk = (use_pll_first) ? ext_clk_syncd : ext_clk;
|
||||
assign core_clk = (use_pll_second) ? pll_clk_divided : core_ext_clk;
|
||||
assign user_clk = (use_pll_second) ? pll_clk90_divided : core_ext_clk;
|
||||
|
||||
// Reset assignment. "reset" comes from POR, while "ext_reset"
|
||||
// comes from standalone SPI (and is normally zero unless
|
||||
// activated from the SPI).
|
||||
|
||||
// Staged-delay reset
|
||||
reg [2:0] reset_delay;
|
||||
|
||||
always @(posedge core_clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
reset_delay <= 3'b111;
|
||||
end else begin
|
||||
reset_delay <= {1'b0, reset_delay[2:1]};
|
||||
end
|
||||
end
|
||||
|
||||
assign resetb_sync = ~(reset_delay[0] | ext_reset);
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,90 @@
|
|||
// 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
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
`define UNIT_DELAY #1
|
||||
`define USE_POWER_PINS
|
||||
|
||||
`ifdef SIM
|
||||
|
||||
`include "defines.v"
|
||||
`include "pads.v"
|
||||
|
||||
/* NOTE: Need to pass the PDK root directory to iverilog with option -I */
|
||||
|
||||
`ifdef EF_STYLE
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_fd_io.v"
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_ef_io.v"
|
||||
`include "libs.ref/verilog/sky130_fd_io/sky130_ef_io__gpiov2_pad_wrapped.v"
|
||||
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hd/primitives.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hd/sky130_fd_sc_hd.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hvl/primitives.v"
|
||||
`include "libs.ref/verilog/sky130_fd_sc_hvl/sky130_fd_sc_hvl.v"
|
||||
`else
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_fd_io.v"
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_ef_io.v"
|
||||
`include "libs.ref/sky130_fd_io/verilog/sky130_ef_io__gpiov2_pad_wrapped.v"
|
||||
|
||||
`include "libs.ref/sky130_fd_sc_hd/verilog/primitives.v"
|
||||
`include "libs.ref/sky130_fd_sc_hd/verilog/sky130_fd_sc_hd.v"
|
||||
`include "libs.ref/sky130_fd_sc_hvl/verilog/primitives.v"
|
||||
`include "libs.ref/sky130_fd_sc_hvl/verilog/sky130_fd_sc_hvl.v"
|
||||
`endif
|
||||
|
||||
`ifdef GL
|
||||
`include "gl/mgmt_core.v"
|
||||
`include "gl/digital_pll.v"
|
||||
`include "gl/DFFRAM.v"
|
||||
`include "gl/storage.v"
|
||||
`include "gl/user_id_programming.v"
|
||||
`include "gl/chip_io.v"
|
||||
`include "gl/mprj_logic_high.v"
|
||||
`include "gl/mprj2_logic_high.v"
|
||||
`include "gl/mgmt_protect.v"
|
||||
`include "gl/mgmt_protect_hv.v"
|
||||
`include "gl/gpio_control_block.v"
|
||||
`include "gl/gpio_logic_high.v"
|
||||
`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 "mprj2_logic_high.v"
|
||||
`include "mgmt_protect.v"
|
||||
`include "mgmt_protect_hv.v"
|
||||
`include "gpio_control_block.v"
|
||||
`include "gpio_logic_high.v"
|
||||
`include "sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped.v"
|
||||
`include "caravel.v"
|
||||
`endif
|
||||
|
||||
`include "simple_por.v"
|
||||
`include "sram_1rw1r_32_256_8_sky130.v"
|
||||
|
||||
`endif
|
|
@ -0,0 +1,796 @@
|
|||
// `default_nettype none
|
||||
// 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_openframe, a project harness for the Google/SkyWater */
|
||||
/* sky130 fabrication process and open source PDK */
|
||||
/* The "openframe" version does not specify a management SoC */
|
||||
/* and only implements the padframe and related infrastructure. */
|
||||
/* */
|
||||
/* Copyright 2020 efabless, Inc. */
|
||||
/* Written by Tim Edwards, December 2019 */
|
||||
/* and Mohamed Shalan, August 2020 */
|
||||
/* This file is open source hardware released under the */
|
||||
/* Apache 2.0 license. See file LICENSE. */
|
||||
/* */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
module caravel_openframe (
|
||||
inout vddio, // Common 3.3V padframe/ESD power
|
||||
inout vddio_2, // Common 3.3V padframe/ESD power
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
inout vssio_2, // Common padframe/ESD ground
|
||||
inout vdda, // Management 3.3V power
|
||||
inout vssa, // Common analog ground
|
||||
inout vccd, // Management/Common 1.8V power
|
||||
inout vssd, // Common digital ground
|
||||
inout vdda1, // User area 1 3.3V power
|
||||
inout vdda1_2, // User area 1 3.3V power
|
||||
inout vdda2, // User area 2 3.3V power
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa1_2, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V power
|
||||
inout vccd2, // User area 2 1.8V power
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
|
||||
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)
|
||||
|
||||
// Note that only two flash data pins are dedicated to the
|
||||
// management SoC wrapper. The management SoC exports the
|
||||
// quad SPI mode status to make use of the top two mprj_io
|
||||
// pins for io2 and io3.
|
||||
|
||||
output flash_csb,
|
||||
output flash_clk,
|
||||
output flash_io0,
|
||||
output flash_io1
|
||||
);
|
||||
|
||||
//------------------------------------------------------------
|
||||
// This value is uniquely defined for each user project.
|
||||
//------------------------------------------------------------
|
||||
parameter USER_PROJECT_ID = 32'h00000000;
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------
|
||||
*
|
||||
* These pins are overlaid on mprj_io space. They have the function
|
||||
* below when the management processor is in reset, or in the default
|
||||
* configuration. They are assigned to uses in the user space by the
|
||||
* configuration program running off of the SPI flash. Note that even
|
||||
* when the user has taken control of these pins, they can be restored
|
||||
* to the original use by setting the resetb pin low. The SPI pins and
|
||||
* UART pins can be connected directly to an FTDI chip as long as the
|
||||
* FTDI chip sets these lines to high impedence (input function) at
|
||||
* all times except when holding the chip in reset.
|
||||
*
|
||||
* JTAG = mprj_io[0] (inout)
|
||||
* SDO = mprj_io[1] (output)
|
||||
* SDI = mprj_io[2] (input)
|
||||
* CSB = mprj_io[3] (input)
|
||||
* SCK = mprj_io[4] (input)
|
||||
* ser_rx = mprj_io[5] (input)
|
||||
* ser_tx = mprj_io[6] (output)
|
||||
* irq = mprj_io[7] (input)
|
||||
*
|
||||
* flash_io2 = mprj_io[36] (inout)
|
||||
* flash_io3 = mprj_io[37] (inout)
|
||||
*
|
||||
* These pins are reserved for any project that wants to incorporate
|
||||
* its own processor and flash controller. While a user project can
|
||||
* technically use any available I/O pins for the purpose, these
|
||||
* four pins connect to a pass-through mode from the SPI slave (pins
|
||||
* 1-4 above) so that any SPI flash connected to these specific pins
|
||||
* can be accessed through the SPI slave even when the processor is in
|
||||
* reset.
|
||||
*
|
||||
* user_flash_csb = mprj_io[8]
|
||||
* user_flash_sck = mprj_io[9]
|
||||
* user_flash_io0 = mprj_io[10]
|
||||
* user_flash_io1 = mprj_io[11]
|
||||
*
|
||||
*--------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// One-bit GPIO dedicated to management SoC (outside of user control)
|
||||
wire gpio_out_core;
|
||||
wire gpio_in_core;
|
||||
wire gpio_mode0_core;
|
||||
wire gpio_mode1_core;
|
||||
wire gpio_outenb_core;
|
||||
wire gpio_inenb_core;
|
||||
|
||||
// User Project Control (pad-facing)
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_inp_dis;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_ib_mode_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_vtrip_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_slow_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_holdover;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_en;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_sel;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_analog_pol;
|
||||
wire [`MPRJ_IO_PADS*3-1:0] mprj_io_dm;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_in;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_out;
|
||||
|
||||
// User Project Control (user-facing)
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_oeb;
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_in;
|
||||
wire [`MPRJ_IO_PADS-1:0] user_io_out;
|
||||
wire [`MPRJ_IO_PADS-10:0] user_analog_io;
|
||||
|
||||
/* Padframe control signals */
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_serial_link_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_serial_link_2;
|
||||
wire mprj_io_loader_resetn;
|
||||
wire mprj_io_loader_clock;
|
||||
wire mprj_io_loader_data_1; /* user1 side serial loader */
|
||||
wire mprj_io_loader_data_2; /* user2 side serial loader */
|
||||
|
||||
// User Project Control management I/O
|
||||
// There are two types of GPIO connections:
|
||||
// (1) Full Bidirectional: Management connects to in, out, and oeb
|
||||
// Uses: JTAG and SDO
|
||||
// (2) Selectable bidirectional: Management connects to in and out,
|
||||
// which are tied together. oeb is grounded (oeb from the
|
||||
// configuration is used)
|
||||
|
||||
// SDI = mprj_io[2] (input)
|
||||
// CSB = mprj_io[3] (input)
|
||||
// SCK = mprj_io[4] (input)
|
||||
// ser_rx = mprj_io[5] (input)
|
||||
// ser_tx = mprj_io[6] (output)
|
||||
// irq = mprj_io[7] (input)
|
||||
|
||||
wire [`MPRJ_IO_PADS-1:0] mgmt_io_in;
|
||||
wire jtag_out, sdo_out;
|
||||
wire jtag_outenb, sdo_outenb;
|
||||
wire gpio_flash_io2_out, gpio_flash_io3_out;
|
||||
|
||||
wire [1:0] mgmt_io_nc; /* no-connects */
|
||||
|
||||
wire clock_core;
|
||||
|
||||
// Power-on-reset signal. The reset pad generates the sense-inverted
|
||||
// reset at 3.3V. The 1.8V signal and the inverted 1.8V signal are
|
||||
// derived.
|
||||
|
||||
wire porb_h;
|
||||
wire porb_l;
|
||||
wire por_l;
|
||||
|
||||
wire rstb_h;
|
||||
wire rstb_l;
|
||||
|
||||
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_io0_do_core, flash_io1_do_core;
|
||||
wire flash_io0_di_core, flash_io1_di_core;
|
||||
|
||||
chip_io padframe(
|
||||
`ifndef TOP_ROUTING
|
||||
// Package Pins
|
||||
.vddio_pad (vddio), // Common padframe/ESD supply
|
||||
.vddio_pad2 (vddio_2),
|
||||
.vssio_pad (vssio), // Common padframe/ESD ground
|
||||
.vssio_pad2 (vssio_2),
|
||||
.vccd_pad (vccd), // Common 1.8V supply
|
||||
.vssd_pad (vssd), // Common digital ground
|
||||
.vdda_pad (vdda), // Management analog 3.3V supply
|
||||
.vssa_pad (vssa), // Management analog ground
|
||||
.vdda1_pad (vdda1), // User area 1 3.3V supply
|
||||
.vdda1_pad2 (vdda1_2),
|
||||
.vdda2_pad (vdda2), // User area 2 3.3V supply
|
||||
.vssa1_pad (vssa1), // User area 1 analog ground
|
||||
.vssa1_pad2 (vssa1_2),
|
||||
.vssa2_pad (vssa2), // User area 2 analog ground
|
||||
.vccd1_pad (vccd1), // User area 1 1.8V supply
|
||||
.vccd2_pad (vccd2), // User area 2 1.8V supply
|
||||
.vssd1_pad (vssd1), // User area 1 digital ground
|
||||
.vssd2_pad (vssd2), // User area 2 digital ground
|
||||
`endif
|
||||
// Power Pins
|
||||
.vddio (vddio_core),
|
||||
.vssio (vssio_core),
|
||||
.vdda (vdda_core),
|
||||
.vssa (vssa_core),
|
||||
.vccd (vccd_core),
|
||||
.vssd (vssd_core),
|
||||
.vdda1 (vdda1_core),
|
||||
.vdda2 (vdda2_core),
|
||||
.vssa1 (vssa1_core),
|
||||
.vssa2 (vssa2_core),
|
||||
.vccd1 (vccd1_core),
|
||||
.vccd2 (vccd2_core),
|
||||
.vssd1 (vssd1_core),
|
||||
.vssd2 (vssd2_core),
|
||||
|
||||
// Signal Pins
|
||||
.gpio(gpio),
|
||||
.mprj_io(mprj_io),
|
||||
.clock(clock),
|
||||
.resetb(resetb),
|
||||
.flash_csb(flash_csb),
|
||||
.flash_clk(flash_clk),
|
||||
.flash_io0(flash_io0),
|
||||
.flash_io1(flash_io1),
|
||||
|
||||
// Clock and Reset Interface
|
||||
.porb_h(porb_h),
|
||||
.por(por_l),
|
||||
.resetb_core_h(rstb_h),
|
||||
.clock_core(clock_core),
|
||||
|
||||
// Core-facing side of the pads
|
||||
.gpio_out_core(gpio_out_core),
|
||||
.gpio_in_core(gpio_in_core),
|
||||
.gpio_mode0_core(gpio_mode0_core),
|
||||
.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),
|
||||
.mprj_io_in(mprj_io_in),
|
||||
.mprj_io_out(mprj_io_out),
|
||||
.mprj_io_oeb(mprj_io_oeb),
|
||||
.mprj_io_inp_dis(mprj_io_inp_dis),
|
||||
.mprj_io_ib_mode_sel(mprj_io_ib_mode_sel),
|
||||
.mprj_io_vtrip_sel(mprj_io_vtrip_sel),
|
||||
.mprj_io_slow_sel(mprj_io_slow_sel),
|
||||
.mprj_io_holdover(mprj_io_holdover),
|
||||
.mprj_io_analog_en(mprj_io_analog_en),
|
||||
.mprj_io_analog_sel(mprj_io_analog_sel),
|
||||
.mprj_io_analog_pol(mprj_io_analog_pol),
|
||||
.mprj_io_dm(mprj_io_dm),
|
||||
.mprj_analog_io(user_analog_io)
|
||||
);
|
||||
|
||||
// Clock and reset
|
||||
wire caravel_clk;
|
||||
wire caravel_clk2;
|
||||
wire caravel_rstn;
|
||||
|
||||
wire mprj_clock;
|
||||
wire mprj_clock2;
|
||||
wire mprj_reset;
|
||||
|
||||
// Mask revision (User ID)
|
||||
wire [31:0] mask_rev;
|
||||
|
||||
// Power Monitoring
|
||||
wire mprj_vcc_pwrgood;
|
||||
wire mprj2_vcc_pwrgood;
|
||||
wire mprj_vdd_pwrgood;
|
||||
wire mprj2_vdd_pwrgood;
|
||||
|
||||
// Open Frame wrapper
|
||||
openframe_wrapper openframe (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
// GPIO (1 pin)
|
||||
.gpio_out_pad(gpio_out_core),
|
||||
.gpio_in_pad(gpio_in_core),
|
||||
.gpio_mode0_pad(gpio_mode0_core),
|
||||
.gpio_mode1_pad(gpio_mode1_core),
|
||||
.gpio_outenb_pad(gpio_outenb_core),
|
||||
.gpio_inenb_pad(gpio_inenb_core),
|
||||
|
||||
// GPIO
|
||||
|
||||
// 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),
|
||||
|
||||
// Clock and reset
|
||||
.core_clk(caravel_clk),
|
||||
.core_rstn(caravel_rstn)
|
||||
);
|
||||
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_serial_link_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_serial_link_2_shifted;
|
||||
|
||||
assign gpio_serial_link_1_shifted = {gpio_serial_link_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_data_1};
|
||||
// Note that serial_link_2 is backwards compared to serial_link_1, so it
|
||||
// shifts in the other direction.
|
||||
assign gpio_serial_link_2_shifted = {mprj_io_loader_data_2,
|
||||
gpio_serial_link_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
|
||||
// Propagating clock and reset to mitigate timing and fanout issues
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_clock_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_clock_2;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_resetn_1;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_resetn_2;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_clock_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_clock_2_shifted;
|
||||
wire [`MPRJ_IO_PADS_1-1:0] gpio_resetn_1_shifted;
|
||||
wire [`MPRJ_IO_PADS_2-1:0] gpio_resetn_2_shifted;
|
||||
|
||||
assign gpio_clock_1_shifted = {gpio_clock_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_clock};
|
||||
assign gpio_clock_2_shifted = {mprj_io_loader_clock,
|
||||
gpio_clock_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
assign gpio_resetn_1_shifted = {gpio_resetn_1[`MPRJ_IO_PADS_1-2:0],
|
||||
mprj_io_loader_resetn};
|
||||
assign gpio_resetn_2_shifted = {mprj_io_loader_resetn,
|
||||
gpio_resetn_2[`MPRJ_IO_PADS_2-1:1]};
|
||||
|
||||
// Clocking control
|
||||
|
||||
caravel_clocking clocking(
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd1v8(VPWR),
|
||||
.vss(VGND),
|
||||
`endif
|
||||
.ext_clk_sel(ext_clk_sel),
|
||||
.ext_clk(clock),
|
||||
.pll_clk(pll_clk),
|
||||
.pll_clk90(pll_clk90),
|
||||
.resetb(resetb),
|
||||
.sel(spi_pll_sel),
|
||||
.sel2(spi_pll90_sel),
|
||||
.ext_reset(ext_reset), // From housekeeping SPI
|
||||
.core_clk(core_clk),
|
||||
.user_clk(user_clk),
|
||||
.resetb_sync(core_rstn)
|
||||
);
|
||||
|
||||
// DCO/Digital Locked Loop
|
||||
digital_pll pll (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(VPWR),
|
||||
.VGND(VGND),
|
||||
`endif
|
||||
.resetb(resetb),
|
||||
.enable(spi_pll_ena),
|
||||
.osc(clock),
|
||||
.clockp({pll_clk, pll_clk90}),
|
||||
.div(spi_pll_div),
|
||||
.dco(spi_pll_dco_ena),
|
||||
.ext_trim(spi_pll_trim)
|
||||
);
|
||||
|
||||
// Housekeeping SPI interface
|
||||
housekeeping_spi housekeeping (
|
||||
`ifdef USE_POWER_PINS
|
||||
.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),
|
||||
.pll_dco_ena(spi_pll_dco_ena),
|
||||
.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),
|
||||
.irq(irq_spi),
|
||||
.reset(ext_reset),
|
||||
.trap(trap),
|
||||
.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
|
||||
mprj_ctrl_wb #(
|
||||
.BASE_ADR(MPRJ_CTRL_ADR)
|
||||
) mprj_ctrl (
|
||||
.wb_clk_i(wb_clk_i),
|
||||
.wb_rst_i(wb_rst_i),
|
||||
|
||||
.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)
|
||||
);
|
||||
|
||||
// Each control block sits next to an I/O pad in the user area.
|
||||
// It gets input through a serial chain from the previous control
|
||||
// block and passes it to the next control block. Due to the nature
|
||||
// of the shift register, bits are presented in reverse, as the first
|
||||
// bit in ends up as the last bit of the last I/O pad control block.
|
||||
|
||||
// There are two types of block; the first two and the last two
|
||||
// are configured to be full bidirectional under control of the
|
||||
// management Soc (JTAG and SDO for the first two; flash_io2 and
|
||||
// flash_io3 for the last two). The rest are configured to be default
|
||||
// (input). Note that the first two and last two are the ones closest
|
||||
// to the management SoC on either side, which minimizes the wire length
|
||||
// of the extra signals those pads need.
|
||||
|
||||
/* First two GPIOs (JTAG and SDO) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
|
||||
) gpio_control_bidir_1 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[1:0]),
|
||||
.serial_clock(gpio_clock_1_shifted[1:0]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[1:0]),
|
||||
.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}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[1:0]),
|
||||
.serial_data_out(gpio_serial_link_1[1:0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[1:0]),
|
||||
.user_gpio_oeb(user_io_oeb[1:0]),
|
||||
.user_gpio_in(user_io_in[1:0]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[1:0]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[1:0]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[1:0]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[1:0]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[1:0]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[1:0]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[1:0]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[1:0]),
|
||||
.pad_gpio_dm(mprj_io_dm[5:0]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[1:0]),
|
||||
.pad_gpio_out(mprj_io_out[1:0]),
|
||||
.pad_gpio_in(mprj_io_in[1:0])
|
||||
);
|
||||
|
||||
/* Section 1 GPIOs (GPIO 0 to 18) */
|
||||
wire [`MPRJ_IO_PADS_1-1:2] one_loop1;
|
||||
|
||||
/* Section 1 GPIOs (GPIO 3 to 7) that start up under management control */
|
||||
|
||||
gpio_control_block #(
|
||||
.DM_INIT(3'b001), // Configured as inputs
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output disabled
|
||||
) gpio_control_in_1a [5:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[7:2]),
|
||||
.serial_clock(gpio_clock_1_shifted[7:2]),
|
||||
|
||||
.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]),
|
||||
|
||||
.one(one_loop1[7:2]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[7:2]),
|
||||
.serial_data_out(gpio_serial_link_1[7:2]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[7:2]),
|
||||
.user_gpio_oeb(user_io_oeb[7:2]),
|
||||
.user_gpio_in(user_io_in[7:2]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[7:2]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[7:2]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[7:2]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[7:2]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[7:2]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[7:2]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[7:2]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[7:2]),
|
||||
.pad_gpio_dm(mprj_io_dm[23:6]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[7:2]),
|
||||
.pad_gpio_out(mprj_io_out[7:2]),
|
||||
.pad_gpio_in(mprj_io_in[7:2])
|
||||
);
|
||||
|
||||
/* Section 1 GPIOs (GPIO 8 to 18) */
|
||||
|
||||
gpio_control_block gpio_control_in_1 [`MPRJ_IO_PADS_1-9:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
.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]),
|
||||
|
||||
.one(one_loop1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_1_shifted[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.serial_data_out(gpio_serial_link_1[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS_1-1):8]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS_1*3-1):24]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS_1-1):8]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS_1-1):8])
|
||||
);
|
||||
|
||||
|
||||
/* Last two GPIOs (flash_io2 and flash_io3) */
|
||||
gpio_control_block #(
|
||||
.MGMT_INIT(1'b1), // Management-controlled
|
||||
.OENB_INIT(1'b1) // Output controlled from bidirectional pin
|
||||
) gpio_control_bidir_2 [1:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
|
||||
.resetn_out(gpio_resetn_1[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.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}),
|
||||
|
||||
.one(),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-1):(`MPRJ_IO_PADS_2-2)]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-1):(`MPRJ_IO_PADS*3-6)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-1):(`MPRJ_IO_PADS-2)])
|
||||
);
|
||||
|
||||
/* Section 2 GPIOs (GPIO 19 to 37) */
|
||||
wire [`MPRJ_IO_PADS_2-3:0] one_loop2;
|
||||
gpio_control_block gpio_control_in_2 [`MPRJ_IO_PADS_2-3:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd_core),
|
||||
.vssd(vssd_core),
|
||||
.vccd1(vccd1_core),
|
||||
.vssd1(vssd1_core),
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
|
||||
.resetn(gpio_resetn_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
.serial_clock(gpio_clock_1_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
|
||||
.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),
|
||||
|
||||
.one(one_loop2),
|
||||
.zero(),
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
.serial_data_in(gpio_serial_link_2_shifted[(`MPRJ_IO_PADS_2-3):0]),
|
||||
.serial_data_out(gpio_serial_link_2[(`MPRJ_IO_PADS_2-3):0]),
|
||||
|
||||
// User-facing signals
|
||||
.user_gpio_out(user_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.user_gpio_oeb(user_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.user_gpio_in(user_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
.pad_gpio_inenb(mprj_io_inp_dis[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ib_mode_sel(mprj_io_ib_mode_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_vtrip_sel(mprj_io_vtrip_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_slow_sel(mprj_io_slow_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_holdover(mprj_io_holdover[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_en(mprj_io_analog_en[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_sel(mprj_io_analog_sel[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_ana_pol(mprj_io_analog_pol[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_dm(mprj_io_dm[(`MPRJ_IO_PADS*3-7):(`MPRJ_IO_PADS_1*3)]),
|
||||
.pad_gpio_outenb(mprj_io_oeb[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_out(mprj_io_out[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)]),
|
||||
.pad_gpio_in(mprj_io_in[(`MPRJ_IO_PADS-3):(`MPRJ_IO_PADS_1)])
|
||||
);
|
||||
|
||||
user_id_programming #(
|
||||
.USER_PROJECT_ID(USER_PROJECT_ID)
|
||||
) user_id_value (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd_core),
|
||||
.VGND(vssd_core),
|
||||
`endif
|
||||
.mask_rev(mask_rev)
|
||||
);
|
||||
|
||||
// Power-on-reset circuit
|
||||
simple_por por (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vdd3v3(vddio_core),
|
||||
.vdd1v8(vccd_core),
|
||||
.vss(vssio_core),
|
||||
`endif
|
||||
.porb_h(porb_h),
|
||||
.porb_l(porb_l),
|
||||
.por_l(por_l)
|
||||
);
|
||||
|
||||
// XRES (chip input pin reset) reset level converter
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped rstb_level (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vddio_core),
|
||||
.LVPWR(vccd_core),
|
||||
.LVGND(vssd_core),
|
||||
.VGND(vssio_core),
|
||||
`endif
|
||||
.A(rstb_h),
|
||||
.X(rstb_l)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// `default_nettype wire
|
|
@ -0,0 +1,444 @@
|
|||
// 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 chip_io(
|
||||
// Package Pins
|
||||
inout vddio_pad, // Common padframe/ESD supply
|
||||
inout vddio_pad2,
|
||||
inout vssio_pad, // Common padframe/ESD ground
|
||||
inout vssio_pad2,
|
||||
inout vccd_pad, // Common 1.8V supply
|
||||
inout vssd_pad, // Common digital ground
|
||||
inout vdda_pad, // Management analog 3.3V supply
|
||||
inout vssa_pad, // Management analog ground
|
||||
inout vdda1_pad, // User area 1 3.3V supply
|
||||
inout vdda1_pad2,
|
||||
inout vdda2_pad, // User area 2 3.3V supply
|
||||
inout vssa1_pad, // User area 1 analog ground
|
||||
inout vssa1_pad2,
|
||||
inout vssa2_pad, // User area 2 analog ground
|
||||
inout vccd1_pad, // User area 1 1.8V supply
|
||||
inout vccd2_pad, // User area 2 1.8V supply
|
||||
inout vssd1_pad, // User area 1 digital ground
|
||||
inout vssd2_pad, // User area 2 digital ground
|
||||
|
||||
// Core Side
|
||||
inout vddio, // Common padframe/ESD supply
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
inout vccd, // Common 1.8V supply
|
||||
inout vssd, // Common digital ground
|
||||
inout vdda, // Management analog 3.3V supply
|
||||
inout vssa, // Management analog ground
|
||||
inout vdda1, // User area 1 3.3V supply
|
||||
inout vdda2, // User area 2 3.3V supply
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V supply
|
||||
inout vccd2, // User area 2 1.8V supply
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
|
||||
inout gpio,
|
||||
input clock,
|
||||
input resetb,
|
||||
output flash_csb,
|
||||
output flash_clk,
|
||||
inout flash_io0,
|
||||
inout flash_io1,
|
||||
// Chip Core Interface
|
||||
input porb_h,
|
||||
input por,
|
||||
output resetb_core_h,
|
||||
output clock_core,
|
||||
input gpio_out_core,
|
||||
output gpio_in_core,
|
||||
input gpio_mode0_core,
|
||||
input gpio_mode1_core,
|
||||
input gpio_outenb_core,
|
||||
input gpio_inenb_core,
|
||||
input flash_csb_core,
|
||||
input flash_clk_core,
|
||||
input flash_csb_oeb_core,
|
||||
input flash_clk_oeb_core,
|
||||
input flash_io0_oeb_core,
|
||||
input flash_io1_oeb_core,
|
||||
input flash_csb_ieb_core,
|
||||
input flash_clk_ieb_core,
|
||||
input flash_io0_ieb_core,
|
||||
input flash_io1_ieb_core,
|
||||
input flash_io0_do_core,
|
||||
input flash_io1_do_core,
|
||||
output flash_io0_di_core,
|
||||
output flash_io1_di_core,
|
||||
// User project IOs
|
||||
inout [`MPRJ_IO_PADS-1:0] mprj_io,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_out,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_oeb,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_inp_dis,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_ib_mode_sel,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_vtrip_sel,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_slow_sel,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_holdover,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_analog_en,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_analog_sel,
|
||||
input [`MPRJ_IO_PADS-1:0] mprj_io_analog_pol,
|
||||
input [`MPRJ_IO_PADS*3-1:0] mprj_io_dm,
|
||||
output [`MPRJ_IO_PADS-1:0] mprj_io_in,
|
||||
// User project direct access to gpio pad connections for analog
|
||||
// (all but the lowest-numbered 7 pads)
|
||||
inout [`MPRJ_IO_PADS-10:0] mprj_analog_io
|
||||
);
|
||||
|
||||
// To be considered: Master hold signal on all user pads (?)
|
||||
// For now, set holdh_n to 1 (NOTE: This is in the 3.3V domain)
|
||||
// and setting enh to porb_h.
|
||||
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_hldh_n;
|
||||
wire [`MPRJ_IO_PADS-1:0] mprj_io_enh;
|
||||
|
||||
assign mprj_io_hldh_n = {`MPRJ_IO_PADS{vddio}};
|
||||
assign mprj_io_enh = {`MPRJ_IO_PADS{porb_h}};
|
||||
|
||||
wire analog_a, analog_b;
|
||||
wire vddio_q, vssio_q;
|
||||
|
||||
// Instantiate power and ground pads for management domain
|
||||
// 12 pads: vddio, vssio, vdda, vssa, vccd, vssd
|
||||
// One each HV and LV clamp.
|
||||
|
||||
// HV clamps connect between one HV power rail and one ground
|
||||
// LV clamps have two clamps connecting between any two LV power
|
||||
// rails and grounds, and one back-to-back diode which connects
|
||||
// between the first LV clamp ground and any other ground.
|
||||
|
||||
sky130_ef_io__vddio_hvc_clamped_pad \mgmt_vddio_hvclamp_pad[0] (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDIO(vddio)
|
||||
`else
|
||||
,.VDDIO_PAD(vddio_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// lies in user area 2
|
||||
sky130_ef_io__vddio_hvc_clamped_pad \mgmt_vddio_hvclamp_pad[1] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDIO(vddio)
|
||||
`else
|
||||
,.VDDIO_PAD(vddio_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad mgmt_vdda_hvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda)
|
||||
`else
|
||||
,.VDDA_PAD(vdda_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped_pad mgmt_vccd_lvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd)
|
||||
`else
|
||||
,.VCCD_PAD(vccd_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssio_hvc_clamped_pad \mgmt_vssio_hvclamp_pad[0] (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSIO(vssio)
|
||||
`else
|
||||
,.VSSIO_PAD(vssio_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssio_hvc_clamped_pad \mgmt_vssio_hvclamp_pad[1] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSIO(vssio)
|
||||
`else
|
||||
,.VSSIO_PAD(vssio_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad mgmt_vssa_hvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa)
|
||||
`else
|
||||
,.VSSA_PAD(vssa_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped_pad mgmt_vssd_lvclmap_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd)
|
||||
`else
|
||||
,.VSSD_PAD(vssd_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// Instantiate power and ground pads for user 1 domain
|
||||
// 8 pads: vdda, vssa, vccd, vssd; One each HV and LV clamp.
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad \user1_vdda_hvclamp_pad[0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda1)
|
||||
`else
|
||||
,.VDDA_PAD(vdda1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad \user1_vdda_hvclamp_pad[1] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda1)
|
||||
`else
|
||||
,.VDDA_PAD(vdda1_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped2_pad user1_vccd_lvclamp_pad (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd1)
|
||||
`else
|
||||
,.VCCD_PAD(vccd1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad \user1_vssa_hvclamp_pad[0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa1)
|
||||
`else
|
||||
,.VSSA_PAD(vssa1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad \user1_vssa_hvclamp_pad[1] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa1)
|
||||
`else
|
||||
,.VSSA_PAD(vssa1_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped2_pad user1_vssd_lvclmap_pad (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd1)
|
||||
`else
|
||||
,.VSSD_PAD(vssd1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// Instantiate power and ground pads for user 2 domain
|
||||
// 8 pads: vdda, vssa, vccd, vssd; One each HV and LV clamp.
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad user2_vdda_hvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda2)
|
||||
`else
|
||||
,.VDDA_PAD(vdda2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped2_pad user2_vccd_lvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd2)
|
||||
`else
|
||||
,.VCCD_PAD(vccd2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad user2_vssa_hvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa2)
|
||||
`else
|
||||
,.VSSA_PAD(vssa2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped2_pad user2_vssd_lvclmap_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd2)
|
||||
`else
|
||||
,.VSSD_PAD(vssd2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
wire [2:0] dm_all =
|
||||
{gpio_mode1_core, gpio_mode1_core, gpio_mode0_core};
|
||||
wire[2:0] flash_io0_mode =
|
||||
{flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core};
|
||||
wire[2:0] flash_io1_mode =
|
||||
{flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core};
|
||||
|
||||
// Management clock input pad
|
||||
`INPUT_PAD(clock, clock_core);
|
||||
|
||||
// Management GPIO pad
|
||||
`INOUT_PAD(
|
||||
gpio, gpio_in_core, gpio_out_core,
|
||||
gpio_inenb_core, gpio_outenb_core, dm_all);
|
||||
|
||||
// Management Flash SPI pads
|
||||
`INOUT_PAD(
|
||||
flash_io0, flash_io0_di_core, flash_io0_do_core,
|
||||
flash_io0_ieb_core, flash_io0_oeb_core, flash_io0_mode);
|
||||
`INOUT_PAD(
|
||||
flash_io1, flash_io1_di_core, flash_io1_do_core,
|
||||
flash_io1_ieb_core, flash_io1_oeb_core, flash_io1_mode);
|
||||
|
||||
`OUTPUT_PAD(flash_csb, flash_csb_core, flash_csb_ieb_core, flash_csb_oeb_core);
|
||||
`OUTPUT_PAD(flash_clk, flash_clk_core, flash_clk_ieb_core, flash_clk_oeb_core);
|
||||
|
||||
// NOTE: The analog_out pad from the raven chip has been replaced by
|
||||
// the digital reset input resetb on caravel due to the lack of an on-board
|
||||
// power-on-reset circuit. The XRES pad is used for providing a glitch-
|
||||
// free reset.
|
||||
|
||||
wire xresloop;
|
||||
sky130_fd_io__top_xres4v2 resetb_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
,.PAD(resetb),
|
||||
`endif
|
||||
.TIE_WEAK_HI_H(xresloop), // Loop-back connection to pad through pad_a_esd_h
|
||||
.TIE_HI_ESD(),
|
||||
.TIE_LO_ESD(),
|
||||
.PAD_A_ESD_H(xresloop),
|
||||
.XRES_H_N(resetb_core_h),
|
||||
.DISABLE_PULLUP_H(vssio), // 0 = enable pull-up on reset pad
|
||||
.ENABLE_H(porb_h), // Power-on-reset
|
||||
.EN_VDDIO_SIG_H(vssio), // No idea.
|
||||
.INP_SEL_H(vssio), // 1 = use filt_in_h else filter the pad input
|
||||
.FILT_IN_H(vssio), // Alternate input for glitch filter
|
||||
.PULLUP_H(vssio), // Pullup connection for alternate filter input
|
||||
.ENABLE_VDDIO(vccd)
|
||||
);
|
||||
|
||||
// Corner cells (These are overlay cells; it is not clear what is normally
|
||||
// supposed to go under them.)
|
||||
|
||||
sky130_ef_io__corner_pad mgmt_corner [1:0] (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd),
|
||||
.VSSA(vssa),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda),
|
||||
.VCCD(vccd),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
|
||||
);
|
||||
sky130_ef_io__corner_pad user1_corner (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd1),
|
||||
.VSSA(vssa1),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda1),
|
||||
.VCCD(vccd1),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
);
|
||||
sky130_ef_io__corner_pad user2_corner (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd2),
|
||||
.VSSA(vssa2),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda2),
|
||||
.VCCD(vccd2),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
);
|
||||
|
||||
mprj_io mprj_pads(
|
||||
.vddio(vddio),
|
||||
.vssio(vssio),
|
||||
.vccd(vccd),
|
||||
.vssd(vssd),
|
||||
.vdda1(vdda1),
|
||||
.vdda2(vdda2),
|
||||
.vssa1(vssa1),
|
||||
.vssa2(vssa2),
|
||||
.vccd1(vccd1),
|
||||
.vccd2(vccd2),
|
||||
.vssd1(vssd1),
|
||||
.vssd2(vssd2),
|
||||
.vddio_q(vddio_q),
|
||||
.vssio_q(vssio_q),
|
||||
.analog_a(analog_a),
|
||||
.analog_b(analog_b),
|
||||
.porb_h(porb_h),
|
||||
.io(mprj_io),
|
||||
.io_out(mprj_io_out),
|
||||
.oeb(mprj_io_oeb),
|
||||
.hldh_n(mprj_io_hldh_n),
|
||||
.enh(mprj_io_enh),
|
||||
.inp_dis(mprj_io_inp_dis),
|
||||
.ib_mode_sel(mprj_io_ib_mode_sel),
|
||||
.vtrip_sel(mprj_io_vtrip_sel),
|
||||
.holdover(mprj_io_holdover),
|
||||
.slow_sel(mprj_io_slow_sel),
|
||||
.analog_en(mprj_io_analog_en),
|
||||
.analog_sel(mprj_io_analog_sel),
|
||||
.analog_pol(mprj_io_analog_pol),
|
||||
.dm(mprj_io_dm),
|
||||
.io_in(mprj_io_in),
|
||||
.analog_io(mprj_analog_io)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// `default_nettype wire
|
|
@ -0,0 +1,525 @@
|
|||
// 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
|
||||
|
||||
/* Alternative padframe that removes the GPIO from the top row, */
|
||||
/* replacing them with un-overlaid power pads which have a */
|
||||
/* direct connection from pad to core. */
|
||||
|
||||
/* For convenience, all of the original GPIO signals remain */
|
||||
/* defined in the I/O list, although some are not connected. */
|
||||
|
||||
/* ANALOG_PADS_1 = Number of GPIO pads in the user 1 section */
|
||||
/* that are replaced by straight-through analog */
|
||||
/* ANALOG_PADS_2 = Number of GPIO pads in the user 2 section */
|
||||
/* that are replaced by straight-through analog */
|
||||
|
||||
module chip_io_alt #(
|
||||
parameter ANALOG_PADS_1 = 5,
|
||||
parameter ANALOG_PADS_2 = 6
|
||||
) (
|
||||
// Package Pins
|
||||
inout vddio_pad, // Common padframe/ESD supply
|
||||
inout vddio_pad2, // Common padframe/ESD supply
|
||||
inout vssio_pad, // Common padframe/ESD ground
|
||||
inout vssio_pad2, // Common padframe/ESD ground
|
||||
inout vccd_pad, // Common 1.8V supply
|
||||
inout vssd_pad, // Common digital ground
|
||||
inout vdda_pad, // Management analog 3.3V supply
|
||||
inout vssa_pad, // Management analog ground
|
||||
inout vdda1_pad, // User area 1 3.3V supply
|
||||
inout vdda1_pad2, // User area 1 3.3V supply
|
||||
inout vdda2_pad, // User area 2 3.3V supply
|
||||
inout vssa1_pad, // User area 1 analog ground
|
||||
inout vssa1_pad2, // User area 1 analog ground
|
||||
inout vssa2_pad, // User area 2 analog ground
|
||||
inout vccd1_pad, // User area 1 1.8V supply
|
||||
inout vccd2_pad, // User area 2 1.8V supply
|
||||
inout vssd1_pad, // User area 1 digital ground
|
||||
inout vssd2_pad, // User area 2 digital ground
|
||||
|
||||
// Core Side
|
||||
inout vddio, // Common padframe/ESD supply
|
||||
inout vssio, // Common padframe/ESD ground
|
||||
inout vccd, // Common 1.8V supply
|
||||
inout vssd, // Common digital ground
|
||||
inout vdda, // Management analog 3.3V supply
|
||||
inout vssa, // Management analog ground
|
||||
inout vdda1, // User area 1 3.3V supply
|
||||
inout vdda2, // User area 2 3.3V supply
|
||||
inout vssa1, // User area 1 analog ground
|
||||
inout vssa2, // User area 2 analog ground
|
||||
inout vccd1, // User area 1 1.8V supply
|
||||
inout vccd2, // User area 2 1.8V supply
|
||||
inout vssd1, // User area 1 digital ground
|
||||
inout vssd2, // User area 2 digital ground
|
||||
|
||||
inout gpio,
|
||||
input clock,
|
||||
input resetb,
|
||||
output flash_csb,
|
||||
output flash_clk,
|
||||
inout flash_io0,
|
||||
inout flash_io1,
|
||||
// Chip Core Interface
|
||||
input porb_h,
|
||||
input por,
|
||||
output resetb_core_h,
|
||||
output clock_core,
|
||||
input gpio_out_core,
|
||||
output gpio_in_core,
|
||||
input gpio_mode0_core,
|
||||
input gpio_mode1_core,
|
||||
input gpio_outenb_core,
|
||||
input gpio_inenb_core,
|
||||
input flash_csb_core,
|
||||
input flash_clk_core,
|
||||
input flash_csb_oeb_core,
|
||||
input flash_clk_oeb_core,
|
||||
input flash_io0_oeb_core,
|
||||
input flash_io1_oeb_core,
|
||||
input flash_csb_ieb_core,
|
||||
input flash_clk_ieb_core,
|
||||
input flash_io0_ieb_core,
|
||||
input flash_io1_ieb_core,
|
||||
input flash_io0_do_core,
|
||||
input flash_io1_do_core,
|
||||
output flash_io0_di_core,
|
||||
output flash_io1_di_core,
|
||||
// User project IOs
|
||||
// mprj_io is defined for all pads, both digital and analog
|
||||
inout [`MPRJ_IO_PADS-1:0] mprj_io,
|
||||
// The section below is for the digital pads only.
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_out,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_oeb,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_inp_dis,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_ib_mode_sel,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_vtrip_sel,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_slow_sel,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_holdover,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_analog_en,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_analog_sel,
|
||||
input [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_analog_pol,
|
||||
input [(`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2)*3-1:0] mprj_io_dm,
|
||||
output [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_in,
|
||||
output [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-1:0] mprj_io_in_3v3,
|
||||
|
||||
// User project direct access to gpio pad connections for analog
|
||||
// "analog" connects to the "esd_0" pin of the GPIO pad, and
|
||||
// "analog_noesd" connects to the "noesd" pin of the GPIO pad.
|
||||
|
||||
// User side 1: Connects to all but the first 7 pads;
|
||||
// User side 2: Connects to all but the last 2 pads
|
||||
inout [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-10:0] mprj_gpio_analog,
|
||||
inout [`MPRJ_IO_PADS-ANALOG_PADS_1-ANALOG_PADS_2-10:0] mprj_gpio_noesd,
|
||||
|
||||
// Core connections for the analog signals
|
||||
inout [ANALOG_PADS_1+ANALOG_PADS_2-1:0] mprj_analog,
|
||||
|
||||
// These are clamp connections for the clamps in the analog cells, if
|
||||
// they are used for power supplies.
|
||||
// User side 1: Connects to
|
||||
input [2:0] mprj_clamp_high,
|
||||
input [2:0] mprj_clamp_low
|
||||
);
|
||||
|
||||
wire analog_a, analog_b;
|
||||
wire vddio_q, vssio_q;
|
||||
|
||||
// To be considered: Master hold signal on all user pads (?)
|
||||
// For now, set holdh_n to 1 (NOTE: This is in the 3.3V domain)
|
||||
// and setting enh to porb_h.
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_hldh_n;
|
||||
wire [`MPRJ_IO_PADS-`ANALOG_PADS-1:0] mprj_io_enh;
|
||||
|
||||
assign mprj_io_hldh_n = {`MPRJ_IO_PADS{vddio}};
|
||||
assign mprj_io_enh = {`MPRJ_IO_PADS{porb_h}};
|
||||
|
||||
// Instantiate power and ground pads for management domain
|
||||
// 12 pads: vddio, vssio, vdda, vssa, vccd, vssd
|
||||
// One each HV and LV clamp.
|
||||
|
||||
// HV clamps connect between one HV power rail and one ground
|
||||
// LV clamps have two clamps connecting between any two LV power
|
||||
// rails and grounds, and one back-to-back diode which connects
|
||||
// between the first LV clamp ground and any other ground.
|
||||
|
||||
sky130_ef_io__vddio_hvc_clamped_pad \mgmt_vddio_hvclamp_pad[0] (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDIO(vddio)
|
||||
`else
|
||||
,.VDDIO_PAD(vddio_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// lies in user area 2
|
||||
sky130_ef_io__vddio_hvc_clamped_pad \mgmt_vddio_hvclamp_pad[1] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDIO(vddio)
|
||||
`else
|
||||
,.VDDIO_PAD(vddio_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad mgmt_vdda_hvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda)
|
||||
`else
|
||||
,.VDDA_PAD(vdda_pad)
|
||||
`endif );
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped_pad mgmt_vccd_lvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd)
|
||||
`else
|
||||
,.VCCD_PAD(vccd_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssio_hvc_clamped_pad \mgmt_vssio_hvclamp_pad[0] (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSIO(vssio)
|
||||
`else
|
||||
,.VSSIO_PAD(vssio_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssio_hvc_clamped_pad \mgmt_vssio_hvclamp_pad[1] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSIO(vssio)
|
||||
`else
|
||||
,.VSSIO_PAD(vssio_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad mgmt_vssa_hvclamp_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa)
|
||||
`else
|
||||
,.VSSA_PAD(vssa_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped_pad mgmt_vssd_lvclmap_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd)
|
||||
`else
|
||||
,.VSSD_PAD(vssd_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// Instantiate power and ground pads for user 1 domain
|
||||
// 8 pads: vdda, vssa, vccd, vssd; One each HV and LV clamp.
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad \user1_vdda_hvclamp_pad[0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda1)
|
||||
`else
|
||||
,.VDDA_PAD(vdda1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad \user1_vdda_hvclamp_pad[1] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda1)
|
||||
`else
|
||||
,.VDDA_PAD(vdda1_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped2_pad user1_vccd_lvclamp_pad (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd1)
|
||||
`else
|
||||
,.VCCD_PAD(vccd1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad \user1_vssa_hvclamp_pad[0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa1)
|
||||
`else
|
||||
,.VSSA_PAD(vssa1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad \user1_vssa_hvclamp_pad[1] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa1)
|
||||
`else
|
||||
,.VSSA_PAD(vssa1_pad2)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped2_pad user1_vssd_lvclmap_pad (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd1)
|
||||
`else
|
||||
,.VSSD_PAD(vssd1_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// Instantiate power and ground pads for user 2 domain
|
||||
// 8 pads: vdda, vssa, vccd, vssd; One each HV and LV clamp.
|
||||
|
||||
sky130_ef_io__vdda_hvc_clamped_pad user2_vdda_hvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VDDA(vdda2)
|
||||
`else
|
||||
,.VDDA_PAD(vdda2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vccd_lvc_clamped2_pad user2_vccd_lvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VCCD(vccd2)
|
||||
`else
|
||||
,.VCCD_PAD(vccd2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssa_hvc_clamped_pad user2_vssa_hvclamp_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSA(vssa2)
|
||||
`else
|
||||
,.VSSA_PAD(vssa2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
sky130_ef_io__vssd_lvc_clamped2_pad user2_vssd_lvclmap_pad (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifdef TOP_ROUTING
|
||||
.VSSD(vssd2)
|
||||
`else
|
||||
,.VSSD_PAD(vssd2_pad)
|
||||
`endif
|
||||
);
|
||||
|
||||
// Instantiate analog pads in user area 1 using the custom analog pad
|
||||
sky130_ef_io__analog_pad user1_analog_pad [ANALOG_PADS_1-2:0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
// .VDDIO(vddio)
|
||||
,.P_PAD(mprj_io[`MPRJ_IO_PADS_1-2:`MPRJ_IO_PADS_1-ANALOG_PADS_1]),
|
||||
`endif
|
||||
.P_CORE(mprj_analog[ANALOG_PADS_1-2:0])
|
||||
);
|
||||
|
||||
// Last analog pad is a power pad, to provide a clamp resource.
|
||||
sky130_ef_io__top_power_hvc user1_analog_pad_with_clamp (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
// .VDDIO(vddio)
|
||||
,.P_PAD(mprj_io[`MPRJ_IO_PADS_1-1]),
|
||||
`endif
|
||||
`HVCLAMP_PINS(mprj_clamp_high[0],
|
||||
mprj_clamp_low[0]),
|
||||
.P_CORE(mprj_analog[ANALOG_PADS_1-1])
|
||||
);
|
||||
|
||||
// Instantiate analog pads in user area 2 using the custom analog pad.
|
||||
sky130_ef_io__analog_pad user2_analog_pad [ANALOG_PADS_2-3:0] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
// .VDDIO(vddio)
|
||||
,.P_PAD(mprj_io[`MPRJ_IO_PADS_1+ANALOG_PADS_2-1:`MPRJ_IO_PADS_1+2]),
|
||||
`endif
|
||||
.P_CORE(mprj_analog[ANALOG_PADS_2+ANALOG_PADS_1-1:ANALOG_PADS_1+2])
|
||||
);
|
||||
|
||||
// Last two analog pads are power pads, to provide clamp resources.
|
||||
sky130_ef_io__top_power_hvc user2_analog_pad_with_clamp [1:0] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
// .VDDIO(vddio)
|
||||
,.P_PAD(mprj_io[`MPRJ_IO_PADS_1+1:`MPRJ_IO_PADS_1]),
|
||||
`endif
|
||||
`HVCLAMP_PINS(mprj_clamp_high[2:1], mprj_clamp_low[2:1]),
|
||||
.P_CORE(mprj_analog[`ANALOG_PADS_1+1:ANALOG_PADS_1])
|
||||
);
|
||||
|
||||
wire [2:0] dm_all =
|
||||
{gpio_mode1_core, gpio_mode1_core, gpio_mode0_core};
|
||||
wire[2:0] flash_io0_mode =
|
||||
{flash_io0_ieb_core, flash_io0_ieb_core, flash_io0_oeb_core};
|
||||
wire[2:0] flash_io1_mode =
|
||||
{flash_io1_ieb_core, flash_io1_ieb_core, flash_io1_oeb_core};
|
||||
|
||||
// Management clock input pad
|
||||
`INPUT_PAD(clock, clock_core);
|
||||
|
||||
// Management GPIO pad
|
||||
`INOUT_PAD(
|
||||
gpio, gpio_in_core, gpio_out_core,
|
||||
gpio_inenb_core, gpio_outenb_core, dm_all);
|
||||
|
||||
// Management Flash SPI pads
|
||||
`INOUT_PAD(
|
||||
flash_io0, flash_io0_di_core, flash_io0_do_core,
|
||||
flash_io0_ieb_core, flash_io0_oeb_core, flash_io0_mode);
|
||||
`INOUT_PAD(
|
||||
flash_io1, flash_io1_di_core, flash_io1_do_core,
|
||||
flash_io1_ieb_core, flash_io1_oeb_core, flash_io1_mode);
|
||||
|
||||
`OUTPUT_PAD(flash_csb, flash_csb_core, flash_csb_ieb_core, flash_csb_oeb_core);
|
||||
`OUTPUT_PAD(flash_clk, flash_clk_core, flash_clk_ieb_core, flash_clk_oeb_core);
|
||||
|
||||
// NOTE: The analog_out pad from the raven chip has been replaced by
|
||||
// the digital reset input resetb on caravel due to the lack of an on-board
|
||||
// power-on-reset circuit. The XRES pad is used for providing a glitch-
|
||||
// free reset.
|
||||
|
||||
wire xresloop;
|
||||
sky130_fd_io__top_xres4v2 resetb_pad (
|
||||
`MGMT_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
,.PAD(resetb),
|
||||
`endif
|
||||
.TIE_WEAK_HI_H(xresloop), // Loop-back connection to pad through pad_a_esd_h
|
||||
.TIE_HI_ESD(),
|
||||
.TIE_LO_ESD(),
|
||||
.PAD_A_ESD_H(xresloop),
|
||||
.XRES_H_N(resetb_core_h),
|
||||
.DISABLE_PULLUP_H(vssio), // 0 = enable pull-up on reset pad
|
||||
.ENABLE_H(porb_h), // Power-on-reset
|
||||
.EN_VDDIO_SIG_H(vssio), // No idea.
|
||||
.INP_SEL_H(vssio), // 1 = use filt_in_h else filter the pad input
|
||||
.FILT_IN_H(vssio), // Alternate input for glitch filter
|
||||
.PULLUP_H(vssio), // Pullup connection for alternate filter input
|
||||
.ENABLE_VDDIO(vccd)
|
||||
);
|
||||
|
||||
// Corner cells (These are overlay cells; it is not clear what is normally
|
||||
// supposed to go under them.)
|
||||
|
||||
sky130_ef_io__corner_pad mgmt_corner [1:0] (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd),
|
||||
.VSSA(vssa),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda),
|
||||
.VCCD(vccd),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
|
||||
);
|
||||
sky130_ef_io__corner_pad user1_corner (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd1),
|
||||
.VSSA(vssa1),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda1),
|
||||
.VCCD(vccd1),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
);
|
||||
sky130_ef_io__corner_pad user2_corner (
|
||||
`ifndef TOP_ROUTING
|
||||
.VSSIO(vssio),
|
||||
.VDDIO(vddio),
|
||||
.VDDIO_Q(vddio_q),
|
||||
.VSSIO_Q(vssio_q),
|
||||
.AMUXBUS_A(analog_a),
|
||||
.AMUXBUS_B(analog_b),
|
||||
.VSSD(vssd2),
|
||||
.VSSA(vssa2),
|
||||
.VSWITCH(vddio),
|
||||
.VDDA(vdda2),
|
||||
.VCCD(vccd2),
|
||||
.VCCHIB(vccd)
|
||||
`else
|
||||
.VCCHIB()
|
||||
`endif
|
||||
);
|
||||
|
||||
mprj_io #(
|
||||
.AREA1PADS(`MPRJ_IO_PADS_1 - ANALOG_PADS_1),
|
||||
.TOTAL_PADS(`MPRJ_IO_PADS - ANALOG_PADS_1 - ANALOG_PADS_2)
|
||||
) mprj_pads (
|
||||
.vddio(vddio),
|
||||
.vssio(vssio),
|
||||
.vccd(vccd),
|
||||
.vssd(vssd),
|
||||
.vdda1(vdda1),
|
||||
.vdda2(vdda2),
|
||||
.vssa1(vssa1),
|
||||
.vssa2(vssa2),
|
||||
.vccd1(vccd1),
|
||||
.vccd2(vccd2),
|
||||
.vssd1(vssd1),
|
||||
.vssd2(vssd2),
|
||||
.vddio_q(vddio_q),
|
||||
.vssio_q(vssio_q),
|
||||
.analog_a(analog_a),
|
||||
.analog_b(analog_b),
|
||||
.porb_h(porb_h),
|
||||
|
||||
.io({mprj_io[`MPRJ_IO_PADS-1:`MPRJ_IO_PADS_1+ANALOG_PADS_2],
|
||||
mprj_io[`MPRJ_IO_PADS_1-ANALOG_PADS_1-1:0]}),
|
||||
.io_out(mprj_io_out),
|
||||
.oeb(mprj_io_oeb),
|
||||
.hldh_n(mprj_io_hldh_n),
|
||||
.enh(mprj_io_enh),
|
||||
.inp_dis(mprj_io_inp_dis),
|
||||
.ib_mode_sel(mprj_io_ib_mode_sel),
|
||||
.vtrip_sel(mprj_io_vtrip_sel),
|
||||
.holdover(mprj_io_holdover),
|
||||
.slow_sel(mprj_io_slow_sel),
|
||||
.analog_en(mprj_io_analog_en),
|
||||
.analog_sel(mprj_io_analog_sel),
|
||||
.analog_pol(mprj_io_analog_pol),
|
||||
.dm(mprj_io_dm),
|
||||
.io_in(mprj_io_in),
|
||||
.io_in_3v3(mprj_io_in_3v3),
|
||||
.analog_io(mprj_gpio_analog),
|
||||
.analog_noesd_io(mprj_gpio_noesd)
|
||||
);
|
||||
|
||||
endmodule
|
||||
// `default_nettype wire
|
|
@ -0,0 +1,213 @@
|
|||
// 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
|
||||
|
||||
/* Integer-N clock divider */
|
||||
`default_nettype none
|
||||
|
||||
module clock_div #(
|
||||
parameter SIZE = 3 // Number of bits for the divider value
|
||||
) (
|
||||
in, out, N, resetb
|
||||
);
|
||||
input in; // input clock
|
||||
input [SIZE-1:0] N; // the number to be divided by
|
||||
input resetb; // asynchronous reset (sense negative)
|
||||
output out; // divided output clock
|
||||
|
||||
wire out_odd; // output of odd divider
|
||||
wire out_even; // output of even divider
|
||||
wire not_zero; // signal to find divide by 0 case
|
||||
wire enable_even; // enable of even divider
|
||||
wire enable_odd; // enable of odd divider
|
||||
|
||||
reg [SIZE-1:0] syncN; // N synchronized to output clock
|
||||
reg [SIZE-1:0] syncNp; // N synchronized to output clock
|
||||
|
||||
assign not_zero = | syncN[SIZE-1:1];
|
||||
|
||||
assign out = (out_odd & syncN[0] & not_zero) | (out_even & !syncN[0]);
|
||||
assign enable_odd = syncN[0] & not_zero;
|
||||
assign enable_even = !syncN[0];
|
||||
|
||||
// Divider value synchronization (double-synchronized to avoid metastability)
|
||||
always @(posedge out or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
syncN <= `CLK_DIV; // Default to divide-by-2 on system reset
|
||||
syncNp <= `CLK_DIV; // Default to divide-by-2 on system reset
|
||||
end else begin
|
||||
syncNp <= N;
|
||||
syncN <= syncNp;
|
||||
end
|
||||
end
|
||||
|
||||
// Even divider
|
||||
even even_0(in, out_even, syncN, resetb, not_zero, enable_even);
|
||||
// Odd divider
|
||||
odd odd_0(in, out_odd, syncN, resetb, enable_odd);
|
||||
|
||||
endmodule // clock_div
|
||||
|
||||
/* Odd divider */
|
||||
|
||||
module odd #(
|
||||
parameter SIZE = 3
|
||||
) (
|
||||
clk, out, N, resetb, enable
|
||||
);
|
||||
input clk; // slow clock
|
||||
output out; // fast output clock
|
||||
input [SIZE-1:0] N; // division factor
|
||||
input resetb; // synchronous reset
|
||||
input enable; // odd enable
|
||||
|
||||
reg [SIZE-1:0] counter; // these 2 counters are used
|
||||
reg [SIZE-1:0] counter2; // to non-overlapping signals
|
||||
reg out_counter; // positive edge triggered counter
|
||||
reg out_counter2; // negative edge triggered counter
|
||||
reg rst_pulse; // pulse generated when vector N changes
|
||||
reg [SIZE-1:0] old_N; // gets set to old N when N is changed
|
||||
wire not_zero; // if !not_zero, we devide by 1
|
||||
|
||||
// xor to generate 50% duty, half-period waves of final output
|
||||
assign out = out_counter2 ^ out_counter;
|
||||
|
||||
// positive edge counter/divider
|
||||
always @(posedge clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
counter <= `CLK_DIV;
|
||||
out_counter <= 1;
|
||||
end else if (rst_pulse) begin
|
||||
counter <= N;
|
||||
out_counter <= 1;
|
||||
end else if (enable) begin
|
||||
if (counter == 1) begin
|
||||
counter <= N;
|
||||
out_counter <= ~out_counter;
|
||||
end else begin
|
||||
counter <= counter - 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg [SIZE-1:0] initial_begin; // this is used to offset the negative edge counter
|
||||
// wire [SIZE:0] interm_3; // from the positive edge counter in order to
|
||||
// assign interm_3 = {1'b0,N} + 2'b11; // guarante 50% duty cycle.
|
||||
localparam [SIZE:0] interm_3 = {1'b0,`CLK_DIV} + 2'b11;
|
||||
|
||||
// Counter driven by negative edge of clock.
|
||||
|
||||
always @(negedge clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
// reset the counter at system reset
|
||||
counter2 <= `CLK_DIV;
|
||||
initial_begin <= interm_3[SIZE:1];
|
||||
out_counter2 <= 1;
|
||||
end else if (rst_pulse) begin
|
||||
// reset the counter at change of N.
|
||||
counter2 <= N;
|
||||
initial_begin <= interm_3[SIZE:1];
|
||||
out_counter2 <= 1;
|
||||
end else if ((initial_begin <= 1) && enable) begin
|
||||
|
||||
// Do normal logic after odd calibration.
|
||||
// This is the same as the even counter.
|
||||
if (counter2 == 1) begin
|
||||
counter2 <= N;
|
||||
out_counter2 <= ~out_counter2;
|
||||
end else begin
|
||||
counter2 <= counter2 - 1'b1;
|
||||
end
|
||||
end else if (enable) begin
|
||||
initial_begin <= initial_begin - 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
//
|
||||
// reset pulse generator:
|
||||
// __ __ __ __ _
|
||||
// clk: __/ \__/ \__/ \__/ \__/
|
||||
// _ __________________________
|
||||
// N: _X__________________________
|
||||
// _____
|
||||
// rst_pulse: __/ \___________________
|
||||
//
|
||||
// This block generates an internal reset for the odd divider in the
|
||||
// form of a single pulse signal when the odd divider is enabled.
|
||||
|
||||
always @(posedge clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
rst_pulse <= 0;
|
||||
end else if (enable) begin
|
||||
if (N != old_N) begin
|
||||
// pulse when reset changes
|
||||
rst_pulse <= 1;
|
||||
end else begin
|
||||
rst_pulse <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
// always save the old N value to guarante reset from
|
||||
// an even-to-odd transition.
|
||||
old_N <= N;
|
||||
end
|
||||
|
||||
endmodule // odd
|
||||
|
||||
/* Even divider */
|
||||
|
||||
module even #(
|
||||
parameter SIZE = 3
|
||||
) (
|
||||
clk, out, N, resetb, not_zero, enable
|
||||
);
|
||||
input clk; // fast input clock
|
||||
output out; // slower divided clock
|
||||
input [SIZE-1:0] N; // divide by factor 'N'
|
||||
input resetb; // asynchronous reset
|
||||
input not_zero; // if !not_zero divide by 1
|
||||
input enable; // enable the even divider
|
||||
|
||||
reg [SIZE-1:0] counter;
|
||||
reg out_counter;
|
||||
wire [SIZE-1:0] div_2;
|
||||
|
||||
// if N=0 just output the clock, otherwise, divide it.
|
||||
assign out = (clk & !not_zero) | (out_counter & not_zero);
|
||||
assign div_2 = {1'b0, N[SIZE-1:1]};
|
||||
|
||||
// simple flip-flop even divider
|
||||
always @(posedge clk or negedge resetb) begin
|
||||
if (resetb == 1'b0) begin
|
||||
counter <= 1;
|
||||
out_counter <= 1;
|
||||
|
||||
end else if (enable) begin
|
||||
// only use switching power if enabled
|
||||
if (counter == 1) begin
|
||||
// divide after counter has reached bottom
|
||||
// of interval 'N' which will be value '1'
|
||||
counter <= div_2;
|
||||
out_counter <= ~out_counter;
|
||||
end else begin
|
||||
// decrement the counter and wait
|
||||
counter <= counter-1; // to start next transition.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule //even
|
||||
`default_nettype wire
|
|
@ -0,0 +1,64 @@
|
|||
// 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
|
||||
|
||||
`ifndef __GLOBAL_DEFINE_H
|
||||
// Global parameters
|
||||
`define __GLOBAL_DEFINE_H
|
||||
|
||||
`define MPRJ_IO_PADS_1 19 /* number of user GPIO pads on user1 side */
|
||||
`define MPRJ_IO_PADS_2 19 /* number of user GPIO pads on user2 side */
|
||||
`define MPRJ_IO_PADS (`MPRJ_IO_PADS_1 + `MPRJ_IO_PADS_2)
|
||||
|
||||
`define MPRJ_PWR_PADS_1 2 /* vdda1, vccd1 enable/disable control */
|
||||
`define MPRJ_PWR_PADS_2 2 /* vdda2, vccd2 enable/disable control */
|
||||
`define MPRJ_PWR_PADS (`MPRJ_PWR_PADS_1 + `MPRJ_PWR_PADS_2)
|
||||
|
||||
// Analog pads are only used by the "caravan" module and associated
|
||||
// modules such as user_analog_project_wrapper and chip_io_alt.
|
||||
|
||||
`define ANALOG_PADS_1 5
|
||||
`define ANALOG_PADS_2 6
|
||||
|
||||
`define ANALOG_PADS (`ANALOG_PADS_1 + `ANALOG_PADS_2)
|
||||
|
||||
// Size of soc_mem_synth
|
||||
|
||||
// Type and size of soc_mem
|
||||
// `define USE_OPENRAM
|
||||
`define USE_CUSTOM_DFFRAM
|
||||
// don't change the following without double checking addr widths
|
||||
`define MEM_WORDS 256
|
||||
|
||||
// Number of columns in the custom memory; takes one of three values:
|
||||
// 1 column : 1 KB, 2 column: 2 KB, 4 column: 4KB
|
||||
`define DFFRAM_WSIZE 4
|
||||
`define DFFRAM_USE_LATCH 0
|
||||
|
||||
// not really parameterized but just to easily keep track of the number
|
||||
// of ram_block across different modules
|
||||
`define RAM_BLOCKS 2
|
||||
|
||||
// Clock divisor default value
|
||||
`define CLK_DIV 3'b010
|
||||
|
||||
// GPIO control default mode and enable for most I/Os
|
||||
// Most I/Os set to be user bidirectional pins on power-up.
|
||||
`define MGMT_INIT 1'b0
|
||||
`define OENB_INIT 1'b0
|
||||
`define DM_INIT 3'b110
|
||||
|
||||
`endif // __GLOBAL_DEFINE_H
|
|
@ -0,0 +1,71 @@
|
|||
// 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
|
||||
// Digital PLL (ring oscillator + controller)
|
||||
// Technically this is a frequency locked loop, not a phase locked loop.
|
||||
|
||||
`include "digital_pll_controller.v"
|
||||
`include "ring_osc2x13.v"
|
||||
|
||||
module digital_pll(
|
||||
`ifdef USE_POWER_PINS
|
||||
VPWR,
|
||||
VGND,
|
||||
`endif
|
||||
resetb, enable, osc, clockp, div, dco, ext_trim);
|
||||
|
||||
`ifdef USE_POWER_PINS
|
||||
input VPWR;
|
||||
input VGND;
|
||||
`endif
|
||||
|
||||
input resetb; // Sense negative reset
|
||||
input enable; // Enable PLL
|
||||
input osc; // Input oscillator to match
|
||||
input [4:0] div; // PLL feedback division ratio
|
||||
input dco; // Run in DCO mode
|
||||
input [25:0] ext_trim; // External trim for DCO mode
|
||||
|
||||
output [1:0] clockp; // Two 90 degree clock phases
|
||||
|
||||
wire [25:0] itrim; // Internally generated trim bits
|
||||
wire [25:0] otrim; // Trim bits applied to the ring oscillator
|
||||
wire creset; // Controller reset
|
||||
wire ireset; // Internal reset (external reset OR disable)
|
||||
|
||||
assign ireset = ~resetb | ~enable;
|
||||
|
||||
// In DCO mode: Hold controller in reset and apply external trim value
|
||||
|
||||
assign itrim = (dco == 1'b0) ? otrim : ext_trim;
|
||||
assign creset = (dco == 1'b0) ? ireset : 1'b1;
|
||||
|
||||
ring_osc2x13 ringosc (
|
||||
.reset(ireset),
|
||||
.trim(itrim),
|
||||
.clockp(clockp)
|
||||
);
|
||||
|
||||
digital_pll_controller pll_control (
|
||||
.reset(creset),
|
||||
.clock(clockp[0]),
|
||||
.osc(osc),
|
||||
.div(div),
|
||||
.trim(otrim)
|
||||
);
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,136 @@
|
|||
// 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
|
||||
// (True) digital PLL
|
||||
//
|
||||
// Output goes to a trimmable ring oscillator (see documentation).
|
||||
// Ring oscillator should be trimmable to above and below maximum
|
||||
// ranges of the input.
|
||||
//
|
||||
// Input "osc" comes from a fixed clock source (e.g., crystal oscillator
|
||||
// output).
|
||||
//
|
||||
// Input "div" is the target number of clock cycles per oscillator cycle.
|
||||
// e.g., if div == 8 then this is an 8X PLL.
|
||||
//
|
||||
// Clock "clock" is the PLL output being trimmed.
|
||||
// (NOTE: To be done: Pass-through enable)
|
||||
//
|
||||
// Algorithm:
|
||||
//
|
||||
// 1) Trim is done by thermometer code. Reset to the highest value
|
||||
// in case the fastest rate clock is too fast for the logic.
|
||||
//
|
||||
// 2) Count the number of contiguous 1s and 0s in "osc"
|
||||
// periods of the master clock. If the count maxes out, it does
|
||||
// not roll over.
|
||||
//
|
||||
// 3) Add the two counts together.
|
||||
//
|
||||
// 4) If the sum is less than div, then the clock is too slow, so
|
||||
// decrease the trim code. If the sum is greater than div, the
|
||||
// clock is too fast, so increase the trim code. If the sum
|
||||
// is equal to div, the the trim code does not change.
|
||||
//
|
||||
|
||||
module digital_pll_controller(reset, clock, osc, div, trim);
|
||||
input reset;
|
||||
input clock;
|
||||
input osc;
|
||||
input [4:0] div;
|
||||
output [25:0] trim; // Use ring_osc2x13, with 26 trim bits
|
||||
|
||||
wire [25:0] trim;
|
||||
reg [2:0] oscbuf;
|
||||
reg [2:0] prep;
|
||||
|
||||
reg [4:0] count0;
|
||||
reg [4:0] count1;
|
||||
reg [6:0] tval; // Includes 2 bits fractional
|
||||
wire [4:0] tint; // Integer part of the above
|
||||
|
||||
wire [5:0] sum;
|
||||
|
||||
assign sum = count0 + count1;
|
||||
|
||||
// Integer to thermometer code (maybe there's an algorithmic way?)
|
||||
assign tint = tval[6:2];
|
||||
// |<--second-->|<-- first-->|
|
||||
assign trim = (tint == 5'd0) ? 26'b0000000000000_0000000000000 :
|
||||
(tint == 5'd1) ? 26'b0000000000000_0000000000001 :
|
||||
(tint == 5'd2) ? 26'b0000000000000_0000001000001 :
|
||||
(tint == 5'd3) ? 26'b0000000000000_0010001000001 :
|
||||
(tint == 5'd4) ? 26'b0000000000000_0010001001001 :
|
||||
(tint == 5'd5) ? 26'b0000000000000_0010101001001 :
|
||||
(tint == 5'd6) ? 26'b0000000000000_1010101001001 :
|
||||
(tint == 5'd7) ? 26'b0000000000000_1010101101001 :
|
||||
(tint == 5'd8) ? 26'b0000000000000_1010101101101 :
|
||||
(tint == 5'd9) ? 26'b0000000000000_1011101101101 :
|
||||
(tint == 5'd10) ? 26'b0000000000000_1011101111101 :
|
||||
(tint == 5'd11) ? 26'b0000000000000_1111101111101 :
|
||||
(tint == 5'd12) ? 26'b0000000000000_1111101111111 :
|
||||
(tint == 5'd13) ? 26'b0000000000000_1111111111111 :
|
||||
(tint == 5'd14) ? 26'b0000000000001_1111111111111 :
|
||||
(tint == 5'd15) ? 26'b0000001000001_1111111111111 :
|
||||
(tint == 5'd16) ? 26'b0010001000001_1111111111111 :
|
||||
(tint == 5'd17) ? 26'b0010001001001_1111111111111 :
|
||||
(tint == 5'd18) ? 26'b0010101001001_1111111111111 :
|
||||
(tint == 5'd19) ? 26'b1010101001001_1111111111111 :
|
||||
(tint == 5'd20) ? 26'b1010101101001_1111111111111 :
|
||||
(tint == 5'd21) ? 26'b1010101101101_1111111111111 :
|
||||
(tint == 5'd22) ? 26'b1011101101101_1111111111111 :
|
||||
(tint == 5'd23) ? 26'b1011101111101_1111111111111 :
|
||||
(tint == 5'd24) ? 26'b1111101111101_1111111111111 :
|
||||
(tint == 5'd25) ? 26'b1111101111111_1111111111111 :
|
||||
26'b1111111111111_1111111111111;
|
||||
|
||||
always @(posedge clock or posedge reset) begin
|
||||
if (reset == 1'b1) begin
|
||||
tval <= 7'd0; // Note: trim[0] must be zero for startup to work.
|
||||
oscbuf <= 3'd0;
|
||||
prep <= 3'd0;
|
||||
count0 <= 5'd0;
|
||||
count1 <= 5'd0;
|
||||
|
||||
end else begin
|
||||
oscbuf <= {oscbuf[1:0], osc};
|
||||
|
||||
if (oscbuf[2] != oscbuf[1]) begin
|
||||
count1 <= count0;
|
||||
count0 <= 5'b00001;
|
||||
prep <= {prep[1:0], 1'b1};
|
||||
|
||||
if (prep == 3'b111) begin
|
||||
if (sum > div) begin
|
||||
if (tval < 127) begin
|
||||
tval <= tval + 1;
|
||||
end
|
||||
end else if (sum < div) begin
|
||||
if (tval > 0) begin
|
||||
tval <= tval - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
if (count0 != 5'b11111) begin
|
||||
count0 <= count0 + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule // digital_pll_controller
|
||||
`default_nettype wire
|
|
@ -0,0 +1,279 @@
|
|||
// 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
|
||||
/*
|
||||
*---------------------------------------------------------------------
|
||||
* See gpio_control_block for description. This module is like
|
||||
* gpio_contro_block except that it has an additional two management-
|
||||
* Soc-facing pins, which are the out_enb line and the output line.
|
||||
* If the chip is configured for output with the oeb control
|
||||
* register = 1, then the oeb line is controlled by the additional
|
||||
* signal from the management SoC. If the oeb control register = 0,
|
||||
* then the output is disabled completely. The "io" line is input
|
||||
* only in this module.
|
||||
*
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------
|
||||
*
|
||||
* This module instantiates a shift register chain that passes through
|
||||
* each gpio cell. These are connected end-to-end around the padframe
|
||||
* periphery. The purpose is to avoid a massive number of control
|
||||
* wires between the digital core and I/O, passing through the user area.
|
||||
*
|
||||
* See mprj_ctrl.v for the module that registers the data for each
|
||||
* I/O and drives the input to the shift register.
|
||||
*
|
||||
*---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
module gpio_control_block #(
|
||||
parameter PAD_CTRL_BITS = 13,
|
||||
// Parameterized initial startup state of the pad.
|
||||
// The default parameters if unspecified is for the pad to be
|
||||
// an input with no pull-up or pull-down, so that it is disconnected
|
||||
// from the outside world.
|
||||
parameter MGMT_INIT = 1'b1,
|
||||
parameter HOLD_INIT = 1'b0,
|
||||
parameter SLOW_INIT = 1'b0,
|
||||
parameter TRIP_INIT = 1'b0,
|
||||
parameter IB_INIT = 1'b0,
|
||||
parameter IENB_INIT = 1'b0,
|
||||
parameter OENB_INIT = `OENB_INIT,
|
||||
parameter DM_INIT = `DM_INIT,
|
||||
parameter AENA_INIT = 1'b0,
|
||||
parameter ASEL_INIT = 1'b0,
|
||||
parameter APOL_INIT = 1'b0
|
||||
) (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd,
|
||||
inout vssd,
|
||||
inout vccd1,
|
||||
inout vssd1,
|
||||
`endif
|
||||
|
||||
// Management Soc-facing signals
|
||||
input resetn, // Global reset, locally propagated
|
||||
output resetn_out,
|
||||
input serial_clock, // Global clock, locally propatated
|
||||
output serial_clock_out,
|
||||
|
||||
output mgmt_gpio_in, // Management from pad (input only)
|
||||
input mgmt_gpio_out, // Management to pad (output only)
|
||||
input mgmt_gpio_oeb, // Management to pad (output only)
|
||||
|
||||
// Serial data chain for pad configuration
|
||||
input serial_data_in,
|
||||
output serial_data_out,
|
||||
|
||||
// User-facing signals
|
||||
input user_gpio_out, // User space to pad
|
||||
input user_gpio_oeb, // Output enable (user)
|
||||
output user_gpio_in, // Pad to user space
|
||||
|
||||
// Pad-facing signals (Pad GPIOv2)
|
||||
output pad_gpio_holdover,
|
||||
output pad_gpio_slow_sel,
|
||||
output pad_gpio_vtrip_sel,
|
||||
output pad_gpio_inenb,
|
||||
output pad_gpio_ib_mode_sel,
|
||||
output pad_gpio_ana_en,
|
||||
output pad_gpio_ana_sel,
|
||||
output pad_gpio_ana_pol,
|
||||
output [2:0] pad_gpio_dm,
|
||||
output pad_gpio_outenb,
|
||||
output pad_gpio_out,
|
||||
input pad_gpio_in,
|
||||
|
||||
// to provide a way to automatically disable/enable output
|
||||
// from the outside with needing a conb cell
|
||||
output one,
|
||||
output zero
|
||||
);
|
||||
|
||||
/* Parameters defining the bit offset of each function in the chain */
|
||||
localparam MGMT_EN = 0;
|
||||
localparam OEB = 1;
|
||||
localparam HLDH = 2;
|
||||
localparam INP_DIS = 3;
|
||||
localparam MOD_SEL = 4;
|
||||
localparam AN_EN = 5;
|
||||
localparam AN_SEL = 6;
|
||||
localparam AN_POL = 7;
|
||||
localparam SLOW = 8;
|
||||
localparam TRIP = 9;
|
||||
localparam DM = 10;
|
||||
|
||||
/* Internally registered signals */
|
||||
reg mgmt_ena; // Enable management SoC to access pad
|
||||
reg gpio_holdover;
|
||||
reg gpio_slow_sel;
|
||||
reg gpio_vtrip_sel;
|
||||
reg gpio_inenb;
|
||||
reg gpio_ib_mode_sel;
|
||||
reg gpio_outenb;
|
||||
reg [2:0] gpio_dm;
|
||||
reg gpio_ana_en;
|
||||
reg gpio_ana_sel;
|
||||
reg gpio_ana_pol;
|
||||
|
||||
/* Derived output values */
|
||||
wire pad_gpio_holdover;
|
||||
wire pad_gpio_slow_sel;
|
||||
wire pad_gpio_vtrip_sel;
|
||||
wire pad_gpio_inenb;
|
||||
wire pad_gpio_ib_mode_sel;
|
||||
wire pad_gpio_ana_en;
|
||||
wire pad_gpio_ana_sel;
|
||||
wire pad_gpio_ana_pol;
|
||||
wire [2:0] pad_gpio_dm;
|
||||
wire pad_gpio_outenb;
|
||||
wire pad_gpio_out;
|
||||
wire pad_gpio_in;
|
||||
wire one;
|
||||
wire zero;
|
||||
|
||||
wire user_gpio_in;
|
||||
wire gpio_in_unbuf;
|
||||
wire gpio_logic1;
|
||||
|
||||
/* Serial shift for the above (latched) values */
|
||||
reg [PAD_CTRL_BITS-1:0] shift_register;
|
||||
|
||||
/* Utilize reset and clock to encode a load operation */
|
||||
wire load_data;
|
||||
wire int_reset;
|
||||
|
||||
/* Create internal reset and load signals from input reset and clock */
|
||||
assign serial_data_out = shift_register[PAD_CTRL_BITS-1];
|
||||
assign int_reset = (~resetn) & (~serial_clock);
|
||||
assign load_data = (~resetn) & serial_clock;
|
||||
|
||||
/* Propagate the clock and reset signals so that they aren't wired */
|
||||
/* all over the chip, but are just wired between the blocks. */
|
||||
assign serial_clock_out = serial_clock;
|
||||
assign resetn_out = resetn;
|
||||
|
||||
always @(posedge serial_clock or posedge int_reset) begin
|
||||
if (int_reset == 1'b1) begin
|
||||
/* Clear shift register */
|
||||
shift_register <= 'd0;
|
||||
end else begin
|
||||
/* Shift data in */
|
||||
shift_register <= {shift_register[PAD_CTRL_BITS-2:0], serial_data_in};
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge load_data or posedge int_reset) begin
|
||||
if (int_reset == 1'b1) begin
|
||||
/* Initial state on reset: Pad set to management input */
|
||||
mgmt_ena <= MGMT_INIT; // Management SoC has control over all I/O
|
||||
gpio_holdover <= HOLD_INIT; // All signals latched in hold mode
|
||||
gpio_slow_sel <= SLOW_INIT; // Fast slew rate
|
||||
gpio_vtrip_sel <= TRIP_INIT; // CMOS mode
|
||||
gpio_ib_mode_sel <= IB_INIT; // CMOS mode
|
||||
gpio_inenb <= IENB_INIT; // Input enabled
|
||||
gpio_outenb <= OENB_INIT; // (unused placeholder)
|
||||
gpio_dm <= DM_INIT; // Configured as input only
|
||||
gpio_ana_en <= AENA_INIT; // Digital enabled
|
||||
gpio_ana_sel <= ASEL_INIT; // Don't-care when gpio_ana_en = 0
|
||||
gpio_ana_pol <= APOL_INIT; // Don't-care when gpio_ana_en = 0
|
||||
end else begin
|
||||
/* Load data */
|
||||
mgmt_ena <= shift_register[MGMT_EN];
|
||||
gpio_outenb <= shift_register[OEB];
|
||||
gpio_holdover <= shift_register[HLDH];
|
||||
gpio_inenb <= shift_register[INP_DIS];
|
||||
gpio_ib_mode_sel <= shift_register[MOD_SEL];
|
||||
gpio_ana_en <= shift_register[AN_EN];
|
||||
gpio_ana_sel <= shift_register[AN_SEL];
|
||||
gpio_ana_pol <= shift_register[AN_POL];
|
||||
gpio_slow_sel <= shift_register[SLOW];
|
||||
gpio_vtrip_sel <= shift_register[TRIP];
|
||||
gpio_dm <= shift_register[DM+2:DM];
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
/* These pad configuration signals are static and do not change */
|
||||
/* after setup. */
|
||||
|
||||
assign pad_gpio_holdover = gpio_holdover;
|
||||
assign pad_gpio_slow_sel = gpio_slow_sel;
|
||||
assign pad_gpio_vtrip_sel = gpio_vtrip_sel;
|
||||
assign pad_gpio_ib_mode_sel = gpio_ib_mode_sel;
|
||||
assign pad_gpio_ana_en = gpio_ana_en;
|
||||
assign pad_gpio_ana_sel = gpio_ana_sel;
|
||||
assign pad_gpio_ana_pol = gpio_ana_pol;
|
||||
assign pad_gpio_dm = gpio_dm;
|
||||
assign pad_gpio_inenb = gpio_inenb;
|
||||
|
||||
/* Implement pad control behavior depending on state of mgmt_ena */
|
||||
|
||||
// assign gpio_in_unbuf = (mgmt_ena) ? 1'b0 : pad_gpio_in;
|
||||
// assign mgmt_gpio_in = (mgmt_ena) ? ((gpio_inenb == 1'b0) ?
|
||||
// pad_gpio_in : 1'bz) : 1'b0;
|
||||
|
||||
assign gpio_in_unbuf = pad_gpio_in;
|
||||
// This causes conflict if output and input drivers are both enabled. . .
|
||||
// assign mgmt_gpio_in = (gpio_inenb == 1'b0) ? pad_gpio_in : 1'bz;
|
||||
assign mgmt_gpio_in = (gpio_inenb == 1'b0 && gpio_outenb == 1'b1)? pad_gpio_in : 1'bz;
|
||||
|
||||
assign pad_gpio_outenb = (mgmt_ena) ? ((mgmt_gpio_oeb == 1'b1) ? gpio_outenb :
|
||||
1'b0) : user_gpio_oeb;
|
||||
assign pad_gpio_out = (mgmt_ena) ?
|
||||
((mgmt_gpio_oeb == 1'b1) ?
|
||||
((gpio_dm[2:1] == 2'b01) ? ~gpio_dm[0] : mgmt_gpio_out) :
|
||||
mgmt_gpio_out) :
|
||||
user_gpio_out;
|
||||
|
||||
/* Buffer user_gpio_in with an enable that is set by the user domain vccd */
|
||||
|
||||
gpio_logic_high gpio_logic_high (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd1(vccd1),
|
||||
.vssd1(vssd1),
|
||||
`endif
|
||||
.gpio_logic1(gpio_logic1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 gpio_in_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(user_gpio_in),
|
||||
.A(~gpio_in_unbuf),
|
||||
.TE(gpio_logic1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__conb_1 const_source (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.HI(one),
|
||||
.LO(zero)
|
||||
);
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,21 @@
|
|||
module gpio_logic_high(
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd1,
|
||||
inout vssd1,
|
||||
`endif
|
||||
|
||||
output wire gpio_logic1
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__conb_1 gpio_logic_high (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd1),
|
||||
.VGND(vssd1),
|
||||
.VPB(vccd1),
|
||||
.VNB(vssd1),
|
||||
`endif
|
||||
.HI(gpio_logic1),
|
||||
.LO()
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,558 @@
|
|||
// 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
|
||||
//-------------------------------------
|
||||
// SPI controller for Caravel (PicoSoC)
|
||||
//-------------------------------------
|
||||
// Written by Tim Edwards
|
||||
// efabless, inc. September 27, 2020
|
||||
//-------------------------------------
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// This is a standalone slave SPI for the caravel chip that is
|
||||
// intended to be independent of the picosoc and independent
|
||||
// of all IP blocks except the power-on-reset. This SPI has
|
||||
// register outputs controlling the functions that critically
|
||||
// affect operation of the picosoc and so cannot be accessed
|
||||
// from the picosoc itself. This includes the PLL enables
|
||||
// and trim, and the crystal oscillator enable. It also has
|
||||
// a general reset for the picosoc, an IRQ input, a bypass for
|
||||
// the entire crystal oscillator and PLL chain, the
|
||||
// manufacturer and product IDs and product revision number.
|
||||
// To be independent of the 1.8V regulator, the slave SPI is
|
||||
// synthesized with the 3V digital library and runs off of
|
||||
// the 3V supply.
|
||||
//
|
||||
// This module is designed to be decoupled from the chip
|
||||
// padframe and redirected to the wishbone bus under
|
||||
// register control from the management SoC, such that the
|
||||
// contents can be accessed from the management core via the
|
||||
// SPI master.
|
||||
//
|
||||
//-----------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Caravel defined registers:
|
||||
// Register 0: SPI status and control (unused & reserved)
|
||||
// Register 1 and 2: Manufacturer ID (0x0456) (readonly)
|
||||
// Register 3: Product ID (= 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_slave.v
|
||||
//------------------------------------------------------
|
||||
// General purpose SPI slave module for the Caravel chip
|
||||
//------------------------------------------------------
|
||||
// Written by Tim Edwards
|
||||
// efabless, inc., September 28, 2020
|
||||
//------------------------------------------------
|
||||
// This file is distributed free and open source
|
||||
//------------------------------------------------
|
||||
|
||||
// SCK --- Clock input
|
||||
// SDI --- Data input
|
||||
// SDO --- Data output
|
||||
// CSB --- Chip select (sense negative)
|
||||
// idata --- Data from chip to transmit out, in 8 bits
|
||||
// odata --- Input data to chip, in 8 bits
|
||||
// addr --- Decoded address to upstream circuits
|
||||
// rdstb --- Read strobe, tells upstream circuit to supply next byte to idata
|
||||
// wrstb --- Write strobe, tells upstream circuit to latch odata.
|
||||
|
||||
// Data format (general purpose):
|
||||
// 8 bit format
|
||||
// 1st byte: Command word (see below)
|
||||
// 2nd byte: Address word (register 0 to 255)
|
||||
// 3rd byte: Data word (value 0 to 255)
|
||||
|
||||
// Command format:
|
||||
// 00000000 No operation
|
||||
// 10000000 Write until CSB raised
|
||||
// 01000000 Read until CSB raised
|
||||
// 11000000 Simultaneous read/write until CSB raised
|
||||
// 11000100 Pass-through read/write to management area flash SPI until CSB raised
|
||||
// 11000010 Pass-through read/write to user area flash SPI until CSB raised
|
||||
// wrnnn000 Read/write as above, for nnn = 1 to 7 bytes, then terminate
|
||||
|
||||
// Lower three bits are reserved for future use.
|
||||
// All serial bytes are read and written msb first.
|
||||
|
||||
// Fixed control and status registers
|
||||
|
||||
// Address 0 is reserved and contains flags for SPI mode. This is
|
||||
// currently undefined and is always value 0.
|
||||
// Address 1 is reserved and contains manufacturer ID low 8 bits.
|
||||
// Address 2 is reserved and contains manufacturer ID high 4 bits.
|
||||
// Address 3 is reserved and contains product ID (8 bits).
|
||||
// Addresses 4 to 7 are reserved and contain the mask ID (32 bits).
|
||||
// Addresses 8 to 255 are available for general purpose use.
|
||||
|
||||
`define COMMAND 3'b000
|
||||
`define ADDRESS 3'b001
|
||||
`define DATA 3'b010
|
||||
`define USERPASS 3'b100
|
||||
`define MGMTPASS 3'b101
|
||||
|
||||
module housekeeping_spi_slave(reset, SCK, SDI, CSB, SDO,
|
||||
sdoenb, idata, odata, oaddr, rdstb, wrstb,
|
||||
pass_thru_mgmt, pass_thru_mgmt_delay,
|
||||
pass_thru_user, pass_thru_user_delay,
|
||||
pass_thru_mgmt_reset, pass_thru_user_reset);
|
||||
|
||||
input reset;
|
||||
input SCK;
|
||||
input SDI;
|
||||
input CSB;
|
||||
output SDO;
|
||||
output sdoenb;
|
||||
input [7:0] idata;
|
||||
output [7:0] odata;
|
||||
output [7:0] oaddr;
|
||||
output rdstb;
|
||||
output wrstb;
|
||||
output pass_thru_mgmt;
|
||||
output pass_thru_mgmt_delay;
|
||||
output pass_thru_user;
|
||||
output pass_thru_user_delay;
|
||||
output pass_thru_mgmt_reset;
|
||||
output pass_thru_user_reset;
|
||||
|
||||
reg [7:0] addr;
|
||||
reg wrstb;
|
||||
reg rdstb;
|
||||
reg sdoenb;
|
||||
reg [2:0] state;
|
||||
reg [2:0] count;
|
||||
reg writemode;
|
||||
reg readmode;
|
||||
reg [2:0] fixed;
|
||||
wire [7:0] odata;
|
||||
reg [6:0] predata;
|
||||
wire [7:0] oaddr;
|
||||
reg [7:0] ldata;
|
||||
reg pass_thru_mgmt;
|
||||
reg pass_thru_mgmt_delay;
|
||||
reg pre_pass_thru_mgmt;
|
||||
reg pass_thru_user;
|
||||
reg pass_thru_user_delay;
|
||||
reg pre_pass_thru_user;
|
||||
wire csb_reset;
|
||||
|
||||
assign odata = {predata, SDI};
|
||||
assign oaddr = (state == `ADDRESS) ? {addr[6:0], SDI} : addr;
|
||||
assign SDO = ldata[7];
|
||||
assign csb_reset = CSB | reset;
|
||||
assign pass_thru_mgmt_reset = pass_thru_mgmt_delay | pre_pass_thru_mgmt;
|
||||
assign pass_thru_user_reset = pass_thru_user_delay | pre_pass_thru_user;
|
||||
|
||||
// Readback data is captured on the falling edge of SCK so that
|
||||
// it is guaranteed valid at the next rising edge.
|
||||
always @(negedge SCK or posedge csb_reset) begin
|
||||
if (csb_reset == 1'b1) begin
|
||||
wrstb <= 1'b0;
|
||||
ldata <= 8'b00000000;
|
||||
sdoenb <= 1'b1;
|
||||
end else begin
|
||||
|
||||
// After CSB low, 1st SCK starts command
|
||||
|
||||
if (state == `DATA) begin
|
||||
if (readmode == 1'b1) begin
|
||||
sdoenb <= 1'b0;
|
||||
if (count == 3'b000) begin
|
||||
ldata <= idata;
|
||||
end else begin
|
||||
ldata <= {ldata[6:0], 1'b0}; // Shift out
|
||||
end
|
||||
end else begin
|
||||
sdoenb <= 1'b1;
|
||||
end
|
||||
|
||||
// Apply write strobe on SCK negative edge on the next-to-last
|
||||
// data bit so that it updates data on the rising edge of SCK
|
||||
// on the last data bit.
|
||||
|
||||
if (count == 3'b111) begin
|
||||
if (writemode == 1'b1) begin
|
||||
wrstb <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
wrstb <= 1'b0;
|
||||
end
|
||||
end else if (state == `MGMTPASS || state == `USERPASS) begin
|
||||
wrstb <= 1'b0;
|
||||
sdoenb <= 1'b0;
|
||||
end else begin
|
||||
wrstb <= 1'b0;
|
||||
sdoenb <= 1'b1;
|
||||
end // ! state `DATA
|
||||
end // ! csb_reset
|
||||
end // always @ ~SCK
|
||||
|
||||
always @(posedge SCK or posedge csb_reset) begin
|
||||
if (csb_reset == 1'b1) begin
|
||||
// Default state on reset
|
||||
addr <= 8'h00;
|
||||
rdstb <= 1'b0;
|
||||
predata <= 7'b0000000;
|
||||
state <= `COMMAND;
|
||||
count <= 3'b000;
|
||||
readmode <= 1'b0;
|
||||
writemode <= 1'b0;
|
||||
fixed <= 3'b000;
|
||||
pass_thru_mgmt <= 1'b0;
|
||||
pass_thru_mgmt_delay <= 1'b0;
|
||||
pre_pass_thru_mgmt <= 1'b0;
|
||||
pass_thru_user = 1'b0;
|
||||
pass_thru_user_delay <= 1'b0;
|
||||
pre_pass_thru_user <= 1'b0;
|
||||
end else begin
|
||||
// After csb_reset low, 1st SCK starts command
|
||||
if (state == `COMMAND) begin
|
||||
rdstb <= 1'b0;
|
||||
count <= count + 1;
|
||||
if (count == 3'b000) begin
|
||||
writemode <= SDI;
|
||||
end else if (count == 3'b001) begin
|
||||
readmode <= SDI;
|
||||
end else if (count < 3'b101) begin
|
||||
fixed <= {fixed[1:0], SDI};
|
||||
end else if (count == 3'b101) begin
|
||||
pre_pass_thru_mgmt <= SDI;
|
||||
end else if (count == 3'b110) begin
|
||||
pre_pass_thru_user <= SDI;
|
||||
pass_thru_mgmt_delay <= pre_pass_thru_mgmt;
|
||||
end else if (count == 3'b111) begin
|
||||
pass_thru_user_delay <= pre_pass_thru_user;
|
||||
if (pre_pass_thru_mgmt == 1'b1) begin
|
||||
state <= `MGMTPASS;
|
||||
pre_pass_thru_mgmt <= 1'b0;
|
||||
end else if (pre_pass_thru_user == 1'b1) begin
|
||||
state <= `USERPASS;
|
||||
pre_pass_thru_user <= 1'b0;
|
||||
end else begin
|
||||
state <= `ADDRESS;
|
||||
end
|
||||
end
|
||||
end else if (state == `ADDRESS) begin
|
||||
count <= count + 1;
|
||||
addr <= {addr[6:0], SDI};
|
||||
if (count == 3'b111) begin
|
||||
if (readmode == 1'b1) begin
|
||||
rdstb <= 1'b1;
|
||||
end
|
||||
state <= `DATA;
|
||||
end else begin
|
||||
rdstb <= 1'b0;
|
||||
end
|
||||
end else if (state == `DATA) begin
|
||||
predata <= {predata[6:0], SDI};
|
||||
count <= count + 1;
|
||||
if (count == 3'b111) begin
|
||||
if (fixed == 3'b001) begin
|
||||
state <= `COMMAND;
|
||||
end else if (fixed != 3'b000) begin
|
||||
fixed <= fixed - 1;
|
||||
addr <= addr + 1; // Auto increment address (fixed)
|
||||
end else begin
|
||||
addr <= addr + 1; // Auto increment address (streaming)
|
||||
end
|
||||
end else begin
|
||||
rdstb <= 1'b0;
|
||||
end
|
||||
end else if (state == `MGMTPASS) begin
|
||||
pass_thru_mgmt <= 1'b1;
|
||||
end else if (state == `USERPASS) begin
|
||||
pass_thru_user <= 1'b1;
|
||||
end // ! state `DATA | `MGMTPASS | `USERPASS
|
||||
end // ! csb_reset
|
||||
end // always @ SCK
|
||||
|
||||
endmodule // housekeeping_spi_slave
|
||||
`default_nettype wire
|
|
@ -0,0 +1,305 @@
|
|||
// 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
|
|
@ -0,0 +1,422 @@
|
|||
// 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
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Buffers protecting the management region from the user region. */
|
||||
/* This mainly consists of tristate buffers that are enabled by a */
|
||||
/* "logic 1" output connected to the user's VCCD domain. This ensures */
|
||||
/* that the buffer is disabled and the output high-impedence when the */
|
||||
/* user 1.8V supply is absent. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* Because there is no tristate buffer with a non-inverted enable, a */
|
||||
/* tristate inverter with non-inverted enable is used in series with */
|
||||
/* another (normal) inverter. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* For the sake of placement/routing, one conb (logic 1) cell is used */
|
||||
/* for every buffer. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
module mgmt_protect (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd,
|
||||
inout vssd,
|
||||
inout vccd1,
|
||||
inout vssd1,
|
||||
inout vccd2,
|
||||
inout vssd2,
|
||||
inout vdda1,
|
||||
inout vssa1,
|
||||
inout vdda2,
|
||||
inout vssa2,
|
||||
`endif
|
||||
|
||||
input caravel_clk,
|
||||
input caravel_clk2,
|
||||
input caravel_rstn,
|
||||
input mprj_cyc_o_core,
|
||||
input mprj_stb_o_core,
|
||||
input mprj_we_o_core,
|
||||
input [3:0] mprj_sel_o_core,
|
||||
input [31:0] mprj_adr_o_core,
|
||||
input [31:0] mprj_dat_o_core,
|
||||
input [2:0] user_irq_core,
|
||||
|
||||
// All signal in/out directions are the reverse of the signal
|
||||
// names at the buffer intrface.
|
||||
|
||||
output [127:0] la_data_in_mprj,
|
||||
input [127:0] la_data_out_mprj,
|
||||
input [127:0] la_oenb_mprj,
|
||||
input [127:0] la_iena_mprj,
|
||||
|
||||
input [127:0] la_data_out_core,
|
||||
output [127:0] la_data_in_core,
|
||||
output [127:0] la_oenb_core,
|
||||
|
||||
input [2:0] user_irq_ena,
|
||||
|
||||
output user_clock,
|
||||
output user_clock2,
|
||||
output user_reset,
|
||||
output mprj_cyc_o_user,
|
||||
output mprj_stb_o_user,
|
||||
output mprj_we_o_user,
|
||||
output [3:0] mprj_sel_o_user,
|
||||
output [31:0] mprj_adr_o_user,
|
||||
output [31:0] mprj_dat_o_user,
|
||||
output [2:0] user_irq,
|
||||
output user1_vcc_powergood,
|
||||
output user2_vcc_powergood,
|
||||
output user1_vdd_powergood,
|
||||
output user2_vdd_powergood
|
||||
);
|
||||
|
||||
wire [461:0] mprj_logic1;
|
||||
wire mprj2_logic1;
|
||||
|
||||
wire mprj_vdd_logic1_h;
|
||||
wire mprj2_vdd_logic1_h;
|
||||
wire mprj_vdd_logic1;
|
||||
wire mprj2_vdd_logic1;
|
||||
|
||||
wire user1_vcc_powergood;
|
||||
wire user2_vcc_powergood;
|
||||
wire user1_vdd_powergood;
|
||||
wire user2_vdd_powergood;
|
||||
|
||||
wire [127:0] la_data_in_mprj_bar;
|
||||
wire [2:0] user_irq_bar;
|
||||
|
||||
wire [127:0] la_data_in_enable;
|
||||
wire [127:0] la_data_out_enable;
|
||||
wire [2:0] user_irq_enable;
|
||||
|
||||
mprj_logic_high mprj_logic_high_inst (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd1(vccd1),
|
||||
.vssd1(vssd1),
|
||||
`endif
|
||||
.HI(mprj_logic1)
|
||||
);
|
||||
|
||||
mprj2_logic_high mprj2_logic_high_inst (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd2(vccd2),
|
||||
.vssd2(vssd2),
|
||||
`endif
|
||||
.HI(mprj2_logic1)
|
||||
);
|
||||
|
||||
// Logic high in the VDDA (3.3V) domains
|
||||
|
||||
mgmt_protect_hv powergood_check (
|
||||
`ifdef USE_POWER_PINS
|
||||
.vccd(vccd),
|
||||
.vssd(vssd),
|
||||
.vdda1(vdda1),
|
||||
.vssa1(vssa1),
|
||||
.vdda2(vdda2),
|
||||
.vssa2(vssa2),
|
||||
`endif
|
||||
.mprj_vdd_logic1(mprj_vdd_logic1),
|
||||
.mprj2_vdd_logic1(mprj2_vdd_logic1)
|
||||
);
|
||||
|
||||
// Buffering from the user side to the management side.
|
||||
// NOTE: This is intended to be better protected, by a full
|
||||
// chain of an lv-to-hv buffer followed by an hv-to-lv buffer.
|
||||
// This serves as a placeholder until that configuration is
|
||||
// checked and characterized. The function below forces the
|
||||
// data input to the management core to be a solid logic 0 when
|
||||
// the user project is powered down.
|
||||
|
||||
sky130_fd_sc_hd__and2_1 user_to_mprj_in_ena_buf [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.X(la_data_in_enable),
|
||||
.A(la_iena_mprj),
|
||||
.B(mprj_logic1[457:330])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__nand2_4 user_to_mprj_in_gates [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Y(la_data_in_mprj_bar),
|
||||
.A(la_data_out_core),
|
||||
.B(la_data_in_enable)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__inv_8 user_to_mprj_in_buffers [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Y(la_data_in_mprj),
|
||||
.A(la_data_in_mprj_bar)
|
||||
);
|
||||
|
||||
// Protection, similar to the above, for the three user IRQ lines
|
||||
|
||||
sky130_fd_sc_hd__and2_1 user_irq_ena_buf [2:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.X(user_irq_enable),
|
||||
.A(user_irq_ena),
|
||||
.B(mprj_logic1[460:458])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__nand2_4 user_irq_gates [2:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Y(user_irq_bar),
|
||||
.A(user_irq_core),
|
||||
.B(user_irq_enable)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__inv_8 user_irq_buffers [2:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Y(user_irq),
|
||||
.A(user_irq_bar)
|
||||
);
|
||||
|
||||
// The remaining circuitry guards against the management
|
||||
// SoC dumping current into the user project area when
|
||||
// the user project area is powered down.
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_rstn_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(user_reset),
|
||||
.A(caravel_rstn),
|
||||
.TE(mprj_logic1[0])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_clk_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(user_clock),
|
||||
.A(~caravel_clk),
|
||||
.TE(mprj_logic1[1])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_clk2_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(user_clock2),
|
||||
.A(~caravel_clk2),
|
||||
.TE(mprj_logic1[2])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_cyc_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_cyc_o_user),
|
||||
.A(~mprj_cyc_o_core),
|
||||
.TE(mprj_logic1[3])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_stb_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_stb_o_user),
|
||||
.A(~mprj_stb_o_core),
|
||||
.TE(mprj_logic1[4])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_we_buf (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_we_o_user),
|
||||
.A(~mprj_we_o_core),
|
||||
.TE(mprj_logic1[5])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_sel_buf [3:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_sel_o_user),
|
||||
.A(~mprj_sel_o_core),
|
||||
.TE(mprj_logic1[9:6])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_adr_buf [31:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_adr_o_user),
|
||||
.A(~mprj_adr_o_core),
|
||||
.TE(mprj_logic1[41:10])
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 mprj_dat_buf [31:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(mprj_dat_o_user),
|
||||
.A(~mprj_dat_o_core),
|
||||
.TE(mprj_logic1[73:42])
|
||||
);
|
||||
|
||||
/* Create signal to tristate the outputs to the user project */
|
||||
|
||||
sky130_fd_sc_hd__and2b_1 la_buf_enable [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.X(la_data_out_enable),
|
||||
.A_N(la_oenb_mprj),
|
||||
.B(mprj_logic1[201:74])
|
||||
);
|
||||
|
||||
/* Project data out from the managment side to the user project */
|
||||
/* area when the user project is powered down. */
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 la_buf [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(la_data_in_core),
|
||||
.A(~la_data_out_mprj),
|
||||
.TE(la_data_out_enable)
|
||||
);
|
||||
|
||||
/* Project data out enable (bar) from the managment side to the */
|
||||
/* user project area when the user project is powered down. */
|
||||
|
||||
sky130_fd_sc_hd__einvp_8 user_to_mprj_oen_buffers [127:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.Z(la_oenb_core),
|
||||
.A(~la_oenb_mprj),
|
||||
.TE(mprj_logic1[329:202])
|
||||
);
|
||||
|
||||
/* The conb cell output is a resistive connection directly to */
|
||||
/* the power supply, so when returning the user1_powergood */
|
||||
/* signal, make sure that it is buffered properly. */
|
||||
|
||||
sky130_fd_sc_hd__buf_8 mprj_pwrgood (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.A(mprj_logic1[461]),
|
||||
.X(user1_vcc_powergood)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__buf_8 mprj2_pwrgood (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.A(mprj2_logic1),
|
||||
.X(user2_vcc_powergood)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__buf_8 mprj_vdd_pwrgood (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.A(mprj_vdd_logic1),
|
||||
.X(user1_vdd_powergood)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__buf_8 mprj2_vdd_pwrgood (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd),
|
||||
.VGND(vssd),
|
||||
.VPB(vccd),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.A(mprj2_vdd_logic1),
|
||||
.X(user2_vdd_powergood)
|
||||
);
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,103 @@
|
|||
// 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
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* mgmt_protect_hv: */
|
||||
/* */
|
||||
/* High voltage (3.3V) part of the mgmt_protect module. Split out into */
|
||||
/* a separate module and file so that the synthesis tools can handle it */
|
||||
/* separately from the rest, since it uses a different standard cell */
|
||||
/* library. See the file mgmt_protect.v for a full description of the */
|
||||
/* whole management protection method. */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
module mgmt_protect_hv (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd,
|
||||
inout vssd,
|
||||
inout vdda1,
|
||||
inout vssa1,
|
||||
inout vdda2,
|
||||
inout vssa2,
|
||||
`endif
|
||||
|
||||
output mprj_vdd_logic1,
|
||||
output mprj2_vdd_logic1
|
||||
|
||||
);
|
||||
|
||||
wire mprj_vdd_logic1_h;
|
||||
wire mprj2_vdd_logic1_h;
|
||||
|
||||
`ifdef USE_POWER_PINS
|
||||
// This is to emulate the substrate shorting grounds together for LVS
|
||||
// purposes
|
||||
assign vssa2 = vssa1;
|
||||
assign vssa1 = vssd;
|
||||
`endif
|
||||
|
||||
// Logic high in the VDDA (3.3V) domains
|
||||
|
||||
sky130_fd_sc_hvl__conb_1 mprj_logic_high_hvl (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdda1),
|
||||
.VGND(vssa1),
|
||||
.VPB(vdda1),
|
||||
.VNB(vssa1),
|
||||
`endif
|
||||
.HI(mprj_vdd_logic1_h),
|
||||
.LO()
|
||||
);
|
||||
|
||||
sky130_fd_sc_hvl__conb_1 mprj2_logic_high_hvl (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdda2),
|
||||
.VGND(vssa2),
|
||||
.VPB(vdda2),
|
||||
.VNB(vssa2),
|
||||
`endif
|
||||
.HI(mprj2_vdd_logic1_h),
|
||||
.LO()
|
||||
);
|
||||
|
||||
// Level shift the logic high signals into the 1.8V domain
|
||||
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1 mprj_logic_high_lv (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdda1),
|
||||
.VGND(vssd),
|
||||
.LVPWR(vccd),
|
||||
.VPB(vdda1),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.X(mprj_vdd_logic1),
|
||||
.A(mprj_vdd_logic1_h)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1 mprj2_logic_high_lv (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdda2),
|
||||
.VGND(vssd),
|
||||
.LVPWR(vccd),
|
||||
.VPB(vdda2),
|
||||
.VNB(vssd),
|
||||
`endif
|
||||
.X(mprj2_vdd_logic1),
|
||||
.A(mprj2_vdd_logic1_h)
|
||||
);
|
||||
endmodule
|
||||
|
||||
`default_nettype wire
|
|
@ -0,0 +1,33 @@
|
|||
// 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
|
||||
|
||||
module mprj2_logic_high (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd2,
|
||||
inout vssd2,
|
||||
`endif
|
||||
output HI
|
||||
);
|
||||
sky130_fd_sc_hd__conb_1 inst (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd2),
|
||||
.VGND(vssd2),
|
||||
.VPB(vccd2),
|
||||
.VNB(vssd2),
|
||||
`endif
|
||||
.HI(HI),
|
||||
.LO()
|
||||
);
|
||||
endmodule
|
|
@ -0,0 +1,462 @@
|
|||
// 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
|
|
@ -0,0 +1,138 @@
|
|||
// 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
|
||||
|
||||
/* Define the array of GPIO pads. Note that the analog project support
|
||||
* version of caravel (caravan) defines fewer GPIO and replaces them
|
||||
* with analog in the chip_io_alt module. Because the pad signalling
|
||||
* remains the same, `MPRJ_IO_PADS does not change, so a local parameter
|
||||
* is made that can be made smaller than `MPRJ_IO_PADS to accommodate
|
||||
* the analog pads.
|
||||
*/
|
||||
|
||||
module mprj_io #(
|
||||
parameter AREA1PADS = `MPRJ_IO_PADS_1,
|
||||
parameter TOTAL_PADS = `MPRJ_IO_PADS
|
||||
) (
|
||||
inout vddio,
|
||||
inout vssio,
|
||||
inout vdda,
|
||||
inout vssa,
|
||||
inout vccd,
|
||||
inout vssd,
|
||||
|
||||
inout vdda1,
|
||||
inout vdda2,
|
||||
inout vssa1,
|
||||
inout vssa2,
|
||||
inout vccd1,
|
||||
inout vccd2,
|
||||
inout vssd1,
|
||||
inout vssd2,
|
||||
|
||||
input vddio_q,
|
||||
input vssio_q,
|
||||
input analog_a,
|
||||
input analog_b,
|
||||
input porb_h,
|
||||
inout [TOTAL_PADS-1:0] io,
|
||||
input [TOTAL_PADS-1:0] io_out,
|
||||
input [TOTAL_PADS-1:0] oeb,
|
||||
input [TOTAL_PADS-1:0] hldh_n,
|
||||
input [TOTAL_PADS-1:0] enh,
|
||||
input [TOTAL_PADS-1:0] inp_dis,
|
||||
input [TOTAL_PADS-1:0] ib_mode_sel,
|
||||
input [TOTAL_PADS-1:0] vtrip_sel,
|
||||
input [TOTAL_PADS-1:0] slow_sel,
|
||||
input [TOTAL_PADS-1:0] holdover,
|
||||
input [TOTAL_PADS-1:0] analog_en,
|
||||
input [TOTAL_PADS-1:0] analog_sel,
|
||||
input [TOTAL_PADS-1:0] analog_pol,
|
||||
input [TOTAL_PADS*3-1:0] dm,
|
||||
output [TOTAL_PADS-1:0] io_in,
|
||||
output [TOTAL_PADS-1:0] io_in_3v3,
|
||||
inout [TOTAL_PADS-10:0] analog_io,
|
||||
inout [TOTAL_PADS-10:0] analog_noesd_io
|
||||
);
|
||||
|
||||
wire [TOTAL_PADS-1:0] loop1_io;
|
||||
wire [6:0] no_connect_1a, no_connect_1b;
|
||||
wire [1:0] no_connect_2a, no_connect_2b;
|
||||
|
||||
sky130_ef_io__gpiov2_pad_wrapped area1_io_pad [AREA1PADS - 1:0] (
|
||||
`USER1_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
,.PAD(io[AREA1PADS - 1:0]),
|
||||
`endif
|
||||
.OUT(io_out[AREA1PADS - 1:0]),
|
||||
.OE_N(oeb[AREA1PADS - 1:0]),
|
||||
.HLD_H_N(hldh_n[AREA1PADS - 1:0]),
|
||||
.ENABLE_H(enh[AREA1PADS - 1:0]),
|
||||
.ENABLE_INP_H(loop1_io[AREA1PADS - 1:0]),
|
||||
.ENABLE_VDDA_H(porb_h),
|
||||
.ENABLE_VSWITCH_H(vssio),
|
||||
.ENABLE_VDDIO(vccd),
|
||||
.INP_DIS(inp_dis[AREA1PADS - 1:0]),
|
||||
.IB_MODE_SEL(ib_mode_sel[AREA1PADS - 1:0]),
|
||||
.VTRIP_SEL(vtrip_sel[AREA1PADS - 1:0]),
|
||||
.SLOW(slow_sel[AREA1PADS - 1:0]),
|
||||
.HLD_OVR(holdover[AREA1PADS - 1:0]),
|
||||
.ANALOG_EN(analog_en[AREA1PADS - 1:0]),
|
||||
.ANALOG_SEL(analog_sel[AREA1PADS - 1:0]),
|
||||
.ANALOG_POL(analog_pol[AREA1PADS - 1:0]),
|
||||
.DM(dm[AREA1PADS*3 - 1:0]),
|
||||
.PAD_A_NOESD_H({analog_noesd_io[AREA1PADS - 8:0], no_connect_1a}),
|
||||
.PAD_A_ESD_0_H({analog_io[AREA1PADS - 8:0], no_connect_1b}),
|
||||
.PAD_A_ESD_1_H(),
|
||||
.IN(io_in[AREA1PADS - 1:0]),
|
||||
.IN_H(io_in_3v3[AREA1PADS - 1:0]),
|
||||
.TIE_HI_ESD(),
|
||||
.TIE_LO_ESD(loop1_io[AREA1PADS - 1:0])
|
||||
);
|
||||
|
||||
sky130_ef_io__gpiov2_pad_wrapped area2_io_pad [TOTAL_PADS - AREA1PADS - 1:0] (
|
||||
`USER2_ABUTMENT_PINS
|
||||
`ifndef TOP_ROUTING
|
||||
,.PAD(io[TOTAL_PADS - 1:AREA1PADS]),
|
||||
`endif
|
||||
.OUT(io_out[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.OE_N(oeb[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.HLD_H_N(hldh_n[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ENABLE_H(enh[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ENABLE_INP_H(loop1_io[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ENABLE_VDDA_H(porb_h),
|
||||
.ENABLE_VSWITCH_H(vssio),
|
||||
.ENABLE_VDDIO(vccd),
|
||||
.INP_DIS(inp_dis[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.IB_MODE_SEL(ib_mode_sel[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.VTRIP_SEL(vtrip_sel[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.SLOW(slow_sel[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.HLD_OVR(holdover[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ANALOG_EN(analog_en[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ANALOG_SEL(analog_sel[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.ANALOG_POL(analog_pol[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.DM(dm[TOTAL_PADS*3 - 1:AREA1PADS*3]),
|
||||
.PAD_A_NOESD_H({no_connect_2a, analog_noesd_io[TOTAL_PADS - 10:AREA1PADS - 7]}),
|
||||
.PAD_A_ESD_0_H({no_connect_2b, analog_io[TOTAL_PADS - 10:AREA1PADS - 7]}),
|
||||
.PAD_A_ESD_1_H(),
|
||||
.IN(io_in[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.IN_H(io_in_3v3[TOTAL_PADS - 1:AREA1PADS]),
|
||||
.TIE_HI_ESD(),
|
||||
.TIE_LO_ESD(loop1_io[TOTAL_PADS - 1:AREA1PADS])
|
||||
);
|
||||
|
||||
endmodule
|
||||
// `default_nettype wire
|
|
@ -0,0 +1,33 @@
|
|||
// 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
|
||||
|
||||
module mprj_logic_high (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vccd1,
|
||||
inout vssd1,
|
||||
`endif
|
||||
output [461:0] HI
|
||||
);
|
||||
sky130_fd_sc_hd__conb_1 insts [461:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vccd1),
|
||||
.VGND(vssd1),
|
||||
.VPB(vccd1),
|
||||
.VNB(vssd1),
|
||||
`endif
|
||||
.HI(HI),
|
||||
.LO()
|
||||
);
|
||||
endmodule
|
|
@ -0,0 +1,172 @@
|
|||
// 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
|
||||
`ifndef TOP_ROUTING
|
||||
`define USER1_ABUTMENT_PINS \
|
||||
.AMUXBUS_A(analog_a),\
|
||||
.AMUXBUS_B(analog_b),\
|
||||
.VSSA(vssa1),\
|
||||
.VDDA(vdda1),\
|
||||
.VSWITCH(vddio),\
|
||||
.VDDIO_Q(vddio_q),\
|
||||
.VCCHIB(vccd),\
|
||||
.VDDIO(vddio),\
|
||||
.VCCD(vccd1),\
|
||||
.VSSIO(vssio),\
|
||||
.VSSD(vssd1),\
|
||||
.VSSIO_Q(vssio_q)
|
||||
|
||||
`define USER2_ABUTMENT_PINS \
|
||||
.AMUXBUS_A(analog_a),\
|
||||
.AMUXBUS_B(analog_b),\
|
||||
.VSSA(vssa2),\
|
||||
.VDDA(vdda2),\
|
||||
.VSWITCH(vddio),\
|
||||
.VDDIO_Q(vddio_q),\
|
||||
.VCCHIB(vccd),\
|
||||
.VDDIO(vddio),\
|
||||
.VCCD(vccd2),\
|
||||
.VSSIO(vssio),\
|
||||
.VSSD(vssd2),\
|
||||
.VSSIO_Q(vssio_q)
|
||||
|
||||
`define MGMT_ABUTMENT_PINS \
|
||||
.AMUXBUS_A(analog_a),\
|
||||
.AMUXBUS_B(analog_b),\
|
||||
.VSSA(vssa),\
|
||||
.VDDA(vdda),\
|
||||
.VSWITCH(vddio),\
|
||||
.VDDIO_Q(vddio_q),\
|
||||
.VCCHIB(vccd),\
|
||||
.VDDIO(vddio),\
|
||||
.VCCD(vccd),\
|
||||
.VSSIO(vssio),\
|
||||
.VSSD(vssd),\
|
||||
.VSSIO_Q(vssio_q)
|
||||
`else
|
||||
`define USER1_ABUTMENT_PINS
|
||||
`define USER2_ABUTMENT_PINS
|
||||
`define MGMT_ABUTMENT_PINS
|
||||
`endif
|
||||
|
||||
`define HVCLAMP_PINS(H,L) \
|
||||
.DRN_HVC(H), \
|
||||
.SRC_BDY_HVC(L)
|
||||
|
||||
`define LVCLAMP_PINS(H1,L1,H2,L2,L3) \
|
||||
.BDY2_B2B(L3), \
|
||||
.DRN_LVC1(H1), \
|
||||
.DRN_LVC2(H2), \
|
||||
.SRC_BDY_LVC1(L1), \
|
||||
.SRC_BDY_LVC2(L2)
|
||||
|
||||
`define INPUT_PAD(X,Y) \
|
||||
wire loop_``X; \
|
||||
sky130_ef_io__gpiov2_pad_wrapped X``_pad ( \
|
||||
`MGMT_ABUTMENT_PINS \
|
||||
`ifndef TOP_ROUTING \
|
||||
,.PAD(X), \
|
||||
`endif \
|
||||
.OUT(vssd), \
|
||||
.OE_N(vccd), \
|
||||
.HLD_H_N(vddio), \
|
||||
.ENABLE_H(porb_h), \
|
||||
.ENABLE_INP_H(loop_``X), \
|
||||
.ENABLE_VDDA_H(porb_h), \
|
||||
.ENABLE_VSWITCH_H(vssa), \
|
||||
.ENABLE_VDDIO(vccd), \
|
||||
.INP_DIS(por), \
|
||||
.IB_MODE_SEL(vssd), \
|
||||
.VTRIP_SEL(vssd), \
|
||||
.SLOW(vssd), \
|
||||
.HLD_OVR(vssd), \
|
||||
.ANALOG_EN(vssd), \
|
||||
.ANALOG_SEL(vssd), \
|
||||
.ANALOG_POL(vssd), \
|
||||
.DM({vssd, vssd, vccd}), \
|
||||
.PAD_A_NOESD_H(), \
|
||||
.PAD_A_ESD_0_H(), \
|
||||
.PAD_A_ESD_1_H(), \
|
||||
.IN(Y), \
|
||||
.IN_H(), \
|
||||
.TIE_HI_ESD(), \
|
||||
.TIE_LO_ESD(loop_``X) )
|
||||
|
||||
`define OUTPUT_PAD(X,Y,INPUT_DIS,OUT_EN_N) \
|
||||
wire loop_``X; \
|
||||
sky130_ef_io__gpiov2_pad_wrapped X``_pad ( \
|
||||
`MGMT_ABUTMENT_PINS \
|
||||
`ifndef TOP_ROUTING \
|
||||
,.PAD(X), \
|
||||
`endif \
|
||||
.OUT(Y), \
|
||||
.OE_N(OUT_EN_N), \
|
||||
.HLD_H_N(vddio), \
|
||||
.ENABLE_H(porb_h), \
|
||||
.ENABLE_INP_H(loop_``X), \
|
||||
.ENABLE_VDDA_H(porb_h), \
|
||||
.ENABLE_VSWITCH_H(vssa), \
|
||||
.ENABLE_VDDIO(vccd), \
|
||||
.INP_DIS(INPUT_DIS), \
|
||||
.IB_MODE_SEL(vssd), \
|
||||
.VTRIP_SEL(vssd), \
|
||||
.SLOW(vssd), \
|
||||
.HLD_OVR(vssd), \
|
||||
.ANALOG_EN(vssd), \
|
||||
.ANALOG_SEL(vssd), \
|
||||
.ANALOG_POL(vssd), \
|
||||
.DM({vccd, vccd, vssd}), \
|
||||
.PAD_A_NOESD_H(), \
|
||||
.PAD_A_ESD_0_H(), \
|
||||
.PAD_A_ESD_1_H(), \
|
||||
.IN(), \
|
||||
.IN_H(), \
|
||||
.TIE_HI_ESD(), \
|
||||
.TIE_LO_ESD(loop_``X))
|
||||
|
||||
`define INOUT_PAD(X,Y,Y_OUT,INPUT_DIS,OUT_EN_N,MODE) \
|
||||
wire loop_``X; \
|
||||
sky130_ef_io__gpiov2_pad_wrapped X``_pad ( \
|
||||
`MGMT_ABUTMENT_PINS \
|
||||
`ifndef TOP_ROUTING \
|
||||
,.PAD(X), \
|
||||
`endif \
|
||||
.OUT(Y_OUT), \
|
||||
.OE_N(OUT_EN_N), \
|
||||
.HLD_H_N(vddio), \
|
||||
.ENABLE_H(porb_h), \
|
||||
.ENABLE_INP_H(loop_``X), \
|
||||
.ENABLE_VDDA_H(porb_h), \
|
||||
.ENABLE_VSWITCH_H(vssa), \
|
||||
.ENABLE_VDDIO(vccd), \
|
||||
.INP_DIS(INPUT_DIS), \
|
||||
.IB_MODE_SEL(vssd), \
|
||||
.VTRIP_SEL(vssd), \
|
||||
.SLOW(vssd), \
|
||||
.HLD_OVR(vssd), \
|
||||
.ANALOG_EN(vssd), \
|
||||
.ANALOG_SEL(vssd), \
|
||||
.ANALOG_POL(vssd), \
|
||||
.DM(MODE), \
|
||||
.PAD_A_NOESD_H(), \
|
||||
.PAD_A_ESD_0_H(), \
|
||||
.PAD_A_ESD_1_H(), \
|
||||
.IN(Y), \
|
||||
.IN_H(), \
|
||||
.TIE_HI_ESD(), \
|
||||
.TIE_LO_ESD(loop_``X) )
|
||||
|
||||
// `default_nettype wire
|
|
@ -0,0 +1,250 @@
|
|||
// 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
|
||||
// Tunable ring oscillator---synthesizable (physical) version.
|
||||
//
|
||||
// NOTE: This netlist cannot be simulated correctly due to lack
|
||||
// of accurate timing in the digital cell verilog models.
|
||||
|
||||
module delay_stage(in, trim, out);
|
||||
input in;
|
||||
input [1:0] trim;
|
||||
output out;
|
||||
|
||||
wire d0, d1, d2, ts;
|
||||
|
||||
sky130_fd_sc_hd__clkbuf_2 delaybuf0 (
|
||||
.A(in),
|
||||
.X(ts)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__clkbuf_1 delaybuf1 (
|
||||
.A(ts),
|
||||
.X(d0)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_2 delayen1 (
|
||||
.A(d0),
|
||||
.TE(trim[1]),
|
||||
.Z(d1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvn_4 delayenb1 (
|
||||
.A(ts),
|
||||
.TE_B(trim[1]),
|
||||
.Z(d1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__clkinv_1 delayint0 (
|
||||
.A(d1),
|
||||
.Y(d2)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_2 delayen0 (
|
||||
.A(d2),
|
||||
.TE(trim[0]),
|
||||
.Z(out)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvn_8 delayenb0 (
|
||||
.A(ts),
|
||||
.TE_B(trim[0]),
|
||||
.Z(out)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module start_stage(in, trim, reset, out);
|
||||
input in;
|
||||
input [1:0] trim;
|
||||
input reset;
|
||||
output out;
|
||||
|
||||
wire d0, d1, d2, ctrl0, one;
|
||||
|
||||
sky130_fd_sc_hd__clkbuf_1 delaybuf0 (
|
||||
.A(in),
|
||||
.X(d0)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_2 delayen1 (
|
||||
.A(d0),
|
||||
.TE(trim[1]),
|
||||
.Z(d1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvn_4 delayenb1 (
|
||||
.A(in),
|
||||
.TE_B(trim[1]),
|
||||
.Z(d1)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__clkinv_1 delayint0 (
|
||||
.A(d1),
|
||||
.Y(d2)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_2 delayen0 (
|
||||
.A(d2),
|
||||
.TE(trim[0]),
|
||||
.Z(out)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvn_8 delayenb0 (
|
||||
.A(in),
|
||||
.TE_B(ctrl0),
|
||||
.Z(out)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__einvp_1 reseten0 (
|
||||
.A(one),
|
||||
.TE(reset),
|
||||
.Z(out)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__or2_2 ctrlen0 (
|
||||
.A(reset),
|
||||
.B(trim[0]),
|
||||
.X(ctrl0)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hd__conb_1 const1 (
|
||||
.HI(one),
|
||||
.LO()
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
// Ring oscillator with 13 stages, each with two trim bits delay
|
||||
// (see above). Trim is not binary: For trim[1:0], lower bit
|
||||
// trim[0] is primary trim and must be applied first; upper
|
||||
// bit trim[1] is secondary trim and should only be applied
|
||||
// after the primary trim is applied, or it has no effect.
|
||||
//
|
||||
// Total effective number of inverter stages in this oscillator
|
||||
// ranges from 13 at trim 0 to 65 at trim 24. The intention is
|
||||
// to cover a range greater than 2x so that the midrange can be
|
||||
// reached over all PVT conditions.
|
||||
//
|
||||
// Frequency of this ring oscillator under SPICE simulations at
|
||||
// nominal PVT is maximum 214 MHz (trim 0), minimum 90 MHz (trim 24).
|
||||
|
||||
module ring_osc2x13(reset, trim, clockp);
|
||||
input reset;
|
||||
input [25:0] trim;
|
||||
output[1:0] clockp;
|
||||
|
||||
`ifdef FUNCTIONAL // i.e., behavioral model below
|
||||
|
||||
reg [1:0] clockp;
|
||||
reg hiclock;
|
||||
integer i;
|
||||
real delay;
|
||||
wire [5:0] bcount;
|
||||
|
||||
assign bcount = trim[0] + trim[1] + trim[2]
|
||||
+ trim[3] + trim[4] + trim[5] + trim[6] + trim[7]
|
||||
+ trim[8] + trim[9] + trim[10] + trim[11] + trim[12]
|
||||
+ trim[13] + trim[14] + trim[15] + trim[16] + trim[17]
|
||||
+ trim[18] + trim[19] + trim[20] + trim[21] + trim[22]
|
||||
+ trim[23] + trim[24] + trim[25];
|
||||
|
||||
initial begin
|
||||
hiclock <= 1'b0;
|
||||
delay = 3.0;
|
||||
end
|
||||
|
||||
// Fastest operation is 214 MHz = 4.67ns
|
||||
// Delay per trim is 0.02385
|
||||
// Run "hiclock" at 2x this rate, then use positive and negative
|
||||
// edges to derive the 0 and 90 degree phase clocks.
|
||||
|
||||
always #delay begin
|
||||
hiclock <= (hiclock === 1'b0);
|
||||
end
|
||||
|
||||
always @(trim) begin
|
||||
// Implement trim as a variable delay, one delay per trim bit
|
||||
delay = 1.168 + 0.012 * $itor(bcount);
|
||||
end
|
||||
|
||||
always @(posedge hiclock or posedge reset) begin
|
||||
if (reset == 1'b1) begin
|
||||
clockp[0] <= 1'b0;
|
||||
end else begin
|
||||
clockp[0] <= (clockp[0] === 1'b0);
|
||||
end
|
||||
end
|
||||
|
||||
always @(negedge hiclock or posedge reset) begin
|
||||
if (reset == 1'b1) begin
|
||||
clockp[1] <= 1'b0;
|
||||
end else begin
|
||||
clockp[1] <= (clockp[1] === 1'b0);
|
||||
end
|
||||
end
|
||||
|
||||
`else // !FUNCTIONAL; i.e., gate level netlist below
|
||||
|
||||
wire [1:0] clockp;
|
||||
wire [12:0] d;
|
||||
wire [1:0] c;
|
||||
|
||||
// Main oscillator loop stages
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 12; i = i + 1) begin : dstage
|
||||
delay_stage id (
|
||||
.in(d[i]),
|
||||
.trim({trim[i+13], trim[i]}),
|
||||
.out(d[i+1])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// Reset/startup stage
|
||||
|
||||
start_stage iss (
|
||||
.in(d[12]),
|
||||
.trim({trim[25], trim[12]}),
|
||||
.reset(reset),
|
||||
.out(d[0])
|
||||
);
|
||||
|
||||
// Buffered outputs a 0 and 90 degrees phase (approximately)
|
||||
|
||||
sky130_fd_sc_hd__clkinv_2 ibufp00 (
|
||||
.A(d[0]),
|
||||
.Y(c[0])
|
||||
);
|
||||
sky130_fd_sc_hd__clkinv_8 ibufp01 (
|
||||
.A(c[0]),
|
||||
.Y(clockp[0])
|
||||
);
|
||||
sky130_fd_sc_hd__clkinv_2 ibufp10 (
|
||||
.A(d[6]),
|
||||
.Y(c[1])
|
||||
);
|
||||
sky130_fd_sc_hd__clkinv_8 ibufp11 (
|
||||
.A(c[1]),
|
||||
.Y(clockp[1])
|
||||
);
|
||||
|
||||
`endif // !FUNCTIONAL
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,92 @@
|
|||
// 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
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
module simple_por(
|
||||
`ifdef USE_POWER_PINS
|
||||
inout vdd3v3,
|
||||
inout vdd1v8,
|
||||
inout vss,
|
||||
`endif
|
||||
output porb_h,
|
||||
output porb_l,
|
||||
output por_l
|
||||
);
|
||||
|
||||
wire mid, porb_h;
|
||||
reg inode;
|
||||
|
||||
// This is a behavioral model! Actual circuit is a resitor dumping
|
||||
// current (slowly) from vdd3v3 onto a capacitor, and this fed into
|
||||
// two schmitt triggers for strong hysteresis/glitch tolerance.
|
||||
|
||||
initial begin
|
||||
inode <= 1'b0;
|
||||
end
|
||||
|
||||
// Emulate current source on capacitor as a 500ns delay either up or
|
||||
// down. Note that this is sped way up for verilog simulation; the
|
||||
// actual circuit is set to a 15ms delay.
|
||||
|
||||
always @(posedge vdd3v3) begin
|
||||
#500 inode <= 1'b1;
|
||||
end
|
||||
always @(negedge vdd3v3) begin
|
||||
#500 inode <= 1'b0;
|
||||
end
|
||||
|
||||
// Instantiate two shmitt trigger buffers in series
|
||||
|
||||
sky130_fd_sc_hvl__schmittbuf_1 hystbuf1 (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdd3v3),
|
||||
.VGND(vss),
|
||||
.VPB(vdd3v3),
|
||||
.VNB(vss),
|
||||
`endif
|
||||
.A(inode),
|
||||
.X(mid)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hvl__schmittbuf_1 hystbuf2 (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdd3v3),
|
||||
.VGND(vss),
|
||||
.VPB(vdd3v3),
|
||||
.VNB(vss),
|
||||
`endif
|
||||
.A(mid),
|
||||
.X(porb_h)
|
||||
);
|
||||
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1 porb_level (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(vdd3v3),
|
||||
.VPB(vdd3v3),
|
||||
.LVPWR(vdd1v8),
|
||||
.VNB(vss),
|
||||
.VGND(vss),
|
||||
`endif
|
||||
.A(porb_h),
|
||||
.X(porb_l)
|
||||
);
|
||||
|
||||
// since this is behavioral anyway, but this should be
|
||||
// replaced by a proper inverter
|
||||
assign por_l = ~porb_l;
|
||||
endmodule
|
||||
`default_nettype wire
|
|
@ -0,0 +1,50 @@
|
|||
// 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
|
||||
|
||||
module sky130_fd_sc_hvl__lsbufhv2lv_1_wrapped (
|
||||
X ,
|
||||
A ,
|
||||
`ifdef USE_POWER_PINS
|
||||
VPWR ,
|
||||
VGND ,
|
||||
LVPWR,
|
||||
LVGND,
|
||||
`endif
|
||||
);
|
||||
|
||||
output X ;
|
||||
input A ;
|
||||
`ifdef USE_POWER_PINS
|
||||
inout VPWR ;
|
||||
inout VGND ;
|
||||
inout LVPWR;
|
||||
inout LVGND;
|
||||
`endif
|
||||
|
||||
sky130_fd_sc_hvl__lsbufhv2lv_1 lvlshiftdown (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(VPWR),
|
||||
.VPB(VPWR),
|
||||
|
||||
.LVPWR(LVPWR),
|
||||
|
||||
.VNB(VGND),
|
||||
.VGND(VGND),
|
||||
`endif
|
||||
.A(A),
|
||||
.X(X)
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,180 @@
|
|||
// 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
|
|
@ -0,0 +1,57 @@
|
|||
// 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
|
||||
// This module represents an unprogrammed mask revision
|
||||
// block that is configured with via programming on the
|
||||
// chip top level. This value is passed to the block as
|
||||
// a parameter
|
||||
|
||||
module user_id_programming #(
|
||||
parameter [ 0:0] USER_PROJECT_ID = 32'h0
|
||||
) (
|
||||
`ifdef USE_POWER_PINS
|
||||
inout VPWR,
|
||||
inout VGND,
|
||||
`endif
|
||||
output [31:0] mask_rev
|
||||
);
|
||||
wire [31:0] mask_rev;
|
||||
wire [31:0] user_proj_id_high;
|
||||
wire [31:0] user_proj_id_low;
|
||||
|
||||
// For the mask revision input, use an array of digital constant logic cells
|
||||
|
||||
sky130_fd_sc_hd__conb_1 mask_rev_value [31:0] (
|
||||
`ifdef USE_POWER_PINS
|
||||
.VPWR(VPWR),
|
||||
.VPB(VPWR),
|
||||
.VNB(VGND),
|
||||
.VGND(VGND),
|
||||
`endif
|
||||
.HI(user_proj_id_high),
|
||||
.LO(user_proj_id_low)
|
||||
);
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 32; i = i+1) begin
|
||||
assign mask_rev[i] = (USER_PROJECT_ID & (32'h01 << i)) ?
|
||||
user_proj_id_high[i] : user_proj_id_low[i];
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
`default_nettype wire
|
Loading…
Reference in New Issue