First of all, sorry for my bad English!
I am new to vhdl (and embdev) , so I will try to clearly explain my
problem (which must come from a problem of comprehension of how a state
machine )
Context : I need to read a ROM, i read data, and after a certain number
of data read ( I know that number) i'll get a data wich is a delay. At
this moment , I want to stay at this state as many clocks as the delay,
before reading on. (And this will loop again ).
You can find quick drawing to explain the process in file joined.
So my problem is about a (intern) signal, the delay !
It takes the good value a the first time, and then goes to zero, but
rom_out is still good so i really do not understand what i'm doing wrong
!
I do not have the code on my computer today so i will try to quickly
rewrite you some code :
1
signaldelay:unsigned(7downto0);
2
3
begin
4
process(clk,rst)
5
begin
6
7
if(rst='1')then
8
curr_state<=start;
9
rom_counter<=(others=>'0');
10
delay<=(others=>'0');
11
flag<=(others=>'0');
12
13
elsif(clk'eventandclk='1')then
14
rom_counter<=next_rom_counter;
15
flag<=next_flag;
16
endif;
17
endprocess;
and i have my other process wich is only my state machine
1
|
2
|
3
|
4
whenS8=>
5
next_rom_counter<=rom_counter+1;
6
flag<="0....0";
7
rom_address<=std_logic_vector(rom_counter);
8
delay<=Rom_out;
9
next_state<=S9;
10
11
12
whenS9=>
13
ifflag=delaythen
14
next_state<=S10;
15
elsenext_state<=S9;
16
endif;
The problem:
In my simulation, everything is fine, i enter S9 with the good delay
value, flag at 0, so, the next_state is S9 a second time but delay goes
from the good value to 0 !
And i don't understand why ? Could you help me please.
What i have tried :
-put everything in the same state (the same problem happened)
-don't use a signal intern and directly compared flag to rom_out : not
working
Thank you for the help !
HacHac.
in one process you have the assignment
> flag<="0....0";
in another process you have the assignement
> flag<=next_flag;
I cannot believe that this works without complaints from your synthesis
tool. Please show your real code, not just code-fragments which "look
similar" to your real code.
Ed H. wrote:> the next_state is S9 a second time but delay goes> from the good value to 0 !
Your second process is not using a Clock, correct? Then you store delay
in a latch, not in a flipflop. That is typically a bad idea. Use a
flipflop if you want to keep information in an FPGA.
Hello !
First of all, thank you for your answer ! I'll post the entire code with
my simulation by monday (when i will have access to my code).
So if i understand well, it's not possible to make two assigment of the
same signal in two different process !
So in my second process, to re-initialize the flag value, i need to
write
1
next_flag<="0..0"
instead of
1
flag<="0..0"
I'll post the code as soon as possible, but i think i have made lots of
mistakes with latches .... because all my previous states are in the
same kind :
1
whenSi=>
2
next_rom_counter<=rom_counter+1;
3
rom_adress<=rom_counter;
4
data_wanted<=rom_out;
5
next_state<=s(i+1);
where data_wanted is a signal unsigned. So i can't do this kind of
assigment for data_wanted because my value will be stored in a latch ?
But why when i simulate, it keep the value i want, so i thought it was
good but i'm wrong ?
And why it keep the value for those signal and not the delay (it will be
difficult to answer whitout the code, i guess)
Thank you for the help !
Ed H. wrote:> So if i understand well, it's not possible to make two assigment of the> same signal in two different process !
You will get a error about "multiple drivers" when you try that in real
hardware...
> but i think i have made lots of mistakes with latches ....
My assumption is: your major problem is the 2-process FSM (one
combinatorial process and one clocked process).
Why not trying the 1-process FSM?
Try this with Google translator:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html
Ed H. wrote:> So if i understand well, it's not possible to make two assigment of the> same signal in two different process !
Correct: how should the hardware know, which of both is the valid
assignment at any given point in time? Maybe in simulation the problem
does not show up, as in simulation the processes are only executed,
which may avoid the conflict of different drivers. But in hardware both
drivers for the same signal would be conflicting permanently with each
other. So if you try to implement in hardware you must get error
messages.
Ed H. wrote:> So i can't do this kind of> assigment for data_wanted because my value will be stored in a latch ?
You can do: it is not impossible to store data in latches. But it is bad
style, if gives (serious) warnings and can make severe problems, which
are sometimes hard to identify and to understand in detail. So just
don't do it. Store the signals in flip-flops: that's the right place.
If you still have problems with the value of "delay" in a flip-flop,
then one can look deeper in your code and try to understand, where the
zero is coming from.
As Lothar wrote: the two-process coding style can very quickly lead to
latches (and to combinatorial loops). This two process style may be good
for teaching and to understand, that the FSM has a combinatorial logic
(described in one process) and a storage flip-flop (described in the
other process). But once you understood this anyhow and you start to
generate real code for real world problems, the one process coding style
of the FSM is much more compact (no need to define every signal twice
like "flag" and "new_flag") and you avoid all the problems of unintended
latches and combinatorial loops.
Ups, sorry: this sentence makes no sense.
Achim S. wrote:> Maybe in simulation the problem> does not show up, as in simulation the processes are only executed,> which may avoid the conflict of different drivers.
It should mean:
Maybe in Simulation the problem does nicht show up, as in simulation the
processes are only executed according to their sensitivity list.....
Thank you both of you for your answers ! It really helps me to
understand how vhdl really works ! (Unfortunately i can't say i
understood everything since i have not yet tried it by myself).
@lkmiller
Why not try a 1-process fsm ? Just because my teachers taught me like
that (with 2 process ) , so I'm a little scared to do it differently.
because, if ever what I do does not work with one process ... I risk of
being slapped on the wrist ! But i have read your entire link, it's
really well done, it helped me understand certain things and I keep in
mind the 1-process FSM method. I 'll try to fix it.
So, when i do my 2-process FSM, when i'm creating new_delay an delay, or
new_counter and counter, i making flipflop, which is much better than
latch (i already know that i have to avoid them) ?
For example if i writing something like that :
1
signaldata_wanted:unsigned(31downto0);
2
signalnext_data_wanted:unsigned(31downto0);
3
4
--My sequentiel process
5
begin
6
process(clk,rst)
7
begin
8
9
if(rst='1')then
10
curr_state<=start;
11
data_wanted<=(others=>'0');
12
maybe_something_else;
13
14
elsif(clk'eventandclk='1')then
15
curr_state<=next_state;
16
data_wanted<=next_data_wanted;
17
endif;
18
endprocess;
and in a state of my second process (combinatorial)
1
whenSi=>
2
next_rom_counter<=rom_counter+1;
3
rom_adress<=rom_counter;
4
next_data_wanted<=rom_out;-- this line
5
next_state<=S(i+1);
I'm storing correctly (in a flip-flop) my data_wanted ? Something like
this (even if it's not very professional and efficient) could be
correct, i mean synthesizable ? And i could re-use data_wanted in an
other state to make conditions ?
Thank you very much for your time !
Ed H. wrote:> So, when i do my 2-process FSM, when i'm creating new_delay an delay, or> new_counter and counter, i making flipflop,
In principle this works: data_wanted is stored in a flipflop,
next_data_wanted "calculates" the input value for that flipflop.
But: you have to describe an assignment to next_data_wanted for every
state Si in your combinatorial process. If you only assign
next_data_wanted in some states but make no assignment to it in others,
then for the other states the value of next_data_wanted still has to be
stored in a latch.
A default-assignment to next_data_wanted at the beginning of the
combinatorial process will solve this problem. Put a
next_data_wanted <= data_wanted there. If you make an assignment to
next_data_wanted in the actual state, then this is overwritten (e.g. by
rom_out). If you are in another state and make no assignemt to it, the
old value of data_wanted (stored in the flipflop) is reassigned.
Ed H. wrote:> Just because my teachers taught me like> that (with 2 process ) , so I'm a little scared to do it differently.
Ok, understood. As long as you write code for your teachers this may be
ok. Once you write code for real life, you may change to the one process
style ;-)
Fast answer and really clear in my head now i think !
So, if i want to avoid latch for next_data_wanted, and to avoid to
assign next_data_wanted in every state to avoid latch, i can do things
like that ?
1
P_FSM:process(.....)
2
begin
3
--HERE I SOLVE THE PROBLEM
4
next_data_wanted<=data_wanted;
5
Casecurrent_stateis
6
whenS1=>...
7
whenS2=>...
8
9
...
If i understood correctly, every time, next_data_wanted take the value
stored in the flip_flop of data_wanted, and , when i'm in a state using
next_data_wanted, i'm overwriting next_data_wanted, and so data_wanted
too (with my other process).
and in my first example, i need to do the same thing for rom_counter and
next_rom_counter if i don't want to assign next_rom_counter at every
state !
Is that correct ?
Thank you very much, i'll try this tomorrow and come back here to tell
you the result !
Ed H. wrote:> If i understood correctly, every time, next_data_wanted take the value> stored in the flip_flop of data_wanted, and , when i'm in a state using> next_data_wanted, i'm overwriting next_data_wanted, and so data_wanted> too (with my other process).
in that specific state you're overwriting next_data_wanted, i.e. the
input of your flip-flop. And with the next rising clock-edge, the output
of the flip-flop (data_wanted) takes the input value.
Ed H. wrote:> and in my first example, i need to do the same thing for rom_counter and> next_rom_counter if i don't want to assign next_rom_counter at every> state !> Is that correct ?
Sounds correct. And you need to do this for pretty much every signal.
And this writing-overhead is one strong reason for using the one process
style.
Hello !
Thank you for all your advices, it's now working and i was able to
synthetize my work ! I mean no error about the problem and no latch.
( Even if after the synthesis it's absolutely not working (everything is
freeze at the first state) but it's another problem !)
Thank you very much !