Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16603 Discussions

[QSYS] Wrong Avalon memory address generation?

Altera_Forum
Honored Contributor II
1,413 Views

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.
0 Kudos
1 Reply
Altera_Forum
Honored Contributor II
632 Views

Hi all, 

 

I changed the address locations to the expected address location by hand (in the given file above, the "<project name>_mm_interconnect_2_router.sv") and now it seems to work fine. So I think this is a bug in Qsys, or could it also be a settings thing? 

 

Anyhow, the code snippet above now becomes: 

// ------------------------------------------------------- // Figure out the number of bits to mask off for each slave span // during address decoding // ------------------------------------------------------- localparam PAD0 = log2ceil(64'h08 - 64'h0); localparam PAD1 = log2ceil(64'h28 - 64'h20); localparam PAD2 = log2ceil(64'h48 - 64'h40); localparam PAD3 = log2ceil(64'h68 - 64'h60); // ------------------------------------------------------- // 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'h68; 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; localparam REAL_ADDRESS_RANGE = OPTIMIZED_ADDR_H - PKT_ADDR_L; reg address; always @* begin address = {PKT_ADDR_W{1'b0}}; address = sink_data; end // ------------------------------------------------------- // Pass almost everything through, untouched // ------------------------------------------------------- assign sink_ready = src_ready; assign src_valid = sink_valid; assign src_startofpacket = sink_startofpacket; assign src_endofpacket = sink_endofpacket; wire default_destid; wire default_src_channel; // ------------------------------------------------------- // Write and read transaction signals // ------------------------------------------------------- wire read_transaction; assign read_transaction = sink_data; soc_system_mm_interconnect_2_router_default_decode the_default_decode( .default_destination_id (default_destid), .default_wr_channel (), .default_rd_channel (), .default_src_channel (default_src_channel) ); always @* begin src_data = sink_data; src_channel = default_src_channel; src_data = default_destid; // -------------------------------------------------- // Address Decoder // Sets the channel and destination ID based on the address // -------------------------------------------------- // ( 0x0 .. 0x400000000 ) if ( {address,{PAD0{1'b0}}} == 35'h0 && read_transaction ) begin src_channel = 4'b1000; src_data = 3; end // ( 0x20 .. 0x400000020 ) // ( no optimization for non-address-span aligned address range ) if ( ( ( sink_data >= 'h20) && (sink_data < 'h28) ) && read_transaction ) begin src_channel = 4'b0010; src_data = 2; src_data = sink_data - 'h20; end // ( 0x40 .. 0x400000040 ) // ( no optimization for non-address-span aligned address range ) if ( ( ( sink_data >= 'h40) && (sink_data < 'h48) ) && read_transaction ) begin src_channel = 4'b0100; src_data = 1; src_data = sink_data - 'h40; end // ( 0x60 .. 0x400000060 ) // ( no optimization for non-address-span aligned address range ) if ( ( ( sink_data >= 'h60) && (sink_data < 'h68) ) && read_transaction ) begin src_channel = 4'b0001; src_data = 0; src_data = sink_data - 'h60; end 

 

Hope this helps others with this problem. However I am still very interested in the reason of this problem. Therefore if you could provide me (a part of) the clue, it would be very welcome!
0 Kudos
Reply