Progressing from where I stopped last week, this week I had to finish everything up and make sure that everything works as it’s supposed to. Before I go in details and describe what I have done, I have to clear some stuff that were left from last week up regarding the placement of the BRAM.
Location of BRAMs:
In my blog entry of last week I have declared that I had some concerns regarding the location of BRAM (Refer to my last blog entry for more info). The solution was quite simple as described by Dr. Shawn. The Locations of each BRAM can be specified earlier in the user constrain file. So when you run Xilinx synthesis and implementation tools on your HDL design with the UCF file that has the location of the BRAM primitives in it, the PAR tool will place those BRAM in the specified location saving you the trouble of checking the BRAM locations in .ncd file every time in order to be able to write the .bmm file.
Completion of the Soc:
This week I had to include another 16 kbyte Data memory to our design. This memory will store the data of the user code. Since both the I/os and the data memory should be connected to the data bus of the processor a simple switch is needed to decide whether the processor wants to communicate with data memory or the I/o (GPIO) based on the MSB in the address bus . So our memory map will be as follows: Our instruction RAM has its own interface with processor so the addresses will start from 0X00000000 up to the end address which is based on the instruction RAM size. But for the processor data bus, both the data memory and the I/O will be sharing it so the upper address will be dedicated to the I/o devices while the lower addresses (0x80000000) will be dedicated to the data memory. So after adding the data memory to our Soc I ran all the Xilinx tools on the new design and checked the output of the xst tool and par tool to make sure that they have inferred the right numbers of block rams in the right locations.
Now the final new bitstream is ready to be initialized with the ELF file content. But to generate an elf file with our required memory addresses we have to feed the compiler with a new linker script that will map the (.data , .bss .. ) sections to the memory locations we want (data memory space) and (.text) section to (instruction memory space) .
In our case and since the data memory reside in the starting address 0x80000000 our new linker script is modified so all the sections related to the data memory are mapped to this address range (0x80000000-0xffffffff).
After creating the new elf file by the new linker script and initialized the new bit stream with it, I wanted to verify that the BRAMs have been initialized with the correct content at the correct addresses.
To do so first I tried to check by dumping the elf file to .mem file using the command:
data2mem -bd UserCode.elf -d -o code.mem but I kept getting segmentation fault I tried to figure out why that happened but I didn’t manage to solve it. It seems that the problem has something to do with the linker script as no errors occurred when the .elf file was compiled with the default linker script. Any way later I managed to find this documentation “data2mem verification in EDK “which presents a step-by-step procedure to do the data2mem verification.
In short, all you have to do is first to dump your .elf file using this command:
mb-objdump -D UserCode.elf > elf_dump.txt
The elf_dump.txt will provide you with the location of your instruction code and the data in the corresponding memory address of your BRAM.
secondly, dump you .bit file as well using the following command:
data2mem -bm x.bmm -bt x.bit -d > dump_x.txt
Thirdly, Compare the content of the your BRAMs with content of the addresses specified in the dump .elf file as explained in the document above 😀 .
By following the procedure above, finally I can say that the final bit stream is initialized with the correct content. Hopefully everything will go smoothly when this bitsream get into the board. 😀 PRAY FOR ME