Reputation: 11
I'm new in everything that involves VHDL physical description code, I have a university project to finish (four different text animations on a Nexys2 or Nexys3 board) and I keep getting this warning messages:
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 7-bit latch for signal . Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg1_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg3_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg2_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
WARNING:PhysDesignRules:372 - Gated clock. Clock net temp_reg4_not0001 is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.
Here is the link to all of the source files (I'm working in Ise Design Suite 14.7) http://www.fileshare.ro/e31590660
Edit: Unfortunately, I've spent almost half a day and I'm still not able to pinpoint precisely where the problem lies. I can only say very roughly though that it's in the process that's in the code below(line 73 and on).
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Folosim mai jos pachetul nostru
use work.Constante_si_componente.all;
entity Optiune1 is
port(
clk_50M:in std_logic;
reset:in std_logic;
catozi: out std_logic_vector(0 to 6);
anozi: out std_logic_vector(0 to 3);
opt1, opt2, opt3, opt4: in std_logic);
end entity;
architecture Behavioral of Optiune1 is
-- Instantierea semnalelor locale
signal local_clk_1Hz: std_logic;
signal local_clk_1Khz: std_logic;
signal adresa: integer range 0 to nr_cuvinte_distincte-1;
signal sec_4: integer range 0 to limita_sup:=0; -- Numara exact 5 secunde
signal cuvant: std_logic_vector(lungime_cuvinte-1 downto 0);
signal reg1, reg2, reg3, reg4: std_logic_vector(0 to 6):=(others=>'0');
signal temp_reg1, temp_reg2, temp_reg3, temp_reg4: std_logic_vector(0 to 6) := (others=> '0');
-- Declarare componente
component ROM
port (addr : in integer range 0 to nr_cuvinte_distincte-1;
data: out std_logic_vector(lungime_cuvinte-1 downto 0));
end component ROM;
component numarator
port(reset: in std_logic;
clk: in std_logic;
limita_numarare: in integer;
count: out integer range 0 to limita_sup);
end component;
component registru
port(clk_1Hz: in std_logic;
reset: in std_logic;
write_mode: in std_logic;
input: in std_logic_vector(0 to 6);
output: out std_logic_vector(0 to 6));
end component;
component RRate
port(clk_1KHz: in std_logic;
reg1, reg2, reg3, reg4: in std_logic_vector(0 to 6);
catozi: out std_logic_vector(0 to 6);
b:out std_logic_vector(0 to 3));
end component;
begin
-- Instantiem divizoarele de tact
COMP_CLOCK_tat: divizor port map(clk_50M=>clk_50M, reset => reset, clk_1Hz => local_clk_1Hz, clk_1KHz=>local_clk_1KHz);
-- Instantiem numaratorul
Numarator_1: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => nr_cuvinte_distincte-1, count => adresa);
Numarator_2: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => 4, count => sec_4);
-- Instantiem memoria
Memorie1: ROM port map(addr => adresa, data => cuvant);
-- Instantiem registrul
Registrul_1: registru port map(local_clk_1Hz, reset, '1', temp_reg1, reg1);
Registrul_2: registru port map(local_clk_1Hz, reset, '1', temp_reg2, reg2);
Registrul_3: registru port map(local_clk_1Hz, reset, '1', temp_reg3, reg3);
Registrul_4: registru port map(local_clk_1Hz, reset, '1', temp_reg4, reg4);
-- Instantiem refresh rate-ul de la anozi
Refresh_Rate: RRate port map (local_clk_1KHz, reg1, reg2, reg3, reg4, catozi, anozi);
process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4)
begin
if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then
temp_reg1 <= cuvant;
temp_reg2 <= temp_reg1;
temp_reg3 <= temp_reg2;
temp_reg4 <= temp_reg3;
elsif(opt1='0')and(opt2='1')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then
temp_reg4 <= cuvant;
temp_reg3 <= temp_reg4;
temp_reg2 <= temp_reg3;
temp_reg1 <= temp_reg2;
elsif(opt1='0')and(opt2='0')and(opt3='1')and(opt4='0')and(local_clk_1Hz='1') then
if sec_4 = 0 then
temp_reg1 <= cuvant;
elsif sec_4 = 1 then
temp_reg2 <= cuvant;
elsif sec_4 = 2 then
temp_reg3 <= cuvant;
elsif sec_4 = 3 then
temp_reg4 <= cuvant;
elsif sec_4 = 4 then
temp_reg1 <= "1111111";
temp_reg2 <= "1111111";
temp_reg3 <= "1111111";
temp_reg4 <= "1111111";
end if;
elsif(opt1='0')and(opt2='0')and(opt3='0')and(opt4='1')and(local_clk_1Hz='1') then
if sec_4 = 0 then
temp_reg1 <= cuvant;
elsif sec_4 = 1 then
temp_reg2 <= cuvant;
temp_reg1<="1111111";
elsif sec_4 = 2 then
temp_reg3 <= cuvant;
temp_reg2<="1111111";
elsif sec_4 = 3 then
temp_reg4 <= cuvant;
temp_reg3<="1111111";
elsif sec_4 = 4 then
temp_reg1 <= "1111111";
temp_reg2 <= "1111111";
temp_reg3 <= "1111111";
temp_reg4 <= "1111111";
end if;
else
temp_reg1 <= (others => '0');
temp_reg2 <= (others => '0');
temp_reg3 <= (others => '0');
temp_reg4 <= (others => '0');
end if;
end process;
end architecture Behavioral;
Last EDIT: I had to turn in the project yesterday and it worked as intended on the Nexys2 FPGA board, and i added David Koontz's multiplexer code to the "Future development" section of the project's documentation.
Thank you vey much for your help :)
Upvotes: 0
Views: 4865
Reputation:
After translating all the Romanian names and comments and noting that temp_reg1
- temp_reg4
are inputs to registers it doesn't appear you intended latches.
The unintentionally inferred latches are due to a lack of full conditional assignment coverage and there is no guarantee the combinatorial clock (or latch enable) is glitch free due to differences in delay through varying number of 'gate' equivalents in the target device, 'wire' delays due to placement and differences in rise and fall times. Preventing latches requires an assignment under every condition or choice in a case statement, essentially a reachable else
or others
.
Jonathan notes a loop in simulation caused by the sensitivity list affecting simulation. Getting rid of the sensitivity list issue can be done by breaking up the process into separate multiplexers.
This is an example solution to both of issues. It's implemented with concurrent signal assignment statements.
I added a declaration for component divizor
for analysis (it's possible it's located in the non-include package Constante_si_componente
).
After genning the three necessary declarations (nr_cuvinte_distincte
, limita_sup
, and lungime_cuvinte
) into a dummy package constante_si_componente
and I replaced the process statement.
I added the following local signal instantiations as architecture declarative items:
-- added declarations
component divizor is
port (
clk_50M: in std_logic;
reset: in std_logic;
clk_1Hz: out std_logic;
clk_1KHz: out std_logic
) ;
end component;
signal some_cond0: std_logic;
signal some_cond1: std_logic;
signal some_cond2: std_logic;
signal some_cond3: std_logic;
begin
These take the place of the outer if statement conditions specified in the unlabelled process:
-- new concurrent signal assignment statements:
some_cond0 <= opt1 and not opt2 and not opt3 and not opt4 and local_clk_1Hz;
some_cond1 <= not opt1 and opt2 and not opt3 and not opt4 and local_clk_1Hz;
some_cond2 <= not opt1 and not opt2 and opt3 and not opt4 and local_clk_1Hz;
some_cond3 <= not opt1 and not opt2 and not opt3 and opt4 and local_clk_1Hz;
These could be named to reflect what the conditions represent. It also looks like you could have binary encoded opt1
through opt4
into two signals, they are exclusive.
The idea is primarily to simplify multiplexer description.
The multiplexers are implemented using conditional signal assignments:
MUX1:
temp_reg1 <= cuvant when some_cond0 = '1' else
temp_reg2 when some_cond1 = '1' else
cuvant when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 < 4 else
"1111111" when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 = 4 else
(others => '0');
MUX2:
temp_reg2 <= temp_reg1 when some_cond0 = '1' else
temp_reg3 when some_cond1 = '1' else
cuvant when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 < 4 else
"1111111" when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 = 4 else
(others => '0');
MUX3:
temp_reg3 <= temp_reg2 when some_cond0 = '1' else
temp_reg4 when some_cond1 = '1' else
cuvant when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 < 4 else
"1111111" when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 = 4 else
(others => '0');
MUX4:
temp_reg4 <= temp_reg3 when some_cond0 = '1' else
cuvant when some_cond1 = '1' else
cuvant when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 < 4 else
"1111111" when (some_cond2 = '1' or some_cond3 = '1') and
sec_4 = 4 else
(others => '0');
With the multiplexers separated there are no sensitivity lists items causing fall through and there's always an assignment - that final else
in each multiplexer.
There are various optimizations you could make in the conditional assignment statements, this example is meant to be traceable to the original process.
If op1
through op4
were encoded on two signals as selects and local_clk_1Hz
used as an enable you could instantiate four 4:1 multiplexers lungime_cuvinte
wide instead.
After modifying your design it analyzed but without the entity/architecture pairs for divizor
, ROM
, numarator
, registru
and RRate
I couldn't elaborate or simulate your design.
Addendum
I broke down and downloaded your RAR, cleaned up my modified copy of your question code to work with your header package. It all analyzed, though I knocked out a few unneeded use clauses.
It elaborated but there was a run time simulation error in numarator
, caused by inter
incrementing beyond the bounds of count
, which also says you didn't simulate this first.
The default value for an integer (inter
in numarator
) is the left bound (typically –2147483647). During initialization there will be an assignment to count
(range 0 to limita_sup
) which will have a bound check failure.
signal inter: integer; -- acest semnal chiar e intermediar fiindca nu prea
should be type positive
instead of integer so the default value falls within the bounds of count
, or it should be supplied with a default value within count' bounds (
0`).
Upvotes: 1
Reputation: 3388
process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4)
begin
if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then
temp_reg1 <= cuvant;
temp_reg2 <= temp_reg1;
temp_reg3 <= temp_reg2;
temp_reg4 <= temp_reg3;
This is likely wrong. Since your process is combinational, the assignment to temp_reg1
will trigger the process again, which will assign the new value of temp_reg1
to temp_reg2
and so forth. Basically, this assigns cuvant
to all 4 temp_regs
, but I'm not sure XST can handle the combinational loopback appropriately.
This is probably not what you want anyways. Normally, this sort of process would use assign the regx
to temp_regx
, this is probably what you want:
temp_reg1 <= cuvant;
temp_reg2 <= reg1;
temp_reg3 <= reg2;
temp_reg4 <= reg3;
As David Koontz pointed out, this code is responsible for the latches:
if sec_4 = 0 then
temp_reg1 <= cuvant;
elsif sec_4 = 1 then
temp_reg2 <= cuvant;
temp_reg1<="1111111";
elsif sec_4 = 2 then
temp_reg3 <= cuvant;
temp_reg2<="1111111";
elsif sec_4 = 3 then
temp_reg4 <= cuvant;
temp_reg3<="1111111";
elsif sec_4 = 4 then
temp_reg1 <= "1111111";
temp_reg2 <= "1111111";
temp_reg3 <= "1111111";
temp_reg4 <= "1111111";
end if;
In a combinational process, every signals assigned in the process must be assigned in every path through the process, otherwise you will get a latch. In this case, temp_reg2
is not assigned when sec_4 = 0
for example.
Upvotes: 1