Generate clocks with ratio for testbench - vhdl

I want to generate a test stimulus for my I2S demux module. The stimulus contains values from an ADC measurement. The I2S standard provides two clocks: LRCLOCK and BITCLOCK. In my case LRCLOCK has a frequency of 48kHz (which is also the sample rate) and BITCLOCK is 64*LRCLOCK which results in a clock of 3.072MHz.
When creating the clocks in the testbench, there is always a offset between the LRCLOCK and the BITLCOCK. And I can't explain where this offset is coming from.
I tried to create a clock generation procedure according to this post: VHDL - How should I create a clock in a testbench?
Both suggested solutions show the same behaviour.
I work with VIVADO 2016.4, the simulator has a resolution of 1ps
Procedure:
procedure clk_gen(signal clk : out std_logic; constant FREQ : real) is
constant PERIOD : time := 1 sec / FREQ; -- Full period
constant HIGH_TIME : time := PERIOD / 2; -- High time
constant LOW_TIME : time := PERIOD - HIGH_TIME; -- Low time; always >= HIGH_TIME
begin
-- Check the arguments
assert (HIGH_TIME /= 0 fs) report "clk_plain: High time is zero; time resolution to large for frequency" severity FAILURE;
-- Generate a clock cycle
loop
clk <= '1';
wait for HIGH_TIME;
clk <= '0';
wait for LOW_TIME;
end loop;
end procedure;
Clock assignment:
process
begin
i2s_lrclock <= '1';
wait until reset /= '1';
clk_gen(i2s_lrclock,48.0e3);
end process;
process
begin
i2s_bitclock <= '1';
wait until reset /= '1';
clk_gen(i2s_bitclock,48.0e3*64);
end process;
I expect the edges of both clocks to be synchronous but there is an offset of 26ps from the i2s_bitclock to i2s_lrclock.

A 3.072MHz clock has a period of 325.5208333... ns, the simulator has to trunk the period somewhere, and it's probably not on the same digit for your other clock.
Try something like that :
signal i2s_lrclock : std_logic := '0';
signal i2s_bitclock : std_logic := '0';
begin
i2s_lrclock <= not(i2s_lrclock) after 10416640 ps; -- 64 * 325.520 ns / 2
i2s_bitclock <= not(i2s_bitclock) after 162760 ps ; -- 325.520 ns / 2
Real value of clocks in simulation is not very important. Ratio between them is.

Related

Is the use of rising_edge on non-clock signal bad practice? Are there alternatives?

I am working on a VHDL design and I have it working, but the code is pretty ugly and the fact that it seems that I am trying to work around the language's design to accomplish my goal makes me feel like something is wrong. I'm pretty new to VHDL, but I have been working on smaller chunks of the project for nearly a month so I have the general idea. However, This part is a bit more complex.
I need a process that will create a one clock period long pulse (LOAD_PULSE) after the rising edge of a signal (END_ADC), but not until 4 clocks has passed from the latest rising edge of that signal (END_ADC) OR the falling edge of a second signal (LVAL).
To accomplish the wait period, I have built a timer module that counts microseconds and periods, here:
entity uS_generator is
generic(
Frequency : integer := 66 -- Frequency in MHz
);
Port (
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
T_CNT : out integer range Frequency downto 1 := 1;
uS_CNT : out integer range 65535 downto 0 := 0
);
end uS_generator;
architecture behavior of uS_generator is
signal T_CNT_INT : integer range Frequency downto 1 := 1; -- Counter for 1 uS
signal uS_CNT_INT : integer range 65535 downto 0 := 0;
begin
COUNT: process(CLK, RESET)
begin
if RESET = '1' then
T_CNT_INT <= 1;
uS_CNT_INT <= 0;
elsif rising_edge(CLK) then
if T_CNT_INT = (Frequency - 1) then -- Increment one clock early so last rising edge sees one uS elapsed.
uS_CNT_INT <= uS_CNT_INT + 1;
T_CNT_INT <= T_CNT_INT + 1;
if uS_CNT_INT = 65535 then
uS_CNT_INT <= 0;
end if;
elsif T_CNT_INT = Frequency then
T_CNT_INT <= 1;
else
T_CNT_INT <= T_CNT_INT + 1;
end if;
end if;
end process COUNT;
T_CNT <= T_CNT_INT;
uS_CNT <= uS_CNT_INT;
end behavior;
The processes I'm using for the pulse generation portion of the design are as follows:
loadPulseProc: process(PIXEL_CLK, END_ADC, RESET)
begin
if RESET = '1' then
PULSE_FLAG <= '0';
LOAD_PULSE <= '0';
elsif rising_edge(END_ADC) then
PULSE_FLAG <= '1';
end if;
if rising_edge(PIXEL_CLK) then
if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then
LOAD_PULSE <= '1', '0' after PIXEL_CLK_T;
PULSE_FLAG <= '0';
end if;
end if;
end process loadPulseProc;
ADCTimerProc: process(END_ADC, RESET)
begin
if RESET = '1' then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process ADCTimerProc;
LVALTimerProc: process(LVAL, RESET)
begin
if RESET = '1' then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process LVALTimerProc;
PIXEL_CLK_T is the period of the clock, 15.152 ns.
This design works, simulation shows that it does as I require, but only after significant hassle avoiding errors due to using multiple rising_edge of falling_edge calls by separating them into separate if statements that really should be together. As far as I've read using rising_edge and falling_edge seems to be reserved for clocks only, so is this just bad practice? How can avoid this behavior but still create the same output?
Thanks!
Yes, rising_edge()/falling_edge() should only be used for clock signal. While it works in simulation it can cause problems and unintended hardware in synthesis.
Synthesis tools infer a clock from the function's argument and place such signals/wires on special tracks in the FPGAs (assuming you are targeting an FPGA for your design). The tool will further infer special clock buffers and warn if your input clock pin is not a clock capable pin.
Introducing several clocks can lead to asynchronous designs and make it vulnerable for cross clock faults.
Detecting a rising or falling edge on a signal is done by an edge detection circuit like the following which compares the signal in the previous clock cycle to the current value.
Needed signals:
signal mySignal_d : std_logic := '0';
signal mySignal_re : std_logic;
Needed logic:
mySignal_d <= mySignal when rising_edge(Clock);
mySignal_re <= not mySignal_d and mySignal;
This first line translates to an 1-bit D-flipflop (You could also use a process). The second lines generates a one cycle strobe signal when mySignal changes from low to high. I'm using *_d to indicate a delayed signal of the original input and *_re for rising edge.
The generated signal is still synchronous to Clock.

Gated Clock in Clock Divider for a Square Wave

I recently have been designing a clock divider for my system - which I redesigned, and now has an asynchronous reset, which generates a synchronous reset for the rest of the system. To do this, I followed the answers & advice to my own question and used a clock enable to toggle an output, thus generating clock with a 50% duty cycle (which is desired).
However, this has thrown up the error when generating the bitstream of
PhysDesignRules:372 - Gated clock. Clock net ... is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
Reading into this question about using the clock enable, it appears when creating a clock enable is correct, however, because I need a square wave (and not just a 1/200MHz pulse), and thus using the enable to toggle another signal, it appears in this question that this is an intentional gated clock.
So my questions are; is this gated clock warning significant? Both in simulation, and on an oscilloscope it appears to function correctly (so I'm inclined to ignore it), but am I storing problems for later? Is there a way of getting a very slow 50% duty cycle pulse without a gated clock?
I've put my code below!
Thanks very much (especially to the handful of people who have collectively given a lot of time to my recent non-stop questions)
David
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
ENTITY CLK_DIVIDER IS
GENERIC(INPUT_FREQ : INTEGER;
OUT1_FREQ : INTEGER;
OUT2_FREQ : INTEGER
);
PORT(SYSCLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
RESET_N_OUT : OUT STD_LOGIC;
OUT1 : OUT STD_LOGIC;
OUT2 : OUT STD_LOGIC);
END CLK_DIVIDER;
architecture Behavioral of Clk_Divider is
constant divider1 : integer := INPUT_FREQ / OUT1_FREQ / 2;
constant divider2 : integer := INPUT_FREQ / OUT2_FREQ / 2;
signal counter1 : integer := 0;
signal counter2 : integer := 0;
signal output1 : std_logic := '0';
signal output2 : std_logic := '0';
signal reset : boolean;
begin
reset_proc : process(RESET_N, SYSCLK)
variable cycles : integer := 0;
variable reset_counter : integer := 0;
begin
if rising_edge(SYSCLK) then
if cycles < 2 then
if reset_counter >= divider1 then
cycles := cycles + 1;
reset_counter := 0;
else
reset_counter := reset_counter + 1;
end if;
reset <= true;
else
reset <= false;
end if;
end if;
if RESET_N = '0' then
cycles := 0;
reset_counter := 0;
reset <= true;
end if;
end process;
output1_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter1 >= divider1 - 1 then
output1 <= not output1;
counter1 <= 0;
else
counter1 <= counter1 + 1;
end if;
if RESET_N = '0' then
counter1 <= 0;
output1 <= '1';
end if;
end if;
end process;
output2_proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
if counter2 >= divider2 - 1 then
output2 <= not output2;
counter2 <= 0;
else
counter2 <= counter2 + 1;
end if;
if RESET_N = '0' then
counter2 <= 0;
output2 <= '1';
end if;
end if;
end process;
OUT1 <= output1;
OUT2 <= output2;
RESET_N_OUT <= '0' when reset else '1';
end Behavioral;
The comments suggest, that the clock-divider is instantiated in a larger design.
If you want to use the generated clock there, you must add a BUFG between signal output2 and the output out2 like this:
out2_bufg : BUFG port map(I => output2, O => out2);
The component BUFG is defined in the library unisim.vcomponents. Same applies to output out1.
The BUFG ensures, that the generated clock is distributed using a clock-tree, so that the clock signal arrives at all destination flip-flops at the same time. This minimizes hold-time violations and gives more room for the setup of data signals.
If you still get the warning/error, then you combined the generated clock signal with another signal elsewhere in the larger design.
The reset_proc process is written with a elsif cycles > 1 then outside the clocked part, and with the condition derived from cycles which is also assigned as part of reset. It is unclear what hardware is actually described here, but it makes the synthesis tool unhappy.
If you want to use RESET_N as asynchronous reset, then just make a simple if RESET_N = '0' then ... end if;, and assign whatever signals or variables required to be reset. Other assignments should be moved to the clocked part.
NOTE: Code was changed after the above update... which may have removed the reason for the question.
Btw. RESET_N is used as asynchronous reset in the reset_proc, but as synchronous reset in the other processes, and this inconsistent use looks like there may be a potential problem with the reset scheme.

VHDL state machine with several delays - best approach?

This is a generic question that has bugged me since I was able to understand the Basics of a finite state machine. Suppose I have four states s0 - s3, where
the FSM will automatically start at 's0' after power is applied. After some defined delay, the FSM shall enter 's1' - the same goes for the other states.
The delay between the different states is not the same.
For example:
Power up -> 's0' -> 100 ms -> 's1' -> 50 us -> 's2' -> 360 us -> 's3' -> 's3'
In a procedural language as C, I'd just call a delay routine with one parameter being the required delay and be done with it.
How do I implement this sort of FSM elegantly ?
best,
Chris
My pattern : a delay counter which each state transition can program as and when required, i.e. at the start of each new delay.
It's all synthesisable, though some tools (notably Synplicity) have trouble with accurate Time calculations unless your clock period is an integer number of nanoseconds. For more information on this bug, see this Q&A. If you run into this situation, magic numbers (32000 instead of Synplicity's calculated 32258 in that question) may be the simplest workaround.
Wrapping it in an entity/architecture left as an (easy) exercise.
-- first, some declarations for readability instead of magic numbers
constant clock_period : time := 10 ns;
--WARNING : Synplicity has a bug : by default it rounds to nanoseconds!
constant longest_delay : time := 100 ms;
subtype delay_type is natural range 0 to longest_delay / clock_period;
constant reset_delay : delay_type := 100 ms / clock_period - 1;
constant s1_delay : delay_type := 50 us / clock_period - 1;
constant s2_delay : delay_type := 360 us / clock_period - 1;
-- NB take care to avoid off-by-1 error!
type state_type is (s0, s1, s2, s3);
-- now the state machine declarations:
signal state : state_type;
signal delay : delay_type;
-- now the state machine itself:
process(clock, reset) is
begin
if reset = '1' then
state <= s0;
delay <= reset_delay;
elsif rising_edge(clock) then
-- default actions such as default outputs first
-- operate the delay counter
if delay > 0 then
delay <= delay - 1;
end if;
-- state machine proper
case state is
when s0 =>
-- do nothing while delay counts down
if delay = 0 then
--start 50us delay when entering S1
delay <= s1_delay;
state <= s1;
end if;
when s1 =>
if delay = 0 then
delay <= s2_delay;
state <= s2;
end if;
when s2 =>
if delay = 0 then
state <= s3;
end if;
when others =>
null;
end case;
end if;
end process;
You could use a combination of a clock divider and counters. Find out what the clock speed on your device is. All the delays you mentioned are factorable by 10us so I'll use a clock divider to get to that speed. Let's assume your original clock speed of your device is 50MHz. You'll need to find out how many cycles you'll need to count to 10us. The following calculation does that:
# of cycles = 10ms * 50MHz = 5000 cycles
So you're going to need a counter that counts to 5000. A rough example would be the following:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity new_clk is
Port (
clk_in : in STD_LOGIC; -- your 50MHZ device clock
reset : in STD_LOGIC;
clk_out: out STD_LOGIC -- your new clock with a 10us period
);
end clk200Hz;
architecture Behavioral of new_clk is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 4999 := 0;
begin
clk_div: process (reset, clk_in) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk_in) then
if (counter = 4999) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;
Note how the counter goes from 0 to 4999. The signal clk_out will now have a period of 10us. You can use this to generate your delays now.
For example, for your 360us delay, count 36 periods of the clk_out signal. The code will be roughly similar to what is above but this time you're counting clk_out and your counter is only going from 0 to 35.
(I can add more later but this should get you started.)
Check chapters 8-9 of "Finite State Machines in Hardware: Theory and Design (with VHDL and SystemVerilog)" MIT Press, 2013, for a detailed discussion covering any case and many complete examples.
a Little Ode To Brian Drummond's Splendid Answer : Thanks Brian ! :)
The Main Difference is The Removal of The Fixed Upper Limit To The Delay's Length : It's Now Only Limited By The 'delay' SIGNAL Type's Length - Which Can, Generally, Be As Long As Needed.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY Test123 IS
PORT (
clk_in1 : IN std_logic := '0';
rst1, en1 : IN std_logic;
);
END ENTITY Test123;
ARCHITECTURE Test123_Arch OF Test123 IS
-- first, some declarations for readability instead of magic numbers
CONSTANT clock_period : TIME := 20 ns; -- 50 MHz
--WARNING : Synplicity has a bug : by default it rounds to nanoseconds!
CONSTANT reset_delay : TIME := 100 ms - clock_period;
CONSTANT s1_delay : TIME := 50 us - clock_period;
CONSTANT s2_delay : TIME := 360 us - clock_period;
-- NB take care to avoid off-by-1 error!
-- now the state machine declarations:
TYPE state_type IS (s0, s1, s2, s3);
SIGNAL state : state_type;
--
--signal delay : unsigned(47 downto 0) := (others => '0'); -- a 48-Bit 'unsigned' Type, Along a 50-MHz Clock, Evaluates To an Upper-Limit of ~90,071,992.5474 Seconds.
SIGNAL delay : NATURAL := 0; -- a 'natural' Type, Along a 50-MHz Clock, Evaluates To an Upper-Limit of ~85.8993459 Seconds.
--
FUNCTION time_to_cycles(time_value : TIME; clk_period : TIME) RETURN NATURAL IS
BEGIN
-- RETURN TO_UNSIGNED((time_value / clk_period), 48); -- Return a 48-Bit 'unsigned'
RETURN (time_value / clk_period); -- Return a 32-Bit 'natural'
END time_to_cycles;
--
BEGIN
-- now the state machine itself:
sm0 : PROCESS (clk_in1, rst1)
BEGIN
IF (rst1 = '1') THEN
state <= s0;
delay <= time_to_cycles(reset_delay, clock_period);
ELSIF rising_edge(clk_in1) THEN
-- default actions such as default outputs first
-- operate the delay counter
IF (delay > 0) THEN
delay <= delay - 1;
END IF;
-- state machine proper
CASE state IS
WHEN s0 =>
-- do nothing while delay counts down
IF (delay = 0) THEN
--start 50us delay when entering S1
delay <= time_to_cycles(s1_delay, clock_period);
state <= s1;
END IF;
WHEN s1 =>
IF (delay = 0) THEN
delay <= time_to_cycles(s2_delay, clock_period);
state <= s2;
END IF;
WHEN s2 =>
IF (delay = 0) THEN
state <= s3;
END IF;
WHEN OTHERS =>
NULL;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE Test123_Arch;

Count Edges over specific Period of Time in VHDL

For speed measurement of an electric motor I would like to count the amount of rising and falling edges of an encoder-input in a time-interval of 10ms.
To do this I have implementet a clock divider for my 40 MHz Clock as follows:
entity SpeedCLK is
Port ( CLK : in STD_LOGIC;
CLKspeed : out STD_LOGIC);
end SpeedCLK;
architecture Behavioral of SpeedCLK is
signal CounterCLK : NATURAL range 0 to 400001;
begin
SpeedCounter : process
begin
wait until rising_edge(CLK);
CounterCLK <= CounterCLK + 1;
if CounterCLK < 400000 then
CLKspeed <= '0';
else
CLKspeed <= '1';
CounterCLK <= 0;
end if;
end process SpeedCounter;
end Behavioral;
This should make CLKSpeed '1' every 10 ms. I use this block as a component in my Toplevel VHDL-Module. In the next Block I count the Edges from my encoderinput(QEPA) with a shift register to debounce the Input Signal.
entity SpeedMeasure is
Port (
QEPA : in STD_LOGIC;
CLK : in STD_LOGIC;
CLKSpeed : in STD_LOGIC;
Speed : OUT INTEGER -- in rpm
);
end SpeedMeasure;
architecture Behavioral of SpeedMeasure is
begin
Edges : process(CLKSpeed, CLK)
variable detect : STD_LOGIC_VECTOR(5 downto 0) := "000000";
variable EdgesPerTime : INTEGER := 0;
variable CountQEPA : INTEGER := 0;
begin
if CLKSpeed = '1' then
EdgesPerTime := countQEPA;
countQEPA := 0;
ELSIF (CLK'EVENT AND CLK = '1') THEN
detect(5 downto 1) := detect(4 downto 0);
detect(0) := QEPA;
if (detect = "011111") OR (detect = "100000") then
countQEPA := countQEPA + 1;
else
countQEPA := countQEPA;
end if;
end if;
Speed <= EdgesPerTime;
end process Edges;
end Behavioral;
This should write the current value of CountQEPA in my variable edgesPerTime every 10 ms and reset the Counter afterwards.
The signal Speed gets transmitted via uart. Unfortunatly with the reset of CountQEPA every 10ms I receive a constant value of 0 for EdgesPerTime. If I remove the reset line in the code, I can receive an increasing value for EdgesPerTime until the largest number for Integer (2^16) is reached, at which Point the Counter resets to 0.
What is the correct implementation in VHDL to count rising and falling edges in a set period of time?
Any help is greatly apreciated as I am still very new to vhdl.
You're building a latch using a variable. Your synthesis tool inferred an asynchronous reset CLKSpeed for countQEPA and since your latch EdgesPerTime latches countQEPA when its write enable CLKSpeed is asserted, you only see the reset countQEPA value of 0.
You should build proper synchronous logic:
signal CountQEPA : integer := 0;
signal detect : std_logic_vector(5 downto 0) := (others => '0');
begin
edge_cnt_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
-- synchronous reset
if (CLKSpeed = '1') then
countQEPA <= 0;
elsif ((detect = "011111") or (detect = "100000")) then
countQEPA <= countQEPA + 1;
end if;
end if;
end process edge_cnt_p;
edge_debounce_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
detect <= detect(detect'left downto 1) & QEPA;
end if;
end process edge_debounce_p;
count_register_p : process (
CLK
)
begin
if (rising_edge(CLK)) then
-- synchronous write enable
if (CLKSpeed = '1') then
Speed <= countQEPA;
end if;
end if;
end process count_register_p;
I'm not a big fan of variables, but it seems synthesis tools got a lot smarter these days. As you can see, I made three separate processes to show what we actually want going on. CountQEPA and debounce are signals now, because they need to be readable from other processes.
I assume CLKSpeed is synchronous to CLK (40 MHz). If it isn't, then you should think about handshaking between the clock domains.
You can of course make a single process out of these individual processes. In general, I try to avoid variables, because they can easily be used to describe behavior that is not synthesizable, like you found out the hard way.
I'm not sure how long your encoder bounces, but if you do sample at 40 MHz, a 6 bit shift register will likely not work as that's only a 125 ns debounce (you use the lower 5 bits only for debouncing, the top bit for noticing state changes).
Speaking of your debouncer. Consider the following case:
debounce QEPA
111111 1
111111 0 <-- glitch/bounce on encoder line; 25 ns wide
111110 1
111101 1
111011 1
110111 1
101111 1
011111 1 <-- fake edge detected
That's probably not what you want. You should compare your debounced signal to the last stable state instead of assuming state'delayed(5 * clk_period) being a stable state.
As I said above, I'm assuming CLK is your 40 MHz clock. You needn't sample your encoder signal that fast, because a proper debouncer would take a large number of shift register bits at no added value to you, because you have to divide that clock down to 1 kHz anyway for your time-slot counting.
Instead, take into account the maximum frequency of your encoder signal. You would want to oversample that at least by double that frequency, quadruple that frequency to be safe. So you have four samples per "bit time".
Since you're expecting many edges at 1 kHz, I assume your encoder is at least two orders of magnitude fast, i.e. 100 kHz. So scale 40 Mhz down to 400 kHz and shift in QEPA for debouncing. Sample these 400 kHz down to 1 kHz for your time slot measurements.
On a side note: What kind of motor encoding only uses a single bit? Are you sure you're not dealing with a quadrature encoder?

How to take samples using fpga?

I want to take samples of digital data coming externaly to FPGA spartan 3.
I want to take 1000 samples/sec initially. How to select a clock frequency in vhdl coding?
Thanks.
Do not use a counter to generate a lower frequency clock signal.
Multiple clock frequencies in an FPGA cause a variety of design problems, some of which come under the heading of "advanced topics" and, while they can (if necessary) all be dealt with and solved, learning how to use a single fast clock is both simpler and generally better practice (synchronous design).
Instead, use whatever fast clock your FPGA board provides, and generate lower frequency timing signals from it, and - crucially - use them as clock enables, not clock signals.
DLLs, DCMs, PLLs and other clock managers do have their uses, but generating 1 kHz clock signals is generally not a good use, even if their limitations permit it. This application is just crying out for a clock enable...
Also, don't mess around with magic numbers, let the VHDL compiler do the work! I have put the timing requirements in a package, so you can share them with the testbench and anything else that needs to use them.
package timing is
-- Change the first two constants to match your system requirements...
constant Clock_Freq : real := 40.0E6;
constant Sample_Rate : real := 1000.0;
-- These are calculated from the above, so stay correct when you make changes
constant Divide : natural := natural(Clock_Freq / Sample_Rate);
-- sometimes you also need a period, e.g. in a testbench.
constant clock_period : time := 1 sec / Clock_Freq;
end package timing;
And we can write the sampler as follows:
(I have split the clock enable out into a separate process to clarify the use of clock enables, but the two processes could be easily rolled into one for some further simplification; the "sample" signal would then be unnecessary)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use work.timing.all;
entity sampler is
Port (
Clock : in std_logic;
Reset : in std_logic;
ADC_In : in signed(7 downto 0);
-- signed for audio, or unsigned, depending on your app
Sampled : out signed(7 downto 0);
);
end sampler;
architecture Behavioral of Sampler is
signal Sample : std_logic;
begin
Gen_Sample : process (Clock,Reset)
variable Count : natural;
begin
if reset = '1' then
Sample <= '0';
Count := 0;
elsif rising_edge(Clock) then
Sample <= '0';
Count := Count + 1;
if Count = Divide then
Sample <= '1';
Count := 0;
end if;
end if;
end process;
Sample_Data : process (Clock)
begin
if rising_edge(Clock) then
if Sample = '1' then
Sampled <= ADC_In;
end if;
end if;
end process;
end Behavioral;
The base clock must be based on an external clock, and can't be generated just through internal resources in a Spartan-3 FPGA. If required, you can use the Spartan-3 FPGA Digital Clock Manager (DCM) resources to scale the external clock. Synthesized VHDL code in itself can't generate a clock.
Once you have some base clock at a higher frequency, for example 100 MHz, you can easily divide this down to generate an indication at 1 kHz for sampling of the external input.
It depends on what clock frequency you have available. If you have a 20MHz clock source, you need to divided it by 20000 in order to get 1KHz, you can do it in VHDL or use a DCM to do this.
This is from an example on how to create a 1kHz clock from a 20MHz input:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk20Hz is
Port (
clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk200Hz;
architecture Behavioral of clk20Hz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 10000 := 0;
begin
frequency_divider: process (reset, clk_in) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk_in) then
if (counter = 10000) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;

Resources