Clock domain crossing in hdl coder

I have an application where i'm generating HDL in a cyclone V for an MII interface to an Ethernet PHY. I read the documentation about using a triggered subystem as a separate clock ( https://www.mathworks.com/help/hdlcoder/ug/use-triggered-subsystem-for-asynchronous-clock-domain.html ) and I noticed the verilog code does treat the RXC signal as a true clock. However, I'm having trouble getting the CDC logic to convert properly. It seems even when I use a Dual Rate Dual Port RAM with different sample rates, it still uses a single clock with clock enables to derive the different rates rather than using RXC as the clock for port A and IPCORE_CLK for port B. I also see no option to use an asynchronous FIFO (dcfifo) in the libraray browser. How can i properly implement CDC logic using simulink tools?

 Accepted Answer

Angela Cuadros Castiblanco
Angela Cuadros Castiblanco on 5 Jun 2026 at 18:58
Edited: Walter Roberson on 8 Jun 2026 at 17:48
Hi John,
Below find explanations of what you are seeing and possible workarounds/modeling options you have.
Why the Dual Rate Dual Port RAM still ends up on one clock with clock enables
When you enable TriggerAsClock in your model and use triggered subsystems to model your clocks, HDL Coder only wires that trigger as a clock signal to the blocks inside that triggered subsystem. Anything that sits outside of the triggered subsystem, at the top level of your DUT, is wired to a global clock instead. On top of that, if HDL Coder finds multiple rates at that top level, it does not create separate clock signals for them. It generates a timing controller that derives those rates from the single global clock using clock enables. That matches what you are seeing on the Dual Rate Dual Port RAM, since it sits outside the triggered subsystem.
So the rule of thumb with trigger as clock is that the logic for each clock domain has to live inside the triggered subsystem that carries that clock. If you want to cross data between two domains this way, you have to model the source side inside one triggered subsystem and the destination side inside another, and wire the crossing between them. That works, but be aware it will split your design across several levels of hierarchy because of how code generation is performed when using trigger as clock.
Relevant doc, as you pointed out, is in:
One workaround: use rates to model multiple clock domains
You can alternatively model your clock domains with distinct Simulink rates and set ClockInputs to multiple. In that case each distinct rate becomes its own clock input in the generated HDL, and you model the CDC logic itself with registers (delays). The rates need to be different so HDL Coder recognizes them as separate domains. In this style the Dual Rate Dual Port RAM does what you expected: the two sets of ports get wired to the clocks that correspond to the rate driving each side.
There is an example published in R2026a that shows multirate, multiclock modeling end to end for an asynchronous use case, including using a Rate Transition configured as a wire together with delay blocks to model the crossing using a pulse based CDC synchronizer:
A couple of notes on it. I am pointing you to it so you can see how multiple clocks and multiple rates are modeled and how the clocks get wired, not because the pulse synchronizer is necessarily the right CDC scheme for your MII data path. Also, the modeling style and concepts in that example have been verified in earlier releases as far back as R2024b, but the synthesis attribute portion (the parts that emit ASYNC_REG and the false path constraints) was part of the release notes in R2026a.
Also note, that CDC logic that you model using rate transitions as wires can show numerical differences between the Simulink simulation and the generated RTL, since the simulation cannot fully represent the asynchronous behavior. This is expected and documented in the Rate Transition reference under Extended Capabilities:
About the async FIFO / dcfifo
There is no shipped dual-clock (async) FIFO block today, which is why you do not see dcfifo in the browser. We are aware of the need and are working on better built in CDC support for a future release. In the meantime, a possible approach for something like a streaming path is to bring in your vendor dual-clock FIFO IP through a blackbox subsystem, modeled with multiple clocks and multiple rates. The high level workflow would be the following:
- Model a simple approximation of the FIFO behavior so you still get something reasonable when you simulate in Simulink and place it on a subsystem.
- Set the subsystem HDL architecture to blackbox. With blackbox, HDL Coder does not generate logic for what is inside the subsystem, it just emits an instantiation, so the contents are used only for Simulink simulation.
- Provide the actual instantiation of your vendor FIFO IP, for example through a DocBlock placed in the subsystem. Match the component name, the parameters, and the port names to the IP exactly, and match the data types and widths to what you have in the model. This text is what shows up in the generated code.
- Drive the write side and the read side with two distinct Simulink rates, one per clock domain. Because each side runs at a different rate, HDL Coder can wire the matching clock to each side of the instantiated IP, you specify the clock names in the HDL Block properties. Keep in mind that the blackbox clock and reset signals are wired fastest to slowest, so you need to specify this accordingly in the HDL Parameters.
DocBlock custom HDL integration:
Hope that helps clear up what you were seeing. If you have follow up questions it would help if you share a bit more about how you want the RXC and IPCORE_CLK domains to meet (a FIFO between them, or just a handful of control signals crossing), and your modeling requirements. If you have follow up questions please share the exact workflow you are running (standalone RTL generation versus IP core generation, and which target interfaces you are mapping if you are using the latter)
Best,
Angela

5 Comments

John
John on 8 Jun 2026 at 14:15
When I read the documentation about using multiple clocks: https://www.mathworks.com/help/hdlcoder/ug/using-multiple-clocks-in-hdl-coder.html ; one thing that confused me is that it refers to instantiating multiple top-level synchronous clock input ports. Does hdl coder assume that the multiple clocks are phase aligned or can you truly have asynchronous clocks as inputs? What does the documentation mean when it refers to synchonous in this context? I would prefer that the two clock domains meet with an asynchronous FIFO between them but I would also like to stay completely within the simulink environment which doesn't seem feasible at this point. I'm leaning toward the black box solution that you referred to but I don't know if hdl coder will treat each simulink rate as being truly independent clocks like it did with the triggered subsystem. I have been using the IP Core Generation target workflow. The target interfaces consist of ports for the MII signals and some AXI signals so data can be read by the HPS. Thanks for your help.
John
John on 8 Jun 2026 at 15:28
Also, I found out that it seems like using multiple clocks with the IP Core Generation workflow isn't even supported because I keep getting this error message: "Failed Setting "Multiple" for parameter "Clock inputs" is not supported in IP Core Generation workflow."
Hi John,
Good follow-up questions. Let me address each one.
What "synchronous" means in the multiple clocks documentation
"Synchronous" in that context refers to what HDL Coder assumes for optimizations and rate transitions. Blocks like Upsample, Downsample, or Rate Transition with data integrity produce logic that relies on aligned clock edges and the HDL Coder optimizations like delay balancing always assume synchronous clocks. However, if you use Rate Transition configured as a wire and turn off HDL timing optimizations, no logic is generated at the crossing boundary and no synchronous relationship is assumed. The clocks become independent bundles and you are responsible for the crossing logic. So HDL Coder does not prevent you from using the generated clocks as truly asynchronous, you just need to use rate-transition-as-wire and disable HDL Coder optimizations.
The IP Core Generation error
That error is expected on R2025b. In R2026a we added multiple clock support in IP Core Generation, but only for the Generic Xilinx Platform. Not directly usable for Intel packaging and constraints, but it can generate the multi-clock HDL itself.
Will HDL Coder treat each Simulink rate as truly independent clocks?
Yes. With ClockInputs set to 'Multiple' and distinct Simulink rates, each rate gets its own clock bundle in the generated HDL.
Practical paths forward (I am assuming you are using R2025b from the Question's Release field)
Staying completely within Simulink for an async FIFO is not feasible today. There is no shipped async FIFO block, though we are working on better CDC support for future releases. Three paths, all involving some manual integration:
  • Stay on R2025b, generate two separate IP cores (one per clock domain), stitch them in Qsys with an Intel DCFIFO between them.
  • Stay on R2025b, use standalone HDL generation (not IP Core Generation) with ClockInputs='Multiple', rate-transition-as-wire, and a black box subsystem with DocBlock to instantiate the Intel DCFIFO. Then manually integrate into Qsys, with this option you would need to generate the interfaces code on your own.
  • Upgrade to R2026a, use Generic Xilinx Platform with ClockInputs='Multiple' and rate-transition-as-wire. Generate the multi-clock HDL IP core, extract the HDL code only and then manually integrate into Qsys. You would have to pack the code manually into a custom IP core and would have to customize the timing constraints that are currently Vivado specific but you could get the interfaces and clock wiring of the design.
Hope this helps.
Best,
Angela
John
John on 9 Jun 2026 at 21:10
Thanks for your help and clarification. Your first bullet point is what I had ended up implementing and I can confirm it works. I generated the the two separate IP cores and the Intel DCFIFO and then I have a top level module to wire them together. It's bit messy of a solution every time there are changes to the simulink model that affect the top level ports and the qsys system has to be regenerated each time. It would be good if you could eventually support multiple clocks on the IP Core Generation workflow for Altera devices and then i could take the black box approach and let simulink handle all of the glue logic.
Glad to hear you got it working and that the separate IP cores approach did the trick. I understand the manual stitching adds friction when the model changes, and your feedback about supporting multiple clocks in IP Core Generation for Intel devices is noted. This is something we are actively working on. In the meantime, glad we could help clarify the options and that you have a working path forward.

Sign in to comment.

More Answers (0)

Products

Release

R2025b

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!