---
# System prepended metadata

title: Serial General Purpose Input Output(SGPIOs)
tags: [Leonton]

---

# 初探 `SGPIOs` 
## Introduction
一般來說，`SoC` 或是 `microcontroller` 上有許多 `Pin` 為`GPIOs` 的 `pin` ，代表其可以設定為 `input` 以及 `Output` 或是使用 `protocal` 來進行傳輸，一般來說用來進行傳輸或是作為 `input/Ouput` 的 `GPIOs Pin` 是足夠使用的，但若是在特定場景，需要許多 `pin` 來去監控狀態或是進行`I/O`控制的，原本晶片上的 `pin` 都會被拿來做 `I/O` 來進行使用是非常沒有效率的，若是多開許多 `port` 單純給予 `I/O` 控制在設計上的 `trade off` 來說會過於昂貴，所以`SGPIOs`就因應而生，`SGPIOs` 全名為 `Serial General Purpose Input Output` ，其主要目的為透過很少的 `GPIOs` 的 `pin` 來去達到 `128 pin` 或以上的 `I/O` 控制。
## Specification
### Serial GPIO Controller
剛剛有提到， `sgpio` 的目的是想要透過少少的 `gpio pin` 來達到好幾倍於這個 `pin` 的 `I/O` 控制， 以 `Microchip` 的 `VSC7429/VSC7428` 這兩顆 `SoC` 為例:
其 `chip` 設計為
透過四根 `GPIO pin` 連接至 `SGPIO controller` 這邊統稱 `SIO controller` 而 `SIO controller` 內含有 `shift Register` 以及 `32 根 Pin`，而每根 `Pin` 可以選擇開啟幾個 `bits` 所以以這顆 `SoC` 為例可以透過 `SGPIO` 達成 $32 \times 4=128$ 根 `pin` 的 `I/O` 使用，通常會使用 `GPIO的 0~3 pin` 來當作 `SGPIOs` 的 四根 `pin` 角以下為例:
```shell
// SGPIO 示意圖

        +-----------------------------+
        |         控制器 (MCU)        |
        |                             |
        |   +---------------------+   |
        |   |   SIO 控制邏輯      |   |
        |   +---------------------+   |
        |         |     |     |   |   |
        +---------|-----|-----|---|---+
                  |     |     |   |
               SIO_CLK  |     |   |
                     SIO_LD   |   |
                         SIO_DO   |
                             SIO_DI

  -----------------------------------------------
  外部電路/裝置（如 LED、感測器等）

    SIO_CLK  --->  移位暫存器  --->  LED/裝置
    SIO_LD   --->  (載入/鎖存)
    SIO_DO   --->  (資料輸出)
    SIO_DI   <---  (資料輸入)

```
### Pin Mapping
* `GPIO 0` -> `SIO_CLK`: `Output` 使用 `SIO_CLOCK.SIO_CLK_FREQ` 建立頻率
* `GPIO 1` -> `SIO_LD` : `Output` `SIO Load data` `Polarity` 使用 `SIO_CONFIG.SIO_LD_POLARITY`
* `GPIO 2` -> `SIO_DO` : `Output` 為 `SIO data output`
* `GPIO 3` -> `SIO_DI` : `Input` 為 `SIO data input`

### Work theoerm
`SIO controller` 會將資料透過 `SIO_DO` 依序移到 `shift register` ，當移動到設定的位元時， `SIO_LD will be trigger to shift register` 將資料正式輸出，在輸出的同時 `SIO_DI` 也可從外部讀取資料，這樣可以同是 `input/output`， `SIO_LD` 的作用為使其資料傳輸可以同步更新，在此可以透過 `SIO_PORT_ENABLE` 跳過不需要的 `sgpio port` 僅針對有開啟的 `sgpio port` 進行使用，`SIO_CONFIG.SIO_PORT_WIDTH` 可以設定每個 `port` 的 `GPIO` 數量。

### SIO Timing
* `Parallel to serial shift register load data on logical 0`
* `serial to parallel shift register output data on rising edge(posedge)`
* `minimum timing` : `28 ns`
* `Burst Gap` : 這是連續傳輸 `burst` 的間隔時間，可以透過設定來調整最大的 `burst gap` 可以設成 `32 bits * 4 cycle count`
* 每個 `posedge` ， `SIO_DI` 以及 `SIO_DO` 會同時將 `1 bit` 資料移入跟移出 `register` 直至資料傳輸完畢後 會有一個 `burst gap` 結束才能繼續傳輸。
* `SGPIO` 資料可以一次性或連續性的傳輸，`single burst` 時 `SIO_CONFIG.SIO_SINGLE_SHOT` 會被設成 `1` ，如果要連續傳輸必須使用 `SIO_CONFIG.SIO_AUTO_REPEAT`
#### SGPIOs Disable Timing
* 等待 `SIO_LD Trigger` 若未觸發，則 `SIO_DO` 處於 `Disable`  
* `SIO_LD` 觸發後進入 `burst`
* `burst` 結束回到 `disable`
* 如果觸發兩個 `SIO_LD` ， 第一次 `burst` 會將暫存器內的資料輸出，第二次 ` burst` 則會將新資料載入並輸出。
* 只有在 `burst` 期間， `SIO_DO` 才會輸出有效資料



### Design Pattern
通常在 `switch` 上的 `sgpio port` 會分為 `3`、`4` 功能的 `port` : 
* `physical port` : 顯而易見，就是 `switch` 上有幾個 `Copper port`
* `fake_spgio_port` : 在設計前會決定哪些 `physical port` 會被 `disable` 藏起來，假如原本有12個 `port` 但藏起來兩個 `port` 的話，必須設定 `fake_sgpio_port` 為 `2` ，用於 `alignment shift register` 以防資料被 `shift` 到不正確的 `port` 例如原本 第八個 `port` 的資料被 `shift to port6`。
* `LED port` : 通常約定成俗的設計會被設計在 `port 28~31`
* `SFP port` : 在 `SFP port` 跟 `physical port` 之間不能放入其餘功能的行為，以防資料被 `shift`
* `SGPIOs constraint` : 每個 `physical port` 只能 `mapping` 至對應的 `sgpio port`，這樣才防止 `data` 不會 `shift` 例如: `physical port 0` -> `sgpio port 0`、`physical port 2` -> `sgpio port 2`
* 如果要採用不連續設計如開啟 `0~3、8~11 port` 則中間的 `7~10` 需要 `disable` 才能確保資料輸出正確
