I'm trying to build a clock divider based on integer counters. the simulation works correctly but the synthesis fails with the error above and marks line 25. I want the clocks to be reset only for one cycle of the clk_100M while the rising edge of reset occurs. I mean even if reset is high for more cycles of the clk. I don't understand the reason why it isn't synthesizable.
the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity divider is
Port (clk_100M: in std_logic;
reset: in std_logic;
clk_5, clk_500: buffer std_logic := '0' );
end divider;
architecture Behavioral of divider is
begin
CLK_GEN:
process(clk_100M)
variable count_5: integer:=0;
variable count_500: integer:=0;
begin
if rising_edge(reset) then
clk_5 <= '0';
clk_500 <= '0';
count_5 := 0;
count_500 := 0;
elsif rising_edge(clk_100M) then
count_5 := count_5 + 1;
count_500 := count_500 + 1;
end if;
if count_5 = 5000000 then
clk_5 <= NOT(clk_5);
count_5 := 0;
end if;
if count_500 = 50000 then
clk_500 <= NOT(clk_500);
count_500 := 0;
end if;
end process;
end Behavioral;
Synthesis tools expect you to write code that targets existing FPGA or ASIC gates. Hence for a flip-flop/register, reset is a level check and clock is a rising_edge (or falling_edge) check. The following refactors your code to match existing hardware:
CLK_GEN:
process(clk_100M)
variable count_5: integer:=0;
variable count_500: integer:=0;
begin
if reset = '1' then
clk_5 <= '0';
clk_500 <= '0';
count_5 := 0;
count_500 := 0;
elsif rising_edge(clk_100M) then
count_5 := count_5 + 1;
count_500 := count_500 + 1;
if count_5 = 5000000 then
clk_5 <= NOT(clk_5);
count_5 := 0;
end if;
if count_500 = 50000 then
clk_500 <= NOT(clk_500);
count_500 := 0;
end if;
end if;
end process;
Since you implemented count_500 and count_5 as variables, this should work the same in simulation as your previous code.
Currently with this code, the logic that does the detect of "count_5 = 5000000" is on the combinational logic that follows the incrementer. There may be other architectures that can allow this to run faster - and be smaller - if it needs to.
Also if these are generating clocks, you may wish to investigate what sort of clock generators your FPGA provides.
WRT rising_edge(reset), there is no flip-flop/register that does that. If you need to reset your circuit only during the first cycle of reset, then you need to create hardware that does this. The code below creates an intReset that is only active during the first cycle of reset. This assumes that reset is already properly synchronized to Clk_100M.
signal ResetReg, intReset : std_logic ;
. . .
ResetConditioningProc: process(clk_100M)
begin
if rising_edge(clk_100M) then
ResetReg <= reset ;
end if ;
end process ;
-- Create intReset during the first cycle of reset
intReset <= reset and not ResetReg ;
CLK_GEN:
process(clk_100M)
variable count_5: integer:=0;
variable count_500: integer:=0;
begin
if intReset = '1' then
. . .