06-13-2019 10:29 PM
We have a design in which registers are programmed/read through axilite interface. Some of the registers are written through axilite and these are only read by
design internally while some registers are written through axilite, their values are modified by design and these modified values are read from axilite interface. So
in HLS implementation of design, how should the parameters representing these registers be passed? (by reference or by value). Our understanding is that if a register
is programmed/written from axilite and its value is only read internally by design (and not modified), it can be passed by value. The registers whose values are
programmed from axilite and modified by design internally are need to be passed by reference. Is this assumption correct?
For example, consider the following top function that takes two variables(a and b) as arguments. We want to know whether 'a' and 'b' should be sent by value or by
void top_function(ap_uint<8> a, ap_uint<8> b)
#pragma HLS INTERFACE s_axilite port=a
#pragma HLS INTERFACE s_axilite port=b
#pragma HLS INTERFACE s_axilite port=return
c = a + b; // we just read a and b
b = c + 5; // we modify b
The 'a' variable will only be read by the DUT and the 'b' will be read as well as modified by the DUT. So how should 'a' and 'b' be sent? Should they be sent by value
or by reference?
We feel a should be passed by value and b by reference. Does presence of axilite make any difference in this understanding. Also can we pass a by reference. In that
case, will the design work correctly.
Can someone help please.
06-14-2019 03:30 AM
We feel a should be passed by value and b by reference. Does presence of axilite make any difference in this understanding. Also can we pass a by reference.
Correct! I would generally pass 'a' by value and 'b' by reference, at least on the HLS side of things.
AXI Lite will have a effect on how the implementation is done. Instead of having a single value for 'b' (as you would in normal C code), in AXI Lite you'll have separate 'write' and 'read' addresses. The generated addresses (from the _hw.h driver file) will look like:
// 0x18 : Data signal of b_i // bit 31~0 - b_i[31:0] (Read/Write) // 0x1c : reserved // 0x20 : Data signal of b_o // bit 31~0 - b_o[31:0] (Read) // 0x24 : Control signal of b_o // bit 0 - b_o_ap_vld (Read/COR) // others - reserved
In this case, when you're writing a value to 'b' from outside the block, you write to address 0x18. To read from 'b' when the block is finished, you wait until 0x24 == 1 (indicating that the value is available) and then read 0x20. This behaviour is a bit odd, and HLS doesn't do it for RAMs (with a RAM on an AXI Lite interface, each address is both read and write) but it's easy to use once you get used to it.
Passing 'a' by reference will have ... no effect at all! HLS is smart enough to see that your block only reads from 'a', so it doesn't bother to include the output side of that port.
06-15-2019 10:36 PM - edited 06-15-2019 10:50 PM
thanks for the detailed reply. We are not clear when the control signal of b_o is to be used. There could be variables which are always valid.
For example, suppose we need to implement a counter, which is preset from the AXIlite, incremented/decremented under some condtions inside DUT and is read through AXIlite. (example could be a statistics counter counting number of packets received for a DUT implementing some network protocol. The counter may need to be preset or reset by software). This counter value is valid every clock (it can be read anytime through axilite). In that case, we need not have control signal for counter (similar to b_o), indicating count is valid. So how can we specifiy to axilite not to generate control signal of count_o? Or is it always generated by default and it is upto the user whether to use it or not ?
06-16-2019 12:39 AM
firstname.lastname@example.org You can use the additional interface type ap_none (ie #pragma HLS INTERFACE ap_none port=b) which should get rid of the control signal.
Note that if you're doing this, you will need to mark the variable as "volatile" in the C code. This tells HLS (and the C compiler) that it should not try to optimize accesses to that variable (eg. by keeping an internal copy and only writing the output value when the block finishes). It will also be impossible to properly simulate this in C, as a C simulation is single-threaded. There is no way to read the value while the block continues to run.