This is a simple demo of using Versal DCAMC IP in a Chisel project. Due to time limitation, the documents are not well-written, so feel free to ask me anything via Github issues. I'll respond once I have time.
-
Please make sure you have already installed mill (https://com-lihaoyi.github.io/mill/mill/Intro_to_Mill.html) Our project relies on an older version of mill, 0.10.11. We tested that mill 1.X does not work on our project :(
-
Download and install Vivado 2025.1 or later! 2024.X has a critical bug on V80 board implementation.
|- common: Package containing common components that are required by the project demo.
|- dcmac: DCMAC package, including an example DCMAC design.
|- versal: Package containing Versal block design wrapper and commonly-used Versal block design IPs.
|- build.sc: Build definition required by mill
|- config.json: Vivado import definition, which will be introduced later.
|- instant.py: A script that quickly generates Verilog testbench template. Likely you will not use it.
|- postElaborating.py: An important script to automatically build your module to Verilog code and provide Tcl script to generate the IPs and block designs in Vivado.
- Create a Vivado project.
- Since the example top module
dcmac/src/examples/DCMACTop.scalaincludes a board design calledCIPSBoardDesign, you need to manually create a board design in Vivado and name itCIPSBoardDesign. - Edit config.json file. The whole JSON is an object, with each key to be a Scala package name (e.g., dcmac in this example). You may add more keys when creating more Scala packages. Each value is an object containing 4 options:
- destIPRepoPath: I'm not sure what this is used for, maybe this is a deprecated option.
- destSrcPath: Location that the generated Verilog file will be copied to.
- monitorDelay: Used by ILA IP. I tend to set this to 6 (maximum).
- projectGeneration: Just set it to "Versal".
- Generate the example project.
dcmac/src/Elaborate.scalais the build entry point. You can add more modules to build following the example project. Note that the key in "case" should match the module name. Since now we already have a moduleDCMACTop, we can simply build the module by executingHere,python3 postElaborating.py dcmac DCMACTop -t -pdcmacis the package name,DCMACTopis the module name,-tindicates generate the Tcl command, and-pindicates moving file to destination location. - Now you will see a lot of outputs in your console. Generally it includes two Tcl scripts:
- The script starting from
create_bd_port -dir ...tovalidate_bd_designare scripts for block design. Open the block design in Vivado, paste and execute the scripts into Tcl Console to automatically generates the modules without clicking and dragging in Vivado's awful GUI. - The script starting with
create_ipandset_propertyare used to create IPs. Open the project manager window instead of block design, paste and execute the scripts to automatically generate and configurate the IPs.
- The script starting from
- Finally, synthese and implement the project to get bitstream (device image).
We follow previous CMAC example design for 100Gbps Ethernet to wrap the complex AXI-Stream segment interfaces to 250MHz 1024-bit AXI-Stream interfaces for both TX and RX direction via our handmade AXISToSeg and SegToAXIS modules (See dcmac/src/XDCMAC.scala).
However, this 1024-bit interface is only lossless for 128B-aligned packets. If you want to send and receive irregular packets (i.e., not multiple of 128B), please either pad the packet to multiple of 128B(1024 bit) or edit the XDCMAC module to bypass AXISToSeg and SegToAXIS modules.
When using 200Gbps high-speed network, it is likely that the receiver cannot receive any data from sender due to physical layer signal loss. In this case, you will see an eye-slice diagram of at least one node shape like this:

Signals of the four levels overlap with each other, and error correction fails to work, while a normal eye-slice diagram should be like this:

If you connect FPGAs with optical fiber, it is even likely that a receiver cannot receive any signal at all.
In both cases, please follow your sense to adjust cursor/precursor/postcursor in Serial I/O Links tab of the hardware manager.