element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
FPGA
  • Technologies
  • More
FPGA
Blog Learning Xilinx Zynq: a Quadrature Oscillator - 2 implementations
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join FPGA to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 4 Aug 2021 8:32 PM Date Created
  • Views 5809 views
  • Likes 13 likes
  • Comments 23 comments
  • zynq
  • xilinx
  • vivado
  • summer of fpgas
  • pynq
Related
Recommended

Learning Xilinx Zynq: a Quadrature Oscillator - 2 implementations

Jan Cumps
Jan Cumps
4 Aug 2021

shabaz made a Software Defined Radio (SDR) Experiment Board. One of the components is a digital quadrature oscillator.

It's a circuit with 4 PWM outputs that are each 90° shifted.

image

In Shabaz' blog, the oscillator is made with flip-flops, and controlled by an external function generator.

Because it's the Summer of FPGAs, I'm proposing 2 FPGA based alternatives.

They work identical, generate the same frequency (input / 4), but the approach is different.

One works by replaying a predefined output pattern on the 4 outputs, with one clock delay for each output.

The second one by calculating the first channel based on a counter value, and left shifting the data through the outputs.

 

The entity is identical for the two approaches:

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity quadrature_oscillator is
  Port (
    i_clk: in std_logic;
    i_nReset: in std_logic;
    o_outputs: out std_logic_vector (3 downto 0)
   );
end quadrature_oscillator;

 

This is the first implementation.

The pattern used to define the outputs is 0011001.

Each of the pins continuously cycles through a (different!) range of 4 bits of the pattern, on the cadence of the clock.

pin 0 from 3 to 6: 1100

pin 1 from 2 to 5: 0110

pin 2 from 1 to 4: 0011

pin 3 from 0 to 3: 1001

They do this at the same time, in parallel.

You can see that this generates an output where each of the pins is 90° shifted.

 

architecture Behavioral of quadrature_oscillator is
  signal s_pattern: std_logic_vector (6 downto 0) := "0011001";
  signal s_counter: natural range 0 to 3 := 0;

begin
process (i_clk, i_nReset)
begin
--  if i_nReset = '0' then
--    s_counter <= 0;
--  els
  if rising_edge(i_clk) then
    if s_counter = 3 then
      s_counter <= 0;
    else
      s_counter <= s_counter + 1;
    end if;
    o_outputs(0) <= s_pattern(s_counter + 3);
    o_outputs(1) <= s_pattern(s_counter + 2);
    o_outputs(2) <= s_pattern(s_counter + 1);
    o_outputs(3) <= s_pattern(s_counter);
  end if;
end process;

end Behavioral;

 

The second implementation takes a different approach.

The data is the output vector is shifted 1 position to the left. That generates 90° phase shift.

I only have to take care that I set the LSB correct each time. For that, I use the MSB of the counter, inversed.

The counter is 2 bits. It cycles 00 -> 01 -> 10 -> 11.

If you take the MSB each time, inversed, you get 1100.

That's the identical as the output of pin 0 in the first implementation. The left-shift does the rest of the magic for the other 3 pins.

 

architecture Behavioral of quadrature_oscillator is
  signal s_counter: UNSIGNED (1 downto 0) := "00";
  signal s_buffer: std_logic_vector (3 downto 0) := (others => '0');

begin
process (i_clk, i_nReset)
begin
  if i_nReset = '0' then
    s_counter <= "00";
    s_buffer <= (others => '0');
  elsif rising_edge(i_clk) then
    if s_counter = "11" then 
      s_counter <= (others => '0');
    else
      s_counter <= (s_counter) + 1;
    end if;
    s_buffer <= s_buffer (2 downto 0) & not(s_counter(1));
    o_outputs <= s_buffer;
  end if;
end process;

end Behavioral;

 

I've attached Vivado project and Jupyter notebook. Implementation #2 is active, approach #1 is commented out.

The VHDL for #2 is adapted, see https://www.element14.com/community/groups/fpga-group/blog/2021/08/04/learning-xilinx-zynq-a-quadrature-oscillator#comme… .

Latest source on github: https://gist.github.com/jancumps/0a1b2692ddfd6edc79e8487adc66539e

 

Which design do you prefer? Or do you have an alternative?

 

Pynq - Zync - Vivado series
Add Pynq-Z2 board to Vivado
Learning Xilinx Zynq: port a Spartan 6 PWM example to Pynq
Learning Xilinx Zynq: use AXI with a VHDL example in Pynq
VHDL PWM generator with dead time: the design
Learning Xilinx Zynq: use AXI and MMIO with a VHDL example in Pynq
Learning Xilinx Zynq: port Rotary Decoder from Spartan 6 to Vivado and PYNQ
Learning Xilinx Zynq: FPGA based PWM generator with scroll wheel control
Learning Xilinx Zynq: use RAM design for Altera Cyclone on Vivado and PYNQ
Learning Xilinx Zynq: a Quadrature Oscillator - 2 implementations
Learning Xilinx Zynq: a Quadrature Oscillator - variable frequency
Learning Xilinx Zynq: Hardware Accelerated Software
Automate Repeatable Steps in Vivado
Learning Xilinx Zynq: Try to make my own Accelerated OpenCV Function - 1: Vitis HLS
Learning Xilinx Zynq: Try to make my own Accelerated OpenCV Function - 2: Vivado Block Design
Learning Xilinx Zynq: Logic Gates in Vivado
Learning Xilinx Zynq: Interrupt ARM from FPGA fabric
Learning Xilinx Zynq: reuse and combine components to build a multiplexer
PYNQ version 2.7 (Austin) is released
PYNQ and Zynq: the Vitis HLS Accelerator with DMA training - Part 1: Turn C++ code into an FPGA IP
PYNQ and Zynq: the Vitis HLS Accelerator with DMA training - Part 2: Add the Accelerated IP to a Vivado design
PYNQ and Zynq: the Vitis HLS Accelerator with DMA training - Part 3: Use the Hardware Accelerated Code in Software
PYNQ and Zynq: the Vitis HLS Accelerator with DMA training - Deep Dive: the data streams between Accelerator IP and ARM processors
Use the ZYNQ XADC with DMA part 1: bare metal
Use the ZYNQ XADC with DMA part 2: get and show samples in PYNQ
VHDL: Convert a Fixed Module into a Generic Module for Reuse

 

Attachments:
quad_osc_jupyter.zip
quadrature_oscillator.zip
  • Sign in to reply

Top Comments

  • Jan Cumps
    Jan Cumps over 4 years ago in reply to jc2048 +4
    These are the GUI settable parameters: Then there's a bespoke Clocking Wizard IP that can be attached to clock signals in fabric: I've not tested it yet, I just put one on the block design and checked…
  • Jan Cumps
    Jan Cumps over 4 years ago +3
    The Vivado / Zynq / Pynq artifacts: Block diagram: Constraints: Jupyter notebook: I've used one of the Zync fabric clocks as input. Any clock works, and output will be clock/4. Here, the input clock was…
  • fmilburn
    fmilburn over 4 years ago +3
    Impressive that you did this so quickly and with so little code
Parents
  • jc2048
    jc2048 over 4 years ago

    Or do you have an alternative?

    Does the Zync clock block allow you to dynamically set the frequency under the control of either the processor or the fabric? If so, it may also give you the ability to produce four outputs at different phases. Then you don't need the logic at all.

     

    The Cyclone 10 part seems to allow control of a PLL, though whether the resolution would be fine enough for sensible tuning of Shabaz's radio I don't know. I'm not sure how accurate the phase settings would be either, though it does seem to allow for adjusting phase.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to jc2048

    jc2048  wrote:

    ...Does the Zync clock block allow you to dynamically set the frequency under the control of either the processor or the fabric? If so, it may also give you the ability to produce four outputs at different phases. Then you don't need the logic at all....

    There are 4 independent (yet sourced from the same root clock) Clock/PLL blocks that link to the fabric and can be dynamically set from the processor.

    Frequency range approx 350 KHz - 400 MHz.

    I haven't checked yet what parameters can be set, besides the frequency.

    In this post, I used one of those 4 as Clk.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • jc2048
    jc2048 over 4 years ago in reply to shabaz

    Unfortunately, it's not going to work, at least not with the Cyclone. The minimum frequency to the phase detector is high (5MHz) - I imagine that's due to the difficulty of fabbing the loop filter on the chip - so if I'm understanding it right, it looks like we might manage about 60kHz or so, which isn't really good enough.

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to jc2048

    The same for the Vivado clock wizard IP outputs: 4.7 MHz seems to be the lowest I can get it to.

    I've tried fiddling with the settings. In PLL mode I can get to 7 MHz and higher, in MMCM 4.7 MHz and higher.

    Minimum inputs 10 MHz and 19 MHz respectively.

    image

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to Jan Cumps

    ... but trying it out anyway, with clock in 10 MHz, out 5 MHz:

     

    image

    image

     

     

    image

    image

    image

    image

    clock 4 seems off ...

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 4 years ago in reply to jc2048

    I see.. I guess external loop filter+VCO ould be used, but then that's becoming a major project in itself. Still, impressive to hear that the FPGA clock capabilities can at least resolve down to 60 kHz ballpark, that's useful to know for other projects too, and where the ADC sample rate allows for more than that bandwidth.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to shabaz

    With the vhdl code version, you can go from Hz to MHz.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • Jan Cumps
    Jan Cumps over 4 years ago in reply to shabaz

    With the vhdl code version, you can go from Hz to MHz.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube