Skip to content

Commit

Permalink
treewide: Add SpinalHDL USB 1.1 controller (#91)
Browse files Browse the repository at this point in the history
* treewide: Add Saxon SoC USB 1.1 (OHCI) controller

* treewide: Clean up USB implementation

* sw: Update `cva6-sdk`

* target/xilinx: Reenable UNBENT

* ci: Exclude Spinal OHCI source from linting

* treewide: Update license information

* sw: Differentiate device trees

* hw: Change SpinalHDL USB configuration

- Reduces the internal buffer size from 2kB to 1088 byte
  minimum is 1023 + DMA_width/8 byte, the max size of a packet
   with overhead for alignment
- BufferCC clock domain crossings for proper constraints

* hw: Remove timescale in USB controller

* sw: Add different device trees (images) for Genesys 2 Linux configs

* docs: Add USB changes to documentation

* target/xilinx: Constrain USB I/O paths

* sw/boot: Revise device trees

---------

Co-authored-by: Luka Guzenko <[email protected]>
Co-authored-by: Paul Scheffler <[email protected]>
Co-authored-by: Philippe Sauter <[email protected]>
  • Loading branch information
4 people authored Jul 4, 2024
1 parent 0deceee commit 4a270af
Show file tree
Hide file tree
Showing 27 changed files with 19,702 additions and 399 deletions.
1 change: 1 addition & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
uses: chipsalliance/verible-linter-action@main
with:
paths: hw
exclude_paths: hw/future/UsbOhciAxi4.v
extra_args: "--waiver_files .github/verible.waiver"
github_token: ${{ secrets.GITHUB_TOKEN }}
fail_on_error: true
Expand Down
4 changes: 2 additions & 2 deletions Bender.lock
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ packages:
- register_interface
- tech_cells_generic
register_interface:
revision: e25b36670ff7aab3402f40efcc2b11ee0f31cf19
version: 0.4.3
revision: ae616e5a1ec2b41e72d200e5ab09c65e94aebd3d
version: 0.4.4
source:
Git: https://github.com/pulp-platform/register_interface.git
dependencies:
Expand Down
4 changes: 3 additions & 1 deletion Bender.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dependencies:
iDMA: { git: "https://github.com/pulp-platform/iDMA.git", version: 0.5.1 }
irq_router: { git: "https://github.com/pulp-platform/irq_router.git", version: 0.0.1-beta.1 }
opentitan_peripherals: { git: "https://github.com/pulp-platform/opentitan_peripherals.git", version: 0.4.0 }
register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.3 }
register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.4 }
riscv-dbg: { git: "https://github.com/pulp-platform/riscv-dbg.git", version: 0.8.1 }
serial_link: { git: "https://github.com/pulp-platform/serial_link.git", version: 1.1.1 }
unbent: { git: "https://github.com/pulp-platform/unbent.git", version: 0.1.6 }
Expand All @@ -35,6 +35,8 @@ export_include_dirs:
- hw/include

sources:
- hw/future/UsbOhciAxi4.v
- hw/future/spinal_usb_ohci.sv
- hw/bootrom/cheshire_bootrom.sv
- hw/regs/cheshire_reg_pkg.sv
- hw/regs/cheshire_reg_top.sv
Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ run -all

## License

Unless specified otherwise in the respective file headers, all code checked into this repository is made available under a permissive license. All hardware sources and tool scripts are licensed under the Solderpad Hardware License 0.51 (see `LICENSE`) with the exception of generated register file code (e.g. `hw/regs/*.sv`), which is generated by a fork of lowRISC's [`regtool`](https://github.com/lowRISC/opentitan/blob/master/util/regtool.py) and licensed under Apache 2.0. All software sources are licensed under Apache 2.0.

Unless specified otherwise in the respective file headers, all code checked into this repository is made available under a permissive license. All hardware sources and tool scripts are licensed under the Solderpad Hardware License 0.51 (see `LICENSE`) or compatible licenses. Register file code (e.g. `hw/regs/*.sv`) is generated by a fork of lowRISC's [`regtool`](https://github.com/lowRISC/opentitan/blob/master/util/regtool.py) and licensed under Apache 2.0. The USB OHCI controller (`hw/future/UsbOhciAxi4.v`) is generated from the [SpinalHDL](https://github.com/SpinalHDL/SpinalHDL) library licensed under the MIT license. All software sources are licensed under Apache 2.0.

## Publication

Expand Down
810 changes: 477 additions & 333 deletions docs/img/arch.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions docs/tg/xilinx.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ make CHS_XILINX_FLASH_BIN=sw/tests/helloworld.gpt.bin chs-xilinx-flash-<myboard>

Flashing an image should take about 10 minutes. *Note that after flashing, your board's bitstream must be reprogrammed* as it is overridden for this task.

If the image given by `CHS_XILINX_FLASH_BIN` does not exist, `make` will attempt to build it before flashing. If `CHS_XILINX_FLASH_BIN` is not provided, the target assumes the board's Linux image by default.
If the image given by `CHS_XILINX_FLASH_BIN` does not exist, `make` will attempt to build it before flashing. If `CHS_XILINX_FLASH_BIN` is not provided, the target assumes the default Linux image for your board.

After flashing your disk image and reprogramming your bitstream, reset into boot mode 2. For `helloworld`, you should again see a `Hello World!` UART output.

Expand All @@ -159,7 +159,9 @@ To create a full Linux disk image from the ZSL, your board's device tree, the fi
make ${CHS_ROOT}/sw/boot/linux.<myboard>.gpt.bin
```

where `CHS_ROOT` is the root of the Cheshire repository. Flash this image to an SD card or SPI flash as described in the preceding sections, then reset into the boot mode corresponding for your boot medium. You should first see the ZSL print on the UART:
where `CHS_ROOT` is the root of the Cheshire repository. Note that for some boards, additional images with different configurations (i.e. `linux.<myboard>_<myconfig>.gpt.bin`) may be available.

Flash your image to an SD card or SPI flash as described in the preceding sections, then reset into the boot mode corresponding for your boot medium. You should first see the ZSL print on the UART:

```
/\___/\ Boot mode: 1
Expand Down
16 changes: 15 additions & 1 deletion docs/um/arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ Cheshire's internal memory map is *static*. While device instantiation and layou
| +-------------------+---------------+------+-------+
| | VGA (Cfg) | `0x0300_7000` | 4K | |
| +-------------------+---------------+------+-------+
| | UNBENT | `0x0300_8000` | 4K | |
| | USB 1.1 (Cfg) | `0x0300_8000` | 4K | |
| +-------------------+---------------+------+-------+
| | UNBENT | `0x0300_9000` | 4K | |
+--------------------+-------------------+---------------+------+-------+
| INTCs @ Reg | PLIC | `0x0400_0000` | 64M | |
| +-------------------+---------------+------+-------+
Expand Down Expand Up @@ -110,6 +112,7 @@ The following global parameters control basic functionality and features and can
| `Dma` | `bit` | Whether DMA is available |
| `SerialLink` | `bit` | Whether serial link is available |
| `Vga` | `bit` | Whether VGA is available |
| `Usb` | `bit` | Whether USB 1.1 (OHCI) host is available |
| `AxiRt` | `bit` | Whether AXI RT is available |
| `Clic` | `bit` | Whether CLIC is available |
| `IrqRouter` | `bit` | Whether IRQ Router is available |
Expand Down Expand Up @@ -228,6 +231,17 @@ The [VGA Controller](https://github.com/pulp-platform/axi_vga) enables the drawi
| `VgaBufferDepth` | `dw_bt` | Depth of internal read data FIFO |
| `VgaMaxReadTxns` | `dw_bt` | Maximum number of outstanding reads |


### USB 1.1 (OHCI) Controller

The USB 1.1 (OHCI) Host Controller was generated from the [SpinalHDL](https://github.com/SpinalHDL/SpinalHDL) library and provides a fully digital root hub with four ports. Note that it currently only supports single-core CVA6 configurations with the default cache and can only access a 32-bit physical address subspaces. It exposes the following parameters:

| Parameter | Type / Range | Description |
| -------------------------- | ------------ | ------------------------------------------------- |
| `UsbDmaMaxReads` | `dw_bt` | Maximum outstanding reads for USB controller DMA |
| `UsbAddrDomain` | `doub_bt` | Address domain to cast USB DMA requests into |
| `UsbAddrMask` | `doub_bt` | Address mask to apply on USB DMA requests |

### Serial Link

The [Serial Link](https://github.com/pulp-platform/serial_link) is a fully digital, double-data-rate (DDR) chip-to-chip or die-to-die interface serializing AXI4. It can be used to communicate with other SoCs using it, such as other Cheshire instances or FPGAs providing further peripheral or accelerator functionality. It exposes the following parameters:
Expand Down
18 changes: 17 additions & 1 deletion hw/cheshire_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ package cheshire_pkg;
localparam int unsigned SlinkNumLanes = serial_link_single_channel_reg_pkg::NumBits/2;
localparam int unsigned SlinkMaxClkDiv = 1 << serial_link_single_channel_reg_pkg::Log2MaxClkDiv;
localparam int unsigned ClintNumCores = clint_reg_pkg::NumCores;
localparam int unsigned UsbNumPorts = spinal_usb_ohci_pkg::NumPhyPorts;

// Default JTAG ID code type
typedef struct packed {
Expand Down Expand Up @@ -132,6 +133,7 @@ package cheshire_pkg;
bit Dma;
bit SerialLink;
bit Vga;
bit Usb;
bit AxiRt;
bit Clic;
bit IrqRouter;
Expand Down Expand Up @@ -172,6 +174,10 @@ package cheshire_pkg;
doub_bt SlinkTxAddrMask;
doub_bt SlinkTxAddrDomain;
dw_bt SlinkUserAmoBit;
// Parameters for USB
dw_bt UsbDmaMaxReads;
doub_bt UsbAddrMask;
doub_bt UsbAddrDomain;
// Parameters for DMA
dw_bt DmaConfMaxReadTxns;
dw_bt DmaConfMaxWriteTxns;
Expand Down Expand Up @@ -212,6 +218,7 @@ package cheshire_pkg;
typedef struct packed {
cheshire_bus_err_intr_t bus_err;
logic [31:0] gpio;
logic usb;
logic spih_spi_event;
logic spih_error;
logic i2c_host_timeout;
Expand Down Expand Up @@ -271,7 +278,7 @@ package cheshire_pkg;
localparam doub_bt AmRegs = 'h0300_0000;
localparam doub_bt AmLlc = 'h0300_1000;
localparam doub_bt AmSlink = 'h0300_6000;
localparam doub_bt AmBusErr = 'h0300_8000;
localparam doub_bt AmBusErr = 'h0300_9000;
localparam doub_bt AmSpm = 'h1000_0000; // Cached region at bottom, uncached on top
localparam doub_bt AmClic = 'h0800_0000;

Expand All @@ -291,6 +298,7 @@ package cheshire_pkg;
aw_bt dma;
aw_bt slink;
aw_bt vga;
aw_bt usb;
aw_bt ext_base;
aw_bt num_in;
} axi_in_t;
Expand All @@ -303,6 +311,7 @@ package cheshire_pkg;
if (cfg.Dma) begin i++; ret.dma = i; end
if (cfg.SerialLink) begin i++; ret.slink = i; end
if (cfg.Vga) begin i++; ret.vga = i; end
if (cfg.Usb) begin i++; ret.usb = i; end
i++;
ret.ext_base = i;
ret.num_in = i + cfg.AxiExtNumMst;
Expand Down Expand Up @@ -384,6 +393,7 @@ package cheshire_pkg;
aw_bt gpio;
aw_bt slink;
aw_bt vga;
aw_bt usb;
aw_bt axirt;
aw_bt irq_router;
aw_bt [2**MaxCoresWidth-1:0] bus_err;
Expand All @@ -408,6 +418,7 @@ package cheshire_pkg;
if (cfg.Gpio) begin i++; ret.gpio = i; r++; ret.map[r] = '{i, 'h0300_5000, 'h0300_6000}; end
if (cfg.SerialLink) begin i++; ret.slink = i; r++; ret.map[r] = '{i, AmSlink, AmSlink +'h1000}; end
if (cfg.Vga) begin i++; ret.vga = i; r++; ret.map[r] = '{i, 'h0300_7000, 'h0300_8000}; end
if (cfg.Usb) begin i++; ret.usb = i; r++; ret.map[r] = '{i, 'h0300_8000, 'h0300_9000}; end
if (cfg.IrqRouter) begin i++; ret.irq_router = i; r++; ret.map[r] = '{i, 'h0208_0000, 'h020c_0000}; end
if (cfg.AxiRt) begin i++; ret.axirt = i; r++; ret.map[r] = '{i, 'h020c_0000, 'h0210_0000}; end
if (cfg.Clic) for (int j = 0; j < cfg.NumCores; j++) begin
Expand Down Expand Up @@ -594,6 +605,7 @@ package cheshire_pkg;
Dma : 1,
SerialLink : 1,
Vga : 1,
Usb : 1,
AxiRt : 0,
Clic : 0,
IrqRouter : 0,
Expand Down Expand Up @@ -634,6 +646,10 @@ package cheshire_pkg;
SlinkTxAddrMask : 'hFFFF_FFFF,
SlinkTxAddrDomain : 'h0000_0000,
SlinkUserAmoBit : 1, // Convention: lower AMO bits for cores, MSB for serial link
// USB config
UsbDmaMaxReads : 16,
UsbAddrMask : 'hFFFF_FFFF,
UsbAddrDomain : 'h0000_0000,
// DMA config
DmaConfMaxReadTxns : 4,
DmaConfMaxWriteTxns : 4,
Expand Down
63 changes: 62 additions & 1 deletion hw/cheshire_soc.sv
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,16 @@ module cheshire_soc import cheshire_pkg::*; #(
output logic vga_vsync_o,
output logic [Cfg.VgaRedWidth -1:0] vga_red_o,
output logic [Cfg.VgaGreenWidth-1:0] vga_green_o,
output logic [Cfg.VgaBlueWidth -1:0] vga_blue_o
output logic [Cfg.VgaBlueWidth -1:0] vga_blue_o,
// USB interface
input logic usb_clk_i,
input logic usb_rst_ni,
input logic [UsbNumPorts-1:0] usb_dm_i,
output logic [UsbNumPorts-1:0] usb_dm_o,
output logic [UsbNumPorts-1:0] usb_dm_oe_o,
input logic [UsbNumPorts-1:0] usb_dp_i,
output logic [UsbNumPorts-1:0] usb_dp_o,
output logic [UsbNumPorts-1:0] usb_dp_oe_o
);

`include "axi/typedef.svh"
Expand Down Expand Up @@ -992,6 +1001,7 @@ module cheshire_soc import cheshire_pkg::*; #(
dma : Cfg.Dma,
serial_link : Cfg.SerialLink,
vga : Cfg.Vga,
usb : Cfg.Usb,
axirt : Cfg.AxiRt,
clic : Cfg.Clic,
irq_router : Cfg.IrqRouter,
Expand Down Expand Up @@ -1653,6 +1663,57 @@ module cheshire_soc import cheshire_pkg::*; #(
assign intr.intn.bus_err.vga = '0;
end

///////////
// USB //
///////////

if (Cfg.Usb) begin : gen_usb

// TODO: USB has no internal error handling, so it should have a bus error unit.

spinal_usb_ohci #(
.AxiMaxReads ( Cfg.UsbDmaMaxReads ),
.AxiAddrWidth ( Cfg.AddrWidth ),
.AxiDataWidth ( Cfg.AxiDataWidth ),
.AxiIdWidth ( Cfg.AxiMstIdWidth ),
.AxiUserWidth ( Cfg.AxiUserWidth ),
.AxiId ( '0 ),
.AxiUser ( Cfg.AxiUserDefault ),
.AxiAddrDomain ( Cfg.UsbAddrDomain ),
.AxiAddrMask ( Cfg.UsbAddrMask ),
.reg_req_t ( reg_req_t ),
.reg_rsp_t ( reg_rsp_t ),
.axi_req_t ( axi_mst_req_t ),
.axi_rsp_t ( axi_mst_rsp_t )
) i_spinal_usb_ohci (
.soc_clk_i ( clk_i ),
.soc_rst_ni ( rst_ni ),
.ctrl_req_i ( reg_out_req[RegOut.usb] ),
.ctrl_rsp_o ( reg_out_rsp[RegOut.usb] ),
.dma_req_o ( axi_in_req[AxiIn.usb] ),
.dma_rsp_i ( axi_in_rsp[AxiIn.usb] ),
.intr_o ( intr.intn.usb ),
.phy_clk_i ( usb_clk_i ),
.phy_rst_ni ( usb_rst_ni ),
.phy_dm_i ( usb_dm_i ),
.phy_dm_o ( usb_dm_o ),
.phy_dm_oe_o ( usb_dm_oe_o ),
.phy_dp_i ( usb_dp_i ),
.phy_dp_o ( usb_dp_o ),
.phy_dp_oe_o ( usb_dp_oe_o )
);

end else begin : gen_no_usb

assign usb_dm_o = '0;
assign usb_dm_oe_o = '0;
assign usb_dp_o = '0;
assign usb_dp_oe_o = '0;

assign intr.intn.usb = 0;

end

//////////////////
// Assertions //
//////////////////
Expand Down
Loading

0 comments on commit 4a270af

Please sign in to comment.