---
+ Post New Thread
Results 1 to 4 of 4
  1. #1
    Newbie level 2
    Points: 495, Level: 4

    Join Date
    Mar 2010
    Posts
    2
    Helped
    0 / 0
    Points
    495
    Level
    4

    Inferring DSP48A1 on Spartan6

    Will the following code infer two DSP48A1 slices? Will they if I use (*Use DSP48*) before the module declaration? If this won't infer DSP48A1 slices, what else would I need to add?
    Code:
    module tap(
    		input clk,
    		input [17:0] xn,
    		input [35:0] addin,
    		input [17:0] errmu,
    		output reg [17:0] xn1,
    		output reg [35:0] addout
        );
    
    
    	always@(posedge clk) begin
    		xn1 <= xn;
    	end
    
    	always@(posedge clk) begin
    		addout <= addin + (wght * xn);
    	end
    
    	always@(posedge clk) begin
    		wght <= wght + (errmu * xn);
    	end
    	
    endmodule

    •   Alt4th May 2011, 22:07

      advertising

        
       

  2. #2
    Newbie level 2
    Points: 495, Level: 4

    Join Date
    Mar 2010
    Posts
    2
    Helped
    0 / 0
    Points
    495
    Level
    4

    Re: Inferring DSP48A1 on Spartan6

    Ok so I have restructured my code a bit. If you can't tell, I'm trying to implement an LMS Adaptive Filter using DSP48A1 slices on a Spartan6. Here I have a tap module and a coefficient update module. I would like each to use one DSP48A1 slice. I'm going to instantiate multiple of each(one coeff module for every tap module), and stitch them together as a Systolic FIR filter with the coeff modules feeding in the coefficients.

    Am I correct in implementing these modules so that a DSP48A1 slice will be used for each?

    Tap Module:
    Code:
    (* USE_DSP48="YES" *)
    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Engineer: 		 John *****
    // Create Date:    22:24:29 05/02/2011  
    // Module Name:    tap 
    // Project Name:   
    // Target Devices:  Atlys Board - Spartan6(XC6SLX45)
    // Description: Infer DSP48A1 Slice - Systolic FIR Tap w/ Coeff Input
    //					 addout = (xin * win) + addin
    //////////////////////////////////////////////////////////////////////////////////
    module tap(
    		input clk,
    		input rst,
    		input ce,
    		input signed [17:0] xin,
    		input signed [17:0] wn,
    		input signed [47:0] addin,
    		output signed [17:0] xout,
    		output signed [47:0] addout
        );
    	
    	
    	//Pipeline registers
    	reg signed [35:0] M;
    	reg signed [47:0] accum;
    	reg signed [17:0] xin_r;
    	reg signed [47:0] addin_r;
    
    	//addout = (xin * win) + addin
    	always@(posedge clk) begin
    		if(rst) begin
    			M <= 0;
    			accum <= 0;
    			xin_r <= 0;
    			xin_r_r <= 0;
    			wn_r <= 0;
    			addin_r <= 0;
    		end
    		else if(ce == 1'b1) 
    			begin
    				xin_r <= xin;
    				wn_r <= wn;
    				
    				M <= xin_r * wn_r;
    				accum <= M + addin;
    			end
    	end
    	assign addout = accum;
    	assign xout = xin_r;
    	
    endmodule
    Coefficient Module:
    Code:
    (* USE_DSP48="YES" *)
    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Engineer: John *****
    // Create Date:    20:31:48 05/04/2011 
    // Module Name:    coeff 
    // Project Name:  
    // Target Devices:  Atlys Board - Spartan6(XC6SLX45)
    // Description: Infer DSP48A1 Slice - New Coeff Generator - LMS Algorithm
    //					 wout = wout + (xin * emu) - (truncated to 18 bits)
    //////////////////////////////////////////////////////////////////////////////////
    module coeff(
    		input clk,
    		input rst,
    		input ce,
    		input signed [17:0] xin,
    		input signed [17:0] emu,
    		output signed [17:0] wout,
        );
    
    	//Pipeline registers
    	reg signed [17:0] xin_r;
    	reg signed [17:0] emu_r;
    	reg signed [35:0] M;
    	reg signed [47:0] wout_r;
    	
    	always@(posedge clk) begin
    		if(rst) begin
    			xin_r <= 0;
    			emu_r <= 0;
    			wout_r <= 0;
    		end
    		else if(ce == 1'b1)
    			begin
    				xin_r <= xin;
    				emu_r <= emu;
    				
    				M <= xin_r * emu_r;
    				wout_r <= wout_r + M;
    			end
    	end
    	assign wout = wout_r[47:30];
    endmodule
    Error Signal Calculation:
    Code:
    (* USE_DSP48="YES" *)
    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Engineer: 		John *****
    // Create Date:    21:01:03 05/04/2011 
    // Module Name:    errcalc 
    // Project Name:    
    // Target Devices:  Atlys Board - Spartan6(XC6SLX45)
    // Description: Infer DSP48A1 Slice - Error Calculation
    //					 
    //////////////////////////////////////////////////////////////////////////////////
    module errcalc(
    		input clk,
    		input rst,
    		input ce,
    		input signed [17:0] mu;
    		input signed [17:0] xin,
    		input signed [17:0] yin,
    		output signed [17:0] err,
    		output signed [17:0] emu
        );
    
    	//Pipeline Registers
    	reg signed [17:0] xin_r;
    	reg signed [17:0] yin_r;
    	reg signed [17:0] mu_r;
    	reg signed [17:0] mu_r_r;
    	
    	reg signed [17:0] preadd;
    	reg signed [47:0] emu_r;
    	
    	always@(posedge clk) begin
    		if(rst) begin
    			xin_r <= 0;
    			yin_r <= 0;
    			mu_r <= 0;
    			mu_r_r <= 0;
    			preadd <= 0;
    			emu_r <= 0;
    		end
    		else if(ce == 1'b1)
    			begin
    				xin_r <= xin;
    				yin_r <= yin;
    				mu_r <= mu;
    				mu_r_r <= mu_r;
    				
    				preadd <= xin_r - yin_r;
    				emu_r <= mu_r_r * preadd;
    			end
    	end
    	assign err = preadd;
    	assign emu = emu_r;
    
    endmodule



    •   Alt5th May 2011, 02:29

      advertising

        
       

  3. #3
    Advanced Member level 5
    Points: 13,689, Level: 28
    mrflibble's Avatar
    Join Date
    Apr 2010
    Posts
    2,480
    Helped
    619 / 615
    Points
    13,689
    Level
    28

    Re: Inferring DSP48A1 on Spartan6

    Quote Originally Posted by rudzz34 View Post
    Am I correct in implementing these modules so that a DSP48A1 slice will be used for each?
    AFAIK, you have to put verilog style attributes right before the "module" for it to take effect. So ...

    Code:
    `default_nettype none
    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Engineer: 		 John *****
    // Create Date:    22:24:29 05/02/2011  
    // Module Name:    tap 
    // Project Name:   
    // Target Devices:  Atlys Board - Spartan6(XC6SLX45)
    // Description: Infer DSP48A1 Slice - Systolic FIR Tap w/ Coeff Input
    //					 addout = (xin * win) + addin
    //////////////////////////////////////////////////////////////////////////////////
    (* USE_DSP48="YES" *)
    module tap(
    		input  wire               clk,
    		input  wire               rst,
    		input  wire               ce,
    		input  wire signed [17:0] xin,
    		input  wire signed [17:0] wn,
    		input  wire signed [47:0] addin,
    		output wire signed [17:0] xout,
    		output wire signed [47:0] addout
        );
    	
    	
    	//Pipeline registers
    	reg signed [35:0] M;
    	reg signed [47:0] accum;
    	reg signed [17:0] xin_r;
    	reg signed [47:0] addin_r;
    
    	//addout = (xin * win) + addin
    	always@(posedge clk) begin
    		if(rst) begin
    			M <= 0;
    			accum <= 0;
    			xin_r <= 0;
    			xin_r_r <= 0;
    			wn_r <= 0;
    			addin_r <= 0;
    		end
    		else if(ce == 1'b1) 
    			begin
    				xin_r <= xin;
    				wn_r <= wn;
    				
    				M <= xin_r * wn_r;
    				accum <= M + addin;
    			end
    	end
    	assign addout = accum;
    	assign xout = xin_r;
    	
    endmodule // tap
    `default_nettype wire

    Also note the "`default_nettype" + explicit "wire" declarations in the port list. That makes your code less vulnerable to the inevitable typo + verilog making up stuff (implicit net declarations, with the wrong typo'd name). Just remember to return it to the default of "`default_nettype wire" so you don't break other people's code that the project also might be using...

    To be sure your design uses the "USE_DSP48" directive as intended, synthesize it. Then go over the synthesis log in the console and look for either the USE_DSP48 string, or for the name of the module "tap". There you will find details about how XST handles this module. And finally another way of knowing is to go the usage report in the design summary. That will also list the total number of DSP48 resources used in the design.

    Hope that helps...



    •   Alt5th May 2011, 10:34

      advertising

        
       

  4. #4
    Advanced Member level 3
    Points: 5,700, Level: 17

    Join Date
    Jul 2010
    Posts
    923
    Helped
    289 / 289
    Points
    5,700
    Level
    17

    Re: Inferring DSP48A1 on Spartan6

    just synthesize the module -- XST will tell you what it does. also "addin_r" gets assigned, but not used. I've had pretty good luck with the basic DSP48 features being inferred from code. some of the advanced features still need manual instantiation. The big issue with inferred code is that you should explain it, otherwise someone will be tempted to take the output of one of the intermediate signals and use it.



+ Post New Thread
Please login