One of my duties in 7 Ways to Leave Your Spartan-6 is to compare Spartan 6 and 7. My fellow reviewers have already reviewed the reference document's differences and elaborated on them. I'd like to show a difference by porting a Spartan-6 design that uses a primitive that's not available in the Spartan-7. Not a lot of specs comparison, but rewriting a design from an old blog post.
In 2017, I wrote XuLA2 FPGA - Up the Clock. It was part of my Spartan-6 learning track. The article shows how to change an external 12 MHz crystal clock input signal into a 264 MHz one, using the Spartan-6 DCM_SP primitive. The Arty S7 board also uses a 12 MHz external clock. A perfect starting point for a migration exercise.
The project generates a differential PWM signal with dead band. This is not important for this blog. Here in this post, I'm talking about the clock signal that's used by the PWM generation VHDL block. More about the PWM here.
Spartan-6: generate 264 Mhz from a 12 Mhz input with Digital Clock Manager primitive
My 2017 example was based on a tutorial from Dave Vandenbout. I used his XuLA board and manual to learn VHDL. Great book, great board (no longer made).
On a Spartan-6, you can alter clock frequencies using a primitive called DCM_SP. A primitive is a block of hardware specifically created for a single purpose on the silicon. While the FPGA fabric is uncommitted, and can be used for many purposes, the primitives are for a specific use. Read Dave's section “Only 12 MHz! Now what?” for a good explanation of the DCM.
In VHDL code that uses a DCM_SP and hooks it up to the downstream logic (in Vivado this would be a block diagram) looks like this:
library UNISIM; use UNISIM.VComponents.all; -- ... architecture Behavioral of Rotary_Pwm is -- ... signal clk_fast : std_logic; begin DCM_SP_inst : DCM_SP generic map ( CLKFX_DIVIDE => 1, -- Divide value on CLKFX outputs - D - (1-32) CLKFX_MULTIPLY => 22 -- Multiply value on CLKFX outputs - M - (2-32) ) port map ( CLKFX => clk_fast, -- 1-bit output: Digital Frequency Synthesizer output (DFS) CLKIN => clk_i, -- 1-bit input: Clock input RST => '0' -- 1-bit input: Active high reset input ); u0 : PwmDeadBand port map ( clk_i => clk_fast, duty_i => accumulator_s, band_i => 64, pwmA_o => pwmA_o, pwmB_o => pwmB_o ); -- ...
A primitive is instantiated, and connected to the 12 MHz input. The clock isn't divided in this case, but directly multiplied by 22. The output clock is 264 MHz. The primitive takes care that the jitter / precision of the clock is controlled. There's a PLL at play. Note that you could not implement pure HDL code that generates a signal that's faster than its input. The primitive in the Spartan-6 takes care that you can get high speeds, with reasonable jitter, using lower frequency input clocks.
In ISE, there's a template wizard that generates the instantiation code for you (look at Dave's book again). It's used in many designs, and will need to be adapted when you move from 6 to 7.
There's more adaption desired (but not mandatory): in Vivado, it's suggested that you no longer use instantiation. That's not hard: the block design will take care that new paradigms are used. A second adaption will be that the glueing between the blocks will not be done in a user HDL script (like shown above), but on a Vivado block diagram.
Spartan-7: generate 264 Mhz from a 12 Mhz input with the Clocking Wizard
Many parts of the Spartan-7 port are the same: the Arty S7 has an input clock with the same frequency as the Spartan-6 XuLA2 kit. The VHDL for the PWM generator I copy from the old project.
Because that PWM module is the only HDL, and the rest of the work is gluing and linking; I'll do the remainder in the block design.
In my first Arty project, I used the board definition file to automate the clock generation. In this example, I'll use the raw F14 12 MHz pin and work from there ...
source: Arty S7 FPGA Board Reference Manual
I manually added a clocking wizard, and set the input frequency to 12 MHz.
Output to 264 MHz:
I changed the Reset to active low and disabled the locked output that I'm not using.
The clock output is linked to the PWM VHDL block. That block's differential outputs will be connected to PMOD header JA.
source: Arty S7 FPGA Board Reference Manual## Pmod Header JA
#set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L4P_T0_D04_14 Sch=ja_p[1]
#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { ja[1] }]; #IO_L4N_T0_D05_14 Sch=ja_n[1]
These pins, and the clock input, will be defined in the constraint file.
Final block design:
Constraints:
The reset was assigned by Vivado, because I took it from the board resources. All others, I've assigned (check the constraint file from Digilent for inspiration):
- CLK: F14
- PMOD JA0: L17
- PMOD JA1: L18
Result: first time right . Same behaviour as on the Spartan-6.