latches in vhdl

X

Xin Xiao

I'm designing a cache memory using a Finite State Machine (in vhdl). This is
the template code:

process (Clk, Reset)
begin
if (Reset = '1') then
STATE <= RESET_STATE;
elsif (rising_edge(Clk)) then
STATE <= NEXT_STATE;
end if;

process (STATE)
variable cache : cache_type;
begin
case STATE is
...
...
end case;
end if;

The problem is that I'm getting millions of warnings from my synthesis tool
because it is inferring latches for variable cache, I suppose this is
because the second process (where I put/get data from the memory) is not
clocked and I'm not assigning values for cache variable in every state (of
course, a memory should keep previous data intact!). Simulation works well
but I'm afraid I will get sim/synth mismatches. What do you think? I don't
think a latch would be a good idea to model a cache memory...
 
K

KJ

I'm designing a cache memory using a Finite State Machine (in vhdl). This is
the template code:

process (Clk, Reset)
begin
  if (Reset = '1') then
   STATE <= RESET_STATE;
  elsif (rising_edge(Clk)) then
   STATE <= NEXT_STATE;
end if;

process (STATE)
    variable cache : cache_type;
begin
    case STATE   is
        ...
        ...
    end case;
end if;

The problem is that I'm getting millions of warnings from my synthesis tool
because it is inferring latches for variable cache, I suppose this is
because the second process (where I put/get data from the memory) is not
clocked and I'm not assigning values for cache variable in every state

That's the reason....and also why the two process model that you're
using is not recommended by many folks. Use one clocked process
(probably just means moving your case statement up into your clocked
process) and make life easier on yourself. If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic). This guarantees that it will be assigned to no
matter what. But like I said, one synchronous process is the
generally cleaner approach.
(of
course, a memory should keep previous data intact!). Simulation works well
but I'm afraid I will get sim/synth mismatches. What do you think? I don't
think a latch would be a good idea to model a cache memory...

It's not a good thing. Fix it before it bites you harder down the
road.

Kevin Jennings
 
X

Xin Xiao

<quote>
If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic). This guarantees that it will be assigned to no
matter what.
</quote>

Yep, the problem is that if I assign default values each time the process is
woken up (ie every state transition) then i'm losing all the information i
stored in the memory, or am I missing something?

OK, if I assign values to my memory in a clocked process I suppose that the
synthesis tool would infer register(s) to store the information. Right?



I'm designing a cache memory using a Finite State Machine (in vhdl). This
is
the template code:

process (Clk, Reset)
begin
if (Reset = '1') then
STATE <= RESET_STATE;
elsif (rising_edge(Clk)) then
STATE <= NEXT_STATE;
end if;

process (STATE)
variable cache : cache_type;
begin
case STATE is
...
...
end case;
end if;

The problem is that I'm getting millions of warnings from my synthesis
tool
because it is inferring latches for variable cache, I suppose this is
because the second process (where I put/get data from the memory) is not
clocked and I'm not assigning values for cache variable in every state

That's the reason....and also why the two process model that you're
using is not recommended by many folks. Use one clocked process
(probably just means moving your case statement up into your clocked
process) and make life easier on yourself. If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic). This guarantees that it will be assigned to no
matter what. But like I said, one synchronous process is the
generally cleaner approach.
(of
course, a memory should keep previous data intact!). Simulation works well
but I'm afraid I will get sim/synth mismatches. What do you think? I don't
think a latch would be a good idea to model a cache memory...

It's not a good thing. Fix it before it bites you harder down the
road.

Kevin Jennings
 
K

KJ

<quote>
If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic).  This guarantees that it will be assigned to no
matter what.
</quote>

Yep, the problem is that if I assign default values each time the process is
woken up (ie every state transition) then i'm losing all the information i
stored in the memory, or am I missing something?
No you're not missing anything...and you're catching on now to one of
the drawbacks to the 'two process style' where you have a purely
combinatorial process with all the logic and a second clocked process
simply for generating the registers. There is nothing really to
recommend this style of design, it is more error prone, more prone to
generating unintended latches, and takes more lines of code.

That style is often taught, you're not alone it recurs in these groups
somewhat frequently but there are no actual advantages to it, only
drawbacks.
OK, if I assign values to my memory in a clocked process I suppose that the
synthesis tool would infer register(s) to store the information. Right?
Most likely. Depending on the size of the memory it might also
synthesize to an embedded memory that is likely available in the
device itself. In either case though, using a single clocked process
is the way to get to what you are trying to accomplish.

Kevin Jennings
 
X

Xin Xiao

I see that the synthesis tool now is using registers to model my cache
memory...

It detected the FSM too...

Wow, but the report says there are 16,968 registers in the design ! this is
cache_type:

subtype cache_range is natural range 1 downto 0;

type entry is record
tag: natural;
valid : boolean;
dirty : boolean;
data : std_logic_vector(15 downto 0);
end record;

type cache_type is array (cache_range) of entry;

Indeed, the synthesis tool is taking a long time to finish and with such
number of registers, delay paths will be huge! maybe I will burn the fpga!


I'm designing a cache memory using a Finite State Machine (in vhdl). This
is
the template code:

process (Clk, Reset)
begin
if (Reset = '1') then
STATE <= RESET_STATE;
elsif (rising_edge(Clk)) then
STATE <= NEXT_STATE;
end if;

process (STATE)
variable cache : cache_type;
begin
case STATE is
...
...
end case;
end if;

The problem is that I'm getting millions of warnings from my synthesis
tool
because it is inferring latches for variable cache, I suppose this is
because the second process (where I put/get data from the memory) is not
clocked and I'm not assigning values for cache variable in every state

That's the reason....and also why the two process model that you're
using is not recommended by many folks. Use one clocked process
(probably just means moving your case statement up into your clocked
process) and make life easier on yourself. If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic). This guarantees that it will be assigned to no
matter what. But like I said, one synchronous process is the
generally cleaner approach.
(of
course, a memory should keep previous data intact!). Simulation works well
but I'm afraid I will get sim/synth mismatches. What do you think? I don't
think a latch would be a good idea to model a cache memory...

It's not a good thing. Fix it before it bites you harder down the
road.

Kevin Jennings
 
A

Andy

I see that the synthesis tool now is using registers to model my cache
memory...

It detected the FSM too...

Wow, but the report says there are 16,968 registers in the design ! this is
cache_type:

subtype cache_range is natural range 1 downto 0;

type entry is record
tag: natural;
valid : boolean;
dirty : boolean;
data : std_logic_vector(15 downto 0);
end record;

type cache_type is array (cache_range) of entry;

Indeed, the synthesis tool is taking a long time to finish and with such
number of registers, delay paths will be huge! maybe I will burn the fpga!







That's the reason....and also why the two process model that you're
using is not recommended by many folks. Use one clocked process
(probably just means moving your case statement up into your clocked
process) and make life easier on yourself. If you insist on using two
processes, then you must provide a value for 'cache' for every
possible way through the process (typically this is done by assigning
a default value at the start of the process and then getting into the
rest of the logic). This guarantees that it will be assigned to no
matter what. But like I said, one synchronous process is the
generally cleaner approach.


It's not a good thing. Fix it before it bites you harder down the
road.

Kevin Jennings

In order to infer memory from your array (besides memory being
available in your target device), the synthesis tool has to be able to
tell from your code that only one element of that array (one address
in the ram) is accessed in the same clock cycle (two elements/
addresses for a dual port ram). Making that clear to the synthesis
tool is where the fun starts...

Andy
 
B

backhus

Hi Xin,
you should describe the memory part separate from the FSM. The way you
did it the synthesis tool is not able to infer a block of memeory.
Instead it creates a single flip flop for each bit to store.

Just imagine your synthesis tool istn't able to infer memory blocks at
all and you have to work with an instantiated memory block.
Now you can design your FSM for controlling this memory block to behave
like a cache.

Afterwards write some code to infer that memory block. ;-)
(separate from your FSM)

have a nice synthesis
Eilert
 
X

Xin Xiao

Hi backhus, could you explain a bit more? how can i work with an
instantiated memory block?
Afterwards write some code to infer that memory block. ;-)
(separate from your FSM)

if you could write a brief example or give me some webpage i'll apreciate
it.
 
X

Xin Xiao

It's more of less what I have in my code, but all the write/read is done
inside my FSM code (to model the cache behaviour). So my synthesis tool
creates a single flip flop to each bit to store (as backhus said), not a ram
block.
 
B

Brian Drummond

I see that the synthesis tool now is using registers to model my cache
memory...

It detected the FSM too...

Wow, but the report says there are 16,968 registers in the design ! this is
cache_type:

subtype cache_range is natural range 1 downto 0;

type entry is record
tag: natural;
valid : boolean;
dirty : boolean;
data : std_logic_vector(15 downto 0);
end record;

type cache_type is array (cache_range) of entry;

Inferring memory is preferable, but if you are trying to compare against all
tags in a cycle to detect matches, it will not be possible.

Why is the tag a natural? You probably want to restrict its range; that would
certainly reduce register usage...

- Brian
 

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

Similar Threads


Staff online

Members online

Forum statistics

Threads
473,992
Messages
2,570,220
Members
46,805
Latest member
ClydeHeld1

Latest Threads

Top