0

I am trying to generate picosecond PWM signal using the Spartan 3e board in VHDL (Xilinx ISE+ISim).

library ieee;
use ieee.std_logic_1164.all;

entity pwm is
  port(clk     : in     std_logic;
       pwm_out : buffer std_logic);
end entity;

architecture rtl of pwm is
begin
  process (clk)
    variable count      : integer range 0 to 50000;
    variable duty_cycle : integer range 0 to 50000;
    variable flag       : integer range 0 to 1;
  begin
    if (rising_edge(clk)) then
      count := count+1;
      if (count = duty_cycle) then
        pwm_out <= '1';
      end if;
      if (count = 50000) then
        pwm_out <= '0';
        count   := 0;
        if(flag = 0) then
          duty_cycle := duty_cycle+50;
        else
          duty_cycle := duty_cycle-50;
        end if;
        if(duty_cycle = 50000) then
          flag := 1;
        elsif(duty_cycle = 0) then
          flag := 0;
        end if;
      end if;
    end if;
  end process;
end rtl;

I am using the embedded 50Mhz for the global clock (C9) but the simulation showed a weird behavior; from 0ps to 1000000ps clk (clock) and pwm_out (output) seems to be HIGH always and there is nothing after 1000000ps both for clk and pwm_out in time domain under ISim.

I am trying to do is to investigate and solve this behavior and then increase the frequency of output (pwm_out). Also I would like to learn about how fast (rise/fall times and in the frequency) can I generate the pulse (physical limitations).

I would appreciate some guidance from experienced users.

Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
y33t
  • 649
  • 4
  • 14
  • 23
  • I think I found the problem, in simulation there is no clock provided from C9 thus the state of the clk is always the same. Still looking for the ways to multiply the frequency. – y33t Jul 09 '13 at 15:20

1 Answers1

0

The pwm_out output has not initial value, so it has to be assigned in the process before it gets a well defined value. But the process variables (holding process state) all have an initial value of zero, and since count is incremented first thing in the process loop, count will not equal duty_cycle (being 0) at the beginning. So pwm_out is not assigned until it equals 50000, which (with a 50 MHz clock) happens at 50000 / 50 MHz = 1 ms.

However, if you synthesize this and run it in the FPGA, you may experience some unexpected behavior, depending on your clock source and control. For example, if the pwm module is running from a clock that is not stable right when the FPGA is loaded, for example an internal PLL clock, then the initial clock behavior may not adhere to the timing constraints applied to the design, and any value may end up in for example the duty_cycle variable (register). But, the design is based on the assumption that the duty_cycle register has a value of (50 * n), and otherwise it won't increment and decrement as anticipated due to the equal compare (=) with 0 and 50000. So if the duty_cycle get the value 1, due to initial timing violations as a result of an initial "invalid" clock, the flag variable (state) won't operate as expected, and so on. One way to amend this is to add a reset input and apply this to the variable state until the clock is stable, or use inequality operators for comparison.

Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49