Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ tasks:
desc: Exports RTL from SpinalHDL/Chisel for the given ip.
cmds:
- "{{.CONTAINER_CHECK}}"
- task: lib-sbt-publishLocal
vars:
project: "modules/elements/vexiiriscv"
- "{{.RUN}} 'IP_ROOT={{.PWD}}/sources/{{.ip}}/ sbt \"runMain digital.peripherals.io.gpio.GpioExport\"'"

build:
Expand All @@ -118,6 +121,9 @@ tasks:
cmds:
- "{{.CONTAINER_CHECK}}"
- "{{.PDK_CHECK}}"
- task: lib-sbt-publishLocal
vars:
project: "modules/elements/vexiiriscv"
- "{{.RUN}} '{{.ORFS_ENV}} && {{.ORFS}} {{if .stage}}{{.stage}}{{end}}'"
- "{{.RUN}} '{{.ORFS_ENV}} && {{.ORFS}} generate_abstract'"
- "{{.RUN}} '{{.ORFS_ENV}} && {{.ORFS}} {{.CDL}}'"
Expand Down
24 changes: 23 additions & 1 deletion exports/GpioExport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package digital.peripherals.io.gpio
import spinal.core._
import spinal.lib._

import nafarr.peripherals.io.gpio.{Apb3Gpio, WishboneGpio, Gpio, GpioCtrl}
import nafarr.peripherals.io.gpio.{Apb3Gpio, TileLinkGpio, WishboneGpio, Gpio, GpioCtrl}

object GpioExport {
def main(args: Array[String]) {
Expand All @@ -28,6 +28,17 @@ object GpioExport {
controller.setDefinitionName("gpio_apb_32b")
controller
}
SpinalConfig(
noRandBoot = false,
targetDirectory = ipRoot + "verilog",
rtlHeader = rtlHeader,
headerWithRepoHash = false,
netlistFileName = "gpio_tl_32b.v"
).generateVerilog {
val controller = TileLinkGpio(parameter32b)
controller.setDefinitionName("gpio_tl_32b")
controller
}
SpinalConfig(
noRandBoot = false,
targetDirectory = ipRoot + "verilog",
Expand All @@ -50,6 +61,17 @@ object GpioExport {
controller.setDefinitionName("gpio_apb_32b")
controller
}
SpinalConfig(
noRandBoot = false,
targetDirectory = ipRoot + "vhdl",
rtlHeader = rtlHeader,
headerWithRepoHash = false,
netlistFileName = "gpio_tl_32b.vhd"
).generateVhdl {
val controller = TileLinkGpio(parameter32b)
controller.setDefinitionName("gpio_tl_32b")
controller
}
SpinalConfig(
noRandBoot = false,
targetDirectory = ipRoot + "vhdl",
Expand Down
5 changes: 3 additions & 2 deletions manifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ SPDX-License-Identifier: CERN-OHL-W-2.0

<default remote="github" sync-j="8" />

<project name="aesc-silicon/elements-nafarr" path="modules/elements/nafarr" revision="18d3c0f41bd1a269bfaa67c280cdc2777e3c5298" />
<project name="aesc-silicon/elements-zibal" path="modules/elements/zibal" revision="4936844d86f5c5f34c3b555622f346ab49402105" />
<project name="aesc-silicon/elements-nafarr" path="modules/elements/nafarr" revision="fe097a0d2a26bc4c4d8472d7b3093f82291fa32d" />
<project name="aesc-silicon/elements-zibal" path="modules/elements/zibal" revision="e2d3a60339fcbf6951c8db21d28220e8e9f41cf2" />
<project name="SpinalHDL/SpinalCrypto" path="modules/elements/SpinalCrypto" revision="f2a4ae9db5e9434c5589d0651efec8719103498e" />
<project name="SpinalHDL/VexiiRiscv" path="modules/elements/vexiiriscv" revision="03587f948b91f84197ecdbd958ba490977fd5671" />
<project name="aesc-silicon/elements-vexriscv" path="modules/elements/vexriscv" revision="6814d54a341562beb330d407bb9898024367e447" />
<project name="aesc-silicon/OpenROAD-flow-scripts" path="tools/OpenROAD-flow-scripts" revision="e2cedfb48aaa471f6be518eef262ece8fab87827" />
</manifest>
1 change: 1 addition & 0 deletions sources/digital/peripherals/io/gpio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ register map, port descriptions, and integration notes.
| Macro | Interface | Width |
|----------------|-----------|-------|
| `gpio_apb_32b` | APB3 | 32 |
| `gpio_tl_32b` | TileLink | 32 |
| `gpio_wb_32b` | Wishbone | 32 |

## PDK Support
Expand Down
45 changes: 45 additions & 0 deletions sources/digital/peripherals/io/gpio/blackbox/chisel/GpioTl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-FileCopyrightText: 2026 aesc silicon
// SPDX-License-Identifier: CERN-OHL-W-2.0
//
// Chisel blackbox for gpio_tl_Nb.
// Use this class to instantiate the hardened macro in a Chisel design.
//
// Port names match the Verilog module exactly. The implicit Chisel clock and
// reset are not used; drive clk and reset explicitly from your clock domain.
//
// Example:
// val gpio = Module(new GpioTl(32)) // elaborates to gpio_tl_32b
// val gpio = Module(new GpioTl(64)) // elaborates to gpio_tl_64b

import chisel3._
import chisel3.experimental.ExtModule

class GpioTl(width: Int = 32) extends ExtModule {
override def desiredName = s"gpio_tl_${width}b"

val io_bus_a_valid = IO(Input(Bool()))
val io_bus_a_ready = IO(Output(Bool()))
val io_bus_a_payload_opcode = IO(Input(UInt(3.W)))
val io_bus_a_payload_param = IO(Input(UInt(3.W)))
val io_bus_a_payload_source = IO(Input(UInt(4.W)))
val io_bus_a_payload_address = IO(Input(UInt(12.W)))
val io_bus_a_payload_size = IO(Input(UInt(3.W)))
val io_bus_a_payload_mask = IO(Input(UInt(4.W)))
val io_bus_a_payload_data = IO(Input(UInt(32.W)))
val io_bus_a_payload_corrupt = IO(Input(Bool()))
val io_bus_d_valid = IO(Output(Bool()))
val io_bus_d_ready = IO(Input(Bool()))
val io_bus_d_payload_opcode = IO(Output(UInt(3.W)))
val io_bus_d_payload_param = IO(Output(UInt(3.W)))
val io_bus_d_payload_source = IO(Output(UInt(4.W)))
val io_bus_d_payload_size = IO(Output(UInt(3.W)))
val io_bus_d_payload_denied = IO(Output(Bool()))
val io_bus_d_payload_data = IO(Output(UInt(32.W)))
val io_bus_d_payload_corrupt = IO(Output(Bool()))
val io_gpio_pins_read = IO(Input(UInt(width.W)))
val io_gpio_pins_write = IO(Output(UInt(width.W)))
val io_gpio_pins_writeEnable = IO(Output(UInt(width.W)))
val io_interrupt = IO(Output(Bool()))
val clk = IO(Input(Clock()))
val reset = IO(Input(Bool()))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// SPDX-FileCopyrightText: 2026 aesc silicon
// SPDX-License-Identifier: CERN-OHL-W-2.0
//
// SpinalHDL blackbox for gpio_tl_Nb.
// Use this class to instantiate the hardened macro in a SpinalHDL design.
//
// Example:
// val gpio = new GpioTl(32) // elaborates to gpio_tl_32b
// val gpio = new GpioTl(64) // elaborates to gpio_tl_64b

import spinal.core._
import spinal.lib._

class GpioTl(width: Int = 32) extends BlackBox {
override def definitionName = s"gpio_tl_${width}b"

val io = new Bundle {
val bus = new Bundle {
val a = new Bundle {
val valid = in Bool()
val ready = out Bool()
val payload = new Bundle {
val opcode = in Bits(3 bits)
val param = in Bits(3 bits)
val source = in Bits(4 bits)
val address = in Bits(12 bits)
val size = in Bits(3 bits)
val mask = in Bits(4 bits)
val data = in Bits(32 bits)
val corrupt = in Bool()
}
}
val d = new Bundle {
val valid = out Bool()
val ready = in Bool()
val payload = new Bundle {
val opcode = out Bits(3 bits)
val param = out Bits(3 bits)
val source = out Bits(4 bits)
val size = out Bits(3 bits)
val denied = out Bool()
val data = out Bits(32 bits)
val corrupt = out Bool()
}
}
}
val gpio = new Bundle {
val pins = new Bundle {
val read = in Bits(width bits)
val write = out Bits(width bits)
val writeEnable = out Bits(width bits)
}
}
val interrupt = out Bool()
}

mapClockDomain(clock = clockDomain.clock, reset = clockDomain.reset)
}
42 changes: 42 additions & 0 deletions sources/digital/peripherals/io/gpio/blackbox/verilog/gpio_tl.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: 2026 aesc silicon
// SPDX-License-Identifier: CERN-OHL-W-2.0
//
// Blackbox stub for gpio_tl_Nb.
// Use this file to instantiate the hardened macro in a Verilog design.
// The (* blackbox *) attribute is recognised by Yosys.
//
// Example:
// gpio_tl #(.WIDTH(32)) u_gpio (...) // instantiates gpio_tl_32b
// gpio_tl #(.WIDTH(64)) u_gpio (...) // instantiates gpio_tl_64b

(* blackbox *)
module gpio_tl #(
parameter WIDTH = 32
) (
input wire io_bus_a_valid,
output wire io_bus_a_ready,
input wire [2:0] io_bus_a_payload_opcode,
input wire [2:0] io_bus_a_payload_param,
input wire [3:0] io_bus_a_payload_source,
input wire [11:0] io_bus_a_payload_address,
input wire [2:0] io_bus_a_payload_size,
input wire [3:0] io_bus_a_payload_mask,
input wire [31:0] io_bus_a_payload_data,
input wire io_bus_a_payload_corrupt,
output wire io_bus_d_valid,
input wire io_bus_d_ready,
output wire [2:0] io_bus_d_payload_opcode,
output wire [2:0] io_bus_d_payload_param,
output wire [3:0] io_bus_d_payload_source,
output wire [2:0] io_bus_d_payload_size,
output wire io_bus_d_payload_denied,
output wire [31:0] io_bus_d_payload_data,
output wire io_bus_d_payload_corrupt,
input wire [WIDTH-1:0] io_gpio_pins_read,
output wire [WIDTH-1:0] io_gpio_pins_write,
output wire [WIDTH-1:0] io_gpio_pins_writeEnable,
output wire io_interrupt,
input wire clk,
input wire reset
);
endmodule
50 changes: 50 additions & 0 deletions sources/digital/peripherals/io/gpio/blackbox/vhdl/gpio_tl.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
-- SPDX-FileCopyrightText: 2026 aesc silicon
-- SPDX-License-Identifier: CERN-OHL-W-2.0
--
-- Blackbox stub for gpio_tl_Nb.
-- Use this component declaration to instantiate the hardened macro in a
-- VHDL design.
--
-- Example:
-- u_gpio : gpio_tl generic map (WIDTH => 32) port map (...);
-- u_gpio : gpio_tl generic map (WIDTH => 64) port map (...);

library ieee;
use ieee.std_logic_1164.all;

entity gpio_tl is
generic (
WIDTH : integer := 32
);
port (
io_bus_a_valid : in std_logic;
io_bus_a_ready : out std_logic;
io_bus_a_payload_opcode : in std_logic_vector(2 downto 0);
io_bus_a_payload_param : in std_logic_vector(2 downto 0);
io_bus_a_payload_source : in std_logic_vector(3 downto 0);
io_bus_a_payload_address : in std_logic_vector(11 downto 0);
io_bus_a_payload_size : in std_logic_vector(2 downto 0);
io_bus_a_payload_mask : in std_logic_vector(3 downto 0);
io_bus_a_payload_data : in std_logic_vector(31 downto 0);
io_bus_a_payload_corrupt : in std_logic;
io_bus_d_valid : out std_logic;
io_bus_d_ready : in std_logic;
io_bus_d_payload_opcode : out std_logic_vector(2 downto 0);
io_bus_d_payload_param : out std_logic_vector(2 downto 0);
io_bus_d_payload_source : out std_logic_vector(3 downto 0);
io_bus_d_payload_size : out std_logic_vector(2 downto 0);
io_bus_d_payload_denied : out std_logic;
io_bus_d_payload_data : out std_logic_vector(31 downto 0);
io_bus_d_payload_corrupt : out std_logic;
io_gpio_pins_read : in std_logic_vector(WIDTH-1 downto 0);
io_gpio_pins_write : out std_logic_vector(WIDTH-1 downto 0);
io_gpio_pins_writeEnable : out std_logic_vector(WIDTH-1 downto 0);
io_interrupt : out std_logic;
clk : in std_logic;
reset : in std_logic
);
end entity gpio_tl;

-- No architecture: this is a blackbox stub for integration with a
-- hardened macro. Bind the LEF/LIB views during synthesis and place
-- and route.
89 changes: 85 additions & 4 deletions sources/digital/peripherals/io/gpio/doc/gpio.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ The core is generated by
| Variant | Bus Interface | Data Width | Address Width |
|-----------------|---------------|-----------|---------------|
| `gpio_apb_32b` | APB3 | 32 bit | 12 bit |
| `gpio_tl_32b` | TileLink | 32 bit | 12 bit |
| `gpio_wb_32b` | Wishbone | 32 bit | 10 bit |

Both variants implement the same register map and functionality. The only
All variants implement the same register map and functionality. The only
difference is the bus interface used to access the registers.

> **Note:** `gpio_wb_32b` will be added in a future release. This document
> already describes the register map which is identical for both variants.

---

## Port Description
Expand Down Expand Up @@ -85,6 +83,89 @@ low, pin `n` is in high-impedance (input) state.

---

### `gpio_tl_32b`

#### TileLink Bus Interface (TL-UL)

##### Channel A (Request)

| Signal | Direction | Width | Description |
|-------------------------------|-----------|-------|--------------------------------------------------|
| `io_bus_a_valid` | Input | 1 | Request valid |
| `io_bus_a_ready` | Output | 1 | Slave ready to accept request |
| `io_bus_a_payload_opcode` | Input | 3 | Operation type (Get, PutFullData, PutPartialData)|
| `io_bus_a_payload_param` | Input | 3 | Operation parameter |
| `io_bus_a_payload_source` | Input | 4 | Transaction source identifier |
| `io_bus_a_payload_address` | Input | 12 | Register address |
| `io_bus_a_payload_size` | Input | 3 | log2 of transfer size in bytes |
| `io_bus_a_payload_mask` | Input | 4 | Byte lane mask |
| `io_bus_a_payload_data` | Input | 32 | Write data |
| `io_bus_a_payload_corrupt` | Input | 1 | Data integrity error (tie low) |

##### Channel D (Response)

| Signal | Direction | Width | Description |
|-------------------------------|-----------|-------|--------------------------------------------------|
| `io_bus_d_valid` | Output | 1 | Response valid |
| `io_bus_d_ready` | Input | 1 | Master ready to accept response |
| `io_bus_d_payload_opcode` | Output | 3 | Response type (AccessAck, AccessAckData) |
| `io_bus_d_payload_param` | Output | 3 | Response parameter |
| `io_bus_d_payload_source` | Output | 4 | Transaction source identifier (echoed from A) |
| `io_bus_d_payload_size` | Output | 3 | log2 of transfer size in bytes (echoed from A) |
| `io_bus_d_payload_denied` | Output | 1 | Access denied |
| `io_bus_d_payload_data` | Output | 32 | Read data |
| `io_bus_d_payload_corrupt` | Output | 1 | Data integrity error |

#### GPIO Pad Interface

| Signal | Direction | Width | Description |
|-----------------------------|-----------|-------|----------------------------------------------------|
| `io_gpio_pins_read` | Input | 32 | Sampled pad values (driven by IO pads) |
| `io_gpio_pins_write` | Output | 32 | Output data driven to pads |
| `io_gpio_pins_writeEnable` | Output | 32 | Output enable per pin. Active-high by default. |

#### Miscellaneous

| Signal | Direction | Width | Description |
|-----------------|-----------|-------|------------------------------------------------|
| `clk` | Input | 1 | Clock (active rising edge) |
| `reset` | Input | 1 | Synchronous reset (active high) |
| `io_interrupt` | Output | 1 | Combined interrupt output (OR of all pending) |

---

### `gpio_wb_32b`

#### Wishbone Bus Interface (Classic, Pipelined)

| Signal | Direction | Width | Description |
|-------------------|-----------|-------|--------------------------------------|
| `io_bus_CYC` | Input | 1 | Bus cycle active |
| `io_bus_STB` | Input | 1 | Strobe / transfer request |
| `io_bus_ACK` | Output | 1 | Transfer acknowledge |
| `io_bus_WE` | Input | 1 | Write enable: 1 = write, 0 = read |
| `io_bus_ADR` | Input | 10 | Word address |
| `io_bus_DAT_MISO` | Output | 32 | Read data (slave to master) |
| `io_bus_DAT_MOSI` | Input | 32 | Write data (master to slave) |

#### GPIO Pad Interface

| Signal | Direction | Width | Description |
|-----------------------------|-----------|-------|----------------------------------------------------|
| `io_gpio_pins_read` | Input | 32 | Sampled pad values (driven by IO pads) |
| `io_gpio_pins_write` | Output | 32 | Output data driven to pads |
| `io_gpio_pins_writeEnable` | Output | 32 | Output enable per pin. Active-high by default. |

#### Miscellaneous

| Signal | Direction | Width | Description |
|-----------------|-----------|-------|------------------------------------------------|
| `clk` | Input | 1 | Clock (active rising edge) |
| `reset` | Input | 1 | Synchronous reset (active high) |
| `io_interrupt` | Output | 1 | Combined interrupt output (OR of all pending) |

---

## Register Map

All registers are 32 bits wide. Unconnected bit positions read as `0`.
Expand Down
Loading
Loading