AXI4 Master Read SDRAM

I'm using a Cyclone V SoC and in my reference design I have a FPGA to HPS SDRAM Interface enabled under the HPS. I'm expecting sensor data to be written to a specific address within this SDRAM. I need the Mathworks generated IP to have a AXI4 master interface in order to read directly from this memory so the sensor values can be used in the generated model. In the plugin_rd() function definition I tried adding something such as this:
% Define AXI4 Master interface
hRD.addAXI4MasterInterface( ...
'InterfaceConnection', 'hps_0.f2h_sdram0_data', ...
'InterfaceID', 'f2h_sdram0', ...
'AddrWidth', 32);
I don't see any blocks I can use in the simulink model in order to be able to read from the SDRAM. Thank you for any help.

 采纳的回答

Umar
Umar 2025-10-7

0 个投票

Hi @John,

Saw your comments about the Cyclone V SoC setup and the missing “read from SDRAM” block—here’s a quick summary and clarification.You’re already on the right path with

hRD.addAXI4MasterInterface( ...
  'InterfaceConnection','hps_0.f2h_sdram0_data', ...
  'InterfaceID','f2h_sdram0', ...
  'AddrWidth',32);

but remember, that line only declares the AXI4 Master interface in the reference design. HDL Coder doesn’t automatically create read logic or a block for you; the actual handshake must live inside your DUT subsystem.

Here’s how to wire it up:

1. Inside `plugin_rd()` Add the master interface with read capability enabled:

     hRD.addAXI4MasterInterface( ...
       'InterfaceConnection','hps_0.f2h_sdram0_data', ...
       'InterfaceID','f2h_sdram0', ...
       'ReadSupport','true', ...
       'WriteSupport','false', ...
       'AddrWidth',32, ...
       'MaxDataWidth',32, ...
       'HasMemoryConnection',true, ...
       'DefaultReadBaseAddr',hex2dec('80000000'), ...
       'ProcessorAccessibleMemoryRegion',[hex2dec('80000000') 
        hex2dec('00200000')]);

2. In the DUT subsystem Expose ports for the simplified AXI4 Master handshake:

     rd_addr     – byte address
     rd_len      – number of words
     rd_avalid   – request valid
     rd_aready   – slave ready
     rd_data     – read data
     rd_dvalid   – data valid

Implement a small FSM that asserts `rd_avalid` when `rd_aready` is high, issues the address and length, then waits for `rd_dvalid` and samples `rd_data`.

3. For simulation Connect those ports to an AXI4 Random Access Memory block from the SoC Blockset. This acts as a stand-in for SDRAM and lets you verify timing and data flow before generating HDL.

Once the FSM is working, map your `rd_*` signals to the `f2h_sdram0` interface in the IP Core Editor (Target Interface tab). The generated IP will then access HPS SDRAM directly at runtime—no extra Simulink memory block needed.

References

Simplified AXI4 Master Interface


https://www.mathworks.com/help/soc/ug/model-design-for-axi4-master-interface-generation.html%E2%80%A8

This page shows exactly which rd_* / wr_* signals you model in your DUT, what their handshaking semantics are, and how HDL Coder translates them into real AXI4 master logic.

Model Design for AXI4 Master Interface Generation


https://www.mathworks.com/help/hdlcoder/ug/model-design-for-axi4-master-interface-generation.html%E2%80%A8

This covers how to design your DUT ports to map to AXI4 master, how the simplified protocol is used in IP Core Generation, and more.

Design a Model for AXI4 Interfaces


<https://www.mathworks.com/help/hdlcoder/modeling-for-deployment.html%E2%80%A8>

This gives a broader view: how to approach modeling algorithms in Simulink/HDL Coder for AXI4-Stream, AXI4 master, etc.

Generate HDL IP Core with Multiple AXI4-Stream and AXI4 Master Interfaces


https://www.mathworks.com/help/hdlcoder/ug/map-dut-ports-to-multiple-axi-interfaces.html%E2%80%A8

Useful when your design has more than one interface; explains how to map ports to multiple AXI interfaces.

Hope this helps.

9 个评论

I was able to create a simple test for writing to a memory location:
and I was able to verify that the value was being written into the memory location I was expecting.
I then tried doing a simple read test where I would read a memory location and write its value to another memory location. However, the processor completely hangs when I attempt this.
I tried simulating this using the AXI4 Random Access Memory and it outputs the data value i expect based on how the memory was initialized.
This was the my interface mapping

Hi @John,

I've gone through your screenshots carefully and I can see exactly what's happening. Good news is your write implementation looks solid - that's why it's working. The read hanging issue is something I've seen before with the Cyclone V f2h SDRAM interface, and I think I've spotted the problem. Looking at your working write test: * You're writing to address 0x10000004 * Using wr_len = 1 (single word transfer) * It completes successfully

Looking at your read test that hangs: * You're trying to read from address 0x10000004 * Using rd_len = 1 (single word transfer) * Then writing that value to another location * Processor hangs during the read operation

Here's the issue: while your simulation with the AXI4 Random Access Memory works fine with rd_len = 1, the actual Cyclone V SDRAM controller often has minimum burst requirements that the simulation block doesn't enforce. From the forum posts and documentation I found, the f2h SDRAM interface can be picky about burst lengths - particularly for reads. So, try this first, change your rd_len from 1 to something like 2, 4, or 8. I know you only need to read one value, but the SDRAM controller may not respond properly to single-beat read bursts.

Here's what to do:

1. Set rd_len to a constant value of 2 (or higher) 2. Keep everything else the same 3. When rd_dvalid goes high, just take the first data word and ignore any subsequent words

The reason writes work with wr_len = 1 but reads don't is that write and read channels can have different timing requirements in the SDRAM controller - reads often need longer bursts to pipeline properly. Now, looking at your interface mapping, it looks correct:

  • read_slave (Input) -> f2h_sdram0 Read -> Read Slave to Master Bus
  • data_in (Input) -> f2h_sdram0 Read -> Data
  • wr_ready (Input) -> f2h_sdram0 Write -> Write Slave to Master Bus
  • read_master (Output) ->f2h_sdram0 Read ->Read Master to Slave Bus
  • Data (Output) -> f2h_sdram0 Write -> Data
  • Write Master to Slave bus (Output) -> f2h_sdram0 Write

This all checks out, so the mapping isn't your issue. I did notice that you are using address 0x10000004, which is 4-byte aligned. That's good for a 32-bit interface. But just to be safe, verify:

 * Your data width in the SDRAM interface configuration matches what you specified (uint32 = 32 bits)
 * The address is definitely within your accessible memory region

So the reason your simulation is working but hardware does not is because of AXI4 Random Access Memory block in simulation is very forgiving - it responds to any valid transaction. The actual Cyclone V SDRAM controller has real hardware constraints:

  • Minimum burst requirements for efficient operation
  • Pipeline depth considerations
  • Internal buffering requirements

These don't show up in simulation because the test block doesn't model them. So, here is step by step fix to try:

1. First test: Change rd_len from constant(1) to constant(2) in your read logic (Image 3, top section where you have the constant '1' connected to rd_len)

2. If that works: Try rd_len = 4 or rd_len = 8 to see if higher bursts are more stable

3. If it still hangs with rd_len = 2: Then we need to look at whether rd_dvalid is even asserting. This would mean the SDRAM controller isn't responding at all, which points to a different issue (like the bridge not being properly enabled or configured)

4. Debug visibility: If you have access to SignalTap or can add some LED indicators, monitor:

    * Is rd_aready going high? (tells you the controller is ready for requests)
    * Is rd_dvalid ever going high? (tells you if data is coming back)
    * What state is your read FSM in when it hangs?

References for the burst length stuff

So, start by changing rd_len to 2 or higher. I'm hoping this will fix it. The SDRAM controller is probably waiting for more data requests before it starts the pipeline, and with rd_len = 1, it's just sitting there forever.

Let me know what happens when you try the higher burst length. If that doesn't fix it, we'll dig into whether the read channel is configured properly in your Qsys system.

Here is a screenshot of the system_soc.qsys project
Unfortunately changing rd_len to 2 did not fix it. It does seem like the IP core is being correctly connected to the f2h_sdram0_data interface. However, when I test using signal tap, the rd_ready and rd_dvalid signals are never asserted.

Hi @John,

The Qsys screenshot shared by you confirms that `f2h_sdram0` (AXI-3, 32-bit) and the clocks are routed correctly, so the topology looks fine. Since `rd_aready` and `rd_dvalid` never assert in SignalTap, this points to a runtime issue — most likely the F2H SDRAM bridge isn’t actually enabled, or there’s an `rd_dready`/address-mapping problem, rather than an RTL wiring error. Try capturing `rd_avalid`, `rd_aready`, `rd_dvalid`, and `rd_dready` in SignalTap, and double-check the HPS handoff (u-boot or device-tree) to make sure the bridge is fully enabled.

I believe this is the relevant section of my dts file:
fpgabridge@3 {
compatible = "altr,socfpga-fpga2sdram-bridge";
linux,phandle = <0x64>;
phandle = <0x64>;
};
It seems like it is correct but i'm not sure how to verify it is fully enabled.

Hi @John,

Your device tree snippet appears correct, enabling the FPGA-to-SDRAM bridge requires more than just including it in the device tree. Here's a step-by-step guide to ensure it's fully enabled:

1. Device Tree Configuration Your device tree entry for the bridge looks correct:

       dts
       fpgabridge@3 {
         compatible = "altr,socfpga-fpga2sdram-bridge";
         linux,phandle = <0x64>;
         phandle = <0x64>;
       };
   * Ensure this node is included in your final `.dtb` file and is accessible at boot time.

2. U-Boot Handoff

   * In U-Boot, use the following command to enable the bridge:
       bridge_enable_handoff
   * This command safely enables the bridge by applying the necessary configurations and releasing resets. 

https://www.intel.com/content/www/us/en/docs/programmable/683360/18-0/access-hps-sdram-via-the-fpga-to-sdram.html

3. Apply Configuration (APPLYCFG)

   * After programming the FPGA, ensure the bridge's configuration is applied:
        devmem 0xFFC2505C 32 0xA
   * This writes `0xA` to the `APPLYCFG` bit in the `STATICCFG` register, which latches the configuration. 

support.criticallink.com

4. Release FPGA Port Reset

   * Once the configuration is applied, release the FPGA ports from reset:
         devmem 0xFFC25080 32 0xFFFF
  • Use SignalTap to monitor the following signals:
* `rd_avalid`: Indicates a valid read address.
* `rd_aready`: Indicates the read address is ready.
* `rd_dvalid`: Indicates valid read data.
* `rd_dready`: Indicates the read data is ready.
  • If `rd_aready` and `rd_dvalid` never assert, it suggests the bridge isn't fully enabled or there's an issue with the configuration.

Let me know how it goes.

As a santiy check, I changed the AXI4 interface to connect to the System ID IP core and read the ID from there. I was able to successfully read the ID so I know matlab is correctly generating the AXI4 master interface and can read data from the bus so the problem definitely seems to be a misconfiguration with my SDRAM or the way I am attempting to read the memory. I atttempted to check the bridge status from Linux:
socfpga> cat /sys/class/fpga_bridge/*/name
lwhps2fpga
hps2fpga
fpga2sdram
socfpga> cat /sys/class/fpga_bridge/*/state
enabled
enabled
enabled
I have been using the Mathworks provided Linux image and I'm not too familiar with altering the U-boot configuration but this seems to indicate that the bridge should be enabled, correct? I will attempt to capture those signals you referenced on SignalTap as a next step.

Hi @John,

Great troubleshooting! This confirms your AXI4 master interface is working correctly and can read from the bus. This definitively narrows the problem to the F2SDRAM bridge configuration, not your MATLAB-generated interface.

You mentioned, " I have been using the Mathworks provided Linux image and I'm not too familiar with altering the U-boot configuration but this seems to indicate that the bridge should be enabled, correct?"

The bridges showing "enabled" is a good sign—it means the kernel driver loaded successfully. However, this doesn't guarantee the low-level hardware registers are properly configured. The "enabled" state just means the bridge isn't actively disabled by Linux.

Good news: you don't need to modify U-Boot for this. The devmem commands I provided can be run directly from your Linux console after boot. They'll configure the hardware registers that control the actual SDRAM port, which may not be set by the Mathworks image.

Next Steps:

Before doing SignalTap debugging, try these commands from Linux:

devmem 0xFFC2505C 32 0xA       # Apply SDRAM bridge configuration
devmem 0xFFC25080 32 0xFFFF    # Release FPGA port reset

After running these commands, test your SDRAM read operation again from MATLAB and check if rd_aready and rd_dvalid now assert.Given that your AXI4 works with System ID but SDRAM signals never assert, this is very likely the missing piece. If these commands fix it, you can add them to a startup script so they run automatically after boot.

If this doesn't solve it:

Then proceed with the SignalTap capture to monitor rd_avalid, rd_aready, rd_dvalid, and rd_dready. Also verify you're reading from valid SDRAM address ranges (typically 0x00000000 - 0x3FFFFFFF on Cyclone V).

Keep me posted. You're doing great!

That worked! Thank you very much. Using devmem is fine now for testing but I assume for the final code I would want those HPS registers to be set by the u-boot script or something like that. I will eventually have to figure that out.

请先登录,再进行评论。

更多回答(0 个)

类别

帮助中心File Exchange 中查找有关 System on Chip (SoC) 的更多信息

产品

版本

R2024b

标签

Community Treasure Hunt

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

Start Hunting!

Translated by