cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
paulJX1
Visitor
Visitor
597 Views
Registered: ‎06-14-2020

Vitis/Vivado HLS 2020.2 ap_done never asserted HIGH for ap_ctrl_hs block-level interface

Jump to solution

Hello HLS-Forum,

I have a seemingly Vitis HLS bug to report:

Version Vitis HLS 2020.2. (same issue occurs in 2018.2 too, causing me to try 2020.2 the most recent version and the problem is similar.)

1. We have an HLS-synthesized RTL module that works/runs nicely with AXI-lite Vivado-SDK interface, controlled by a Microblaze soft processor.

2. Recently we are converting the control interface from AXI-lite to ap_crtl_hs block-level interface, namely {ap_idle, ap_start, ap_ready, ap_done} with directly wired input and output data, exerted by an adjacent hand-crafted RTL block.

3. But such direct ap_ctrl_hs interface does not work. The ap_idle signal does get asserted HIGH, and when ap_start is asserted HIGH, ap_idle goes LOW. However, ap_ready or ap_done never goes HIGH at all. Thus the HLS block seems to be stuck.

4. We are pretty sure that ap_rst is properly asserted and released by the Block Design; Also in order to ensure that the problem is not due to clocking, we experimented with lowering the clock from 83.333MHz (that had worked fine for AXI-Lite SDK interface) to 50MHz, but that did not help.

5. Again as stated before, this problem persists from 2018.2 to 2020.2.

6. The FPGA being used is Artix7-100T, and the board is Digilent's Arty-100T board.

Thanks.

Paul

0 Kudos
1 Solution

Accepted Solutions
paulJX1
Visitor
Visitor
431 Views
Registered: ‎06-14-2020

It turns out to be my own lack of understanding of the ap_ctrl_hs signaling protocol. Now solved by my own trials-and-errors because no responses whatsoever were given by the forum.

The host controller sequencer that drives the HLS-IP block (as a slave) operates with a slower clock, thus responding to ephemeral ap_ready, ap_done and ap_vld (output valid signals) could not be timely enough before those signals disappear. Thus I constructed a small Verilog module to do buffering and responding, including a) self-clearing ap_start upon ap_ready, b) buffer/latch ap_ready, c) buffer/latch ap_done, d) latch output data upon ap_vld, and so on. And now everything seems to work fine.

With only one question remaining, for a non-pipelining HLS module, can I self-clear ap_start with a one clock-period pulse, or should I stick to clearing ap_start upon ap_ready?

This case can be closed. Thanks.

Paul

 

View solution in original post

0 Kudos
2 Replies
paulJX1
Visitor
Visitor
527 Views
Registered: ‎06-14-2020

The following cpp code fragments show the style-conversion from AXILITE to ap_ctrl_hs .

 

/*-----------------------------------------------------------------------------*/

typedef unsigned int uint;
typedef unsigned char byte;

#define MAX_INDATA_BSIZE 114
#define MAX_IODATA_BSIZE100 100
#define MAX_INDATA_BSIZE68 68

/* start AXILITE_template:

bool foobar(byte functn_index, byte result_barr[MAX_IODATA_BSIZE100], byte data1_barr[MAX_INDATA_BSIZE],
int data1_barr_Length, byte data2_barr[MAX_INDATA_BSIZE68], byte datar_index,
uint data_out_in6, uint data_out_in5, uint data_out_in4, uint data_out_in3, uint data_out_in2,
uint data_out_in1, uint data_out_in0);
#pragma HLS INTERFACE s_axilite port=functn_index bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=result_barr bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=data1_barr bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=data1_barr_Length bundle=BUS_A
#pragma HLS INTERFACE s_axilite port=data2_barr bundle=BUS_A
#pragma HLS INTERFACE ap_none port=datar_index
#pragma HLS INTERFACE ap_none port=data_out_in6
#pragma HLS INTERFACE ap_none port=data_out_in5
#pragma HLS INTERFACE ap_none port=data_out_in4
#pragma HLS INTERFACE ap_none port=data_out_in3
#pragma HLS INTERFACE ap_none port=data_out_in2
#pragma HLS INTERFACE ap_none port=data_out_in1
#pragma HLS INTERFACE ap_none port=data_out_in0
#pragma HLS INTERFACE s_axilite port=return bundle=BUS_A

* end AXILITE_template */


/* start APCTRLHS_template:

bool foobar(byte functn_index,
uint *result_barr00, uint *result_barr01, uint *result_barr02, uint *result_barr03,
uint *result_barr04, uint *result_barr05, uint *result_barr06, uint *result_barr07,
uint *result_barr08, uint *result_barr09, uint *result_barr10, uint *result_barr11,
uint *result_barr12, uint *result_barr13, uint *result_barr14, uint *result_barr15,
uint *result_barr16, uint *result_barr17, uint *result_barr18, uint *result_barr19,
uint *result_barr20, uint *result_barr21, uint *result_barr22, uint *result_barr23,
uint *result_barr24,
uint data1_barr00, uint data1_barr01, uint data1_barr02, uint data1_barr03,
uint data1_barr04, uint data1_barr05, uint data1_barr06, uint data1_barr07,
uint data1_barr08, uint data1_barr09, uint data1_barr10, uint data1_barr11,
uint data1_barr12, uint data1_barr13, uint data1_barr14, uint data1_barr15,
uint data1_barr16, uint data1_barr17, uint data1_barr18, uint data1_barr19,
uint data1_barr20, uint data1_barr21, uint data1_barr22, uint data1_barr23,
uint data1_barr24, uint data1_barr25, uint data1_barr26, uint data1_barr27,
byte data1_barrB112, byte data1_barrB113,
byte data1_barr_bLength,
uint data2_barr00, uint data2_barr01, uint data2_barr02, uint data2_barr03,
uint data2_barr04, uint data2_barr05, uint data2_barr06, uint data2_barr07,
uint data2_barr08, uint data2_barr09, uint data2_barr10, uint data2_barr11,
uint data2_barr12, uint data2_barr13, uint data2_barr14, uint data2_barr15,
uint data2_barr16,
byte datar_index,
uint data_out_in6, uint data_out_in5, uint data_out_in4, uint data_out_in3, uint data_out_in2,
uint data_out_in1, uint data_out_in0);

* end APCTRLHS_template */
/*-----------------------------------------------------------------------------*/

0 Kudos
paulJX1
Visitor
Visitor
432 Views
Registered: ‎06-14-2020

It turns out to be my own lack of understanding of the ap_ctrl_hs signaling protocol. Now solved by my own trials-and-errors because no responses whatsoever were given by the forum.

The host controller sequencer that drives the HLS-IP block (as a slave) operates with a slower clock, thus responding to ephemeral ap_ready, ap_done and ap_vld (output valid signals) could not be timely enough before those signals disappear. Thus I constructed a small Verilog module to do buffering and responding, including a) self-clearing ap_start upon ap_ready, b) buffer/latch ap_ready, c) buffer/latch ap_done, d) latch output data upon ap_vld, and so on. And now everything seems to work fine.

With only one question remaining, for a non-pipelining HLS module, can I self-clear ap_start with a one clock-period pulse, or should I stick to clearing ap_start upon ap_ready?

This case can be closed. Thanks.

Paul

 

View solution in original post

0 Kudos