How do we set FSM Initial State in VHDL? - logic

While implementing a state machine on VHDL I was wondering how can I set the output / current state initial condition. I read on one of the questions on here.
One of the answers said we do the initialization before the case structure:
process(currentstate, a)
begin
b <= '1';
c <= '1';
case currentstate is
when s1 =>
if (a = '1') then
c <= '0';
end if;
nextstate <= s2;
However doesn't that make us automatically set b<='1' and c<='1' whenever we get into the process? So if we are at a state say A and we are at the conditions of moving to B whenever we enter the process this directly puts b<='1' and c<='1' isn't that true ?
Or does it actually just run once we start the program and then gets bounded in the case structure ?
Also check this link.
In their FSM implementation they did not specify the initial state how does the compiler or FPGA determine the start state ?

The lines you are looking at are not performing initialization.
b <= '1';
c <= '1';
Remember that VHDL is a hardware description language, not a programming language. What those two assignments do is to set a default assignment for those signals, unless something else contradicts these assignments later in the process. You can assign to the same signal several times in one process, and whichever assignment happens last will take priority. This saves having to write code like:
case State is
when s1 =>
a <= '0';
b <= '1';
c <= '1';
when s2 =>
a <= '1';
b <= '0';
c <= '1';
when s2 =>
a <= '1';
b <= '1';
c <= '0';
end case;
It can end up being quite repetitive and error prone to have the same assignments in many states, so default assignments can really tidy it up:
a <= '1';
b <= '1';
c <= '1';
case State is
when s1 =>
a <= '0';
when s2 =>
b <= '0';
when s2 =>
c <= '0';
end case;
The same pattern works for if statements where you don't want to cover every output signal in every logical branch.
If you want an initial state, there are two approaches that may be applicable depending on the scenario. Here you would assert reset at start-up to set the initial state. Note that the case statement is inside a clocked process:
process (clk)
begin
if (rising_edge(clk)) then
if (reset = '1') then
State <= s1;
else
case State is
when s1 =>
State <= s2;
when s2 =>
State <= s1;
end case;
end if;
end if;
end process;
The other option is to define your state signal with an initial value:
signal State : state_type := s1;
I won't go into the pros and cons of using initial values as there are existing questions that explore this.

Related

Signal assignment method

I am new to VHDL and have had some difficulty in performing the assignment of two different values to the same signal inside a process. For example,
process(CLK)
if rising_edge(CLK) then
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
LED0 <= VALUE;
OUTPUT0 <= Y(0);
OUTPUT1 <= Y(1);
OUTPUT2 <= Y(2);
LED1 <= VALUE;
end if;
end process;
Note that VALUE is an output dependent on the values assigned to OUTPUT0, OUTPUT1, OUTPUT2.
From what I understand in a process is that the last assignment to the same signal is always applied. What I am trying to do is apply two different sets of values to one set of inputs, map the output and it be done sequentially. I have tried separate processes tied to the same clock, a FSM to attempt to move sequentially and so on. At this point I have exhausted my knowledge of things to try.
My question is: What would be the best way to sequentially assign two values to one input and map its output in order?
EDIT:
As per Brian's suggestion on the state machine I had went ahead and implemented one again and found my error and fixed it. This gave the sequential assignment I was looking for.
I was reading 2 addresses from one instance of 32x1 distributed RAM which is the reason for a sequential assignment. Apologies for not providing the best example. Below is my final implementation:
RAM_READ_FSM : process(CLOCK) -- FSM to read the RAM addresses sequentially
begin
if rising_edge(CLOCK) then
case curr_state is
when S0 => if SW2 = '1' then
RAMADDR0 <= XYVEC(5); -- Y addresses
RAMADDR1 <= XYVEC(6);
RAMADDR2 <= XYVEC(7);
RAMADDR3 <= XYVEC(8);
RAMADDR4 <= XYVEC(9);
LED1 <= RAMOUT;
curr_state <= S1;
else
curr_state <= S0;
end if;
when S1 => if SW2 = '1' then
RAMADDR0 <= XYVEC(0); -- X addresses
RAMADDR1 <= XYVEC(1);
RAMADDR2 <= XYVEC(2);
RAMADDR3 <= XYVEC(3);
RAMADDR4 <= XYVEC(4);
LED2 <= RAMOUT;
curr_state <= S0;
else
curr_state <= S1;
end if;
end case;
end if;
end process;
The signals should be driven from the same process : multiple drivers would interfere with each other..
See Is process in VHDL reentrant? on signal assignment semantics.
now you can see there is need for some delay (even just 2 delta cycles, if the logic calculating VALUE is just a simple signal assignment) between the X and LED0 assignments.
You were on the right lines with a state machine but you didn't say anything about how it failed. Worth adding that to the Q to get a fuller answer.
Meanwhile there is a simple way to add delay :
like
LEDS : process is
begin
wait until rising_edge(CLK);
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
wait until rising_edge(CLK);
LED0 <= VALUE;
wait until rising_edge(CLK);
OUTPUT0 <= Y(0);
-- etc
end process LEDS;

Issue with Synchronous Sequential Circuit using Flip Flop D

Right now i'm working on a project concerning the use of D Flip Flop on Falling Edge, with x and y being the inputs and z being the output.
The Circuit will only give z ='1' only if x and y are both 0 and also if they were both 0 in a previous clock cycle, and the transitions only occurring in the clock's falling edge.
Variables a and b will represent states Q0(a) and Q1(b).
The Mealy machine is of two states : Q0 and Q1, and the transations are as follow:
Q0
x y z
0 0 1
0 1 x
1 0 0 --> goes to next state (Q1)
1 1 x
Q1
x y z
0 0 0 --> goes to next state (Q0) only this time z='0'
0 1 x
1 0 x
1 1 0 --> stays in current state (Q1)
The problem is that when the transition from Q1 to Q0 happens, z is still '1' instead of '0'.
Is there any advice on how could i manage to get around that fast transition?
Here is the code so far:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Mealys is
Port (
inicio: in std_logic;
clk: in std_logic;
x: in std_logic;
y: in std_logic;
z: out std_logic;
a: out std_logic;
b: out std_logic
);
end Mealys;
architecture behavior of Mealys is
type nombres_estados is (Q0, Q1);
signal estado: nombres_estados;
signal entrada_aux: std_logic_vector (1 downto 0);
begin
entrada_aux <= x & y;
FF_D: process (clk)
begin
if (inicio = '1') then
estado <= Q0;
elsif falling_edge(clk) then
case estado is
when Q0 =>
case entrada_aux is
when "00" => estado<=Q0;
when "10" => estado<=Q1;
when others => estado<=Q0;
end case;
when Q1 =>
case entrada_aux is
when "00" => estado<=Q0;
when "11" => estado<=Q1;
when others => estado<=Q1;
end case;
when others => estado<=Q0;
end case;
end if;
end process;
next_decode: process(estado, entrada_aux)
begin
case (estado) is
when Q0 =>
a <= '1';
b <= '0';
if entrada_aux <= "00" then
z<='1';
elsif entrada_aux <= "10" then
z<='0';
end if;
when Q1 =>
a <= '0';
b <= '1';
if entrada_aux <= "00" then
z<='0';
elsif entrada_aux <= "11" then
z<='0';
end if;
end case;
end process;
end behavior;
And here is the state diagram
Thank you for you time.
I assume that you are learning VHDL, that you are starting with the VHDL subset for synthesis and that the final goal is to synthesize your design.
Your design comprises two processes: a synchronous one and a combinatorial one. Both are bogus for synthesis.
Your synchronous process does not correctly handle the reset. If your reset is asynchronous (that is, is taken into account immediately when asserted), it should be in the sensitivity list:
process(clk, inicio)
begin
if inicio = '1' then
<initialize things>
elsif falling_edge(clk) then
<do things>
end if;
end process;
And if it is synchronous (that is taken into account only on the clock falling edge), it should not be in the sensitivity list but the reset part of your process should be under the scope of the clock edge test:
process(clk)
begin
if falling_edge(clk) then
if inicio = '1' then
<initialize things>
else
<do things>
end if;
end if;
end process;
Your combinatorial process has 3 outputs: a, band z. They must all be assigned a value during any execution of the process. This is what combinatorial means: each time an input changes, the signals propagate and all outputs finally get a new value. The new value can be the same as the previous one but this must be by accident, not because the output has not been assigned. Else, it would mean to a synthesizer: "keep the previous value", which usually leads to the inference of latches to store the previous value... Not what you want in a true combinatorial process. In your process, when estado or entrada_aux change, a and b are assigned but not always z (I let you understand why).
There is another problem in this process: the equality test operator is =, not <= which is the less or equal test operator. Note that your code should not even compile as it is.
It is not easy to propose a fixed version of this process because your specification is not 100% clear. What do these x mean in the transition table? For instance, what happens to z if we are in state Q0 and xy is 01 or 11? If the answer is "z does not change", then its computation must involve a memory element and you must describe this in your synchronous process. Else, if it means "z takes any value" (we don't care), then you must decide yourself before coding and add this to your combinatorial process (for instance with an else statement).
I will assume that it means "z does not change". So, you need a memory element (a D-flip-flop) to store the previous value. Add another signal (previous_z) and assign it in your synchronous process:
signal previous_z: std_logic:
...
process(clk, inicio)
begin
if inicio = '1' then
previous_z <= '0';
<initialize other things>
elsif falling_edge(clk) then
previous_z <= z;
<do other things>
end if;
end process;
There is a potential problem here because we are reading the value of z which is an output port of your entity. In VHDL versions previous 2008 this was forbidden. If you are using a pre-2008 version of VHDL you must declare another internal signal (local_z) that you can read and assign, use it everywhere, and assign it to the output z, for instance in a concurrent signal assignment (outside any process):
signal previous_z: std_logic:
signal local_z: std_logic:
...
process(clk, inicio)
begin
if inicio = '1' then
previous_z <= '0';
<initialize other things>
elsif falling_edge(clk) then
previous_z <= local_z;
<do other things>
end if;
end process;
z <= local_z;
Now, you can use this previous_z signal in your combinatorial process to compute local_z (or z in VHDL 2008):
next_decode: process(estado, entrada_aux, previous_z)
begin
case estado is
when Q0 =>
a <= '1';
b <= '0';
if entrada_aux = "00" then
local_z <= '1';
elsif entrada_aux = "10" then
local_z <= '0';
else
local_z <= previous_z;
end if;
when Q1 =>
a <= '0';
b <= '1';
if entrada_aux = "00" then
local_z <= '0';
elsif entrada_aux = "11" then
local_z <= '0';
else
local_z <= previous_z;
end if;
end case;
end process;
Note that previous_z must be added to the sensitivity list. Do you see now how the local_z output of the process will always be assigned?
There is an even better option which consists in assigning a default value to each output, unconditionally, at the beginning of the process and change this if and only if needed:
next_decode: process(estado, entrada_aux, previous_z)
begin
a <= '0':
b <= '0';
local_z <= previous_z;
case estado is
when Q0 =>
a <= '1';
if entrada_aux = "00" then
local_z <= '1';
elsif entrada_aux = "10" then
local_z <= '0';
end if;
when Q1 =>
b <= '1';
if entrada_aux = "00" then
local_z <= '0';
elsif entrada_aux = "11" then
local_z <= '0';
end if;
end case;
end process;
This works because, in a combinatorial process, when a signal is assigned several times, it is the last assignment that wins. And this coding style has a good property: you cannot forget to assign an output.
There is another good option: concurrent signal assignments (outside any process):
a <= '1' when estado = Q0 else '0';
b <= '1' when estado = Q1 else '0';
local_z <= '1' when estado = Q0 and entrada_aux = "00" else
'0' when estado = Q0 and entrada_aux = "10" else
'0' when estado = Q1 and entrada_aux = "00" else
'0' when estado = Q1 and entrada_aux = "11" else
previous_z;
Concurrent signal assignments, when the logic is simple enough, are maybe even better than the two other options because there is no need to worry about sensitivity lists and always assigning the outputs. Probably very good points, at least for beginners.
One last remark: you use the std_logic resolved type without any good reason. This is unfortunate and error prone. You should use std_ulogic, its unresolved parent type instead (u for Unresolved). But this is out of scope your question.

VHDL. Why doesn't my "rdy" value change to 1? Still confused

In my waveform diagram, I am wondering why my "rdy" value does not change to 1 after 400ns.
And why does my "d" value not output anything after the first two outputs? I've tried finding the error for hours but to no avail. Please help, thank you in advance.
Here is my waveform diagram:
And here is my main code.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity GCD is
port(st , clk: in std_logic; --clk temporarily taken out
d1, d2 : in std_logic_vector(7 downto 0);
dout : out std_logic_vector(7 downto 0);
rdy : out std_logic);
end GCD;
architecture behav of GCD is
type state is (S0, S1, S2, S3, S4, S5, S6, S7);
--temporary clk
--signal clk : std_logic;
signal new_state : state;
signal eq : boolean;
signal eq1 : boolean;
signal lt : boolean;
begin
--State transition
process is
variable curr_state : state:= S0;
begin
if clk = '1' then
case curr_state is
when S0 =>
if st = '1' then curr_state := S1;
end if;
when S1 =>
curr_state := S2;
when S2 =>
if eq and not lt then curr_state := S7;
elsif lt and not eq then curr_state := S4;
elsif not eq and not lt then curr_state := S3;
end if;
when S3 =>
curr_state := S4;
when S4 =>
curr_state := S5;
when S5 =>
if eq1 = true then curr_state := S7;
else curr_state := S6;
end if;
when S6 =>
curr_state := S1;
when S7 =>
if st = '0' then curr_state := S0;
end if;
end case;
new_state <= curr_state;
end if;
wait on clk;
end process;
--Asserted Output Process
process is
variable M, N, dout_val, tmp: std_logic_vector(7 downto 0);
variable rdy_val : std_logic;
variable lt_val, eq_val, eq1_val : boolean;
begin
rdy_val := '0';
case new_state is
when S0 =>
M := d1;
N := d2;
when S1 =>
if (to_integer(M) = to_integer(N)) then eq_val := true;
elsif (to_integer(M) < to_integer(N)) then lt_val := true;
end if;
when S2 =>
when S3 =>
M := N;
N := M;
when S4 =>
if (to_integer(M) = 1) then eq1_val := true;
end if;
when S5 =>
when S6 =>
N := (N - M);
when S7 =>
rdy_val := '1';
dout_val := M;
end case;
dout <= dout_val;
rdy <= rdy_val;
lt <= lt_val;
eq <= eq_val;
eq1 <= eq1_val;
wait on new_state;
end process;
end behav;
And here is my testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.all;
entity test_GCD is
end test_GCD;
architecture testbench of test_GCD is
signal m, n ,d: std_logic_vector(7 downto 0);
signal clk, st, rdy : std_logic;
begin
--Component Instantiation
device : GCD
port map( clk => clk, st => st, d1 => m,
d2 => n, dout => d, rdy => rdy);
--Process to Generate Test Data
process is
begin
st <= '0';
wait for 10ns;
m <= "00001001"; --9 , 15
n <= "00001111";
wait for 10ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
st <= '0';
wait for 10ns;
m <= "00001111"; --15, 9
n <= "00001001";
wait for 10ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
st <= '0';
wait for 10ns; --15 , 14
m <= "00001111";
n <= "00001110";
wait for 10ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
st <= '0';
wait for 10ns;
m <= "00010010"; --18 , 36
n <= "00100100";
wait for 30ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
st <= '0';
wait for 10ns;
m <= "01011011"; --91 = 01011011 , 39 = 00100111
n <= "00100111";
wait for 10ns;
st <= '1';
--wait for 10ns;
wait until rdy = '1';
wait for 10ns;
st <= '0';
wait for 10ns;
m <= "01111111"; --127, 127
n <= "01111111";
wait for 10ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
wait;
end process;
process is
begin
clk <= '0', '1' after 15ns;
wait for 30ns;
end process;
end testbench;
You're the second one to ask a question here today with the same assignment.
In the third st/rdy set you've upset the timing relation:
st <= '0';
wait for 10ns;
m <= "00010010"; --18 , 36
n <= "00100100";
wait for 30ns;
st <= '1';
wait until rdy = '1';
wait for 10ns;
The previous two sets have wait for 10 ns. This one has 30 ns. What does that do?
You're state machine in the unlabelled state transition process is missing the st <= '1', because it's not looking for it when it occurs, add waveforms down in GCD, try new_state.
There's a fine balance between helping someone and doing their assignment for them.
addendum
Can you elaborate what you mean by I am missing the st<='1' in my state transition? I've declared st as a std_logic so I can't use the "<=" assignment for it. Do you mean I am missing the st<='1' in my testbench?
The idea was to get you to look at the operation of the state machine spread across two unlabelled processes.
Your state machine is operating on the positive clock edge even though your code is not written to be synthesis eligible. The process is driven by only one event, clk and the expression clk = '1'is evaluated in the first if statement condition.
if you add new_state to your waveform dump (show it in the waveform display):
(you can open the image in a separate tab or window, it's a link to itself)
(And notice the first GCD 'answer' is all U's. The second 'answer' also doesn't appear to be the greatest common denominator between 15 and 9, either.)
You'll see your state machine quits transitioning, remaining stuck in S2 which evaluates ltand eqbut doesn't modify them in the Asserted Output Process (and you could use labels instead of comments, any statement can be labelled in VHDL).
We look to the previous state S1, where eq_val and lt_val are assigned. They are dependent on M and N, which are assigned from d1 and d2 in S0.
Back in S2 notice:
when S2 =>
if eq and not lt then
curr_state := S7;
elsif lt and not eq then
curr_state := S4;
elsif not eq and not lt then
curr_state := S3;
end if;
And if you look at eq and lt in the above waveform you see they are both true. How can that be? There is to transition condition for that, you stick in S2.
So how can both conditions be true at the same time?
when S1 =>
if (to_integer(M) = to_integer(N)) then
eq_val := true;
elsif (to_integer(M) < to_integer(N)) then
lt_val := true;
end if;
You are only assigning one of them.
However, the other one remains in it's previous state, latched by new_state.
As a short term demonstration I assigned eq_val and lt_val both false right before they are evaluated. That will leave at most only one true.
Unfortunately that reveals another flaw in your design:
And that's not the subject of your question.
You appear to use a Euclid (GCD) algorithm shown in the flow chart (figure 1) in the PDF found in the link. The Boolean types appears to be an assignment requirement (the other student used them as well). The resulting VHDL expresses this algorithm with at least one more error.
You use N as an accumulator in finding the GCD, and you also change the contents of M. N has three sources, d2, the result of N-M in S6 and swappingMandNinS3(which has the effect of assigningNtoM, andN` to itself, variable assignment is immediate). M and N should be signals, or you need an intermediary value to swap through. (They should be signals).
You can use your waveform display to troubleshoot your design. You should also be aware when you are inferring latches, which occur when you have conditional assignments without the equivalent of an 'else'.
The open source tools I used looking at your design (ghdl and gtkwave) don't capture variables in waveform dumps. I'd suspect DesignWorks 5 doesn't either (and could be wrong).
The impact of this is you can't see what the data is doing during the simulation. Your design is small enough you could have used signals throughout without impacting simulation time significantly. Assigning to eq and lt directly in S1 would require else assignments (false). If you're required to use variables for the assignment you can assign them to signals so they are visible, should DesignWorks 5 not display variables. Once you're done you can remove the signals.
The answer to Why doesn't my “rdy” value change to 1? is that you have inferred latches creating a case you don't detect for branching out of S2.
Once you straighten out the M and N swap in S3 it looks like it may have a good chance or working (there could be another gotcha or two in there).
And when you use tmp to hold the value of M (not using signals):
when S3 =>
tmp := M;
M := N;
N := tmp;
You start getting the right answers:
Without seeing the handout you were given for your project I'd anticipate you worked from pseudo code like found in the linked PDF's figure 1. It may have been written in the anticipation of the use of signals.

Undesiderated 1-bit latch (VHDL)

I'm programming a N-bit non-restoring divider, but I faced a little problem.
I have an Operative Part (combinatorial) and a Control Part (Finite State Machine).
The Control Part has a 2 processes FSM, 1 for updating the next state and 1 for the "state sequence".
update: process(clk_in, next_state)
begin
if rising_edge(clk_in) then
current_state <= next_state;
end if;
end process;
And this is the second process:
control: process(current_state, start, S_in, counted)
variable sub_tmp : STD_LOGIC := '0';
begin
[...]
sub <= sub_tmp; -- sub is an output signal of my entity that goes in the Operative Part
case current_state is
when idle =>
if start='1' then
next_state <= init;
else
next_state <= idle;
end if;
when init =>
-- [...]
next_state <= subtract;
when subtract =>
en_A <= '1';
sub_tmp := '1';
next_state <= test;
when test => -- shift
en_Q <= '1';
if S_in='0' then
sub_tmp := '1';
else
sub_tmp := '0';
end if;
if counted=N/2-1 then
next_state <= finished;
else
next_state <= operation;
end if;
when operation =>
en_A <= '1';
next_state <= test;
when finished =>
stop <= '1';
next_state <= idle;
end case;
end process;
As you can see, I need to change the value of the sub ONLY in 2 cases (subtract and test), while I don't have to change in the other cases.
The problem is that when I try to synthesize this code it turns out that sub_tmp is a LATCH, but I don't want a latch.
I need to do something like this:
state 1 => set sub to '1' or '0' (depending on another input)
state 2 => do other operations (but sub must remain the value set before) and return to state 1
etc...
To clarify more: in certain states of my FSM (not all of them) I set the value of a variable (let's call it sub_tmp). In other states I don't change its value. Then let's say I have an output PIN called "sub_out". Now, independently of the variable value, I want to output its value to this pin (sub_out <= sub_tmp; or similar).
What am I missing?
What you are missing is the behavior you describe IS a latch. Anything with memory (ie: "in other states I don't change it's value") is either a latch or a register (flip-flop). If you don't want a latch or a register, you need to assign a specific value to the signal in each and every code path, and not let it 'remember' it's previous state.

Design VHDL state machine for initialization

How do you smartest design a VHDL state machine for initializing a chip.
My current design is (in pseudo code):
....
....
case state:
when s0 =>
VHDL_CODE_FOR_WRITING_VALUE_TO_REGISTER
state := s1;
when s1 =>
VHDL_CODE_FOR_WRITING_ANOTHER_VALUE_TO_REGISTER
state := s1;
when s2 =>
DO_SOMETHING_ELSE_TO_FINISH_INIT
....
....
end case;
The code in s0 and s1 only differs by the value that is written to the register.
This made me think that there must be a smarter way (which is still Synthesize able)?
What made me think something can be done more clever, is the phrase "Don't repeat yourself", but I'm not sure this applies to VHDL.
If you have common assignments in states s0 and s1, pull it out of the case statement.
case state:
when s0 =>
a <= '0';
b <= '1';
c <= '0';
nextState <= s1;
when s1 =>
a <= '0';
b <= '1';
c <= '1';
nextState <= s2;
when s2 =>
a <= '1';
b <= '0';
c <= '1';
endcase;
...would become...
a <= '0';
b <= '1';
c <= '1';
case state:
when s0 =>
c <= '0';
nextState <= s1;
when s1 =>
nextState <= s2;
when s2 =>
a <= '1';
b <= '0';
endcase;
...or if that isn't suitable, pull the code into a function and call that in each case.
There's nothing VHDL specific about this though.
Although the continuous refrain of VHDL answerers (including me) is "think hardware, not software", this time the software thought process is the one that serves you well :)
The usual don't repeat yourself(DRY) solution is to encapsulate the behaviour you want in a function or procedure. You can do just this in VHDL and any competent tool will be fine with it.

Resources