Data transfer between fpga (14 bits) vhdl block to NIos II system (16 bits)

459 views Asked by At

I am writing C code to program Altera Nios II system in Cyclone IV E. The Nios II system is used to control some custom FPGA blocks written in VHDL in Quartus II.

In the vhdl block "a", "data" is defined as follow where it has a total of 14 bits, msb as the signed bit, the following 7 bits are integer and the last 6 bits are fractional.

data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 7, -6));

"scale" is any number to represent the peak value, "in" is a sinusoidal waveform. "data" is the input to the Nios II.

In the C code, initially, I read the data from vhdl block using the C code below:

int16_t data=0;
data =  IORD_ALTERA_AVALON_PIO_DATA(data_base);

In the C code, since Altera compiler only supports "8", "16" or "32" bits of data length, after I read "data", I have to check if "data" is negative, if it is, I need to pad the msb with bits '1' as shown in the following code:

if (data & 0x2000) 
     data |= 0xC000;

After this, the Nios system do some calculation (multiply with "a" for instance) to give a new value of "data", say name it as "data_new".

data_new=((float)data/ 64.0f)*(a);

After the calculation, I want to assign "data_new" back to another custom block in vhdl say "block b". So I need to format the "data_new" back to 14 bits instead of 16 bits using the following code:

if (data_new & 0x2000) 
      data_new &= 0x3fff;

Finally, I write the "data_new" back to another custom block in vhdl say "block b".

IOWR_ALTERA_AVALON_PIO_DATA(data_new_base, (int16_t)data_new);

I am sure something is wrong with the way I did above, cause I am expecting to get a constant output voltage and current but I kept getting output voltage and current that keep changing every second. I don't have this issue if I feed the data_new directly from one vhdl block to another vhdl block.

Could you give me some hints? have been trying for a week still could not figure out. I am trying to form the question as clear as I could, please let me know if additional information should be provided, much appreciated.

1

There are 1 answers

0
Jens On

Maybe you should avoid the floating point computation in

 data_new = ((float)data/64.0f) * (a);

Dividing by 64 is a 6 bit shift:

 data_new = (data >> 6) * (a);

I hope you are not surprised that data_new and data are not the same even if a is 64. Or is that the reason why you want to use floating point operations?