Altera_Forum
Honored Contributor
8 years ago[QSYS] Wrong Avalon memory address generation?
Hi folks,
New year, new opportunities, new problems :P Tl;dr: It looks like Qsys generates address outside of the address space (instead of 0x20, it makes it 0x400000020). Does anybody knows why and/or how to fix this? I came upon the following problem. I have a Qsys system for a CycloneV (see attached screen shot) with some custom made FIFOs (I make the FIFOs myself because the Altera FIFOs are too slow for the application). The basis of this Qsys system originates from this tutorial (https://bitlog.it/hardware/building-embedded-linux-for-the-terasic-de10-nano-and-other-cyclone-v-soc-fpgas/). The FIFOs are used to buffer the data coming from the FPGA with the HPS as destination. The Avalon memory mapped interfaces (two data-out interfaces and two Control-Status-Register interfaces) of those FIFOs are at 0x0, 0x20, 0x40, and 0x60. Qsys accepts this system and has no problems generating it without significant warnings. However, when I want to try to compile this system in Quartus, it starts producing errors. It has to do with the interconnect and addresses of these FIFOs. Instead of mapping the FIFOs to 0x0, 0x20, 0x40, and 0x60, it maps these interfaces to 0x400000000, 0x400000020, 0x400000040, and 0x400000060. Those addresses are, of course, out of the 32 bit address space of the Avalon buss, which results in problems. I have no clue why this happens for my custom IPs, while all other (Altera) IPs at the same Avalon h2f_lw buss are mapped to the right memory address. A sniplet of the errorous code generated by Quartus is shown below (in my case it is the file soc_system_lw_mm_interconnect_3_router.sv).
// -------------------------------------------------------
// Figure out the number of bits to mask off for each slave span
// during address decoding
// -------------------------------------------------------
localparam PAD0 = log2ceil(64'h400000000 - 64'h0);
localparam PAD1 = log2ceil(64'h400000020 - 64'h20);
localparam PAD2 = log2ceil(64'h400000040 - 64'h40);
localparam PAD3 = log2ceil(64'h400000060 - 64'h60);
localparam PAD4 = log2ceil(64'h4010 - 64'h4000);
localparam PAD5 = log2ceil(64'h5010 - 64'h5000);
localparam PAD6 = log2ceil(64'h10008 - 64'h10000);
localparam PAD7 = log2ceil(64'h20008 - 64'h20000);
localparam PAD8 = log2ceil(64'h30100 - 64'h30000);
// -------------------------------------------------------
// Work out which address bits are significant based on the
// address range of the slaves. If the required width is too
// large or too small, we use the address field width instead.
// -------------------------------------------------------
localparam ADDR_RANGE = 64'h400000060;
localparam RANGE_ADDR_WIDTH = log2ceil(ADDR_RANGE);
localparam OPTIMIZED_ADDR_H = (RANGE_ADDR_WIDTH > PKT_ADDR_W) ||
(RANGE_ADDR_WIDTH == 0) ?
PKT_ADDR_H :
PKT_ADDR_L + RANGE_ADDR_WIDTH - 1;
localparam RG = RANGE_ADDR_WIDTH-1;
// ( 0x0 .. 0x400000000 )
if ( {address,{PAD0{1'b0}}} == 35'h0 && read_transaction ) begin
src_channel = 9'b000100000;
src_data = 6;
end
// ( 0x20 .. 0x400000020 )
// ( no optimization for non-address-span aligned address range )
if ( ( ( sink_data >= 'h20) && (sink_data < 'h400000020) )
&& read_transaction ) begin
src_channel = 9'b000000100;
src_data = 5;
src_data = sink_data - 'h20;
end
// ( 0x40 .. 0x400000040 )
// ( no optimization for non-address-span aligned address range )
if ( ( ( sink_data >= 'h40) && (sink_data < 'h400000040) )
&& read_transaction ) begin
src_channel = 9'b001000000;
src_data = 4;
src_data = sink_data - 'h40;
end
// ( 0x60 .. 0x400000060 )
// ( no optimization for non-address-span aligned address range )
if ( ( ( sink_data >= 'h60) && (sink_data < 'h400000060) )
&& read_transaction ) begin
src_channel = 9'b000001000;
src_data = 3;
src_data = sink_data - 'h60;
end
The parameter RG will therefore become 34, which is out of the 32 bit address space (and out of the 0 to 33 bits bitvector bit address (actually I don't understand why this bitvector is 34 bits wide instead of 32 but yeah...probably some extra status bits added by the Avalon bus or so)). If I see the code-part with the if-statements. It looks like it maps the FIFOs not from i.e. 0x00 to 0x1f but from 0x00 to 0x400000000. I also tried to use the f2h_axi buss instead of the f2h_lw_axi bus, but that does result in the same problems. Do you know where this problem originates from and/or how to fix this issue? Thanks a lot :) P.s: I have tried to change 0x4000000Y0 addresses to 0xY0 addresses by hand in the first 10-ish lines functional code (untill and including "localparam ADDR_RANGE = 64'h400000060;"). The thing does compile than, but there still seems to be problems with accessing the memory addresses via the HPS/unix. Therefore I think that this is not the solution.