2
\$\begingroup\$

I am reading the Spartan 6 DSP slice user guide, and I need to use the DSP slice in a project of mine.

I stumbled upon this question, which basically suggests 3 ways of using the DSP slices

  1. Inferring the DSP slice
  2. Using Core generator
  3. Using the RAW DSP instantiating template

The second option is almost self explanatory, but I somehow don't feel like using it, since it feels somewhat superficial. I am interested in using the first and third options, since those options are the most customisable, but I am having a hard time understanding where to start.

These are the questions I have on my mind :

  • What are the different ways in which you can infer a DSP slice in your design ?
  • Where do I find the RAW DSP instantiating template? I have been googling for it, but I didn't find a definitive guide to it.
  • Building up on my second question, there are a lot of xilinx documents one can read to get information on a lot of things. Since I am a noob, I always get confused about what to read, and I always like to have a mindmap of what all is out there, and so what options I have. Is there a place where all the xilinx documents with their description are listed, or what all documents I can refer for a particular application ?
\$\endgroup\$
2
  • \$\begingroup\$ shouldn't it be in the xilinx ide template? That is the usual place you instantiate a function provided at silicon (ram, pll etc..) \$\endgroup\$
    – user16222
    Commented Feb 5, 2017 at 12:02
  • \$\begingroup\$ @JonRB That would be method 2, using the Core generator. \$\endgroup\$
    – DKNguyen
    Commented Nov 1, 2019 at 20:34

4 Answers 4

3
\$\begingroup\$

Inferring DSP slices is actually pretty straightforward. The Spartan 6 has DSP48A1 DSP slices, so take a look at Xilinx UG389. Page 15 has a block diagram of the DSP slice. XST is quite good about inferring DSP slices. Just make sure to get all of the pipeline registers in there for maximum performance, and make sure all of your bit widths are no wider than those shown on the block diagram. Here is a simple multiplier with AXI stream interfaces that infers a DSP slice on a Spartan 6: https://github.com/alexforencich/verilog-dsp/blob/master/rtl/dsp_mult.v .

Also take a look at the XST user guide, ug627, pages 98-121. One rather annoying thing to note: the pipelined multipliers in that section will not synthesize to completely pipelined DSP48 slices (they will probably infer slices, but you will get a performance penalty as the registers will not necessarily be in the correct locations). For example, the coding examples and block diagram on pages 104-108 all show a multiplier with one pipeline register before and three after. When I first looked at that, I assumed that XST would be smart enough to move the registers to match the actual DSP slice (it is possible to move registers "through" the multiplier without changing the operation). It isn't. You should add registers (with only synchronous resets!) exactly as shown in the DSP slice manual in order for XST to infer a DSP slice properly with the pipeline registers in the right places for maximum performance (note that this registers are implemented internally in the DSP slice; adding all of the pipeline registers shown in the DSP slice user guide will only result in a latency penalty - they will not consume fabric flip-flops). I would recommend printing out the DSP slice block diagram and tacking it up on the wall as a reference. And also don't forget to look at the synthesis logs to make sure the DSP slices are pulling in the pipeline registers correctly.

As far as a listing of documentation, there isn't one good place for everything (FPGAs, IP cores, software, etc.). For just the features of a single FPGA, take a look at the product page. For example, http://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html#documentation . Make sure to select 'user guides', not 'datasheets'. That should give you a pretty comprehensive list of the Spartan 6 documentation.

\$\endgroup\$
2
  • \$\begingroup\$ After looking at the github code, it has become quiet clear how to infer a DSP slice, but now I don't understand between "inferring a DSP slice" and "using RAW DSP instantiating template". Are they different ? \$\endgroup\$
    – ironstein
    Commented Mar 6, 2016 at 5:29
  • \$\begingroup\$ I don't think there is a huge difference, except maybe the template is a bit more explicit about what is in the DSP slice and what is not. Here is another file to look at: github.com/alexforencich/verilog-dsp/blob/master/rtl/… . This one infers two DSP slices with full pipeline registers (multiplier and post-adder). However, it is not so clear exactly what is going where. If you went the 'template' route, then I think it would be much more obvious how the DSP slice inputs are connected. \$\endgroup\$ Commented Mar 6, 2016 at 5:35
1
\$\begingroup\$

Alex has already written a lot about infering the DSP slices. My answer focuses only on:

Where do I find the RAW DSP instantiating template? I have been googling for it, but I didn't find a definitive guide to it.

The template can be found in the Libraries Guide for HDL Designs from Xilinx. For your Spartan-6 FPGA it is UG615. The description of the DSP48A1 slices can be found on page 92 ff.. The VHDL instantiation template is for example:

Library UNISIM;
use UNISIM.vcomponents.all;

-- DSP48A1: 48-bit Multi-Functional Arithmetic Block
-- Spartan-6
-- Xilinx HDL Libraries Guide, version 14.7

DSP48A1_inst : DSP48A1
generic map (
    A0REG => 0, -- First stage A input pipeline register (0/1)
    A1REG => 1, -- Second stage A input pipeline register (0/1)
    B0REG => 0, -- First stage B input pipeline register (0/1)
    B1REG => 1, -- Second stage B input pipeline register (0/1)
    CARRYINREG => 1, -- CARRYIN input pipeline register (0/1)
    CARRYINSEL => "OPMODE5", -- Specify carry-in source, "CARRYIN" or "OPMODE5"
    CARRYOUTREG => 1, -- CARRYOUT output pipeline register (0/1)
    CREG => 1, -- C input pipeline register (0/1)
    DREG => 1, -- D pre-adder input pipeline register (0/1)
    MREG => 1, -- M pipeline register (0/1)
    OPMODEREG => 1, -- Enable=1/disable=0 OPMODE input pipeline registers
    PREG => 1, -- P output pipeline register (0/1)
    RSTTYPE => "SYNC" -- Specify reset type, "SYNC" or "ASYNC"
)
port map (
    -- Cascade Ports: 18-bit (each) output: Ports to cascade from one DSP48 to another
    BCOUT => BCOUT, -- 18-bit output: B port cascade output
    PCOUT => PCOUT, -- 48-bit output: P cascade output (if used, connect to PCIN of another DSP48A1)

    -- Data Ports: 1-bit (each) output: Data input and output ports
    CARRYOUT => CARRYOUT, -- 1-bit output: carry output (if used, connect to CARRYIN pin of another
                          -- DSP48A1)
    CARRYOUTF => CARRYOUTF, -- 1-bit output: fabric carry output
    M => M, -- 36-bit output: fabric multiplier data output
    P => P, -- 48-bit output: data output

    -- Cascade Ports: 48-bit (each) input: Ports to cascade from one DSP48 to another
    PCIN => PCIN, -- 48-bit input: P cascade input (if used, connect to PCOUT of another DSP48A1)

    -- Control Input Ports: 1-bit (each) input: Clocking and operation mode
    CLK => CLK, -- 1-bit input: clock input
    OPMODE => OPMODE, -- 8-bit input: operation mode input

    -- Data Ports: 18-bit (each) input: Data input and output ports
    A => A, -- 18-bit input: A data input
    B => B, -- 18-bit input: B data input (connected to fabric or BCOUT of adjacent DSP48A1)
    C => C, -- 48-bit input: C data input
    CARRYIN => CARRYIN, -- 1-bit input: carry input signal (if used, connect to CARRYOUT pin of another
                        -- DSP48A1)
    D => D, -- 18-bit input: B pre-adder data input

    -- Reset/Clock Enable Input Ports: 1-bit (each) input: Reset and enable input ports
    CEA => CEA, -- 1-bit input: active high clock enable input for A registers
    CEB => CEB, -- 1-bit input: active high clock enable input for B registers
    CEC => CEC, -- 1-bit input: active high clock enable input for C registers
    CECARRYIN => CECARRYIN, -- 1-bit input: active high clock enable input for CARRYIN registers
    CED => CED, -- 1-bit input: active high clock enable input for D registers
    CEM => CEM, -- 1-bit input: active high clock enable input for multiplier registers
    CEOPMODE => CEOPMODE, -- 1-bit input: active high clock enable input for OPMODE registers
    CEP => CEP, -- 1-bit input: active high clock enable input for P registers
    RSTA => RSTA, -- 1-bit input: reset input for A pipeline registers
    RSTB => RSTB, -- 1-bit input: reset input for B pipeline registers
    RSTC => RSTC, -- 1-bit input: reset input for C pipeline registers
    RSTCARRYIN => RSTCARRYIN, -- 1-bit input: reset input for CARRYIN pipeline registers
    RSTD => RSTD, -- 1-bit input: reset input for D pipeline registers
    RSTM => RSTM, -- 1-bit input: reset input for M pipeline registers
    RSTOPMODE => RSTOPMODE, -- 1-bit input: reset input for OPMODE pipeline registers
    RSTP => RSTP -- 1-bit input: reset input for P pipeline registers
);
\$\endgroup\$
1
\$\begingroup\$

Re the issue of the Xilinx documents, Xilinx made a nice tool to help out with that problem: DocNav.

It's a browsable catalog of all the Xilinx documentation, with filterable categories for things you are/aren't interested in, and a reasonably good search within documents.

If you do use it, make sure to get the right one (Vivado vs ISE tabs on the download page, although the ISE installer still has Vivado branding for some reason) and update the catalog when you first use it.

\$\endgroup\$
1
\$\begingroup\$

I find myself in a similar situation, Ironstein. In my application I need to support Spartan-6 FPGAs (requiring use of XST) and also Artix-7 FPGAs (requiring Vivado in some cases, and XST or Vivado with other models). I’ve become facile with the memory and clock management tiles.

I agree with your assessment that using IPcores is easiest, but then from a project management standpoint I find it can become tricky to manage as there are so many files which need to be at the correct location 'just so'. I prefer to only use IPcores to instantiate distributed memory elements.

I am a bit wary of inferred designs in general as the slightest change may 'break' the DSP architecture, or some of the subtleties of how registers are allocated as Alex.Forencich pointed out.

I prefer to have explicit control of precisely what is going on, and so I am on the arduous learning curve to understanding the DSP48A1 block, and the related macro blocks: ADDMACC_MACRO, ADDSUB_MACRO, COUNTER_LOAD_MACRO, MULT_MACRO, and MACC_MACRO. These macros address common functions which can get you started without having to know all of the complexity of the full DSP48A1 primitive of the Spartan-6 family.

You can find VHDL/Verilog templates for the DSP48A1 primitive and these macros in the UG615 user guide as has been suggested. However, these templates are long enough that I prefer to make use of the Language Templates feature in XST to more directly copy/paste them into my designs. That's accessed via "Edit > Language Templates… > VHDL || Verilog > Device Macro Instantiation" (for macros) or "Edit > Language Templates… > VHDL || Verilog > Device Macro Primitives" (for the primitive modules). You then select the FPGA family and DSP, and you're all set. Since my designs also span the Spartan-6 / Artix-7 families that are supported by XST, I find the Language Templates feature to be quite handy.

\$\endgroup\$
2
  • \$\begingroup\$ This is what I finally ended up doing (after trying a lot of things) :) \$\endgroup\$
    – ironstein
    Commented Feb 5, 2017 at 13:25
  • \$\begingroup\$ I’m glad my answer was useful. That said, you might want to upvote my answer since I’m relatively new here and could use the ‘rep’. ;-) \$\endgroup\$ Commented Nov 25, 2018 at 23:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.