Synthesis error in VHDL clock synchronizer - vhdl

I am trying to implement clock synchronization and clock divider in the following piece of VHDL code. The clocks(clk_rx and clk_tx) should synchronize at the rising and falling edges of 'RX' signal on the bus. I can simulate the following but it is not synthesizable in ISE since i am using " RX'EVENT ". Could any one suggest an alternative for this? (Verilog also will work)
-------------------------------------------- CLOCK DIVIDER----------------------------------------------------------------------------------------
PROCESS (CLK_I, RX)
BEGIN
IF (RX'EVENT) THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSIF (CLK_I'EVENT AND CLK_I = '1') THEN
IF clk_cnt >2499 THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSE
clk_cnt <= clk_cnt + 1;
END IF;
END IF;
END PROCESS;
clk_rx <= '1' WHEN clk_cnt = 1250 ELSE '0'; -----clk_rx=1 only at the half of the counter period----------clk enable
clk_tx <= '1' WHEN clk_cnt = 2499 ELSE '0';

You can find a suggestion for code below. Note the following properties:
clk_rx_o (clk_rx) and clk_rx_o (clk_tx) are generated as outputs from flip-flops, since to avoid glitches which may occur if the signals are generated based on combinatorial compare of cnt outside the process
rx_i is synchronized by two flip-flops, assuming that it is not already synchronous to clk_i
Clock division is by 2501, since cnt goes from 0 .. 2500 due to wrap when (cnt > 2499). For division by 2500 use (cnt >= 2499) instead.
VHDL coding style: All signal names are lower case, as are VHDL statements, consistent spacing around expressions for readability
Code:
library ieee;
use ieee.std_logic_1164.all;
entity mdl is
port(
clk_i : in std_logic;
rx_i : in std_logic;
clk_rx_o : out std_logic;
clk_tx_o : out std_logic);
end entity;
library ieee;
use ieee.numeric_std.all;
architecture syn of mdl is
signal rx_meta : std_logic;
signal rx_sync : std_logic;
signal cnt : std_logic_vector(12 - 1 downto 0);
begin
-- rx_i sync to clk_i
process (clk_i) is
begin
if rising_edge(clk_i) then
rx_meta <= rx_i;
rx_sync <= rx_meta;
end if;
end process;
process (clk_i) is
begin
if rising_edge(clk_i) then
-- Clock align and divide
if rx_sync = '1' then
cnt <= std_logic_vector(to_unsigned(0, cnt'length));
else
if unsigned(cnt) > 2499 then
cnt <= std_logic_vector(to_unsigned(0, cnt'length));
else
cnt <= std_logic_vector(unsigned(cnt) + 1);
end if;
end if;
-- Clock generate as single cycle pulse
clk_rx_o <= '0';
if unsigned(cnt) = 1250 then
clk_rx_o <= '1';
end if;
clk_tx_o <= '0';
if unsigned(cnt) = 2499 then
clk_tx_o <= '1';
end if;
end if;
end process;
end architecture;

The problem is not simply that you are using RX'EVENT, it's that you have a CLK_I'EVENT conditional inside an RX'EVENT condition. That's just not synthesizable.
Assuming that CLK_I is much higher frequency than RX'EVENT, try sampling RX using CLK_I. If the previous value of RX is low and the current value is high, then synchronously reset clk_cnt on CLK_I'EVENT. Note that if RX is truly asynchronous to CLK_I you need to worry about metastability and you should add 2 flip-flops to synchronize RX before you look for a change from 0 to 1.

Try this code. There are still no flip flops in my code to solve metastability of RX as #Joe Hass explains.
But there is a scheme for synchronizing the RX signal.
PROCESS (CLK_I, RX)
BEGIN
IF (CLK_I'EVENT AND CLK_I = '1') THEN
IF (RX='1') THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSE
IF clk_cnt >2499 THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSE
clk_cnt <= clk_cnt + 1;
END IF;
END IF;
END IF;
END PROCESS;

Thank you very much for your support.
I modified the code as #Joe and #MortenZdk suggested. Now I am able to synthesize it.
I have to detect both posedge and negedge of "RX". So I changed the code as follows:
PROCESS(CLK_I) -- Stabilizing the RX signal to avoid meta stable state
begin
if rising_edge(CLK_I) then
rx_meta <= RX;
rx_sync <= rx_meta;
end if;
END PROCESS;
PROCESS (CLK_I)
BEGIN
IF (CLK_I'EVENT AND CLK_I = '1') THEN
tmp_RX <= rx_sync;
IF (rx_sync /= tmp_RX) THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSE
IF clk_cnt >2499 THEN
clk_cnt <= to_unsigned(0,clk_cnt'LENGTH);
ELSE
clk_cnt <= clk_cnt + 1;
END IF;
END IF;
-- Clock generate as single cycle pulse
clk_rx <= '0';
IF clk_cnt = 1250 THEN
clk_rx <= '1';
END IF;
clk_tx <= '0';
IF clk_cnt = 2500 THEN
clk_tx <= '1';
END IF;
END IF;
END PROCESS;

Related

In behavioral simulation, my FSM have a state that take more than 1 clock cycle ... And i don't like it

Please forgive myself if you will find some trivial errors in my code .. I'm still a beginner with VHDL.
Well, I have to deal with a serial interface from an ADC. The interface is quite simple ... there is a wire for the serial data (a frame of 24 bits), a signal DRDY that tells me when the new sample data is available and a serial clock (SCLK) that push the bit into (rising edge). Everything is running continuously...
I need to capture correctly the 24 bit of the sample, put them on a parallel bus (shift register) and provide a "data valid" signal for the blocks that will process the samples ...
Due to the fact that my system clock is x4 the frequency of the serial interface, i was thinking that doing the job with a FSM will be easy ...
When you look into the code you will see a process to capture the rising edges of the DRDY and SCLK.
Then a FSM with few states (Init, wait_drdy, wait_sclk, inc_count, check_count).
I use a counter (cnt unsigned) to check if I've already captured the 24 bits, using also to redirect the states of the FSM in "check_count" state.
Here a picture:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity serial_ads1675 is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
sclk : in std_logic;
sdata : in std_logic;
drdy : in std_logic;
pdata : out std_logic_vector(23 downto 0);
pdready : out std_logic
);
end serial_ads1675;
architecture Behavioral of serial_ads1675 is
-- Internal declarations
signal ipdata : std_logic_vector (23 downto 0);
signal ipdready : std_logic;
signal tmp1, tmp2, tmp3, tmp4 : std_logic;
signal rise_drdy, rise_sclk : std_logic;
signal cnt : unsigned (4 downto 0);
type state is (init, wait_drdy, wait_sclk, inc_count, check_count);
signal actual_state, next_state : state;
begin
-- Concurrent statements
pdata <= ipdata;
pdready <= ipdready;
rise_drdy <= '1' when ((tmp1 = '1') and (tmp2 = '0')) else '0';
rise_sclk <= '1' when ((tmp3 = '1') and (tmp4 = '0')) else '0';
-- Process
process (clk, reset)
begin
if(reset = '0') then
tmp1 <= '0';
tmp2 <= '0';
tmp3 <= '0';
tmp4 <= '0';
elsif (falling_edge(clk)) then
tmp1 <= drdy;
tmp2 <= tmp1;
tmp3 <= sclk;
tmp4 <= tmp3;
end if;
end process;
process (reset, clk)
begin
if (reset = '0') then
actual_state <= init;
elsif (rising_edge(clk)) then
actual_state <= next_state;
end if;
end process;
process (rise_sclk, rise_drdy) -- Next State affectation
begin
case actual_state is
when init =>
next_state <= wait_drdy;
ipdata <= (others => '0');
ipdready <= '0';
cnt <= (others => '0');
when wait_drdy =>
if (rise_drdy = '0') then
next_state <= actual_state;
else
next_state <= wait_sclk;
end if;
cnt <= (others => '0');
when wait_sclk =>
if (rise_sclk = '0') then
next_state <= actual_state;
else
next_state <= inc_count;
end if;
ipdready <= '0';
when inc_count =>
next_state <= check_count;
cnt <= cnt + 1;
ipdready <= '0';
ipdata(23 downto 1) <= ipdata(22 downto 0);
ipdata(0) <= sdata;
when check_count =>
case cnt is
when "11000" =>
next_state <= wait_drdy;
ipdready <= '1';
when others =>
next_state <= wait_sclk;
ipdready <= '0';
end case;
when others =>
next_state <= init;
end case;
end process;
end Behavioral;
My problem is during the check_count state ...
I'm expecting that this state should last one system clock cycle, but actually it last much more.
Here a snapshot of the behavioral simulation:
Due to the fact that this state last more than expected, i miss the following SCLK pulse and don't record the next bit ...
I don't understand why this state last so many system clock cycles instead of just one ...
Anyone has some clues and bring some light in my dark night ?
Thanks in advance.
Edit: I've tried to change the signal cnt for an integer variable internal to the process of the FSM ... Same results
The error is this:
process (rise_sclk, rise_drdy) -- Next State affectation
begin
-- code omitted, but does generally this:
next_state <= SOME_VALUE;
end process;
Because the sensitivity list includes only the signals rise_sclk and rise_drdy, the process is "executed" only if any of these signals changes. You can follow this in the wave diagram.
You don't have a synchronous design running on clk. Put clk on the sensitivity list and base the decisions on the levels of rise_sclk and rise_drdy. As an excerpt:
process (clk) -- Next State affectation
begin
if rising_edge(clk) then
case actual_state is
when init =>
next_state <= wait_drdy;
-- and so on
end case;
end if;
end process;

VHDL - Using output of one entitiy as input of another

I am trying to make a basic distance indicating module using ultrasonic sensor. When I dumped the code for the same into my FPGA board(Helium V1.1 developed by IIT-B) all the LEDs in the board started glowing since the clock frequency was too high. So now I am using a frequency divider to reduce my clock speed but I am not getting how to use the output of my frequency divider code as an input to my main code. Can someone help me since this is the first time I am working on FPGA and I dont quite understand VHDL yet?
Code for frequency divider
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity Clock_Divider is
port ( clk,reset: in std_logic;
clock_out: out std_logic);
end Clock_Divider;
architecture bhv of Clock_Divider is
signal count: integer:=1;
signal tmp : std_logic := '0';
begin
process(clk,reset)
begin
if(reset='1') then
count<=1;
tmp<='0';
elsif(clk'event and clk='1') then
count <=count+1;
if (count = 25000) then
tmp <= NOT tmp;
count <= 1;
end if;
end if;
clock_out <= tmp;
end process;
end bhv;
Code to measure distance using ultrasonic:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ultrasonic is
port(
CLOCK: in std_logic;
LED: out std_logic_vector(7 downto 0);
TRIG: out std_logic;
ECHO: in std_logic
);
end ultrasonic;
architecture rtl of ultrasonic is
signal microseconds: std_logic;
signal counter: std_logic_vector(17 downto 0);
signal leds: std_logic_vector(7 downto 0);
signal trigger: std_logic;
begin
process(CLOCK)
variable count0: integer range 0 to 7;
begin
if rising_edge(CLOCK) then
if count0 = 5 then
count0 := 0;
else
count0 := count0 + 1;
end if;
if count0 = 0 then
microseconds <= not microseconds;
end if;
end if;
end process;
process(microseconds)
variable count1: integer range 0 to 262143;
begin
if rising_edge(microseconds) then
if count1 = 0 then
counter <= "000000000000000000";
trigger <= '1';
elsif count1 = 10 then
trigger <= '0';
end if;
if ECHO = '1' then
counter <= counter + 1;
end if;
if count1 = 249999 then
count1 := 0;
else
count1 := count1 + 1;
end if;
end if;
end process;
process(ECHO)
begin
if falling_edge(ECHO) then
if counter < 291 then
leds <= "11111111";
elsif counter < 581 then
leds <= "11111110";
elsif counter < 871 then
leds <= "11111100";
elsif counter < 1161 then
leds <= "11111000";
elsif counter < 1451 then
leds <= "11110000";
elsif counter < 1741 then
leds <= "11100000";
elsif counter < 2031 then
leds <= "11000000";
elsif counter < 2321 then
leds <= "10000000";
else
leds <= "00000000";
end if;
end if;
end process;
LED <= leds;
TRIG <= trigger;
end rtl;
I am using Quartus for simulating these codes.
welcome to the HDL languages :)
For simulation clock_out is missing from the sensitivity list process(...)
For synthesis/implementation you might need to check all processes as they should be dependent on your clock signal. I've learned it's considered bad practice to use rising/falling edge on other signals than clock signals.
You probably want to go for a pattern something like:
...
-- entity declaration
s : in std_logic;
...
-- architecture declaration
signal s_d : std_logic;
begin
...
process(clk)
begin
if rising_edge(clk) then
-- s_d is s one clock cycle delayed
s_d <= s;
-- detect s transition from 0 to 1 == rising edge
if s = '1' and s_d = '0' then
-- Code dependent on rising edge s
end if;
end if;
end process;
NOTE: s may be an internal signal and is not needed to come from entity. If s is a strobe (1 clock cycle long generated with the same clock) s_d is not needed as there is no need to detect the edge, just the signal state.

How can i reduce number of ALMs in my VHDL design?

I'm trying to implement an alarm module for the digital clock in VHDL. I have written architecture for it, but when I run Compilation I get too many Adaptive Logic Modules (around 2000), which I think is too much. I will post my code below.
I think division and modulus operation could be causing it, in this line of code.
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
Still, I'm not sure how can I work around this.
Also, I would be very grateful if You give more comments on my design, and point out some mistakes, and ways how I can improve my design. I'm fairly new to VHDL so any advice is appreciated.
Thanks a lot.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity alarm is
port(
--INPUTS
reset : in std_logic;
clock : in std_logic;
alarm_enable : in std_logic;
alarm_set : in std_logic;
alarm_increment : in std_logic;
alarm_decrement : in std_logic;
currentTime_hour1 : in std_logic_vector(3 downto 0);
currentTime_hour0 : in std_logic_vector(3 downto 0);
currentTime_minute1 : in std_logic_vector(3 downto 0);
currentTime_minute0 : in std_logic_vector(3 downto 0);
--OUTPUTS
alarm_buzzer : out std_logic;
alarm_hour1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_hour0 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute1 : buffer std_logic_vector(3 downto 0) := "0000";
alarm_minute0 : buffer std_logic_vector(3 downto 0) := "0000"
);
end alarm;
architecture alarmBehaviour of alarm is
--ALARM TIME
signal savedHours : integer := 0;
signal savedMinutes : integer := 0;
signal incrementDecrementbuttonDetect : std_logic;
signal set_lastButtonState : std_logic := '0';
signal setButtonDetect : std_logic := '0';
--STATE MACHINE
type state_type is (idle, setHour, setMinute);
signal state_reg, state_next : state_type;
begin
incrementDecrementbuttonDetect <= alarm_increment or alarm_decrement;
--STATE REGISTER
process(clock, reset)
begin
if (reset = '1') then
state_reg <= idle;
elsif rising_edge(clock) then
state_reg <= state_next;
end if;
end process;
--SET BUTTON PRESSED
process(clock)
begin
if(rising_edge(clock)) then
if(alarm_set = '1' and set_lastButtonState = '0') then
setButtonDetect <= '1';
else
setButtonDetect <= '0';
end if;
set_lastButtonState <= alarm_set;
end if;
end process;
--NEXT STATE
process(state_reg, setButtonDetect)
begin
case state_reg is
when idle =>
if setButtonDetect = '1' then
state_next <= setHour;
else
state_next <= idle;
end if;
when setHour =>
if setButtonDetect = '1' then
state_next <= setMinute;
else
state_next <= setHour;
end if;
when setMinute =>
if setButtonDetect = '1' then
state_next <= idle;
else
state_next <= setMinute;
end if;
end case;
end process;
process (incrementDecrementbuttonDetect, state_reg)
begin
if rising_edge(incrementDecrementbuttonDetect) then
case state_reg is
when idle =>
when setHour =>
if alarm_increment = '1' then
if savedHours = 23 then
savedHours <= 0;
else
savedHours <= savedHours + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedHours = 0 then
savedHours <= 23;
else
savedHours <= savedHours - 1;
end if;
else null;
end if;
when setMinute =>
if alarm_increment = '1' then
if savedMinutes = 59 then
savedMinutes <= 0;
else
savedMinutes <= savedMinutes + 1;
end if;
else null;
end if;
if alarm_decrement = '1' then
if savedMinutes = 0 then
savedMinutes <= 59;
else
savedMinutes <= savedMinutes - 1;
end if;
else null;
end if;
end case;
end if;
end process;
alarm_hour1 <= std_logic_vector(to_unsigned(savedHours/10,alarm_hour1'length));
alarm_hour0 <= std_logic_vector(to_unsigned(savedHours mod 10,alarm_hour0'length));
alarm_minute1 <= std_logic_vector(to_unsigned(savedMinutes/10,alarm_minute1'length));
alarm_minute0 <= std_logic_vector(to_unsigned(savedMinutes mod 10,alarm_minute0'length));
--ALARM BUZZER CONDITION
process (currentTime_hour1, currentTime_hour0, currentTime_minute1, currentTime_minute0,
alarm_enable, alarm_hour1, alarm_hour0, alarm_minute1, alarm_minute0)
begin
if((alarm_hour1 = currentTime_hour1) and (alarm_hour0 = currentTime_hour0)
and (alarm_minute1 = currentTime_minute1) and (alarm_minute0 = currentTime_minute0) and alarm_enable = '1') then
alarm_buzzer <= '1';
else
alarm_buzzer <= '0';
end if;
end process;
end alarmBehaviour;
Consider keeping the alarm time in Binary-Coded Decimal (BCD) format instead of binary format, whereby you can compare it directly with the current time, that is provided in BCD format.
This is a good example of how using the appropriate internal data format can reduce the computational problem significantly, since you can simply eliminate the costly division and modulo operations by keeping just one data format (BCD) instead of mixing BCD and binary data formats.
The range of signals savedHours and savedMinutes is not specified, so Quartus assumes they are 32 bits wide. Inference of a divider with one 32-bit operand results into a large tree of conditional subtractions.
Updating your code to something like
--ALARM TIME
signal savedHours : natural range 0 to 23 := 0;
signal savedMinutes : natural range 0 to 59 := 0;
will very likely result into less ALM usage.
Also, please note that rising_edge should be used for clock signals only (at VHDL starter level). Instead of connecting logic to the clock input of a register, what you probably want is some button debounce logic.

How to implement a clock enable in VHDL?

So basically what I'm trying to do is to activate and deactivate a clock after a certain time. Here's a little example of what I'm looking for : `
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
entity example is
generic (
clk1 : in std_logic; --- 100hz
clk2 : in std_logic ; --- 10hz
);
end example;
architecture example_arch of example is
signal clk_count1, clk_count2 : integer range 0 to 1000:= 0;
signal clk_enable1 : std_logic := '1';
signal clk_enable2 : std_logic := '0';
begin
process (clk1)
begin
if rising_edge(clk1) and clk_enable1 = '1' then
if clk_count = 1000 then
clk_enable1 <= '0';
clk_enable2 <= '1';
clk_count1 <= 0;
else
clk_count1 <= clk_count1 + 1;
[...] --- do what you want to do while you are using clk1
end if;
end if;
end process;
process (clk2)
begin
if rising_edge(clk2) and clk_enable2 = '1' then
if clk_count2 = 1000 then
clk_enable1 <= '1';
clk_enable2 <= '0';
clk_count2 <= 0;
else
clk_count2 <= clk_count2 + 1;
[...] --- do what you want to do while you are using clk2
end if;
end if;
end process;
end example_arch;
`
So in this example we have two clock where clk1 has a greater frequency than clk2. When clk_enable1 is '1', we are working with the first process and when clk_enable2 is '1', we are working with the second one.
The problem with this code is that even if we know what clk_enable is at '1', it stills allow the two process to execute themselves after each clock events of the two clocks. What I'm trying to do is to deactivate a clock while I'm using the other one so that there is no clock events with the clock that I've deactivated so we never execute the process of this clock while we're executing the other process. In other words, when a clock can be at 1 or 0, the other is in high impedance (Z). I want something like this :
flip-flop
Thank you for your help, hoping that I find a solution.

VHDL edge detection

I want to detect the edges on the serial data signal (din). I have written the following code in VHDL which is running successfully but the edges are detected with one clock period delay i.e change output is generated with one clk_50mhz period delay at each edge. Could anyone please help me to detect edges without delay. Thank you.
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if (rst = '0') then
shift_reg <= (others => '0');
else
shift_reg(1) <= shift_reg(0);
shift_reg(0) <= din;
end if;
end if;
end process;
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if rst = '0' then
change <= '0' ;
elsif(clk_enable_2mhz = '1') then
change <= shift_reg(0) xor shift_reg(1);
end if ;
end if ;
end process ;
When I changed my code to following I am able to detect the edges
process (clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
if (RST = '0') then
shift_reg <= (others=>'0');
else
shift_reg(1) <= shift_reg(0);
shift_reg(0) <= din;
end if;
end if;
end process;
change <= shift_reg(1) xor din;
Here you go
library ieee;
use ieee.std_logic_1164.all;
entity double_edge_detector is
port (
clk_50mhz : in std_logic;
rst : in std_logic;
din : in std_logic;
change : out std_logic
);
end double_edge_detector;
architecture bhv of double_edge_detector is
signal din_delayed1 :std_logic;
begin
process(clk_50mhz)
begin
if rising_edge(clk_50mhz) then
if rst = '1' then
din_delayed1 <= '0';
else
din_delayed1 <= din;
end if;
end if;
end process;
change <= (din_delayed1 xor din); --rising or falling edge (0 -> 1 xor 1 -> 0)
end bhv;
You have to use a combinatorial process to detect the difference without incurring extra clock cycle delays. (You will still need one register to delay the input as well.)
DELAY: process(clk_50mhz)
begin
if clk_50mhz'event and clk_50mhz = '1' then
din_reg <= din;
end if;
end process;
change <= din xor din_reg;

Resources