Modification RCL_PWM_x48

3 posts in this topic

I need a 20-bit PWM with the counter clocked at 210MHz or greater. I looked at the RCL_PWM_x48 symbol code and tried to modify it to accept a clock separate from the soft core. Can someone take a look at the following and let me know if I'm on the right track? Thanks!

-- Copyright (c) 1995-2013 Xilinx, Inc.  All rights reserved.
--   ____  ____ 
--  /   /\/   / 
-- /___/  \  /    Vendor: Xilinx 
-- \   \   \/     Version : 14.7
--  \   \         Application : 
--  /   /         Filename : xil_12112_30
-- /___/   /\     Timestamp : 09/23/2014 15:24:59
-- \   \  /  \ 
--  \___\/\___\ 
--Design Name: 

library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
library UNISIM;
use UNISIM.Vcomponents.ALL;

--library work;
--use work.Wishbone_to_Registers_n_package.all;

library DesignLab;
use DesignLab.ALL;
use DesignLab.Wishbone_to_Registers_n_package.all;

entity PWM_20b_x5 is
	generic ( 
				pwm_count : integer := 5;
				pwm_width : integer := 20;
				register_count : integer := 5	--Each PWM has 1 register
   port ( wishbone_in  : in    std_logic_vector (100 downto 0); 
          wishbone_out : out   std_logic_vector (100 downto 0);
			 --Put your external connections here
			 PWM : out std_logic_vector(pwm_count-1 downto 0)
--			 DIR : out std_logic_vector(pwm_count-1 downto 0);
			 PWM_clk : in std_logic
end PWM_20b_x5;

architecture BEHAVIORAL of PWM_20b_x5 is

	COMPONENT Wishbone_to_Registers_n
	generic ( register_count : integer := register_count );
		wishbone_in : IN std_logic_vector(100 downto 0);         
		wishbone_out : OUT std_logic_vector(100 downto 0);
		PWM_clk : in std_logic;
		register_in : in register_type(0 to register_count-1);
		register_out : out register_type(0 to register_count-1)
	generic (
		C_PWM_WIDTH : integer := pwm_width;
		C_PWM_TYPE : integer := 1           -- 2 phase, 1 phase or Enable chopping
		Clk : in std_logic;
		Duty : in std_logic_vector(C_PWM_WIDTH-1 downto 0);
		Out1 : out std_logic;
		Out2 : out std_logic 
  signal register_in_array : register_type(0 to register_count-1);
  signal register_out_array : register_type(0 to register_count-1);
  signal DIR : std_logic_vector(pwm_count-1 downto 0);
  signal PWM_clk : std_logic;  
	--Put your unique register names here

	--Put your code here
	for j in 0 to pwm_count-1 generate
		Inst_pwm_inst: PWMGenerator 
			C_PWM_WIDTH => pwm_width,
			C_PWM_TYPE => 1
			CLK => PWM_clk,
			Duty => register_out_array(j)(pwm_width-1 downto 0),
			Out1 => PWM(j),
			Out2 => DIR(j)
		--register_in_array(j) <= register_out_array(j); 	--So we can read back what was written to the register.
	end generate GEN_PWMS;

	--Do not touch
	Inst_Wishbone_to_Registers_n: Wishbone_to_Registers_n 
	generic map (register_count => register_count) 
		wishbone_in => wishbone_in,
		wishbone_out => wishbone_out,
		clk_96Mhz => clk_96Mhz,
		register_in => register_in_array,
		register_out => register_out_array



Share this post

Link to post
Share on other sites

Some thoughts, more from what you're trying to do than from looking at your code:

  • 210MHz is a rather high clock rate to get on these FPGAs.  I think it can be done, but might require some trickery (especially pipelining) for it to make timing.
  • PWM is a rather simple thing: You have a counter, and you compare the counter value with your setting, and the result of the comparison is your output.
  • When you have more than one clock, the interaction between logic that uses the one clock, and logic which uses the other clock, can be tricky
    • I really haven't experimented with this much, usually I use the same clock for everything.
    • I think you're on the right track with this code -- where there's a piece which handles the Wishbone bus interaction (Wishbone_to_Registers_n, on the 96MHz clock) and another part which handles the PWM (on the >=210 MHz clock) and a simple one-way connection between them (register_out_array).
    • But you may have to put one or two clock cycles' worth of register delays between the components, to give XST a chance to synch them up.  In between, it tries to make logic respond within the worst-case period between the 210MHz clock and the 96MHz one.  I think for 210MHz that's something like 300ps!
    • Choosing your clock rate wisely might improve that: I believe for 216MHz it would be 1160ps, for 192MHz, 5200ps.
    • All this assumes your two clocks are derived from the same off-chip source (the 32MHz clock on the Papilio board).  If you have a second clock signal coming from off-chip then the situation gets more complicated.
  • I don't see anywhere "clk_96mhz" is being supplied to your code.  You use it (passing it to Wishbone_to_Registers_n) but the only clock you're getting is "PWM_clk".  You need to get both from somewhere...
  • If you want to see code which handles multiple clocks, in DesignLab, you might look for the video code.  It uses multiple clocks for the video output, and presumably still uses the 96MHz system clock for its Wishbone bus interface.  It's probably a rather complicated example, but at least it's an example.

Share this post

Link to post
Share on other sites


I'm using the PWM generator block successfully, but the PWM signals have a frequency of about 375KHz (way too fast for my application). Is it possible to reuse that code for setting up a different PWM generator that uses a exteral clock that may allow me to generate PWMs at 1/100 frequency ? I'm not very familiar with VHDL.



Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now