Edit - Can't Infer Register Because It's Behavior Does Not Match Any Supported Register Model VHDL - vhdl

This is a branch off of a separate question I asked. I am going to explain more in depth on what I am trying to do and what it is not liking. This is a school project and doesn't need to follow standards.
I am attempting to make the SIMON game. Right now, what I am trying to do is use a switch case for levels and each level is supposed to be faster (hence different frequency dividers). The first level is supposed to be the first frequency and a pattern of LEDs is supposed to light up and disappear. Before I put in a switch case, the first level was by itself (no second level stuff) and it lit up and disappeared like it should. I also used compare = 0 in order to compare in output to an input. (The user is supposed to flip up the switches in the light pattern they saw). This worked when the first level was by itself but now that it is in a switch case, it doesn't like compare. I'm not sure how to get around that in order to compare an output to an input.
The errors I am getting are similar to before:
Error (10821): HDL error at FP.vhd(75): can't infer register for "compare" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[0]" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[1]" because its behavior does not match any supported register model
Error (10821): HDL error at FP.vhd(75): can't infer register for "count[2]" because its behavior does not match any supported register model
Error (10822): HDL error at FP.vhd(80): couldn't implement registers for assignments on this clock edge
Error (10822): HDL error at FP.vhd(102): couldn't implement registers for assignments on this clock edge
Error (12153): Can't elaborate top-level user hierarchy
I also understand that it doesn't like the rising_edge(toggle) but I need that in order to make the LED pattern light up and disappear.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity FP is
port(
clk, reset : in std_logic;
QF : out std_logic_vector (3 downto 0);
checkbtn : in std_logic;
Switch : in std_logic_vector(3 downto 0);
sel : in std_logic_vector (1 downto 0);
score : out std_logic_vector (6 downto 0)
);
end FP;
architecture behavior of FP is
signal time_count: integer:=0;
signal toggle : std_logic;
signal toggle1 : std_logic;
signal count : std_logic_vector (2 downto 0);
signal seg : std_logic_vector (3 downto 0);
signal compare : integer range 0 to 1:=0;
type STATE_TYPE is (level1, level2);
signal level : STATE_TYPE;
--signal input : std_logic_vector (3 downto 0);
--signal sev : std_logic_vector (6 downto 0);
begin
process (clk, reset, sel)
begin
if (reset = '0') then
time_count <= 0;
toggle <= '0';
elsif rising_edge (clk) then
case sel is
when "00" =>
if (time_count = 1249999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "01" =>
if (time_count = 2499999) then
toggle1 <= not toggle1;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "10" =>
if (time_count = 4999999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
when "11" =>
if (time_count = 12499999) then
toggle <= not toggle;
time_count <= 0;
else
time_count <= time_count+1;
end if;
end case;
end if;
end process;
Process (toggle, compare, switch)
begin
case level is
when level1 =>
if sel = "00" then
count <= "001";
seg <= "1000";
elsif (rising_edge (toggle)) then
count <= "001";
compare <= 0;
if (count = "001") then
count <= "000";
else
count <= "000";
end if;
end if;
if (switch = "1000") and (compare = 0) and (checkbtn <= '0') then
score <= "1111001";
level <= level2;
else
score <= "1000000";
level <= level1;
end if;
when level2 =>
if sel = "01" then
count <= "010";
seg <= "0100";
elsif (rising_edge (toggle1)) then
count <= "010";
compare <= 1;
if (count = "010") then
count <= "000";
else
count <= "000";
end if;
end if;
if (switch = "0100") and (compare = 1) and (checkbtn <= '0') then
score <= "0100100";
else
score <= "1000000";
level <= level1;
end if;
end case;
case count is
when "000"=>seg<="0000";
when "001"=>seg<="1000";
when "010"=>seg<="0100";
when "011"=>seg<="0110";
when "100"=>seg<="0011";
when others=>seg<="0000";
end case;
end process;
QF <= seg;
end behavior;
Thanks again in advance!

Well... it is hard to tell what is wrong, because this state machine is written in wrong way. You should look for references about proper modeling of FSM in VHDL. One good example is here.
If you use Quartus, you could also look for Altera's description on how to model FSM specifically for their compiler.
I will now give you just two advices. First is that you shouldn't (or mabye even you can't) use is two
if rising_edge (clk)
checks in one process. If your process is supposed to be sensitive on clock edge, write it once at the beginning.
Second thing is that if you want to model FSM with one process with synchronous reset, then put just clk on sensitivity list.
EDIT after question and code edit:
Ok, much better now. But another few things:
Your FSM is still not like it should. Look again at the example in the source I gave you above and edit it to be like there, or make it one process FSM like in example in this link.
Intends! Very important. I couldn't spot some of obvious errors, before I made proper intendation in your code. This leads me to...
Look at the places, there you assign values to count, in particular the if statements. No mater what, you assign the same value of "000".
Similar story with another signal - seg. You assign to it some value in the process, and then at the end of this process there is case statement in which you assign to it some other value, making this previous assignments irrelevant.
Use rising_edge only once in the process, only to clock, and only at the very beginning of the process, or in the way you did in the first process, that has asynchronous reset. In second process you did all this three things.
In sequential process with rising_edge, like the first one, you don't have to put to sensitivity list anything more than clock, and reset if it is asynchronous, like in your case.
Sensitivity list in second process. It is parallel process, so you should put there signals, that you check in a process, and can change outside of it. It is not the case for compare. But there should be signals: level, sel and toggle1.
As I'm still not sure what are you trying to achieve, I will not tell you what exactly to do. Fix your code according to points above, then maybe it will just work.

Related

VHDL - synthesis results is not the same as behavioral

I have to write program in VHDL which calculate sqrt using Newton method. I wrote the code which seems to me to be ok but it does not work.
Behavioral simulation gives proper output value but post synthesis (and launched on hardware) not.
Program was implemented as state machine. Input value is an integer (used format is std_logic_vector), and output is fixed point (for calculation
purposes input value was multiplied by 64^2 so output value has 6 LSB bits are fractional part).
I used function to divide in vhdl from vhdlguru blogspot.
In behavioral simulation calculating sqrt takes about 350 ns (Tclk=10 ns) but in post synthesis only 50 ns.
Used code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity moore_sqrt is
port (clk : in std_logic;
enable : in std_logic;
input : in std_logic_vector (15 downto 0);
data_ready : out std_logic;
output : out std_logic_vector (31 downto 0)
);
end moore_sqrt;
architecture behavioral of moore_sqrt is
------------------------------------------------------------
function division (x : std_logic_vector; y : std_logic_vector) return std_logic_vector is
variable a1 : std_logic_vector(x'length-1 downto 0):=x;
variable b1 : std_logic_vector(y'length-1 downto 0):=y;
variable p1 : std_logic_vector(y'length downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to y'length-1 loop
p1(y'length-1 downto 1) := p1(y'length-2 downto 0);
p1(0) := a1(x'length-1);
a1(x'length-1 downto 1) := a1(x'length-2 downto 0);
p1 := p1-b1;
if(p1(y'length-1) ='1') then
a1(0) :='0';
p1 := p1+b1;
else
a1(0) :='1';
end if;
end loop;
return a1;
end division;
--------------------------------------------------------------
type state_type is (s0, s1, s2, s3, s4, s5, s6); --type of state machine
signal current_state,next_state: state_type; --current and next state declaration
signal xk : std_logic_vector (31 downto 0);
signal temp : std_logic_vector (31 downto 0);
signal latched_input : std_logic_vector (15 downto 0);
signal iterations : integer := 0;
signal max_iterations : integer := 10; --corresponds with accuracy
begin
process (clk,enable)
begin
if enable = '0' then
current_state <= s0;
elsif clk'event and clk = '1' then
current_state <= next_state; --state change
end if;
end process;
--state machine
process (current_state)
begin
case current_state is
when s0 => -- reset
output <= "00000000000000000000000000000000";
data_ready <= '0';
next_state <= s1;
when s1 => -- latching input data
latched_input <= input;
next_state <= s2;
when s2 => -- start calculating
-- initial value is set as a half of input data
output <= "00000000000000000000000000000000";
data_ready <= '0';
xk <= "0000000000000000" & division(latched_input, "0000000000000010");
next_state <= s3;
iterations <= 0;
when s3 => -- division
temp <= division ("0000" & latched_input & "000000000000", xk);
next_state <= s4;
when s4 => -- calculating
if(iterations < max_iterations) then
xk <= xk + temp;
next_state <= s5;
iterations <= iterations + 1;
else
next_state <= s6;
end if;
when s5 => -- shift logic right by 1
xk <= division(xk, "00000000000000000000000000000010");
next_state <= s3;
when s6 => -- stop - proper data
-- output <= division(xk, "00000000000000000000000001000000"); --the nearest integer value
output <= xk; -- fixed point 24.6, sqrt = output/64;
data_ready <= '1';
end case;
end process;
end behavioral;
Below screenshoots of behavioral and post-sythesis simulation results:
Behavioral simulation
Post-synthesis simulation
I have only little experience with VHDL and I have no idea what can I do to fix problem. I tried to exclude other process which was for calculation but it also did not work.
I hope you can help me.
Platform: Zynq ZedBoard
IDE: Vivado 2014.4
Regards,
Michal
A lot of the problems can be eliminated if you rewrite the state machine in single process form, in a pattern similar to this. That will eliminate both the unwanted latches, and the simulation /synthesis mismatches arising from sensitivity list errors.
I believe you are also going to have to rewrite the division function with its loop in the form of a state machine - either a separate state machine, handshaking with the main one to start a divide and signal its completion, or as part of a single hierarchical state machine as described in this Q&A.
This code is neither correct for simulation nor for synthesis.
Simulation issues:
Your sensitivity list is not complete, so the simulation does not show the correct behavior of the synthesized hardware. All right-hand-side signals should be include if the process is not clocked.
Synthesis issues:
Your code produces masses of latches. There is only one register called current_state. Latches should be avoided unless you know exactly what you are doing.
You can't divide numbers in the way you are using the function, if you want to keep a proper frequency of your circuit.
=> So check your Fmax report and
=> the RTL schematic or synthesis report for resource utilization.
Don't use the devision to shift bits. Neither in software the compiler implements a division if a value is shifted by a power of two. Us a shift operation to shift a value.
Other things to rethink:
enable is a low active asynchronous reset. Synchronous resets are better for FPGA implementations.
VHDL code may by synthesizable or not, and the synthesis result may behave as the simulation, or not. This depends on the code, the synthesizer, and the target platform, and is very normal.
Behavioral code is good for test-benches, but - in general - cannot be synthesized.
Here I see the most obvious issue with your code:
process (current_state)
begin
[...]
iterations <= iterations + 1;
[...]
end process;
You are iterating over a signal which does not appear in the sensitivity list of the process. This might be ok for the simulator which executes the process blocks just like software. On the other hand side, the synthesis result is totally unpredictable. But adding iterations to the sensitivity list is not enough. You would just end up with an asynchronous design. Your target platform is a clocked device. State changes may only occur at the trigger edge of the clock.
You need to tell the synthesizer how to map the iterations required to perform this calculation over the clock cycles. The safest way to do that is to break down the behavioural code into RTL code (https://en.wikipedia.org/wiki/Register-transfer_level#RTL_in_the_circuit_design_cycle).

VHDL code behaves abnormally after synthesis (I2C)

First of all, because of company disclosure agreement I am not allowed to post my code thus I will describe the symptoms of the behavior and hopefully it's enough.
I am using the IP for I2C master provided by Scott Larson on eewiki and I use it the same way in the example provided on the page. The difference is that I have several procedures as described in the example
WHEN get_data => --state for conducting this transaction
busy_prev <= i2c_busy; --capture the value of the previous i2c busy signal
IF(busy_prev = '0' AND i2c_busy = '1') THEN --i2c busy just went high
busy_cnt := busy_cnt + 1; --counts the times busy has gone from low to high during transaction
END IF;
CASE busy_cnt IS --busy_cnt keeps track of which command we are on
WHEN 0 => --no command latched in yet
i2c_ena <= '1'; --initiate the transaction
i2c_addr <= slave_addr; --set the address of the slave
i2c_rw <= '0'; --command 1 is a write
i2c_data_wr <= data_to_write; --data to be written
WHEN 1 => --1st busy high: command 1 latched, okay to issue command 2
i2c_rw <= '1'; --command 2 is a read (addr stays the same)
WHEN 2 => --2nd busy high: command 2 latched, okay to issue command 3
i2c_rw <= '0'; --command 3 is a write
i2c_data_wr <= new_data_to_write; --data to be written
IF(i2c_busy = '0') THEN --indicates data read in command 2 is ready
data(15 DOWNTO 8) <= i2c_data_rd; --retrieve data from command 2
END IF;
WHEN 3 => --3rd busy high: command 3 latched, okay to issue command 4
i2c_rw <= '1'; --command 4 is read (addr stays the same)
WHEN 4 => --4th busy high: command 4 latched, ready to stop
i2c_ena <= '0'; --deassert enable to stop transaction after command 4
IF(i2c_busy = '0') THEN --indicates data read in command 4 is ready
data(7 DOWNTO 0) <= i2c_data_rd; --retrieve data from command 4
busy_cnt := 0; --reset busy_cnt for next transaction
state <= home; --transaction complete, go to next state in design
END IF;
WHEN OTHERS => NULL;
END CASE;
For example at the end if the get_data instead of going to home I go to an initializing case to reset busy_cnt and i2c_ena and other signals then to another case for writing similar to get_data.
Current Situation
The code executes well in simulation, I switch the i2c_busy on and off and the behavior is as expected.
There are no warnings regarding the sensitivity list or any latches. I have a warning that 5 clock signals were routed using generic routing resource and might suffer from excessive delay and/or skew
The Problem
As I mentioned before the code is divided into several cases similar to get_data in the example above and when executing it is stuck in an infinite loop in one of them. And when I change something in the case that is stuck another case before it misbehaves and also stuck in an infinite loop. Even changing a simple signal that has nothing to do with the algorithm (LED output for debugging) in one case might cause a case before it to misbehave.
The infinite loop behavior is also strange and shows state is not set at the end of the case.
Note that I am not using the same way in the example to update state rather I use a separate Process for the state update (curr_state <= next_state;) and the next_state is the one updated.
My Speculation
I assumed that the problem could be because I have to set every output in every case. But even after setting all I could the behavior was similar.
For the sake of completion: The development environment is Lattice Diamond and the FPGA is MachXO2.
The posted code snippet has severe problems, if it's not part of a clocked process anymore according to the comments:
Me: Is the posted code still part of a clocked process?
mmahdich: #Martin In my code it's not, the clocked process only updates the curr_state <= next_state
If I embed the code from the question into the following test architecture, then the synthesis compiler XST (from ISE 14.7) reports warnings about latches for the signals busy_cnt, busy_prev and data. The reason that the OP observes no latch warnings may result from further optimizations or interference from the undisclosed code parts. (I have no Lattice Diamond at hand.)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_test is
port (
clk : in std_logic;
i2c_busy : in std_logic;
slave_addr : in std_logic;
data_to_write : in std_logic_vector(7 downto 0);
new_data_to_write : in std_logic_vector(7 downto 0);
i2c_data_rd : in std_logic_vector(7 downto 0);
i2c_ena : out std_logic;
i2c_addr : out std_logic;
i2c_rw : out std_logic;
i2c_data_wr : out std_logic_vector(7 downto 0);
data : out std_logic_vector(15 downto 0));
end i2c_test;
architecture rtl of i2c_test is
type state_t is (get_data, home);
signal curr_state : state_t := home;
signal state : state_t; -- next state is named "state" in OP code
signal busy_prev : std_logic;
begin -- rtl
process (clk)
begin -- process
if rising_edge(clk) then
curr_state <= state;
end if;
end process;
process(curr_state, busy_prev, i2c_busy, slave_addr, data_to_write, new_data_to_write, i2c_data_rd)
variable busy_cnt : integer range 0 to 4 := 0;
begin
state <= curr_state; -- next state is named "state" in OP code
i2c_ena <= '0';
i2c_addr <= '-';
i2c_rw <= '-';
i2c_data_wr <= (others => '-');
-- no default assignments for busy_prev and data here, because the usage
-- below indicates that a register was intended
case curr_state is
when home => state <= get_data;
---------------------------------------------------------------
-- Add code from question here
---------------------------------------------------------------
end case;
end process;
end rtl;
First of all, the signal for the next state seems to be named state.
Then, XST founds latches for the signals busy_prev and data. I have not added default assignments for these signals in the combinational process because the following assignments in the OP's code indicate that a register was intended:
busy_prev <= i2c_busy; --capture the value of the previous i2c busy signal
data(15 DOWNTO 8) <= i2c_data_rd; --retrieve data from command 2
data(7 DOWNTO 0) <= i2c_data_rd; --retrieve data from command 4
Finally, one cannot (easily) implement this wait counter without a clocked process:
WHEN get_data => --state for conducting this transaction
IF(busy_prev = '0' AND i2c_busy = '1') THEN --i2c busy just went high
busy_cnt := busy_cnt + 1; --counts the times busy has gone from low to high during transaction
END IF;
EDIT
Synthesizing the above would require flip-flops for busy_cnt which is triggered by all signals listed in the process sensitivity list. Of course, a new state will be loaded into the flip-flops only if the condition (curr_state = get_data and busy_prev = '0' and i2c_busy = '1') is true. For example, XST synthesizes a latch for this, which is enabled when the condition is true. But then, busy_cnt forms a combinational loop during an enabled latch. This synthesized behaviour does not match the VHDL description.
The solution would be to implement the registers busy_prev, data and busy_cnt in the clocked process.

Cannot create latch and counter with 2 clock signals in VHDL

I am completely new to programming CPLDs and I want to program a latch + counter in Xilinx ISE Project Navigator using VHDL language. This is how it must work and it MUST be only this way: this kind of device gets 2 clock signals. When one of them gets from HIGH to LOW state, data input bits get transferred to outputs and they get latched. When the 2nd clock gets from LOW to HIGH state, the output bits get incremented by 1. Unfortunately my code doesn't want to work....
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter8bit is
port(CLKDA, CLKLD : in std_logic;
D : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0));
end counter8bit;
architecture archi of counter8bit is
signal tmp: std_logic_vector(7 downto 0);
begin
process (CLKDA, CLKLD, D)
begin
if (CLKLD'event and CLKLD='0') then
tmp <= D;
elsif (CLKDA'event and CLKDA='1') then
tmp <= tmp + 1;
end if;
end process;
Q <= tmp;
end archi;
Is there any other way around to achieve this?? Please for replies. Any kind of help/suggestions will be strongly appreciated. Many thanks in advance!!
Based on the added comments on what the counter is for, I came up with the following idea. Whether it would work in reality is hard to decide, because I would need a proper timing diagram for the EPROM interface. Importantly, there could be clock domain crossing issues depending on what restrictions there are on how the two clock signals are asserted; if there can be a falling edge of CLKLD close to a rising edge of CLKDA, the design may not work reliably.
signal new_start_address : std_logic := '0';
signal start_address : std_logic_vector(D'range) := (others => '0');
...
process (CLKLD, CLKDA)
begin
if (CLKDA = '1') then
new_start_address <= '0';
elsif (falling_edge(CLKLD)) then
start_address <= D;
new_start_address <= '1';
end if;
end process;
process (CLKDA)
begin
if (rising_edge(CLKDA)) then
if (new_start_address = '1') then
tmp <= start_address;
else
tmp <= tmp + 1;
end if;
end if;
end process;
I'm not completely clear on the interface, but it could be that the line tmp <= start_address; should become tmp <= start_address + 1;
You may also need to replace your assignment of Q with:
Q <= start_address when new_start_address = '1' else tmp;
Again, it's hard to know for sure without a timing diagram.

Error(10820) and (10822) VHDL

i am trying to write a code but i get error, i dont understand that, i am new to vhdl, any help would be appreciated.
code:
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end if;
end process;
count <= count_value;
end rtl;
Errors:
Error (10820): Netlist error at counter.vhd(28): can't infer register for count_value[1] because its behavior depends on the edges of multiple distinct clocks
Error (10822): HDL error at counter.vhd(28): couldn't implement registers for assignments on this clock edge
The first problem is that you're trying to use the edge of two different 'clocks' in one process. A particular process can only respond to one clock.
The second problem is that your code does not translate into any real-world hardware. There's nothing in the FPGA that can respond to there not being an edge of a clock, which is what you have described with your if(rst'event and rst = '0') then else structure.
Nicolas pointed out another problem (which your compiler didn't get as far as), which is that you're assigning count both inside and outside a process; this is not allowed, as signals can only be assigned in one process.
Generally the type of reset it looks like you're trying to implement would be written as in the example below:
process (rst,pressed,upp_down)
begin
if(rst = '0') then
count_value <= "0000";
elsif(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end process;
count <= count_value;
The reason for changing the reset to affect count_value, is that without this, the effect of your reset would only last one clock cycle, after which the count would resume from where it left off (Thanks #Jim Lewis for this suggestion).
In addition to your compile errors, you should try to use the rising_edge() or falling_edge() functions for edge detection, as they behave better than the 'event style.
The reset can be more easily implemented using count_value <= (others => '0'); this makes all elements '0', no matter how long count is.
Lastly, it looks like you're using the std_logic_arith package. There are many other answers discouraging the use of this package. Instead, you should use the numeric_std package, and have your counter of type unsigned. If your output must be of type std_logic_vector, you can convert to this using a cast: count <= std_logic_vector(count_value);.
One more thing, I just noticed that your counter is not initialised; this can be done in the same way as I suggested for the reset function, using the others syntax.
"count" can't be assigned inside and outside a process.
count <= "0000"; <-- inside process
count <= count_value; <-- outside process.
You should do "count <= count_value;" inside your process :
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
count <= count_value;
end if;
end if;
end process;
end rtl;

VHDL error can't infer register because its behavior does not match any supported register model

I am new to VHDL and trying to make a delay/gate application for programmable FPGA, with adjustable lenght of delay and gate output. As soon as the input signal is recieved, the thing should ignore any other inputs, until generating of gate signal is finished.
I want to use this component for 8 different inputs and 8 different outputs later, and set desired delay/gate prameters separately for each one by means of writing registers.
When trying to compile in Quartus II v 11.0 i am getting this error:
Error (10821): HDL error at clkgen.vhd(46): can't infer register for "control_clkgen" because its behavior does not match any supported register model
And as well
Error (10822): HDL error at clkgen.vhd(37): couldn't implement registers for assignments on this clock edge
No idea whats wrong, here is the code of the component:
library ieee;
use IEEE.Std_Logic_1164.all;
use IEEE.Std_Logic_arith.all;
use IEEE.Std_Logic_unsigned.all;
ENTITY clkgen is
port(
lclk : in std_logic;
start_clkgen : in std_logic;
gate_clkgen : in std_logic_vector(31 downto 0);
delay_clkgen : in std_logic_vector(31 downto 0);
output_clkgen : out std_logic
);
END clkgen ;
ARCHITECTURE RTL of clkgen is
signal gate_cycles_clkgen : std_logic_vector(32 downto 0);
signal delay_cycles_clkgen : std_logic_vector(32 downto 0);
signal total_cycles_clkgen : std_logic_vector(32 downto 0);
signal counter_clkgen : std_logic_vector(32 downto 0);
signal control_clkgen : std_logic;
begin
gate_cycles_clkgen <= '0' & gate_clkgen;
delay_cycles_clkgen <= '0' & delay_clkgen;
total_cycles_clkgen <= gate_cycles_clkgen + delay_cycles_clkgen;
start_proc: process(lclk, start_clkgen)
begin
if (start_clkgen'event and start_clkgen = '1') then
if control_clkgen = '0' then
control_clkgen <= '1';
end if;
end if;
if (lclk'event and lclk = '1') then
if control_clkgen = '1' then
counter_clkgen <= counter_clkgen + 1;
if (counter_clkgen > delay_cycles_clkgen - 1 AND counter_clkgen < total_cycles_clkgen + 1) then
output_clkgen <= '1';
elsif (counter_clkgen = total_cycles_clkgen) then
counter_clkgen <= (others => '0');
output_clkgen <= '0';
control_clkgen <= '0';
end if;
end if;
end if;
end process start_proc;
END RTL;
Big thanks in advance for help.
The problem is that in the way you has described the element control_clkgen - it is edge sensitive to two different signals (lclk, and start_clkgen). What the tools are telling you is that "hey, as I am trying to make your valid VHDL design fit into a real piece of hardware, I have found that there are not any pieces of hardware that can implement what you want. Basically, there are no flip flops that can be edge sensitive to two signals (only one, typically the clock.
Possible solution: Do you really need control_clkgen to be sensitive to the edge of start_clkgen? Would it be good enough, or could you find another solution where start_proc is sensitive only to lclk and you simply check if start_clkgen is high?
start_proc: process(lclk)
begin
if (rising_edge(lclk)) then
start_clkgen_d <= start_clkgen;
if (start_clkgen='1' and start_clkgen_d='0') then
if control_clkgen = '0' then
control_clkgen <= '1';
end if;
end if;
end if;
...
You are describing a register control_clkgen which has two clocks start_clkgen and lclk. I guess that's not supported by your synthesis tool.
You have to describe this behavior in another way. Maybe use start_clkgen as asynchronous or synchronous preset signal or combine those two signals into one single clock signal or use more than one flipflop for that functionality.

Resources