Xilinx ISE collapsing registers, how can I prevent it?

C

creon100

Hi everyone, I'm using Xilinx tools again for the first time in a few
years so I'm hoping this is something simple I'm doing wrong in the
options, so I'll ask first before I actually post any code.

Basically, I have a design that implements an asynchronous EMIF bus
interface to a Virtex-4. In the Virtex-4 is logic that controls some
other peripherals in the system using state machine and also has
configuration registers for those devices embedded in it so that the
processor can do configuration of the devices over the EMIF bus.

My VHDL top-level is two instantiated components, 1) my EMIF bus
interface, 2) the control system. The EMIF interface just takes data
from the bus and latches it onto the appropriate latches based on the
address. The latch outputs are just tied directly to the inputs of the
control system. Many of these are control signals that are simply
passed through the FPGA and out to the devices's configuration pins.
One register is used to load a count load value for an internal counter
in the control system. Basically, the counter continuously counts down
from the load value, and whenever the count is lower than 600 it raises
an external signal high, otherwise the signal is low. This all works
fine behaviorally, but after I implement everything it seems the tools
are removing a bytes worth of the load value latches as well as many of
the configuration latches that just pass through the device.

I'm not sure if it's doing this to the load value latches due to the <=
comparison to 600 or not, but I was hoping someone could tell me if
there was some kind of option I'm overlooking that can prevent this
kind of removal of signals. I'm optimizing for speed, not area, and
setting all the usual normal synthesis options as well.

When I view the design in the Floorplanner after the PAR alot of these
apparently removed latches are present in the latch listing, but don't
actually show up in the graphic display, so I'm assuming that even
though they're listed they've actually been removed (which seems to be
born out by my post-route simulation.

Does anyone have any ideas. I could post some simplified code if
anyone needs to see it to get a better idea. Thanks.
 
G

ghelbig

Check to see if the latches are getting packed into the I/O cells.

If the very 1st thing you do to a signal is latch it with system clock,
they will get moved there. Which is a good thing. If you don't like
this, there is an option to prevent it.

Hope that helps.
 
C

creon100

Thanks, I'll check, and I don't mind if they're moved to the I/O cells,
but I don't just mean I can't find them, I mean they appear to be
completely gone during post-synthesis simulation. My 32-bit counter is
turned into a 10-bit counter for instance, which completely makes using
it unfeasible. I'd imagine the software simply moving the latches to
the I/O cells wouldnt' exhibit such behavior?
 
R

radarman

What you are describing looks like a normal part of optimization. If
the tool figures out that there are no downstream gates dependent on
the output of a f-f, it will optimize it away. This is good, because
you can write more generic code, and let the tools deal with creating a
minimal circuit.

In your case, what was downstream from your 32-bit counter? Were all
32-bits being used?
 
C

creon100

Yes, I guess I didn't word my question correctly, since I realized it
was probably optimizing them out, I just didn't know if I was maybe
missing some software option to better control the optimizations it
tries to do.

Looking more closely it seems the actual counter itself isn't being
optimized smaller, but instead the register I use to load it is. I
have a 32-bit register (or that's the length it should be) named RATE,
which is used to continuously load the counter, this register is
accessible to the system's DSP via the bus interface so that it can
write new values to it to change the pulse rate of the output signal.

So in my control system component I have two processes, one to count
and one to generate the signal based on the count (this is just pseudo
code):

1) count process:
if(clk'event and clk=0)
if reset then
counter <= RATE;
elsif system_enabled = 1 then
if counter = 0 then
counter <= RATE;
else
counter <= counter - 1;
end if;
end process;

2) signal generate process:
if(clk'event and clk=0) then
if system_enabled = 1 then
if counter <= 600 then
output <= '1';
else
output <= '0';
end if;
else
output <= '1';
end if;
end if;
end process;

What it seems to be doing is truncating the RATE register to 10-bits.
This obviously won't work if I need to write out a count value larger
than 10-bits from the DSP (which thankfully I was doing in my testbench
or else I wouldn't have noticed the issue). The next largest register
I have in the interface system is 10-bits, so I'm not sure if it's
truncating because it's matching to that other register or if it's
truncating because it see the <= 600 comparison and knows it needs only
10-bits for that comparison. If it were the latter I'd think it would
truncate the counter though and not just the RATE register. In any
case, playing with the code in both places (changing all the other
registers to 32-bit even though the unused bits will get optimized out
anyway, and playing with the <= 600 comparison so that it involves the
upper bytes of the count through some different ways of doing the
comparison) don't do anything to solve the problem.
 
D

Dave Pollum

Yes, I guess I didn't word my question correctly, since I realized it
was probably optimizing them out, I just didn't know if I was maybe
missing some software option to better control the optimizations it
tries to do.

Looking more closely it seems the actual counter itself isn't being
optimized smaller, but instead the register I use to load it is. I
have a 32-bit register (or that's the length it should be) named RATE,
which is used to continuously load the counter, this register is
accessible to the system's DSP via the bus interface so that it can
write new values to it to change the pulse rate of the output signal.

So in my control system component I have two processes, one to count
and one to generate the signal based on the count (this is just pseudo
code):

1) count process:
if(clk'event and clk=0)
if reset then
counter <= RATE;
elsif system_enabled = 1 then
if counter = 0 then
counter <= RATE;
else
counter <= counter - 1;
end if;
end process;

2) signal generate process:
if(clk'event and clk=0) then
if system_enabled = 1 then
if counter <= 600 then
output <= '1';
else
output <= '0';
end if;
else
output <= '1';
end if;
end if;
end process;

What it seems to be doing is truncating the RATE register to 10-bits.
This obviously won't work if I need to write out a count value larger
than 10-bits from the DSP (which thankfully I was doing in my testbench
or else I wouldn't have noticed the issue). The next largest register
I have in the interface system is 10-bits, so I'm not sure if it's
truncating because it's matching to that other register or if it's
truncating because it see the <= 600 comparison and knows it needs only
10-bits for that comparison. If it were the latter I'd think it would
truncate the counter though and not just the RATE register. In any
case, playing with the code in both places (changing all the other
registers to 32-bit even though the unused bits will get optimized out
anyway, and playing with the <= 600 comparison so that it involves the
upper bytes of the count through some different ways of doing the
comparison) don't do anything to solve the problem.

I created the following VHDL code from your descriptions. I used ISE
7.1 (sp4) and Modelsim IIXE 5.7g. The 32-bit registers stayed 32-bits
long.

--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity top is
Port ( reset : in std_logic;
data_in : in std_logic_vector(31 downto 0);
rate_ld : in std_logic;
system_enabled : in std_logic;
clk : in std_logic;
output : out std_logic );
end top;

architecture Behavioral of top is

signal rate : unsigned(31 downto 0);
signal counter : unsigned(31 downto 0);

begin

process ( reset, clk ) is
begin
if reset = '1' then
rate <= (others => '0');
elsif falling_edge( clk ) then
if rate_ld = '1' then
rate <= unsigned(data_in);
end if;
end if;
end process;


count: process ( reset, clk ) is
begin
if falling_edge( clk ) then
if reset = '1' then
counter <= RATE;
elsif system_enabled = '1' then
if counter = 0 then
counter <= RATE;
else
counter <= counter - 1;
end if;
end if;
end if;
end process;


signal_generate: process ( clk ) is
begin
if falling_edge( clk ) then
if system_enabled = '1' then
if counter <= 600 then
output <= '1';
else
output <= '0';
end if;
else
output <= '0';
end if;
end if;
end process;

end Behavioral;

HTH
-Dave Pollum
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top