Forum Discussion

JLee25's avatar
JLee25
Icon for Contributor rankContributor
2 years ago
Solved

Accumulator IP to Verilog

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

  • 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.

    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.

12 Replies

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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.

    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.

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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):

    Code posted above simulation (image):

    Thanks,

    Best Regards,

    Sheng

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

    • JLee25's avatar
      JLee25
      Icon for Contributor rankContributor

      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

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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:

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

    Thanks,

    Best Regards,

    Sheng

    • JLee25's avatar
      JLee25
      Icon for Contributor rankContributor

      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

  • 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

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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):

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

    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.

    • JLee25's avatar
      JLee25
      Icon for Contributor rankContributor

      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

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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):

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

    Thanks,

    Best Regards,

    Sheng

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

    • JLee25's avatar
      JLee25
      Icon for Contributor rankContributor

      Hi Sheng,

      Thank you for the signed code..

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

      BRs,

      Johnson

  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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


  • ShengN_altera's avatar
    ShengN_altera
    Icon for Super Contributor rankSuper Contributor

    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