System Verilog - Reading a line from testbench and splitting the data - arrays

I'm a beginner in SystemVerilog Programming. I have a file called "input.in" and it has around 32 bits of data. The value is present in only one line of the file.
The data once sent from the testbench must be split into an array or 4 variables, each containing only 8 bits of the input. Please. Somebody help me :(

I think, you want to split the 32 bits of data into 4 bytes of data.
Please try the following:
{>>{a,b,c,d}} = var_32_bit ; //a,b,c,d are 8 bits variable.
// var_32_bit is an array of 32 bits size or a 32-bit variable. {bit a[] or bit [31:0]}
Is this the one you need ?

Related

Writing integer values to a file in binary using C

I am trying to write 9 bit numbers to a binary file.
For example, i want to write the integer value: 275 as 100010011 and so on. fwrite only allows one byte to be written at a time and I am not sure how to manipulate the bits to be able to do this.
You have to write a minimum of two bytes to store a 9-bits value. An easy solution is to use 16 bits per 9 bits value
Choose a 16 bits unsigned type, eg uint16_t and store the 2 bytes
uint16_t w = 275;
fwrite(&w, 1, 2, myfilep);
Reading the word w, ensure it actually uses only its 9 first bits (bits 0~8)
w &= 0x1FF;
Note that you might have endianness issues if you read the file on another system that doesn't have the same endianness as the system that wrote the word.
You could also optimize that solution using 9 bits of a 16 bits word, then using the remaining 7 bits to store the first 7 bits of the next 9 bits value etc...
See this answer that explains how to work with bit shifting in C.

Perl: Efficiently store/get 2D array of constrained integers in file

This is an attempt to improve my
Perl: seek to and read bits, not bytes by explaining more
thoroughly what I was trying to do.
I have x, a 9136 x 42 array of integers that I want to store
super-efficiently in a file. The integers have the following
constraints:
All of the 9136 integers in x[0..9135][0] are between
-137438953472 and 137438953471, and can therefore be stored
using 38 bits.
All of the 9136 integers in x[0..9135][1] are between -16777216 and
16777215, and can therefore be stored using 25 bits.
And so on... (the integer bit constraints are known in
advance; Perl doesn't have to compute them)
Question: Using Perl, how do I efficiently store this array in a file?
Notes:
If an integer can be stored in 25 bits, it can also be stored
in 4 bytes (32 bits), if you're willing to waste 7 bits. In my
situation, however, every bit counts.
I want to use file seek() to find data quickly, not read
sequentially through the file.
The array will normally be accessed as x[i]. In other words,
I'll want the 42 integers corresponding to a given x[i], so
these 42 integers should be stored close to each other
(ideally, they should be stored adjacent to each other in the
file)
My initial approach was to just lay down a bitstream, and
then find a way to read it back and change it back into an
integer. My original question focused on that, but perhaps
there's a better solution to the bigger problem that I'm not
seeing.
Far too much detail on what I'm doing:
https://github.com/barrycarter/bcapps/blob/master/ASTRO/bc-read-cheb.m
https://github.com/barrycarter/bcapps/blob/master/ASTRO/bc-read-cheb.pl
https://github.com/barrycarter/bcapps/blob/master/ASTRO/playground.pl
I'm not sure I should be encouraging you, but it loks like Data::BitStream will do what you ask.
The program below writes a 38-bit value and a 25-bit value to a file, and then opens and retrieves the values intact.
#!/usr/bin/perl
use strict;
use warnings;
use Data::BitStream;
{
my $bs_out = Data::BitStream->new(
mode => 'w',
file => 'bits.dat',
);
printf "Maximum %d bits per word\n", $bs_out->maxbits;
$bs_out->write(38, 137438953471);
$bs_out->write(25, 16777215);
printf "Total %d bits written\n\n", $bs_out->len;
}
{
my $bs_in = Data::BitStream->new(
mode => 'ro',
file => 'bits.dat',
);
printf "Total %d bits read\n\n", $bs_in->len;
print "Data:\n";
print $bs_in->read(38), "\n";
print $bs_in->read(25), "\n";
}
output
Maximum 64 bits per word
Total 63 bits written
File size 11 bytes
Total 63 bits read
Data:
137438953471
16777215
38 and 25 is 63 bits of data written, which the module confirms. But there is clearly some additional housekeeping data involved as the total size of the resulting file is eleven bytes, and not just the eight that would be the minimum necessary. Note that, when reopened, the data remembers that it is 63 bits long. However, it is shorter than the sixteen bytes that a file would have to be to contain two simple 64-bit integers.
What you do with this information is up to you, but remember that data packed in this way will be extremely difficult to debug with a hex editor. You may be shooting yourself in the foot if you adopt something like this.

C : Array of bytes which stores unsigned ints using 3 bytes

this is my first question so please take me easy, I'm a beginner in C and I'd like to know more about it.
Could someone help me write this function? I can't really picture how the array of bytes should look like:
"An array of bytes stores unsigned ints each using 3 bytes, least significant byte first. Write a function that takes an array and its byte length and prints the numbers in hex."
[lowbyte-of-value-0, middlebyte-of-value-0, highbyte-of-value-0,lowbyte-of-value-1, middlebyte-of-value-1, highbyte-of-value-1, ... lowbyte-of-value-n, middlebyte-of-value-n, highbyte-of-value-n]
Your task is to walk through that array, pull the bytes one by one or in groups of 3 as you choose, and reassemble them into unsigned integer values.

Write 9 bits binary data in C

I am trying to write to a file binary data that does not fit in 8 bits. From what I understand you can write binary data of any length if you can group it in a predefined length of 8, 16, 32,64.
Is there a way to write just 9 bits to a file? Or two values of 9 bits?
I have one value in the range -+32768 and 3 values in the range +-256. What would be the way to save most space?
Thank you
No, I don't think there's any way using C's file I/O API:s to express storing less than 1 char of data, which will typically be 8 bits.
If you're on a 9-bit system, where CHAR_BIT really is 9, then it will be trivial.
If what you're really asking is "how can I store a number that has a limited range using the precise number of bits needed", inside a possibly larger file, then that's of course very possible.
This is often called bitstreaming and is a good way to optimize the space used for some information. Encoding/decoding bitstream formats requires you to keep track of how many bits you have "consumed" of the current input/output byte in the actual file. It's a bit complicated but not very hard.
Basically, you'll need:
A byte stream s, i.e. something you can put bytes into, such as a FILE *.
A bit index i, i.e. an unsigned value that keeps track of how many bits you've emitted.
A current byte x, into which bits can be put, each time incrementing i. When i reaches CHAR_BIT, write it to s and reset i to zero.
You cannot store values in the range –256 to +256 in nine bits either. That is 513 values, and nine bits can only distinguish 512 values.
If your actual ranges are –32768 to +32767 and –256 to +255, then you can use bit-fields to pack them into a single structure:
struct MyStruct
{
int a : 16;
int b : 9;
int c : 9;
int d : 9;
};
Objects such as this will still be rounded up to a whole number of bytes, so the above will have six bytes on typical systems, since it uses 43 bits total, and the next whole number of eight-bit bytes has 48 bits.
You can either accept this padding of 43 bits to 48 or use more complicated code to concatenate bits further before writing to a file. This requires additional code to assemble bits into sequences of bytes. It is rarely worth the effort, since storage space is currently cheap.
You can apply the principle of base64 (just enlarging your base, not making it smaller).
Every value will be written to two bytes and and combined with the last/next byte by shift and or operations.
I hope this very abstract description helps you.

Efficient way to create/unpack large bitfields in C?

I have one microcontroller sampling from a lot of ADC's, and sending the measurements over a radio at a very low bitrate, and bandwidth is becoming an issue.
Right now, each ADC only give us 10 bits of data, and its being stored in a 16-bit integer. Is there an easy way to pack them in a deterministic way so that the first measurement is at bit 0, second at bit 10, third at bit 20, etc?
To make matters worse, the microcontroller is little endian, and I have no control over the endianness of the computer on the other side.
EDIT: So far, I like #MSN's answer the best, but I'll respond to the comments
#EvilTeach: I'm not sure if the exact bit pattern would be helpful, or how to best format it with text only, but I'll think about it.
#Jonathan Leffler: Ideally, I'd pack 8 10-bit values into 10 8-bit bytes. If it makes processing easier, I'd settle for 3 values in 4 bytes or 6 values in 8 bytes (although the 2 are equivalent to me, same amount of 'wasted' bits)
Use bit 0 and 31 to determine endianness and pack 3 10-bit values in the middle. One easy way to test matching endianness is to set bit 0 to 0 and bit 31 to 1. On the receiving end, if bit 0 is 1, assert that bit 31 is 0 and swap endianness. Otherwise, if bit 0 is 0, assert that bit 31 is 1 and extract the 3 values.
You can use bitfields, but the ordering within machine words is not defined:
That said, it would look something like:
struct adc_data {
unsigned first :10;
unsigned second :10;
unsigned third :10;
};
EDIT: Corrected, thanks to Jonathan.
The simplest thing to do about endian-ness is to simply pick one for your transmission. To pack the bits in the transmission stream, use an accumulator (of at least 17 bits in your case) in which you shift in 10 bits at a time and keep track of how many bits are in it. When you transmit a byte, you pull a byte out of the accumulator, subtract 8 from your count, and shift the accumulator by 8. I use "transmit" here loosely, your probably storing into a buffer for later transmission.
For example, if transmission is little endian, you shift in your 10 bits at the top of the acccumator (in its MS bits), and pull your bytes from the bottom. For example: for two values a and b:
Accumulator Count
(MS to LS bit)
aaaaaaaaaa 10 After storing a
aa 2 After sending first byte
bbbbbbbbbbaa 12 After storing b
bbbb 4 After sending second byte
Reception is a similar unpacking operation.

Resources