How do you detect rising edge synchronization of 2 different clocks(different frequencies) in VHDL programming using Xilinx software?
There is a main clock of frequency 31.845 Mhz , and another clock of frequency 29.972 Mhz. So the basic aim is to trigger an action when there is synchronization between the rising edges of 2 clocks. We tried implementing it using flipflops but we could achieve only Level synchronization, not Edge sync.
And we cannot compare the rising edges of 2 different clocks in statements like IF and WAIT in vhdl, So that is out of question.
We are trying to count pulses using a counter. For that, we need to stop the count whenever edge matching takes place. We are trying to implement a method called 'Vernier Interpolation'.
Initially, we used the following statement code, but since rising edges of 2 different clocks (clk0, clk1) cannot be compared in an IF statement, we had to drop it.
if(rising_edge(clk0)=rising_edge(clk1)) then wait;
We then tried using WAIT statements (wait until) but it failed.
Then we tried using flipflops and delay circuits (D flipflop), but it resulted in level sync, and not Edge sync.
Firstly I'm not sure why you would want to do this. What you will get out is a new clock at the beat frequency between the two clocks.
The correct way to do this is to sample both clocks using another clock which is at least twice the frequency of the highest expected input. You could generate this higher clock using one of the PLLs in the device. x2 is a minimum. Ideally use a clock which is much higher than both sampled clocks.
Remember VHDL is not a language, it a description of synthesis of real hardware. So just saying Rising_Edge(clk1) = Rising_Edge(clk2) does not make the 'software' detect edges. All the function Rising_Edge really does is to tell the hardware to connect the clk signal to the clock input of a flipflop.
The proper solution is sample both 'clocks' in a process which is clocked by the a sample clock, look for edges (an edge being two subsequent samples that are different) then AND the result and latch if required.
sample code (untested, sorry no time right now).
entity twoclocks is
port (
op : out std_logic;
clk1 : in std_logic;
clk2 : in std_logic;
sample_clk : in std_logic);
end entity;
architecture RTL of twoclocks is
begin
process sample(sample_clock, clk1, clk2):
begin
if rising_edge(sample_clock):
clk1_d <= clk1;
clk2_d <= clk1;
if clk1_d != clk1 and clk2_d != clk2 then
op <= '1';
else
op <= '0';
end if;
end if;
end process;
end architecture;
The kind of vernier interpolator you want needs to be build using very tight timing constraints, thus you can probably not make it using VHDL alone. You need (a lot of) device specific constraints on resource locations and timing.
Please check out the work by A.Aloisio et al.. Aloisio and colleagues have build a vernier interpolator using specific Xilinx delay elements.
Standard VHDL synthesis is mostly suited for register transfer level descriptions. I.e. clocked/synchronous logic. But to compare these two inputs, you would need to sample them at a frequency of the least common multiple of both frequencies. For 31.845 MHz and 29.972 MHz that is a whopping 954.458340 MHz, which is a lot. I have seen these kind of speeds in FPGA logic though.
... But I'm thinking you might even need to double that, due to Nyquist. Maybe FPGA logic can nowadays handle 2 GHz swichting rate. But I'm not sure.
It might be possible to utilize a GT transceiver for this, but since that would be non-standard use of a such a transceiver, it might be hard to realize.
Related
We use after [some delay] statement for providing delay and that we can analysis in simulation. But when we will load this model in to FPGA so in actual hardware being made by VHDL code will have affect of delay or this delay is limited to simulation only?
a <= not b after 1s;
So suppose I connected one switch to b and LED to a so will I get one second delay in between pressing the switch and updating LED status?
as said before, the wait statement cannot be synthesized and will only affect the simulation. However, I should add that even in simulation you might not get what you expect. Allow me to explain.
VHDL offers 2 delay models: transport delay and inertial delay, the latter being the default, which you selected by not specifying which model to use.
If b would happen not to be stable in the course of the delay, say it toggles every 500ms, a would not toggle as you may desire. To really introduce pure delay, select the transport delay model as follows:
a <= transport not b after 1s;
Of course, again, this cannot be synthesized and is for simulation purposes only.
When you are simulating you need to provide when things happen and what happens to the inputs. After implementing it on the FPGA, exterior events create the inputs and the simulation has nothing to do about it.
So if I understood your question right, yes, the delay you are showing will only affect the simulation.
EDIT :
Regarding the timer, you know the FPGA's clock frequency. So you can create a variable and increment it on each clk_up (I use CLK = '1' and CLK'Event but there are better ways to do it), and when it reaches the same value as the clock frequency, 1 sec has passed.
Not-so-Pseudo code:
signal clock: unsigned (9 downto 0);
if CLK = '1' and CLK'Event then
clock<= clock + 1;
if clock = "1100100000" then --clock frequency (this is an example)
clock <= "0000000000"
-- 1 secound passed!
end if;
end if;
my doubt is how to pass a clock between two entities that are at the same hierarchical level in VHDL.
What I have is an entity "wrapper" in which there are instantiated two components "comp_1" and "comp_2". comp_1 has an output port (let's say "clk_out") that is its clock and that must be also the clock for comp_2. Now, if I use a signal in "wrapper" to pass the clock from comp_1 to comp_2, this cause a functional error in simulation (at least with Modelsim), because the two designs are considered not synchronous (right?). Can this cause an error also in synthesis (with Xilinx)? How can I avoid the problem without changing all the structure?
architecture bhv of my_wrap is
signal tmp_clk : std_logic;
begin
comp_1_i : comp_1
port map(out_clk => tmp_clk,
...
);
compo_2_i : comp_2
port map(in_clk => tmp_clk,
...
);
In this case, in simulation there is the delta cycle problem in the signals between the two components. Can this problem also affect the implemented design on FPGA?
It sounds like you may have a delta cycle delay on the clock, which is a feature in VHDL, but it may appear as if clock and data is out of sync.
This only shows in simulation, but is general VHDL thus not ModelSim specific. After synthesis (in hardware) the internal delay gives similar behavior. Note that ModelSim has a feature ("Expanded Time Delta Mode") to show delta delays.
Without code, I guess that the generated clock in comp_1 is also used for output generation, besides being output on clk_out. Depending on the implementation, it may result in a delta cycle delay difference between clock and data, which is may appear as not synchronous, but it is actually a delta cycle issue.
A possible fix is to output the generated clock from comp_1 without using it, and then making an additional clk_in input on comp_1, similar to the clk_in on comp_2, and then use that clock internally in comp_1. The clock use will then be similar on comp_1 and comp_2, removing the issue with delta delays on clock.
As Morten also pointed out some source code could help making your question more precise.
There is nothing wrong in connecting the clock out signal from one component to the clock in signal of another component. What might be a problem in your case is the way you generate the clock signal.
Depending on your use case you have different options.
If your target is an FPGA you should use a clock generator IP form the given vendor.
I am doing this project that will output a desired frequency. For most frequencies i can make valid code, but when it comes to frequency like 300 Hz I'm having trouble.
So here is my code for most of them:
library ieee;
use ieee.std_logic_1164.all;
entity test is
port(
clk:in std_logic:='0';
clk_o:buffer std_logic:='0'
);
end test;
architecture Behavioral of test is
begin
process(clk)
variable temp:integer range 0 to 1000000:=0;
begin
if(clk'event)then
temp:=temp+1;
if(temp>=1000000)then
clk_o<=not clk_o;
temp:=0;
end if;
end if;
end process;
end Behavioral;
This will generate frequency of 50 Hz because the clock speed of my FPGA is 50 MHz. So first I tried to divide it, but problem is that you can't generate 300 Hz because 50*10^6/300 is 166666.667 and so on.
Then I saw that you can make time type of variable and make period last 1/300 but then i realized it is not synthesis eligible so it's no good. Also goes with REAL type of variable that could make it more accurate then integer variable but it's also not synthesis eligible.
So I'm out of ideas, if anyone can give me some hint I would much appreciate it.
If you just use 166666 you will only be too fast by 0.0004% or 4ppm. This is such a small error that it typically won't matter in a real implementation - your 50MHz oscillator probably has more error than that.
[EDIT: as noted in the comments, crystal oscillators are likely to have 10-20ppm error, but there are other types of oscillators that have much higher or lower error (although the 50MHz FPGA clock is probably a crystal)]
If you really need to get rid of that 0.0004% error, you can use a DCM/MMCM/PLL (depending on the capabilities of your FPGA) to multiply your 50MHz clock to 150MHz first which will divide evenly to 300 Hz.
As Brian Drummond mentioned, you could also use a 0-2 counter to count to 166667 2 out of every 3 cycles and to 166666 on the other, which will avoid cumulative phase error if you were trying to remain in-phase with a perfectly ideal 300MHz source.
The fact that no real oscillators are perfectly matched to the advertized frequency is why RS232 re-syncs to the clock (to avoid cumulative phase error) frequently and why higher speed transfers use source synchronous clocking or Clock-and-data-recovery PLLs.
In my coding when I write this statement, it is simulated, but not synthesizable. why? Now what should I do to solve this problem???
IF ((DS0='1' OR DS1='1')and rising_edge(DS0) and rising_edge(DS1) AND DTACK='1' AND BERR='1') THEN
RV0 <= not RV;
else
RV0 <= RV;
The most important thing when doing FPGA-designs is to think hardware.
An FPGA consists of a number of hardware blocks, with a predetermined set of inputs and outputs - the code you write needs to be able to map to these blocks. So even if you write code that is syntactically correct, it doesn't mean that it can actually map to the hardware at hand.
What your code tries to do is:
IF ((DS0='1' OR DS1='1')and rising_edge(DS0) and rising_edge(DS1) AND DTACK='1' AND BERR='1') THEN
(...)
If DS0 and DS1 currently have a rising edge (implying that they're also both '1', making the first part with (DS='1' OR DS1='1') redundant), and if DTACK and BERR are both 1, then do something.
This requires an input block that takes two clock inputs (since you have two signals that you want to test for rising edges simultaneously), and such a block does not exist in any FPGA I've encountered - and also, how close together would such two clock events need to be to be considered "simultaneous"? It doesn't really make sense, unless you specify it within some interval, for instance by using a real clock signal (in the sense of the clock signal going to the clock input of a flip-flop), to sample DS0 and DS1 as shown in Morten Zilmers answer.
In general, you'd want to use one dedicated clock signal in your design (and then use clock enables for parts that need to run slower), or implement some cross-clock-domain synchronization if you need to have different parts of your design run with different clocks.
Depending on the IDE environment you use, you may have access to some language templates for designing various blocks, that can help you with correctly describing the available hardware blocks. In Xilinx ISE you can find these in Edit > Language Templates, then, for instance, have a look at VHDL > Synthesis Constructs > Coding Examples > Flip Flops.
An addition to sonicwave's good answer about thinking hardware and synthesis to
the available elements.
The rising_edge function is generally used to detect the rising edge of a
signal, and synthesis will generally use that signal as a clock input to a
flip-flop or synchronous RAM.
If what you want, is to detect when both DS0 and DS1 goes from '0' to
'1' at the "same" time, then such check is usually made at each rising edge
of a clock, and the change is detected by keeping the value from the
previous rising clock.
Code may look like:
...
signal CLOCK : std_logic;
signal DS0_PREV : std_logic;
signal DS1_PREV : std_logic;
begin
process (CLOCK) is
begin
if rising_edge(CLOCK) then
if (DS0 = '1' and DS0_PREV = '0') and -- '0' to '1' change of DS0
(DS1 = '1' and DS1_PREV = '0') and -- '0' to '1' change of DS1
DTACK = '1' AND BERR = '1' then
RV0 <= not RV;
else
RV0 <= RV;
end if;
DS0_PREV <= DS0; -- Save value
DS1_PREV <= DS1; -- Save value
end if;
end process;
...
I am implementing a digital design in VHDL which has to be low power. The design has a lot of inputs that are declared as multiple standard logic vectors. The device is allowed to wake up if anything changes on any input. This has to be combinatorical logic because the device is in power down. The code of what I am trying to do says it all: (ToggleSTDBY is a signal so this is legal)
P_Wakeup: PROCESS (VEC1, VEC2, VEC3, Rst_N) IS
BEGIN
IF Rst_N = '0' THEN
ToggleSTDBY <= '0';
ELSIF VEC1'event OR VEC2'event OR VEC3'event THEN
ToggleSTDBY <= NOT(ToggleSTDBY);
END IF;
END PROCESS P_Wakeup;
This is legal in simulation, but upon synthesis it says "'event is only supported for single bit signals". How can I fix this? There are a total of 66 bits in the vectors all together and I really don't want to write 66 processes for waking the device up. A bitwise OR on all bits will not solve anything, since most signals will be high, so the OR on all bits will always result in a high. The following code:
P_Wakeup: PROCESS (VEC, Rst_N) IS
BEGIN
IF Rst_N = '0' THEN
ToggleSTDBY <= '0';
ELSE
FOR i IN VEC'RANGE LOOP
IF VEC(i)'EVENT THEN
ToggleSTDBY <= NOT(ToggleSTDBY);
END IF;
END LOOP;
END IF;
END PROCESS P_Wakeup;
gives error "The prefix of signal attribute 'EVENT must be a static signal name". How can I fix it AND keep the code readable?
The HDL part of VHDL is abbreviation for Hardware Description Language (HDL),
so the VHDL constructions you can use must be possible to map by the synthesis
tool to the target. The use of 'event is typically tied to sequential
(clocked) hardware elements like flip flops or RAMs, and the synthesis tool
typically requires that you write the VHDL in a specific way, so the tool can
identify that a particular hardware elements is to be used.
Even though you may write VHDL code for a simulator, for example ModelSim, that
can compile and simulate use of 'event as in your examples, the synthesis
tool will typically not be able to map this to any available target hardware
element, since there is probably no such hardware elements as an 'event
detector.
But an 'event actually indicates a change in signal value, so you can maybe
write the signal value change detector explicitly in VHDL like:
change <= '1' if (vec_now /= vec_previous) else '0';
Depending on the low-power hardware elements available, you may start the clock
when an '1' is detected asynchronously on change, maybe through
ToggleSTDBY, and then process the change. The last thing before going into
sleep mode is then to capture the current vec value in vec_previous, so
another change can be detected while in sleep mode.
The possibility for doing low-power design of the kind I assume you are doing
based on the description, depends entirely on the features provided in the
target FPGA/ASIC technology. So before trying to get the VHDL syntax right,
you may want to determine how the resulting hardware should look like, based on
the available low power features.
Even if it is possible to write a VHDL code that models your intended behavior, I believe it won't work as you expect. I suggest that before writing the code you try to sort out the details of how exactly your ToggleSTDBY would be set, tested, and reset (a circuit diagram could help).
If you decide to implement ToggleSTDBY as a vector, one solution for the "event is only supported for single bit signals" problem is to move the loop to outside the process, using a for-generate:
gen: for i in ToggleSTDBY'range generate
p_wakeup : process (vec, rst_n) is
begin
if rst_n = '0' then
ToggleSTDBY(i) <= '0';
else
if vec(i)'event then
ToggleSTDBY(i) <= not (ToggleSTDBY(i));
end if;
end if;
end process p_wakeup;
end generate;