Well this week the progress was relatively slow, and the output could really approach to zero, although the task at first glance seemed quite easy and that it could be done within one day only 😛 .
Picking up from where we left off last week, the total project integration continued. In this week my task was divided into three: first I should modify some part of project which related to Xilinx synthesis tool (XST) and the project file that is needed during the process, the second task was related to the addresses of the I/Os that the user defined and finally getting the user C++ code compiled and merged with the bitstream.
Okay let’s talk about them one by one:
The XST project file:
If you worked with Xilinx synthesis tool (XST) before, you would notice that this tool needs file called project file which lists all the HDL modules that the tool needs to consider during running the synthesis process. Previously, I used to edit this file manually every time I added new modules to my Verilog top level module, but in our project this file should be automatically modified and updated with the modules that the user instantiate in the C++ code. The solution for this issue was simply described by Dr. Shawn. Instead of listing all the modules files names we can simply list only when Verilog file that has all the required modules definition written down on it. To achieve this I simply first used this command:
iverilog -wall -tvhdl -y (path of the Verilog modules lib) -o (output vhdl file) (Verilog top module file)
Running this command line will convert all the modules definition in the top module to vhdl and list them all out in one file. Trying to Synthesize this file produce too many errors. So I turn to use the same technique but using Verilog language instead of vhdl. At the end I managed to get it done and worked. Any way that was expected.
Although the task seemed easy, finding the right terminal commands to create the final big Verilog file took a significant time.
Drivers and I/O addresses:
Previously, during the creation of the Verilog top module, I managed to extract the addresses of the I/Os devices based on their location and connection with the switches. So now the time comes to make use of these addresses, those addresses are used to tell the processor where the I/Os are located. So the processor can perform the task of writing and reading from them successfully.
At first I was really interested to know how from C+ + code we could directly access the hardware. By studying the Driver C++ class that was created by previous intern and the C++ code that used that class I formed a better picture about the process. These online Pages were helpful too.
1-register Access in C++
2- Methods of hardware access in C++
From what I understood, When the processor looks to the I/O , it looks to it similar to the way it looks to the memory .. Just bunch of registers. So in c++ code declaring a pointer with same address of that register allows us to talk to that device either to read from it or write to it using C++.
Well I think that was simply the whole idea. In C++ , the accessing of those hardware register can be done even elegantly by using C++ classes where the data members of these classes are the device registers and their addresses are just an offset from the class object base address.
Now the issue is that our I/Os drivers are written as C++ classes. The objects of those classes can be instantiated at certain addresses during their declaration (In this case the same address of the hardware registers) but we don’t want that, in our project we don’t want the user to bother himself with the addresses , and from my point of view that might complicate the creation of the Verilog top module. So my task is that when the user declare an object of certain class (without address) I have to (somehow) set this object at its base addresses in the hardware system. The first approach I tried was checking if there’s a way to change the addresses of the objects of classes during (compilation, assembling, linking …) but this didn’t work.
Secondly, since what we are interested in are basically the driver class data member which represent the I/O registers.. So if those variables can be set at certain addresses (The addresses of the I/O registers) independently of their class object address that might somehow help. Apparently defining those data members as static variables will enable us to set them at specific addresses. But even, we assume that that might work. I’m still stuck on how to modify the class driver every time an object is declared with the required address. …. Anyway, at the end of this week I didn’t come to any solution to this matter. It seemed that I had to take it along with me to next week. :\ . Any way something kept telling me that the solution might be in the class templates … I don’t know 🙁 .
That’s all for this week, I’ll try to be optimistic and see the glass half full but this week was really horrible, hopefully the next week will be better