Playing around with Bit streams
For a short period of time I’ll be writing a couple of C++ programs to do some tasks in our project. The first of them is what took my time this week and it’s more or less playing around with a bit stream. In this post I’ll explain what are the changes required for the bit stream and the reason behind them. Moreover, I’ll explain how my code works for now.
A bit stream is the final output from software that is used to configure an FPGA. For our project, the bit stream will be written to the FPGA by a PIC through UART. The PIC will obtain this bit stream through Ethernet and will temporarily be stored on an SD card. Thus this Bit stream need to have a CRC check sum appended to the end of each 512 Bytes block. The SD card uses this check sum to verify data blocks. Moreover, those blocks with the appended CRC need to be encoded into Base64 before it’s transferred through Ethernet.
The first task is dealing with data in files. To examine the bitstream from the command line you can use the xxd command to create a hex dump and instead of dumping the whole file you can use the dd command to copy certain parts of the file and operate on them.
As for C++, I used the file stream classes to operate on the files. The input file stream, ifstream, class contains functions to handle all reading operation from a file, some are it’s own functions and others are inherited from it’s parents. You can use the class constructor to open a file and associate it with a new object. Then you can use the is_open function to confirm the existence of the file. tellg helps you obtain the current position in the input sequence, Seekg can set that position and finally read is to be used for obtaining data from the file. When it comes to writing to the file ofstream is the class to do the job. When initiating a new object with it’s constructor a file will be created if it didn’t exist. To output Binary data to the file use the write function. This guide is more profound about file I/O.
After opening the file I scan through it’s first bytes until I reach the end of the header characterized by a 6500 hex value followed by 3 bytes showing the size of the bit stream body. Next, I set the input sequence to the beginning of the body and calculate the padding required to make the body an integer number of 512 bytes blocks.
Next I take each Block, and bit reverse each byte in it. There is various methods to do bit reversal, but I chose the parallel bit wise approach which was found to be an acceptable according to the results obtained here. Nonetheless, the core point of the later article is to always measure whatever algorithm on the architecture carrying it. Since I have no idea where is my program going to run, I can’t claim any deep research to use this method. It just looks fine!
For CRC, I used the Boost library intended for CRC. It’s pretty straight forward and the documentation given is good enough. You can use this tool to verify your CRC value. You should always confirm first that the Boost library is installed on your computer and part of the include directory for what ever compiler you are using.
After I calculate the CRC and append it to my the data block, I should encode this block into Base64 encoding. The Boost library can calculate the CRC and there is libb64 as well but seeing how straight forward Base64 is I’m tempted to write my own class for calculating it. I can always use this page to confirm my obtained Base64 output.
Thus, I’ve explored various libraries and encoding algorithms required for my program and put them successfully to the test. Still, I need to turn my program into proper classes. Following that I need to write the class for creating the SOC top which I expect to be straight forward having explored files I/O in this week’s task. Hopefully I can get back to finalizing my beloved Verilog designs by the end of next week.