can I specify a time-varying clock?

Guest
I need to simulate a circuit that uses a clock that varies over time,
e.g. starts out nominal at, say 80 MHz, and then, gradually slows down
to 2% below that center frequency, then gradually increases in
frequency to 2% above that frequency, then comes back to the nominal
80 MHz rate in a period of, say, 1/60 second.

Imagine using a sweep signal generator to produce such a cycle.

Is there a cool way to specify such a thing in VHDL?

Thanks!
 
On Sat, 21 Mar 2009 09:41:06 -0700 (PDT), edick@hotmail.com wrote:

I need to simulate a circuit that uses a clock that varies over time,
e.g. starts out nominal at, say 80 MHz, and then, gradually slows down
to 2% below that center frequency, then gradually increases in
frequency to 2% above that frequency, then comes back to the nominal
80 MHz rate in a period of, say, 1/60 second.

Imagine using a sweep signal generator to produce such a cycle.

Is there a cool way to specify such a thing in VHDL?
Use a signal of type TIME to represent the period,
or a signal of type REAL to represent the frequency
error (percentage). A standard clock-generator process
can then respond to that value and generate the right
cycle timing:


signal frequency_error: real := 0.0;
...
clock_gen: process
variable period: time;
constant nominal_Hz: real := 80.0e6;
begin
-- Compute the period
period := 1 sec / (nominal_Hz * (1.0 + frequency_error));
-- Generate one cycle at the appropriate period
clock <= '0', '1' after period/2;
wait for period;
-- And then loop back.
end process;

Now you can write another process that updates "frequency_error"
in any way you choose as a function of time.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Sat, 21 Mar 2009 09:41:06 -0700 (PDT), edick@hotmail.com wrote:

I need to simulate a circuit that uses a clock that varies over time,
e.g. starts out nominal at, say 80 MHz, and then, gradually slows down
to 2% below that center frequency, then gradually increases in
frequency to 2% above that frequency, then comes back to the nominal
80 MHz rate in a period of, say, 1/60 second.

Imagine using a sweep signal generator to produce such a cycle.

Is there a cool way to specify such a thing in VHDL?
Manipulating the real value "frequency" is left as an exercise to you :)


clk_and_rst.vhd:
===========================================================================
--
-- entity clk_and_reset.vhd
-- (c) jul 2007 Gerhard Hoffmann, ghf at hoffmann - hochfrequenz . de
-- open source under BSD conditions
--
-- canonic location: /lib/vhdl/tb/clk_and_rst/clk_and_rst.vhdl
--
-- Solution to an everyday problem.
-- This module produces a clock for a simulation with selectable frequency
-- and a reset signal with selectable width.
-- The clock duty cycle is 1:1.
-- The reset is active from the beginning and removed synchronously shortly
-- after a rising clock edge.
--
-- setting verbose to true gives some diagnostics.
--
-- Make sure that your simulator has a time resolution of at least 1 ps.
-- For modelsim, this is set up by the various modelsim.ini files
-- and/or the project file (foobar.mpf)


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

entity clk_and_rst is
generic (
verbose: boolean := false
);
port (

clock_frequency: in real := 100.0e6;
min_resetwidth: in time := 12 ns; -- minimum resetwidth, is synchronized to clk

clk: out std_logic;
rst: out std_logic
);
end entity clk_and_rst;


--
architecture rtl of clk_and_rst is

signal iclk: std_logic := '0'; -- entity-internal clk and rst
signal irst: std_logic := '1';
signal halfcycle: time := 0 ps;


-- The clock frequency is given in Hz in floating point format.
-- compute the equivalent half cycle time.

function frequency2halfcycle(f: real; verbose: boolean) return time is

variable picoseconds: real;
variable retval: time;

begin
assert f > 1.0e-10
report "clk_and_rst.vhd: requested clock frequency is unreasonably low or even negative - danger of 1/0.0"
severity error;

picoseconds := (0.5 / f ) / 1.0e-12;
retval := integer(picoseconds) * 1 ps;

if verbose then
report "function frequency2halfcycle in clk_and_rst.vhd: picoseconds = " & real'image(picoseconds);
report "halfcycle = " & time'image(retval);
end if;

assert retval > 0 ps
report "frequency2halfcycle: length of halfcycle truncated to 0 ps. "
& "Set simulator resolution to 1 ps or smaller in modelsim.ini or foobar.mpf"
severity error;

return retval;
end;


----------------------------------------------------------------------------------------------------
begin

-- generate the internal system clock

u_determine_halfcycle: process (clock_frequency) is
begin
halfcycle <= frequency2halfcycle(clock_frequency, verbose);
end process u_determine_halfcycle;


u_sysclock: process is
begin
wait for halfcycle;
iclk <= '1';

wait for halfcycle;
iclk <= '0';
end process u_sysclock;

clk <= iclk;


--
-- generate internal reset

u_rst: process is
begin
irst <= '1';
wait for min_resetwidth;
wait until rising_edge(iclk);
irst <= '0';
wait; -- forever
end process u_rst;

rst <= irst;

end architecture rtl;
===========================================================================







clk_and_rst_tb.vhd:
===========================================================================
--
-- testbed for entity clk_and_reset.vhd
-- (c) jul 2007 Gerhard Hoffmann, ghf at hoffmann - hochfrequenz . de
-- open source under BSD conditions
-- slightly modified 2009-mar-23

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.numeric_std.all;


entity clk_and_rst_tb is
end entity clk_and_rst_tb;

--
architecture rtl of clk_and_rst_tb is

component clk_and_rst is
generic (
verbose: boolean := false
);
port (
clock_frequency: in real := 100.0e6;
min_resetwidth: in time := 12 ns; -- minimum resetwidth, is synchronized to clk

clk: out std_logic;
rst: out std_logic
);
end component;

signal clk: std_logic;
signal rst: std_logic;
signal frequency: real;

begin


frequency <= 100.0e6, 50.0e6 after 200 ns, 10.0e6 after 400 ns;

uut: clk_and_rst
generic map(
verbose => true
)
port map(

clock_frequency => frequency,
min_resetwidth => 153 ns,

clk => clk,
rst => rst
);


end architecture rtl;

===========================================================================

and the result:
http://www.bilder-hochladen.net/files/9hqp-3-gif.html


regards, Gerhard
 
On 24 mar, 11:32, Gerhard Hoffmann <dk...@hoffmann-hochfrequenz.de>
wrote:
On Sat, 21 Mar 2009 09:41:06 -0700 (PDT), ed...@hotmail.com wrote:
I need to simulate a circuit that uses a clock that varies over time,
e.g. starts out nominal at, say 80 MHz, and then, gradually slows down
to 2% below that center frequency, then gradually increases in
frequency to 2% above that frequency, then comes back to the nominal
80 MHz rate in a period of, say, 1/60 second.
You probably need this feature for a spread-spectrum clocking
simulation.
Here is another example of clock you may consider using:

use generics to provide the values for:

SSC_ENABLE : boolean := FALSE;
SSC_PERIOD : real := 33333000.0; -- expressed in [ps] (this would be
1/60 expressed in [ps] in your case)

use the following procedure to compute the <Iterations> and <Delta>
parameters:

procedure ComputeIterationsAndDelta(variable Iterations: out integer;
variable Delta: out real) is
variable T_start : real; -- start period
variable T_stop : real; -- stop period
variable Iterations_real : real;
begin

-- replace values of T_start and T_stop as required by you
freq. modulation specifications ...

-- T_start = 4000 ps; (12500 ps in your case)
-- T_stop = T_start + Iterations*Delta = 4020 ps; because it is
modulated 0.5% (2% in your case 12750 ps)
-- where <Iterations> is to be determined and <Delta > is also to be
determined
-- at this point we know <Iterations*Delta> = 20 ps! (250 ps for you)

-- we also know that :
-- T_start + (T_start + Delta) + ((T_start + 2*Delta) + ....
+ ((T_start + Iterations*Delta) = SSC_PERIOD/2
-- or: 2*(Iterations + 1)*T_start + Iterations*(Iterations + 1)*Delta
= SSC_PERIOD
-- or: 8020[ps]*(Iterations + 1) = SSC_PERIOD

-- !!!!! You should change accordingly the values below)

Iterations_real := (SSC_PERIOD - 8020.0) / (8020.0);
Delta := 20.0e-12 / Iterations_real;

Iterations := integer(Iterations_real);
end procedure;

and the code to have either a SSC modulation or a normal clock.
The code is very simple.

SSC_GENERATE: if (SSC_ENABLE = TRUE) generate

-- Generate SSC Reference Clock input (250MHz)
process
variable Iterations : integer;
variable Delta : real;
variable it : integer;
variable sign : integer;
variable my_time : time;
begin
ComputeIterationsAndDelta(Iterations, Delta);

it := 0;
sign := +1;

loop
my_time := REFCLK_PERIOD + (real(it) * Delta)*1 sec;

refclk_n_r <= '1';
wait for my_time/2;
refclk_n_r <= '0';
wait for my_time/2;

if (it = Iterations) then sign := -1;
elsif (it = 0) then sign := +1;
end if;

it := it + sign*1;
end loop;
end process;

end generate SSC_GENERATE;

NO_SSC_GENERATE: if (SSC_ENABLE = FALSE) generate
-- Generate Reference Clock input (250MHz)
process begin
refclk_n_r <= '1';
wait for REFCLK_PERIOD/2;
refclk_n_r <= '0';
wait for REFCLK_PERIOD/2;
end process;
end generate;

refclk_p_r <= not refclk_n_r;

Good luck!
Cristian
 

Welcome to EDABoard.com

Sponsor

Back
Top