This site uses cookies to deliver our services and to show you relevant ads and job listings. By using our site, you acknowledge that you have read and understand our Cookie Policy , Privacy Policy , and our Terms of Service . Your use of the Related Sites, including DSPRelated.com, FPGARelated.com, EmbeddedRelated.com and Electronics-Related.com, is subject to these policies and terms.

1. DSP48 Slice in Xilinx FPGA

There are many DSP48 Slices in most Xilinx® FPGAs, one DSP48 slice in Spartan6® FPGA is shown in Figure 1, the structure may different depending on the device, but broadly similar.

Figure 1: A whole DSP48A1 Slice in Spartan6 (www.xilinx.com)

2. Symmetric Systolic Half-band FIR

Figure 2: Symmetric Systolic Half-band FIR Filter

3. Two-channel Symmetric Systolic Half-band FIR

Figure 3: 2-Channel Symmetric Systolic Half-band FIR Filter

y1[n] =(x[n]+x[n-14])h0 + (x[n-2]+x[n-12])h2 + (x[n-4]+x[n-10])h4 + (x[n-6]+x[n-8])h6

y2[n] =x[n-7]h7

y[n]=y1[n]+y2[n]

4. Advantages and Disadvantages

The symmetric systolic FIR filter is considered an optimal solution for parallel filter architectures.

The advantages to using the Systolic FIR filter are:

Highest Performance : Maximum performance can be achieved with this structure because there is no high fanout input signal. Larger filters can be routing-limited if the number of coefficients exceeds the number of DSP slices in a column on a device.

Efficient Mapping to the DSP48 Slice : Mapping is enabled by the adder chain structure of the Systolic FIR Filter. This extendable structure supports large and small FIR filters.

No External Logic: No external FPGA fabric is required, enabling the highest possible performance.

The disadvantage to using the Systolic FIR filter is:

Higher Latency: The latency of the filter is a function of how many coefficients are in the filter. The larger the filter, the higher the latency:

from Log2N (add tree) to N (Systolic) : N is the number of multiplies.

5. Rounding

The number of bits on the output of the filters must be reduced to a manageable width.Truncation introduces an undesirable DC data shift due to the nature of two’s complement numbers. The DC shift can be improved with the use of symmetric rounding, where positive numbers are rounded up and negative numbers are rounded down.

The rounding is achieved in the following manner:

For positive numbers: Binary Data Value + 0.10000...and then truncate

For negative numbers: Binary Data Value + 0.01111... and then truncate

/**************************************************************

module name : Half_band_fir_down2

version : 0.3

author : Lyons Zhang ( fpgaplayer@gmail.com )

description : 2-Channel interleaved input/output half-band filter downsample 2 ,the filter is a little long,because I'd like to show the original appearance of the practical application.

revision history:

---------------------------------------------------------------

1. 2010-11-11, initial version

2. 2010-11-30, second version, revise by advice of old cfelton

3. 2011-03-28, third version, symmetric rounding used to improved DC shift

---------------------------------------------------------------

//coefficient of Half Band Filter : ( 1,14,14 )

//output data of Half Band Filter : ( 2,28,24 ) ---> ( 1,14,10 )

***************************************************************/

`timescale 1ns/1ps

module Half_band_fir_down2

(

//input signals

Clk, //FPGA's master clock

Reset, //Global reset

Data_in_0, //Data_in_0 rate is Clk/2

Data_in_1, //Data_in_1 rate is Clk/2

Index, //Index reverse every Clk period



//output signals

Data_out_0, //Data_out_0 rate is Clk/4

Data_out_1, //Data_out_1 rate is Clk/4

Hb_overflow_0, //Indicate filter overflow, be of use in practise

Hb_overflow_1 //Indicate filter overflow, be of use in practise

);

/*****************************************************/

/*--- Input and Output Ports declaration -----*/

/*****************************************************/

input Clk;

input Reset;

input [14:0] Data_in_0;

input [14:0] Data_in_1;

input Index;

output [13:0] Data_out_0;

output [13:0] Data_out_1;

output Hb_overflow_0;

output Hb_overflow_1;

/*****************************************************/

/*------- Ports Type declaration --------*/

/*****************************************************/

reg [13:0] Data_out_0;

reg [13:0] Data_out_1;

reg Hb_overflow_0;

reg Hb_overflow_1;

/*****************************************************/

/*------- parameter declaration --------*/

/*****************************************************/

//Coefficients of half band filter

parameter Coef_c0_c46 = -17'd8;

parameter Coef_c2_c44 = 17'd27;

parameter Coef_c4_c42 = -17'd68;

parameter Coef_c6_c40 = 17'd146;

parameter Coef_c8_c38 = -17'd281;

parameter Coef_c10_c36 = 17'd499;

parameter Coef_c12_c34 = -17'd837;

parameter Coef_c14_c32 = 17'd1353;

parameter Coef_c16_c30 = -17'd2161;

parameter Coef_c18_c28 = 17'd3547;

parameter Coef_c20_c26 = -17'd6561;

parameter Coef_c22_c24 = 17'd20727;

parameter Coef_c23 = 17'd32768;

/*****************************************************/

/------ Variable declaration --------*/

/*****************************************************/

wire [14:0] Add_a[11:0];

wire [14:0] Add_d[11:0];

wire [32:0] Add_c[11:0];

wire [16:0] Mult_b[11:0];

wire [33:0] Dsp_r[11:0];



reg [14:0] Data_in_reg[92:0];



reg [33:0] Data_result; //Expand to 34 bits not only avoid overflow,

wire [33:0] Data_result_carry; //But also for several gains by cut different LSBs

reg Index_1;

reg [13:0] Data_out_0_reg;



/*****************************************************/

/*------- Main Code --------*/

/*****************************************************/

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_in_reg[0] <= 15'b0;

else if ( Index == 1'b1 )

Data_in_reg[0] <= Data_in_0;

else

Data_in_reg[0] <= Data_in_1;

end

genvar Numd;

generate

for (Numd = 1; Numd <= 92; Numd = Numd + 1)

begin : U_data_in_reg

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_in_reg[Numd] <= 15'b0;

else

Data_in_reg[Numd] <= Data_in_reg[Numd-1];

end

end

endgenerate

//adder A between DSPs has 5 registers

assign Add_a[0] = Data_in_reg[0];

assign Add_a[1] = Data_in_reg[5];

assign Add_a[2] = Data_in_reg[10];

assign Add_a[3] = Data_in_reg[15];

assign Add_a[4] = Data_in_reg[20];

assign Add_a[5] = Data_in_reg[25];

assign Add_a[6] = Data_in_reg[30];

assign Add_a[7] = Data_in_reg[35];

assign Add_a[8] = Data_in_reg[40];

assign Add_a[9] = Data_in_reg[45];

assign Add_a[10] = Data_in_reg[50];

assign Add_a[11] = Data_in_reg[55];

//adder D between DSPs has 3 registers

assign Add_d[0] = Data_in_reg[92];

assign Add_d[1] = Data_in_reg[89];

assign Add_d[2] = Data_in_reg[86];

assign Add_d[3] = Data_in_reg[83];

assign Add_d[4] = Data_in_reg[80];

assign Add_d[5] = Data_in_reg[77];

assign Add_d[6] = Data_in_reg[74];

assign Add_d[7] = Data_in_reg[71];

assign Add_d[8] = Data_in_reg[68];

assign Add_d[9] = Data_in_reg[65];

assign Add_d[10] = Data_in_reg[62];

assign Add_d[11] = Data_in_reg[59];

//Add_c

assign Add_c[0] = 33'b0;

assign Add_c[1] = Dsp_r[0][32:0];

assign Add_c[2] = Dsp_r[1][32:0];

assign Add_c[3] = Dsp_r[2][32:0];

assign Add_c[4] = Dsp_r[3][32:0];

assign Add_c[5] = Dsp_r[4][32:0];

assign Add_c[6] = Dsp_r[5][32:0];

assign Add_c[7] = Dsp_r[6][32:0];

assign Add_c[8] = Dsp_r[7][32:0];

assign Add_c[9] = Dsp_r[8][32:0];

assign Add_c[10] = Dsp_r[9][32:0];

assign Add_c[11] = Dsp_r[10][32:0];

//Mult_b are filter coefficient

assign Mult_b[0] = Coef_c0_c46;

assign Mult_b[1] = Coef_c2_c44;

assign Mult_b[2] = Coef_c4_c42;

assign Mult_b[3] = Coef_c6_c40;

assign Mult_b[4] = Coef_c8_c38;

assign Mult_b[5] = Coef_c10_c36;

assign Mult_b[6] = Coef_c12_c34;

assign Mult_b[7] = Coef_c14_c32;

assign Mult_b[8] = Coef_c16_c30;

assign Mult_b[9] = Coef_c18_c28;

assign Mult_b[10] = Coef_c20_c26;

assign Mult_b[11] = Coef_c22_c24;

//* (A+D)*B+C

//14 pipelines

genvar Num;

generate

for (Num = 0; Num <= 11; Num = Num + 1)

begin : U_DDC_HF2_DSP

DDC_HF2_DSP DDC_HF2_DSP

(

//* Inputs

.clk ( Clk ),

.a ( Add_a[Num] ),

.d ( Add_d[Num] ),

.b ( Mult_b[Num] ),

.c ( Add_c[Num] ),

//* Outputs

.p ( Dsp_r[Num] )

);

end

endgenerate

//Data_in_reg_57 add 3 pipelines

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_result <= 34'd0;

else

Data_result <= Dsp_r[11] + { {4{Data_in_reg[60][14]}},Data_in_reg[60],15'b0 };

end

assign Data_result_carry = ( Data_result[33]== 1'b0 ) ? ( Data_result + 34'h000010000 ) : ( Data_result + 34'h00000ffff ); //Symmetric Rounding

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Index_1 <= 1'b0;

else if ( Index == 1'b0 )

Index_1 <= ~Index_1;

else

;

end

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_out_0_reg <= 14'b0;

else if ( ( Index == 1'b1 ) && ( Index_1 == 1'b1 ) )

begin

if ( ( Data_result_carry[33:30] == 4'b0000 ) || ( Data_result_carry[33:30] == 4'b1111 ) )

Data_out_0_reg <= Data_result_carry[30:17];

else if ( Data_result_carry[33] == 1'b0 )

Data_out_0_reg <= 14'h1fff;

else

Data_out_0_reg <= 14'h2000;

end

else

;

end

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_out_0 <= 14'b0;

else

Data_out_0 <= Data_out_0_reg;

end

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Data_out_1 <= 14'b0;

else if ( ( Index == 1'b0 ) && ( Index_1 == 1'b1 ) )

begin

if ( ( Data_result_carry[33:30] == 4'b0000 ) || ( Data_result_carry[33:30] == 4'b1111 ) )

Data_out_1 <= Data_result_carry[30:17];

else if ( Data_result_carry[33] == 1'b0 )

Data_out_1 <= 14'h1fff;

else

Data_out_1 <= 14'h2000;

end

else

;

end

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Hb_overflow_0 <= 1'b0;

else if ( ( Index == 1'b1 ) && ( Index_1 == 1'b1 ) )

begin

if ( ( Data_result_carry[33:30] == 4'b0000 ) || ( Data_result_carry[33:30] == 4'b1111 ) )

Hb_overflow_0 <= 1'b0;

else

Hb_overflow_0 <= 1'b1;

end

else

;

end

always @ ( posedge Clk or posedge Reset )

begin

if ( Reset == 1'b1 )

Hb_overflow_1 <= 1'b0;

else if ( ( Index == 1'b0 ) && ( Index_1 == 1'b1 ) )

begin

if ( ( Data_result_carry[33:30] == 4'b0000 ) || ( Data_result_carry[33:30] == 4'b1111 ) )

Hb_overflow_1 <= 1'b0;

else

Hb_overflow_1 <= 1'b1;

end

else

;

end

endmodule

/*****************************************************/

/*------- the end --------*/

/*****************************************************/

In the codes I use DSP48 as figure 4.

figure 4 DDC_HF2_DSP(generated by DSP48) in the code

References:

[1]www.xilinx.com, DSP:Designing for Optimal Results,2005.