UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 55279

Vivado HLS Coding Examples: Implement a simple parallel read/​write mechanism in Vivado HLS

Description

In the example code below,  a simple parallel read/write mechanism is being implemented.
 
The purpose of this test module is to check how the code is capable of reading/writing in every clock cycle.

Are there specific pragmas, or design suggestions available for such problems?
 
void paralleltest(bool _doWrite, int _writeAddr, int  _writeData,
                  bool _doRead,  int _readAddr,  int* _readData)
{
   static const int BufferSize = 1024;
   static       int buffer[BufferSize];
  
   if (_doWrite) {
      buffer[_writeAddr % BufferSize] = _writeData;
   }
   if (_doRead) {
      *_readData = buffer[_readAddr % BufferSize];
   }
}

Solution

Below are some Directives which can be used together to achieve this. 

This article covers how to apply each of these directives individually and what effect they will have.

It also shows the effect of applying all of the Directives together.

Simulation without any Directive:

3.png
1) INTERFACE Directive

Description: This directive controls how the function arguments would be synthesized into RTL port.

Example: #pragma HLS INTERFACE ap_ctrl_none port=return : Used to avoid a function call handshake.

If the Directive is not used, the Interface list is as below:

1.png
When the Directive is used, the Interface list is as below:

2.png
You would see that the control signals ap_start, ap_done, ap_idle and ap_ready are not present. 

This prevents the function handshake.

2) PIPELINE Directive

Description: Reduces the initiation interval of the function by allowing the concurrent execution of operations within a function.

Example: #pragma HLS PIPELINE II=1: Used to allow new data in the input in every clock cycle.

This directive would not have any impact when used alone due to dependency between load and store operation.

This is from the synthesis log:
@I [SCHED-61] Pipelining function 'paralleltest'.
@W [SCHED-68] Unable to enforce a carried dependency constraint (II = 1, distance = 1)
   between 'load' operation ('buffer_load', paralleltest.cpp:11) on array 'buffer' and 'store' operation (paralleltest.cpp:7) of variable '_WriteData' on array 'buffer'.
@W [SCHED-68] Unable to enforce a carried dependency constraint (II = 2, distance = 1)
   between 'load' operation ('buffer_load', paralleltest.cpp:11) on array 'buffer' and 'store' operation (paralleltest.cpp:7) of variable '_WriteData' on array 'buffer'.
@I [SCHED-61] Pipelining result: Target II: 1, Final II: 3, Depth: 3.

Simulation with the PIPELINE directive:

4.png
 
3) DEPENDENCE Directive.

Description: Used to provide additional information that can overcome loop-carry dependencies.

Example: #pragma HLS DEPENDENCE variable=buffer inter WAR false: Used to remove dependency between read and write.

This directive would not have any impact when used alone due to less dependency between read and write.

Simulation with the DEPENDENCE directive:

5.png
 
4) RESOURCE Directive.

Description: Specify which hardware resource (RAM component) an array maps to (if used on Array's)

Example: #pragma HLS RESOURCE variable=buffer core=RAM_2P_BRAM:  A dual-port RAM, using separate read and write ports, implemented with a block RAM.

Simulation with the RESOURCE directive:
 
6.png

When all of these directives are applied on our example code, the resulting code is capable of reading/writing in every clock cycle. (See the Read/Write wrt ap_clk)

Simulation with directives:

7.png


Attachments

Associated Attachments

Name File Size File Type
Project.zip 18 KB ZIP
AR# 55279
Date Created 03/31/2013
Last Updated 06/25/2014
Status Active
Type General Article
Devices
  • Kintex-7
Tools
  • Vivado Design Suite - 2012.4