FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6343 Discussions

Accumulator IP to Verilog

JLee25
Novice
1,928 Views

Hi support,

  I am trying porting an old desine on C3 to C10.

 

Then I met a problem on the IP conversion.

The accumulator is not supported on C10.

I attached the IP file for your reference.

And I am wondering if I can the following code to replace it,

module acc_19i_25o (

clken,

clock,

data,

sload,

result);

 

input  clken;

input  clock;

input [18:0] data;

input  sload;

output [25:0] result;

 

wire [25:0] sub_wire0;

wire [25:0] result = sub_wire0[25:0];

 

reg [25:0] acc_data;

always@(posedge clock)

begin

if(clken) begin

if(sload)

acc_data <= acc_data + data;

end

end

 

assign sub_wire0 = acc_data ;

 

Thank you!

BRs,

Johnson

0 Kudos
1 Solution
ShengN_Intel
Employee
1,682 Views

Hi @JLee25 ,

 

I found out there's bug on overflow triggering for signed custom code posted before. I had fixed the problem. I found this link http://www.pldworld.com/_altera/html/_sw/q2help/source/mega/mega_file_altaccumulate.htm and had followed the altaccumulate megafunction truth table which shown in red circle of image below.

ShengN_Intel_0-1680025832418.png

Here is the updated code (highlighted bold are changes):

module acc_19i_25o2 (

 clken,

 clock,

 data,

 sload,

 cin,

 result,

 overflow

 //result_prev_out,

 //data_prev_out

);

 

input clken;

input clock;

input signed [30:0] data;

input sload;

input cin;

output signed [30:0] result;

output overflow;

//output signed [30:0] result_prev_out;

//output signed [30:0] data_prev_out;

 

wire signed [30:0] sub_wire0;

wire signed [30:0] result = sub_wire0[30:0];

 

reg signed [30:0] acc_data;

reg signed [30:0] acc_data_reg;

reg signed [30:0] result_prev;

reg signed [30:0] data_prev;

reg overflow_reg;

 

always @(posedge clock) begin

 if (clken) begin

  if (result_prev != acc_data) begin // check if result has changed

   result_prev <= acc_data; //previous result

  end 

if (data_prev != data ) begin // check if data has changed

  data_prev <= data; //previous data

end

 end

 

 if (sload && clken) begin

  acc_data <= data;

  acc_data_reg <= acc_data;

if ((data_prev<0&result_prev<0&acc_data>=0) | (data_prev>=0&result_prev>=0&acc_data<0)) begin

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

 end else if (clken) begin

  acc_data <= acc_data + data + cin;

acc_data_reg <= acc_data;

if ((data_prev<0&result_prev<0&acc_data>=0) | (data_prev>=0&result_prev>=0&acc_data<0)) begin

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

 end else begin

  acc_data <= acc_data;

  acc_data_reg <= acc_data_reg;

  overflow_reg <= overflow_reg;

 end

end

assign sub_wire0 = acc_data_reg;

assign overflow = overflow_reg;

//assign result_prev_out = result_prev;

//assign data_prev_out = data_prev;

endmodule

Note:

a: data, data_prev

previous result: result_prev

result: acc_data

 

I had tested the custom code and altaccumulate megafunction (SIGNED, 1 cycle latency, Width 31) for 3 simulations. Simulation results and folder are attached below. The results are all exactly the same. The altaccumulate megafunction that I used don't have add_sub port. You may further verify from your end and let me know if there's any further concern.

 

Thanks,

Best Regards,

Sheng

p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer.

 

View solution in original post

12 Replies
ShengN_Intel
Employee
1,905 Views

Hi,

 

Yes. The altaccumulate Megafunction is not supported on C10. I think you probably can't replace the altaccumulate Megafunction with the code posted above because both of them having different simulation result check below.

altaccumulate Megafunction simulation (image):

accum.pngaccum_wave0.jpg

Code posted above simulation (image):

acc_19i_25o.png

 

Thanks,

Best Regards,

Sheng

p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer.

 

0 Kudos
JLee25
Novice
1,894 Views

Hi Sheng,

  Thanksfor getting back!

I change the design following the simulation result below,

module acc_19i_25o (

clken,

clock,

data,

sload,

result);

input  clken;

input  clock;

input [18:0] data;

input  sload;

output [25:0] result;

 

wire [25:0] sub_wire0;

wire [25:0] result = sub_wire0[25:0];

 

reg [25:0] acc_data;

always@(posedge clock)

begin

if(sload) begin

  acc_data <= data;

else if(clken)

  acc_data <= accdata + data;

else

  acc_data <= accdata

end

 

assign sub_wire0 = acc_data ;

 

Please check this for me!

 

Thank you.

 

BRs,

Johnson

0 Kudos
ShengN_Intel
Employee
1,882 Views

Hi Johnson,

 

With the updated code posted and minor syntax error modified below:

always@(posedge clock)

begin

if(sload) begin

 acc_data <= data;

end else if(clken) 

 acc_data <= acc_data + data;

else 

 acc_data <= acc_data;

end

I'm getting the exactly same simulation result as altaccumulate Megafunction check image:

acc_19i_25o2.png

Try with other input values also getting the same simulation for both updated code and altaccumulate Megafunction check image:

accum_v3.pngacc_19i_25o2_v3.png

 

Thanks,

Best Regards,

Sheng

 

0 Kudos
JLee25
Novice
1,860 Views

Hi Sheng,

  Thank you very much.

 

By the way, I would like to address on the EXTRA_LATENCY in my original design file.

Do you think the simulation has this parameter included?

 

BRs,

Johnson

0 Kudos
JLee25
Novice
1,853 Views

Hi Sheng,

  In the sample desing, I have another instance with new parameters like,

altaccumulate_component.extra_latency = 1,
altaccumulate_component.lpm_representation = "SIGNED",
altaccumulate_component.lpm_type = "altaccumulate",
altaccumulate_component.width_in = 31,
altaccumulate_component.width_out = 31;

 

I attached the file for your reference.

Any suggestions on how to replace it?

 

Thank you!

 

BRs,

Johnson

0 Kudos
ShengN_Intel
Employee
1,832 Views

Hi Johnson,

 

Below is the updated verilog code for input/output width: 31, lpm_representation: UNSIGNED, extra_latency: 1 cycle

[Edited: below code is for UNSIGNED]

module acc_19i_25o2 (

  clken,

  clock,

  data,

  sload,

  cin,

  result,

  overflow

);

 

input clken;

input clock;

input [30:0] data;

input sload;

input cin;

output [30:0] result;

output reg overflow;

 

wire [30:0] sub_wire0;

wire [30:0] result = sub_wire0[30:0];

 

reg [30:0] acc_data;

reg [30:0] acc_data_reg;

reg overflow_reg;

 

always @(posedge clock) begin

  if (sload && clken) begin

    acc_data <= data;

    acc_data_reg <= acc_data;

 overflow_reg <= 1'b0;

 overflow <= overflow_reg;

  end else if (clken) begin

    {overflow_reg, acc_data} <= acc_data + data + cin;

 overflow <= overflow_reg;

    acc_data_reg <= acc_data;

  end else begin

    acc_data <= acc_data;

 acc_data_reg <= acc_data_reg;

 overflow_reg <= overflow_reg;

  end

end

assign sub_wire0 = acc_data_reg;

endmodule

 

The code above being simulated without problem (same result with altaccumulate Megafunction):

altaccumulate Megafunction simulation (input/output width: 31, lpm_representation: UNSIGNED, extra_latency: 1 cycle):

accum.png

Custom verilog code simulation (input/output width: 31, lpm_representation: UNSIGNED, extra_latency: 1 cycle):

acc_19i_25o2.png

Some changes are made:

1.Change if (sload) begin to if (sload && clken) begin (previous code needs this change as well)

2.Added cin, registered overflow, registered acc_data (extra latency)

3.Input/output width

4.UNSIGNED data representation

 

Thanks,

Best Regards,

Sheng

p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer.

 

0 Kudos
JLee25
Novice
1,754 Views

Hi Sheng,

  Thank you!

 

But would you check if this code has "extra_latency=1" ?

I don't see this behavior on the simulation result followed.

 

BRs,

Johnson

0 Kudos
ShengN_Intel
Employee
1,798 Views

Hi Johnson,

 

For your reference, below is the verilog code for lpm_representation: SIGNED with input/output width: 31 and extra_latency: 1 cycle:

module acc_19i_25o2 (

 clken,

 clock,

 data,

 sload,

 cin,

 result,

 overflow

);

 

input clken;

input clock;

input signed [30:0] data;

input sload;

input cin;

output signed [30:0] result;

output overflow;

 

wire signed [30:0] sub_wire0;

wire signed [30:0] result = sub_wire0[30:0];

 

reg signed [30:0] acc_data;

reg signed [30:0] acc_data_reg;

reg overflow_reg;

 

always @(posedge clock) begin 

 if (sload && clken) begin

  acc_data <= data;

  acc_data_reg <= acc_data;

if ((acc_data_reg>0&data>0&acc_data<0) | (acc_data_reg<0&data<0&acc_data>=0)) begin //use >= instead of >

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

 end else if (clken) begin

  acc_data <= acc_data + data + cin;

if ((acc_data_reg>0&data>0&acc_data<0) | (acc_data_reg<0&data<0&acc_data>=0)) begin //use >= instead of >

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

  acc_data_reg <= acc_data;

 end else begin

  acc_data <= acc_data;

  acc_data_reg <= acc_data_reg;

  overflow_reg <= overflow_reg;

 end

end

assign sub_wire0 = acc_data_reg;

assign overflow = overflow_reg;

endmodule

 

The simulation result of code above is same with altaccumulate Megafunction:

altaccumulate Megafunction simulation (input/output width: 31, lpm_representation: SIGNED, extra_latency: 1 cycle):

accum_signed.png

Custom verilog code simulation (input/output width: 31, lpm_representation: SIGNED, extra_latency: 1 cycle):

acc_19i_25o2_signed.png

Thanks,

Best Regards,

Sheng

p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer.

 

0 Kudos
JLee25
Novice
1,720 Views

Hi Sheng,

  Thank you for the signed code..

 

But I am curious on the data<0 condition...

JLee25_0-1679896825619.png

BRs,

Johnson

0 Kudos
ShengN_Intel
Employee
1,750 Views

Hi Johnson,


I had posted verilog code for input/output width: 31, lpm_representation: UNSIGNED, extra_latency: 1 cycle and input/output width: 31, lpm_representation: SIGNED, extra_latency: 1 cycle


I had compared the simulation result of custom verilog code with altaccumulate Megafunction having input/output width: 31, lpm_representation: UNSIGNED/SIGNED, extra_latency: 1 cycle. Both custom verilog code and altaccumulate Megafunction having exactly same simulation, I had attached the image in previous post.


Thanks,

Best Regards,

Sheng


0 Kudos
ShengN_Intel
Employee
1,734 Views

Attached the design folder below for your reference (Using Quartus Standard v22.1).

waveform1.vwf for accum.v (altaccumulate Megafunction)

waveform.vwf for acc_19i_25o2_signed.v & acc_19i_25o2_unsigned.v (Both module name are acc_19i_25o2)

(**Note: In .vwf file, remember to change the path in Simulation -> Simulation Settings -> Timing Simulation Settings)

 

Thanks,

B.Regards,

Sheng

 

0 Kudos
ShengN_Intel
Employee
1,683 Views

Hi @JLee25 ,

 

I found out there's bug on overflow triggering for signed custom code posted before. I had fixed the problem. I found this link http://www.pldworld.com/_altera/html/_sw/q2help/source/mega/mega_file_altaccumulate.htm and had followed the altaccumulate megafunction truth table which shown in red circle of image below.

ShengN_Intel_0-1680025832418.png

Here is the updated code (highlighted bold are changes):

module acc_19i_25o2 (

 clken,

 clock,

 data,

 sload,

 cin,

 result,

 overflow

 //result_prev_out,

 //data_prev_out

);

 

input clken;

input clock;

input signed [30:0] data;

input sload;

input cin;

output signed [30:0] result;

output overflow;

//output signed [30:0] result_prev_out;

//output signed [30:0] data_prev_out;

 

wire signed [30:0] sub_wire0;

wire signed [30:0] result = sub_wire0[30:0];

 

reg signed [30:0] acc_data;

reg signed [30:0] acc_data_reg;

reg signed [30:0] result_prev;

reg signed [30:0] data_prev;

reg overflow_reg;

 

always @(posedge clock) begin

 if (clken) begin

  if (result_prev != acc_data) begin // check if result has changed

   result_prev <= acc_data; //previous result

  end 

if (data_prev != data ) begin // check if data has changed

  data_prev <= data; //previous data

end

 end

 

 if (sload && clken) begin

  acc_data <= data;

  acc_data_reg <= acc_data;

if ((data_prev<0&result_prev<0&acc_data>=0) | (data_prev>=0&result_prev>=0&acc_data<0)) begin

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

 end else if (clken) begin

  acc_data <= acc_data + data + cin;

acc_data_reg <= acc_data;

if ((data_prev<0&result_prev<0&acc_data>=0) | (data_prev>=0&result_prev>=0&acc_data<0)) begin

overflow_reg <= 1'b1;

end else begin

overflow_reg <= 1'b0;

end

 end else begin

  acc_data <= acc_data;

  acc_data_reg <= acc_data_reg;

  overflow_reg <= overflow_reg;

 end

end

assign sub_wire0 = acc_data_reg;

assign overflow = overflow_reg;

//assign result_prev_out = result_prev;

//assign data_prev_out = data_prev;

endmodule

Note:

a: data, data_prev

previous result: result_prev

result: acc_data

 

I had tested the custom code and altaccumulate megafunction (SIGNED, 1 cycle latency, Width 31) for 3 simulations. Simulation results and folder are attached below. The results are all exactly the same. The altaccumulate megafunction that I used don't have add_sub port. You may further verify from your end and let me know if there's any further concern.

 

Thanks,

Best Regards,

Sheng

p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer.

 

Reply