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?

Respuestas (1)

Angela Cuadros Castiblanco
Angela Cuadros Castiblanco hace alrededor de 5 horas

1 voto

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:
https://www.mathworks.com/help/hdlcoder/ug/use-triggered-subsystem-for-asynchronous-clock-domain.html
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:
https://www.mathworks.com/help/hdlcoder/ug/generate-cdc-synchronizer-using-multiple-clock-ip-core-generation.html
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:
https://www.mathworks.com/help/simulink/slref/ratetransition.html#refsect-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:
https://www.mathworks.com/help/hdlcoder/ug/integrate-custom-hdl-code-using-docblock.html
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

Productos

Versión

R2025b

Etiquetas

Preguntada:

el 5 de Jun. de 2026 a las 14:44

Respondida:

el 5 de Jun. de 2026 a las 18:58

Community Treasure Hunt

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

Start Hunting!

Translated by