# cdbus_ip
**Repository Path**: enjoyNow/cdbus_ip
## Basic Information
- **Project Name**: cdbus_ip
- **Description**: CDBUS Protocol and the IP Core for FPGA users
- **Primary Language**: Verilog
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-05-30
- **Last Updated**: 2024-12-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[//]: # (IP Core for CDBUS Protocol)
CDBUS IP Core
=======================================
(This is an 8-bit version, please switch to the corresponding branch for the 32-bit version.)
1. [CDBUS Protocol](#cdbus-protocol)
2. [Block Diagram](#block-diagram)
3. [Registers](#registers)
4. [Interface](#interface)
5. [Examples](#examples)
6. [Simulation](#simulation)
7. [Ready To Use Devices](#ready-to-use-devices)
8. [License](#license)
## CDBUS Protocol
CDBUS is a protocol for Asynchronous Serial Communication,
it has a 3-byte header: `[src_addr, dst_addr, data_len]`, then user data, and finally 2 bytes of CRC.
It's suitable for one-to-one communication, e.g. UART or RS232.
In this case, the address for each side are usually carefully selected and fixed,
e.g: `[0x55, 0xaa, data_len, ...]`, and the backward is: `[0xaa, 0x55, data_len, ...]`.
The CDBUS protocol is more valuable for bus communication, e.g. RS485 or Single Line UART.
In this case:
### Arbitration Mode (CDBUS-A)
* It introduces an arbitration mechanism that automatically avoids conflicts like the CAN bus.
* Support dual baud rate, provide high speed communication, maximum rate ≥ 10 Mbps.
* Supports unicast, multicast and broadcast.
* Max payload data size is 253 byte (you can increase it to 255 byte, but not recommended).
* Hardware packing, unpacking, verification and filtering, save your time and CPU usage.
* Backward compatible with traditional RS485 hardware (still retains arbitration function).
The protocol example timing, include only one byte user data:
(How long to enter idle and how long to allow sending can be set.)

Tips:
- When high-priority node send unimportant data, the transmission wait time (TX_PERMIT_LEN) can be dynamically increased.
Arbitration example:
### Break Sync Mode (CDBUS-BS)
In CDBUS-A mode, if the low-speed part takes a lot of time, it will be a communication efficiency bottleneck.
In this case, single-rate peer-to-peer bus communication can be implemented by CDBUS-BS mode:
- Configure different TX_PERMIT_LEN parameters for each node, and the difference should be sufficient to avoid conflicts.
- If any node has pending tx frame before TX-permit point, then start sent at the TX-permit point.
- Or wait for the idle time to exceed the MAX_IDLE_LEN, then send a break character to bring the bus out of idle mode.
The CDBUS-BS mode is suitable for high-speed applications with few nodes and is also suitable for software implementation.
## Block Diagram
#### Operation
## Registers
| Register Name | Addr | Access | Default | Description | Remarks |
|-------------------|---------|--------|-----------------|-------------------------------|------------------------------------------------------|
| VERSION | 0x00 | RD | 0x0a | Hardware version | |
| SETTING | 0x02 | RD/WR | 0x10 | Configs | |
| IDLE_WAIT_LEN | 0x04 | RD/WR | 0x0a | How long to enter idle | Bit 7~0 |
| TX_PERMIT_LEN_L | 0x05 | RD/WR | 0x14 | How long to allow sending | Bit 7~0 |
| TX_PERMIT_LEN_H | 0x06 | RD/WR | 0x00 | | Bit 9~8 |
| MAX_IDLE_LEN_L | 0x07 | RD/WR | 0xc8 | Max idle for BS mode | Bit 7~0 |
| MAX_IDLE_LEN_H | 0x08 | RD/WR | 0x00 | | Bit 9~8 |
| TX_PRE_LEN | 0x09 | RD/WR | 0x01 | Active TX_EN before TX | Bit 1~0, not used in arbitration mode |
| FILTER | 0x0b | RD/WR | 0xff | Set to local address | |
| DIV_LS_L | 0x0c | RD/WR | 0x5a | Low-speed rate setting | Bit 7~0 |
| DIV_LS_H | 0x0d | RD/WR | 0x01 | | Bit 15~8 |
| DIV_HS_L | 0x0e | RD/WR | 0x5a | High-speed rate setting | If not use dual rate, set the same value as DIV_LS |
| DIV_HS_H | 0x0f | RD/WR | 0x01 | | |
| INT_FLAG | 0x10 | RD | n/a | Status | |
| INT_MASK | 0x11 | RD/WR | 0x00 | Interrupt mask | |
| RX | 0x14 | RD | n/a | Read RX page | |
| TX | 0x15 | WR | n/a | Write TX page | |
| RX_CTRL | 0x16 | WR | n/a | RX control | |
| TX_CTRL | 0x17 | WR | n/a | TX control | |
| RX_ADDR | 0x18 | RD/WR | 0x00 | RX page read pointer | Rarely used |
| RX_PAGE_FLAG | 0x19 | RD | n/a | RX page flag | For debugging |
| FILTER1 | 0x1a | RD/WR | 0xff | Multicast filter1 | |
| FILTER2 | 0x1b | RD/WR | 0xff | Multicast filter2 | |
**SETTING:**
| FIELD | DESCRIPTION |
|-------- |---------------------------------------------------|
| [0] | Enable push-pull output for tx and tx_en pin |
| [1] | Invert tx output |
| [2] | CRC maintained by user |
| [3] | Save broken frame |
| [4] | Enable arbitration |
| [5] | Break Sync mode |
| [6] | Full duplex mode |
| [4] | [5] | [6] | DESCRIPTION |
|-----|-----|-----|---------------------------------|
| 1 | 0 | 0 | CDBUS-A mode (default) |
| 0 | 1 | 0 | CDBUS-BS mode |
| 0 | 0 | 1 | Full-duplex mode |
| 0 | 0 | 0 | Traditional half-duplex mode |
**FILTERS:**
Match from top to bottom:
| SRC_ADDR | DST_ADDR | FILTER | FILTERn | Receive or drop | Remarks |
|---------- |----------|--------------|------------------|-----------------|------------------|
| not care | not care | 255 | not care | Receive | Promiscuous mode |
| = FILTER | not care | != 255 | not care | Drop | Avoid loopback |
| != FILTER | 255 | not care | not care | Receive | Broadcast |
| != FILTER | != 255 | not care | any = DST_ADDR | Receive | Multicast |
| != FILTER | != 255 | = DST_ADDR | not care | Receive | Unicast |
| not care | != 255 | != DST_ADDR | all != DST_ADDR | Drop | |
It is recommended to reserve the address from `0xe0` to `0xfe` as the multicast address.
The default value 0xff of FILTERn means not enabled.
**DIV_xx_x:**
Baud rate divider value:
DIV_xx[15:0] = sys_freq ÷ baud_rate − 1
**INT_FLAG:**
| FIELD | DESCRIPTION |
|-------- |----------------------------------------------|
| [0] | 1: Bus in IDLE mode |
| [1] | 1: RX page ready for read |
| [2] | 1: Receive break character |
| [3] | 1: RX lost: no empty page for RX |
| [4] | 1: RX error: frame broken |
| [5] | 1: TX page released by hardware |
| [6] | 1: TX collision detected |
| [7] | 1: TX error: tx is 0, but rx is 1 |
**INT_MASK:**
Output of irq = ((INT_FLAG & INT_MASK) != 0).
**RX_CTRL:**
| FIELD | DESCRIPTION |
|-------- |-----------------------------|
| [0] | Reset RX page read pointer |
| [1] | Switch RX page |
| [2] | Clear RX lost flag |
| [3] | Clear RX error flag |
| [4] | Reset RX block |
| [5] | Clear RX break flag |
**TX_CTRL:**
| FIELD | DESCRIPTION |
|-------- |-------------------------------------------------------------|
| [0] | Reset TX page write pointer |
| [1] | Switch TX page |
| [2] | Clear TX collision flag |
| [3] | Clear TX error flag |
| [4] | Abort TX |
| [5] | Send break character (for full-duplex and traditional mode) |
**RX_PAGE_FLAG:**
Value zero indicate the frame in current RX page is correct;
Non-zero indicate the pointer of last received byte of the disturbed frame, include CRC.
## Interface
```verilog
parameter DIV_LS = 346, // default: 115200 bps for 40MHz clk
parameter DIV_HS = 346
input clk, // core clock
input reset_n, // asynch active low reset
input chip_select, // reduce ram_rx power consumption
output irq, // interrupt output
// avalon-mm slave interface, read and write without latency
// support burst read and write (normally for REG_TX and REG_RX)
input [4:0] csr_address,
input csr_read,
output [7:0] csr_readdata,
input csr_write,
input [7:0] csr_writedata,
// connect to external PHY chip, e.g. MAX3485
input rx,
output tx,
output tx_en
```
## Examples
```python
# Configuration
write(REG_SETTING, [0x11]) # Enable push-pull output
# TX
write(REG_TX, [0x0c, 0x0d, 0x01, 0xcd]) # Write frame without CRC
while (read(REG_INT_FLAG) & 0x20) == 0: # Make sure we can successfully switch to the next page
pass
write(REG_TX_CTRL, [0x03]) # Trigger send by switching TX page
# RX
while (read(REG_INT_FLAG) & 0x02) == 0: # Wait for RX page ready
pass
header = read(REG_TX, len=3)
data = read(REG_TX, len=header[2])
write(REG_RX_CTRL, [0x03]) # Finish read by switching RX page
```
## Simulation
Install `iverilog` (>= v10) and `cocotb`, goto `tests/` folder, then type the command:
```sh
$ COCOTB=/path/to/cocotb make
```
Then you can checkout the waveform `cdbus.vcd` by GTKWave.
## Ready To Use Devices
The CDCTL controller family uses the CDBUS IP Core, which provide SPI, I2C and PCIe peripheral interfaces.
E.g. The tiny CDCTL-Bx module support SPI and I2C interfaces:
For more information, visit: http://dukelec.com
## License
```
This Source Code Form is subject to the terms of the Mozilla
Public License, v. 2.0. If a copy of the MPL was not distributed
with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
Notice: The scope granted to MPL excludes the ASIC industry.
The CDBUS protocol is royalty-free for everyone except chip manufacturers.
Copyright (c) 2017 DUKELEC, All rights reserved.
```