Reputation: 1
In the following code the following error takes place:
Error (10821): HDL error at ClockGen.vhd(33): can't infer register for "cont[0]" because its behavior does not match any supported register model
I tried using signed and unsigned variables to do the comparison, but it did not work.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY ClockGen IS
GENERIC
(Ratio : INTEGER RANGE 0 TO 100 := 10);
PORT
(clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
clk_en : OUT STD_LOGIC);
END ENTITY ClockGen;
ARCHITECTURE Behavior OF ClockGen IS
SIGNAL cont : INTEGER RANGE 0 TO 100 :=0;
BEGIN
--STATEMENTS
Counting : PROCESS (clk, reset)
BEGIN
IF reset='1'
THEN
cont <= 0; clk_en <= '0';
ELSIF RISING_EDGE(clk)
THEN
cont <= cont + 1;
END IF;
IF cont=Ratio AND clk='1' --THE ERROR OCCURS IN THIS LINE
THEN
clk_en <= '1';
ELSIF cont=Ratio AND clk='0'
THEN
clk_en <= '0';
cont<=0;
END IF;
END PROCESS Counting;
END ARCHITECTURE Behavior;
Upvotes: 0
Views: 10024
Reputation: 1
Thank you everyone for the help! With you I managed it. Reorganised the code with the "IF" statements. Result is as follows:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY ClockGen IS
GENERIC
(Ratio : INTEGER RANGE 0 TO 100 := 5);
PORT
(clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
clk_en : OUT STD_LOGIC);
END ENTITY ClockGen;
ARCHITECTURE Behavior OF ClockGen IS
SIGNAL cont : INTEGER RANGE 0 TO 100 :=1;
SIGNAL IRatio : INTEGER RANGE 0 TO 100 :=0;
BEGIN
Counting : PROCESS (clk, reset)
BEGIN
IRatio <= Ratio;
IF reset='0'
THEN
cont <= 1;
ELSIF RISING_EDGE(clk)
THEN
cont <= cont + 1;
IF cont=IRatio
THEN
clk_en <= '1';
cont<=1;
ELSE clk_en<='0';
END IF;
END IF;
END PROCESS Counting;
END ARCHITECTURE Behavior;
Upvotes: 0
Reputation: 3730
Your process detects a clock edge, and then later a clock level. This does not conform to the standard for synthesizable VHDL code.
Try this skeleton for your processes:
name : process (clk, rst) is
begin
if rst = '1' then
-- stuff here for resetting everything
elsif rising_edge(clk) then
-- more stuff here for doing useful things
end if;
end process name;
Upvotes: 1
Reputation: 3973
Draw a picture of what you really want.
In your code, you are creating a flip-flop that asynchronously resets with the reset signal. However, then you add an additional condition after clock and separately from it that also impacts the output cont. In effect, it also asynchronously resets your flip-flop when clk='1' and cont=Ratio. My bet this is not what you want. Generally a register has only one asynchronous reset and it is connected to the global reset line and not ever to logic (logic can glitch and effect a reset).
In addition, although a much simpler similar asynchronous reset coding style is specified by 1076.6-2004 (VHDL RTL synthesis coding standard), it is not well supported yet. Which may be why @phineas saw his version of the code work and you did not.
What are you trying to accomplish with clk_en? Do you intend that it is active only for a 1/2 clock cycle and never valid at a rising edge of Clk?
If clk_en is ok being a clock wide, then try the following:
Counting1 : PROCESS (clk, reset)
BEGIN
IF reset='1' THEN
cont <= 0;
clk_en <= '0';
ELSIF RISING_EDGE(clk) THEN
if cont/=Ratio then
cont <= cont + 1;
clk_en <= '0';
else
cout <= 0 ;
clk_en <= '1';
end if;
END IF;
end process;
If you really need clk_en as a half clock wide, then you have some work to do. After I throw away extra stuff, what you coded for clk_en would similar to:
ClkEnProc : PROCESS (clk)
BEGIN
IF clk='0' THEN
clk_en <= '0';
ELSIF RISING_EDGE(clk) THEN
if cont=Ratio then
clk_en <= '1';
end if;
END IF;
end process;
I would be surprised if you find a synthesis tool that will support that. You may need to compose your clock enable using both a rising edge flip-flop and a falling edge one. Using the clk_en from counting1 process, try the following:
ClkEnNegProc : PROCESS (clk)
BEGIN
IF FALLING_EDGE(clk) THEN
clk_en_neg <= clk_en;
END IF;
end process;
clk_en_half <= clk_en and not clk_en_neg ;
Upvotes: 1