//
//  Copyright (c) 2003 Launchbird Design Systems, Inc.
//  All rights reserved.
//  
//  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//    Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//    Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
//  
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
//  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
//  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//  
//  
//  Overview:
//  
//    Performs finite impulse response (FIR) filtering.
//    The filter's sum of products is pipelined with a register after
//    every multiplier and adder.  The adder network is a balanced binary
//    tree to minimize latency.  The sum of products has no numeric loss because the
//    multipliers keep all resulting bits and each adder extends the precision by 1.
//  
//  Interface:
//  
//    Synchronization:
//      clock_c  : Clock input.
//      reset_i  : Filter delay bank synchronous reset.  Does not reset sum of products pipeline registers.
//  
//    Inputs:
//      data_i  : Input data.
//      k0_i    : Coefficient 0 multiplied by in_i(0).
//      k1_i    : Coefficient 1 multiplied by in_i(k-1).
//      k2_i    : Coefficient 2 multiplied by in_i(k-2).
//      ...
//      k<order>_i : Coefficient <order> multiplied by in_i(k-<order>).
//  
//    Outputs:
//      data_o : Output data.
//  
//  Built In Parameters:
//  
//    Filter Order             = 3
//    Input Precision          = 8
//    Coefficient Precision    = 8
//    Sum of Products Latency  = 3
//  
//  
//  
//  
//  Generated by Confluence 0.6.3  --  Launchbird Design Systems, Inc.  --  www.launchbird.com
//  
//  Build Date : Fri Aug 22 09:45:46 CDT 2003
//  
//  Interface
//  
//    Build Name    : cf_fir_3_8_8
//    Clock Domains : clock_c  
//    Vector Input  : reset_i(1)
//    Vector Input  : data_i(8)
//    Vector Input  : k0_i(8)
//    Vector Input  : k1_i(8)
//    Vector Input  : k2_i(8)
//    Vector Input  : k3_i(8)
//    Vector Output : data_o(18)
//  
//  
//  

module cf_fir_3_8_8 (clock_c, reset_i, data_i, k0_i, k1_i, k2_i, k3_i, data_o);
input  clock_c;
input  reset_i;
input  [7:0] data_i;
input  [7:0] k0_i;
input  [7:0] k1_i;
input  [7:0] k2_i;
input  [7:0] k3_i;
output [17:0] data_o;
wire   [17:0] n1;
cf_fir_3_8_8_1 s1 (clock_c, reset_i, k0_i, k1_i, k2_i, k3_i, data_i, n1);
assign data_o = n1;
endmodule

module cf_fir_3_8_8_1 (clock_c, i1, i2, i3, i4, i5, i6, o1);
input  clock_c;
input  i1;
input  [7:0] i2;
input  [7:0] i3;
input  [7:0] i4;
input  [7:0] i5;
input  [7:0] i6;
output [17:0] o1;
wire   n1;
wire   n2;
wire   [17:0] s3_1;
assign n1 = 1'b1;
assign n2 = 1'b0;
cf_fir_3_8_8_2 s3 (clock_c, n1, n2, i1, i2, i3, i4, i5, i6, s3_1);
assign o1 = s3_1;
endmodule

module cf_fir_3_8_8_2 (clock_c, i1, i2, i3, i4, i5, i6, i7, i8, o1);
input  clock_c;
input  i1;
input  i2;
input  i3;
input  [7:0] i4;
input  [7:0] i5;
input  [7:0] i6;
input  [7:0] i7;
input  [7:0] i8;
output [17:0] o1;
reg    [7:0] n1;
reg    [7:0] n2;
reg    [7:0] n3;
reg    [7:0] n4;
wire   n5;
wire   [17:0] n6;
wire   n7;
wire   [17:0] n8;
wire   [17:0] n9;
reg    [17:0] n10;
wire   [16:0] s11_1;
wire   [16:0] s11_2;
wire   [15:0] s12_1;
wire   [15:0] s12_2;
wire   [15:0] s12_3;
wire   [15:0] s12_4;
always @ (posedge clock_c)
begin
  if (i3 == 1'b1)
    n1 <= 8'b00000000;
  else if (i1 == 1'b1)
    n1 <= i8;
  if (i3 == 1'b1)
    n2 <= 8'b00000000;
  else if (i1 == 1'b1)
    n2 <= n1;
  if (i3 == 1'b1)
    n3 <= 8'b00000000;
  else if (i1 == 1'b1)
    n3 <= n2;
  if (i3 == 1'b1)
    n4 <= 8'b00000000;
  else if (i1 == 1'b1)
    n4 <= n3;
  if (i2 == 1'b1)
    n10 <= 18'b000000000000000000;
  else if (i1 == 1'b1)
    n10 <= n9;
end
assign n5 = s11_1[16];
assign n6 = {n5, s11_1};
assign n7 = s11_2[16];
assign n8 = {n7, s11_2};
assign n9 = n6 + n8;
cf_fir_3_8_8_4 s11 (clock_c, i1, i2, s12_1, s12_2, s12_3, s12_4, s11_1, s11_2);
cf_fir_3_8_8_3 s12 (clock_c, i1, i2, i4, i5, i6, i7, n1, n2, n3, n4, s12_1, s12_2, s12_3, s12_4);
assign o1 = n10;
endmodule

module cf_fir_3_8_8_3 (clock_c, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, o1, o2, o3, o4);
input  clock_c;
input  i1;
input  i2;
input  [7:0] i3;
input  [7:0] i4;
input  [7:0] i5;
input  [7:0] i6;
input  [7:0] i7;
input  [7:0] i8;
input  [7:0] i9;
input  [7:0] i10;
output [15:0] o1;
output [15:0] o2;
output [15:0] o3;
output [15:0] o4;
wire   [15:0] n1;
reg    [15:0] n2;
wire   [15:0] n3;
reg    [15:0] n4;
wire   [15:0] n5;
reg    [15:0] n6;
wire   [15:0] n7;
reg    [15:0] n8;
assign n1 = {8'b00000000, i3} * {8'b00000000, i7};
always @ (posedge clock_c)
begin
  if (i2 == 1'b1)
    n2 <= 16'b0000000000000000;
  else if (i1 == 1'b1)
    n2 <= n1;
  if (i2 == 1'b1)
    n4 <= 16'b0000000000000000;
  else if (i1 == 1'b1)
    n4 <= n3;
  if (i2 == 1'b1)
    n6 <= 16'b0000000000000000;
  else if (i1 == 1'b1)
    n6 <= n5;
  if (i2 == 1'b1)
    n8 <= 16'b0000000000000000;
  else if (i1 == 1'b1)
    n8 <= n7;
end
assign n3 = {8'b00000000, i4} * {8'b00000000, i8};
assign n5 = {8'b00000000, i5} * {8'b00000000, i9};
assign n7 = {8'b00000000, i6} * {8'b00000000, i10};
assign o4 = n8;
assign o3 = n6;
assign o2 = n4;
assign o1 = n2;
endmodule

module cf_fir_3_8_8_4 (clock_c, i1, i2, i3, i4, i5, i6, o1, o2);
input  clock_c;
input  i1;
input  i2;
input  [15:0] i3;
input  [15:0] i4;
input  [15:0] i5;
input  [15:0] i6;
output [16:0] o1;
output [16:0] o2;
wire   n1;
wire   [16:0] n2;
wire   n3;
wire   [16:0] n4;
wire   [16:0] n5;
reg    [16:0] n6;
wire   n7;
wire   [16:0] n8;
wire   n9;
wire   [16:0] n10;
wire   [16:0] n11;
reg    [16:0] n12;
assign n1 = i3[15];
assign n2 = {n1, i3};
assign n3 = i4[15];
assign n4 = {n3, i4};
assign n5 = n2 + n4;
always @ (posedge clock_c)
begin
  if (i2 == 1'b1)
    n6 <= 17'b00000000000000000;
  else if (i1 == 1'b1)
    n6 <= n5;
  if (i2 == 1'b1)
    n12 <= 17'b00000000000000000;
  else if (i1 == 1'b1)
    n12 <= n11;
end
assign n7 = i5[15];
assign n8 = {n7, i5};
assign n9 = i6[15];
assign n10 = {n9, i6};
assign n11 = n8 + n10;
assign o2 = n12;
assign o1 = n6;
endmodule

