vhdl clock input to output as a finite state machine - vhdl

I have to generate the vhdl code for the signal generator above as a finite state machine. What I cant manage to implement is this. How to generate
the clock values to output. To be more specific, I want for half period
output 0 and the other half 1, when the state machine is in state clock. My implementation, as you can see on the
code below, is output <= clock but this obviously does not work. I made a finite machine with 4 states (s1, s2, s3, s4)
My testbench and my vhdl code are these:
testbench
library ieee;
use ieee.std_logic_1164.all;
entity signal_generator_tb is
end entity;
architecture signal_generator_tb_arch of signal_generator_tb is
signal clock_tb, reset_tb: std_logic;
signal output_tb: std_logic;
component signal_generator
port(clock, reset: in std_logic;
output: out std_logic);
end component;
begin
dut : signal_generator port map(clock_tb, reset_tb, output_tb);
stim_reset : process
begin
reset_tb <= '0'; wait for 10 ns;
reset_tb <= '1'; wait;
end process;
stim_clock : process
begin
clock_tb <= '1'; wait for 10 ns;
clock_tb <= '0'; wait for 10 ns;
end process;
end architecture;
and my vhdl code is that:
library ieee;
use ieee.std_logic_1164.all;
entity signal_generator is
port (clock, reset: in std_logic;
output: out std_logic);
end entity;
architecture signal_generator_arch of signal_generator is
type state_type is (s0, s1, s2, s3); --This is the states of the
finite state machine and we can create signlas with this type
signal current_state, next_state: state_type; --We can only assign
w_open and w_closed because there are type of state_type
begin
STATE_MEMORY : process(clock, reset)
begin
if(reset = '0') then
current_state <= s0;
elsif(falling_edge(clock)) then
current_state <= next_state;
end if;
end process;
NEXT_STATE_LOGIC : process(current_state)
begin
case(current_state) is
when s0 => next_state <= s1;
when s1 => next_state <= s2;
when s2 => next_state <= s3;
when s3 => next_state <= s0;
when others => next_state <= s0;
end case;
end process;
OUTPUT_LOGIC : process(current_state)
begin
case(current_state) is
when s0 => output <= '1';
when s1 => if(rising_edge(clock)) then
output <= '1';
else
output <= '0';
end if;
when s2 => output <= '1';
when s3 => output <= '0';
when others => output <= '0';
end case;
end process;
end architecture;
wave form

Your state machine does not work because of your OUTPUT_LOGIC process. It should also be sensitive to clock and when in state s1 it should output clock itself:
OUTPUT_LOGIC : process(current_state, clock)
begin
case(current_state) is
when s0 => output <= '1';
when s1 => output <= clock;
when s2 => output <= '1';
when s3 => output <= '0';
when others => output <= '0';
end case;
end process;
Note that you could simplify all this by simply passing your clock through a AND gate (to force it to 0) and a OR gate (to force it to 1) and output the result. A two bits counter that you would initialize to "11" and decrement would provide the current state, encoded in a very convenient way to force the output to 0 and 1:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity signal_generator is
port(clock, reset: in std_ulogic;
output: out std_ulogic);
end entity signal_generator;
architecture arc of signal_generator is
signal cnt: std_ulogic_vector(1 downto 0); -- the state
begin
process(clock, reset)
begin
if reset = '0' then
cnt <= "11";
elsif falling_edge(clock) then
cnt <= cnt - 1;
end if;
end process;
output <= (clock and cnt(1)) or cnt(0);
end architecture arc;
Note: always prefer std_ulogic (unresolved) to std_logic (resolved) when you do not plan to have multiple drive situations on a signal. This way, if you accidentally create a multiple drive situation you will get a meaningful error message instead of spending hours trying to understand where all these X values in your waveforms come from.

Related

In behavioral simulation, my FSM have a state that take more than 1 clock cycle ... And i don't like it

Please forgive myself if you will find some trivial errors in my code .. I'm still a beginner with VHDL.
Well, I have to deal with a serial interface from an ADC. The interface is quite simple ... there is a wire for the serial data (a frame of 24 bits), a signal DRDY that tells me when the new sample data is available and a serial clock (SCLK) that push the bit into (rising edge). Everything is running continuously...
I need to capture correctly the 24 bit of the sample, put them on a parallel bus (shift register) and provide a "data valid" signal for the blocks that will process the samples ...
Due to the fact that my system clock is x4 the frequency of the serial interface, i was thinking that doing the job with a FSM will be easy ...
When you look into the code you will see a process to capture the rising edges of the DRDY and SCLK.
Then a FSM with few states (Init, wait_drdy, wait_sclk, inc_count, check_count).
I use a counter (cnt unsigned) to check if I've already captured the 24 bits, using also to redirect the states of the FSM in "check_count" state.
Here a picture:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity serial_ads1675 is
Port (
clk : in STD_LOGIC;
reset : in STD_LOGIC;
sclk : in std_logic;
sdata : in std_logic;
drdy : in std_logic;
pdata : out std_logic_vector(23 downto 0);
pdready : out std_logic
);
end serial_ads1675;
architecture Behavioral of serial_ads1675 is
-- Internal declarations
signal ipdata : std_logic_vector (23 downto 0);
signal ipdready : std_logic;
signal tmp1, tmp2, tmp3, tmp4 : std_logic;
signal rise_drdy, rise_sclk : std_logic;
signal cnt : unsigned (4 downto 0);
type state is (init, wait_drdy, wait_sclk, inc_count, check_count);
signal actual_state, next_state : state;
begin
-- Concurrent statements
pdata <= ipdata;
pdready <= ipdready;
rise_drdy <= '1' when ((tmp1 = '1') and (tmp2 = '0')) else '0';
rise_sclk <= '1' when ((tmp3 = '1') and (tmp4 = '0')) else '0';
-- Process
process (clk, reset)
begin
if(reset = '0') then
tmp1 <= '0';
tmp2 <= '0';
tmp3 <= '0';
tmp4 <= '0';
elsif (falling_edge(clk)) then
tmp1 <= drdy;
tmp2 <= tmp1;
tmp3 <= sclk;
tmp4 <= tmp3;
end if;
end process;
process (reset, clk)
begin
if (reset = '0') then
actual_state <= init;
elsif (rising_edge(clk)) then
actual_state <= next_state;
end if;
end process;
process (rise_sclk, rise_drdy) -- Next State affectation
begin
case actual_state is
when init =>
next_state <= wait_drdy;
ipdata <= (others => '0');
ipdready <= '0';
cnt <= (others => '0');
when wait_drdy =>
if (rise_drdy = '0') then
next_state <= actual_state;
else
next_state <= wait_sclk;
end if;
cnt <= (others => '0');
when wait_sclk =>
if (rise_sclk = '0') then
next_state <= actual_state;
else
next_state <= inc_count;
end if;
ipdready <= '0';
when inc_count =>
next_state <= check_count;
cnt <= cnt + 1;
ipdready <= '0';
ipdata(23 downto 1) <= ipdata(22 downto 0);
ipdata(0) <= sdata;
when check_count =>
case cnt is
when "11000" =>
next_state <= wait_drdy;
ipdready <= '1';
when others =>
next_state <= wait_sclk;
ipdready <= '0';
end case;
when others =>
next_state <= init;
end case;
end process;
end Behavioral;
My problem is during the check_count state ...
I'm expecting that this state should last one system clock cycle, but actually it last much more.
Here a snapshot of the behavioral simulation:
Due to the fact that this state last more than expected, i miss the following SCLK pulse and don't record the next bit ...
I don't understand why this state last so many system clock cycles instead of just one ...
Anyone has some clues and bring some light in my dark night ?
Thanks in advance.
Edit: I've tried to change the signal cnt for an integer variable internal to the process of the FSM ... Same results
The error is this:
process (rise_sclk, rise_drdy) -- Next State affectation
begin
-- code omitted, but does generally this:
next_state <= SOME_VALUE;
end process;
Because the sensitivity list includes only the signals rise_sclk and rise_drdy, the process is "executed" only if any of these signals changes. You can follow this in the wave diagram.
You don't have a synchronous design running on clk. Put clk on the sensitivity list and base the decisions on the levels of rise_sclk and rise_drdy. As an excerpt:
process (clk) -- Next State affectation
begin
if rising_edge(clk) then
case actual_state is
when init =>
next_state <= wait_drdy;
-- and so on
end case;
end if;
end process;

VHDL: Mealy FSM not producing state changes at clock edges?

I am fairly new to VHDL and am following this tutorial to implement the following Mealy Finite State Machine:
and have written the following code in VHDL:
library ieee;
use ieee.std_logic_1164.all;
entity fsm is
port(clk, rst, in1 : in std_logic; o1 : out std_logic);
end fsm;
architecture mealy of fsm is
type state is (state1, state2);
signal current_state, next_state : state;
begin
comb: process(current_state, in1) begin
next_state <= current_state; -- default case
case current_state is
when state1 =>
o1 <= '0';
if in1 = '1' then
o1 <= '1';
next_state <= state2;
end if;
when state2 =>
o1 <= '1';
if in1 = '0' then
o1 <= '0';
next_state <= state1;
end if;
end case;
end process;
mem: process(clk, rst) begin
if rst = '1' then
current_state <= state1;
else
current_state <= next_state;
end if;
end process;
end mealy;
However on applying the following testbench:
library ieee;
use ieee.std_logic_1164.all;
entity fsm_tb is
end fsm_tb;
architecture sim of fsm_tb is
constant clockperiod : time := 10 ns; -- 100 Mhz clock
signal clk : std_logic := '0';
signal rst : std_logic;
signal in1, o_mealy : std_logic;
begin
uut_mealy : entity work.fsm(mealy) port map( clk => clk, rst => rst, in1 => in1, o1 => o_mealy);
clk <= not clk after clockperiod/2;
process begin
-- initial reset
in1 <= '0';
rst <= '1';
wait until rising_edge(clk);
-- take device out of reset
rst <= '0';
-- apply same inputs to both the devices
in1 <= '0'; wait for 23 ns;
in1 <= '1'; wait for 32 ns;
in1 <= '0'; wait for 7 ns;
in1 <= '1'; wait for 15 ns;
wait;
end process;
end sim;
the waveforms that I have obtained do not make sense to me:
As you can see the output o_mealy changes even without clock edge. It simply seems to only be following the input. By contrast, I have implemented the equivalent Moore machine and it seems to be working just fine:
If anyone can point out what I am doing wrong, it would be highly appreciated. Again, I have used this video for reference. I am using GHDL with GTKWave.
Taking a look at your concurrent logic:
case current_state is
when state1 =>
o1 <= '0';
if in1 = '1' then
o1 <= '1';
next_state <= state2;
end if;
when state2 =>
o1 <= '1';
if in1 = '0' then
o1 <= '0';
next_state <= state1;
end if;
end case;
In any of the two states, if in1 = '1', the output is 1, if in1 = '0' the output is 0. So the FSM works fine, but looking from the outside in you just cannot see the difference between the two states.
In terms of what are you doing wrong: I think this is correct, actually, looking at your drawing. In a mealy machine, the output is depended on the current state and the current input, which is exactly what is happening here.
Using GHDL's GHW dump file format to allow gtkwave to display enumerated type values we see:
where in current_state is being updated on both edges of clock (in a manner not likely supported for synthesis).
That can be corrected by evaluating a single clock edge in a manner conducive to synthesis:
mem: process(clk, rst) begin
if rst = '1' then
current_state <= state1;
elsif rising_edge(clk) then -- evaluate clock edge
current_state <= next_state;
end if;
end process;
And that gives us
current_state transitioning on one clock edge only.

FSM in vhdl using counter as output

I am currently writing my first FSM and am unsure of if I have the logic correct. I am tasked with creating a state diagram for the following logic:
A = 00
B = 01
C = 10
D = 11
Output is 1 when:
BDA
BAA
BAD
So I created the following vhdl code to accomplish this:
So every time I get it to output 1 I send it back to B and make count + 1. This is supposed to display on the LED as the number of times it is found in an 18 bit sequence.
Did I approach this in the correct way? I am confused on how I move it through the 18 bit sequence. I am supposed to us the swtiches on the board as my 18 bits which is represented as SW. Would I replace data_in with SW(17 downto 0)?
This is a comment not an answer I putting it in answer as I am not eligible to comment yet.
I think you have some problem in FSM concepts. Also as in the comment said data_in is std_logic not a vector.
you are taking input serially one bit at a time so accordingly write the processes. you can write code to detect the sequences BDA, BAA, BAD that is sequences "011100","010000" and "010011". I would write a simple FSM code so that you can clear you concepts then you can try.
library ieee;
use IEEE.std_logic_1164.all;
entity mealy is
port (clk : in std_logic;
reset : in std_logic;
input : in std_logic;
output : out std_logic
);
end mealy;
architecture behavioral of mealy is
type state_type is (s0,s1,s2,s3); --type of state machine.
signal current_s,next_s: state_type; --current and next state declaration.
begin
process (clk,reset)
begin
if (reset='1') then
current_s <= s0; --default state on reset.
elsif (rising_edge(clk)) then
current_s <= next_s; --state change.
end if;
end process;
--state machine process.
process (current_s,input)
begin
case current_s is
when s0 => --when current state is "s0"
if(input ='0') then
output <= '0';
next_s <= s1;
else
output <= '1';
next_s <= s2;
end if;
when s1 =>; --when current state is "s1"
if(input ='0') then
output <= '0';
next_s <= s3;
else
output <= '0';
next_s <= s1;
end if;
when s2 => --when current state is "s2"
if(input ='0') then
output <= '1';
next_s <= s2;
else
output <= '0';
next_s <= s3;
end if;
when s3 => --when current state is "s3"
if(input ='0') then
output <= '1';
next_s <= s3;
else
output <= '1';
next_s <= s0;
end if;
end case;
end process;
end behavioral;

Vhdl How Can I reset this signal

I'm trying to send two data to PC according to a counter. I need to send this two data just once, so I'm using a signal called "New_data_s". But my problem is this signal stays "High" too much and the data is being sent more than once. I'm sending "Datafll_s" by the way.
This is a picture of the first simulation: Sim1
Then I added another signal called "Stop_s" to reset this "New_data_s". Okay it sends the data just once, but this time, I can't reset "Stop_s". Once it goes "High" it stays "High" until I press the button. So I can't send the second data.
This is a picture of the second simulation: Sim2
I know if I don't press the button this "ELSIF(Go_s='1' and Go_s_ff='0')Then" condition is not TRUE, so that's why "Stop_s" stays "High" until I press the button. But, I couldn't find a way to do this.
Counter part:
IF(Cnt_Spc_P1>15 and Cnt_Spc_P1<=30)Then
Three_spc_s<='1';
Seven_spc_s<='0';
ELSIF(Cnt_Spc_P1>30 and Cnt_Spc_P1<50)Then
Three_spc_s<='0';
Seven_spc_s<='1';
ELSIF(Cnt_Spc_P1=50)Then
Three_spc_s<='0';
Seven_spc_s<='1';
Enable_1_s<='0';
Cnt_Spc_P1<=0;
ELSE
Three_spc_s<='0';
Seven_spc_s<='0';
END IF;
Main part:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
-------------------------------------------------------------------------------
Entity Letters is
Port(
Clk: in std_logic;
Reset: in std_logic;
Dot: in std_logic;
Dash: in std_logic;
Error : out std_logic;
New_data: out std_logic;
three_spc: in std_logic;
seven_spc: in std_logic;
d_out_d: out std_logic_vector(6 downto 0);
d_out_a: out std_logic_vector(7 downto 0)
);
END Letters;
-------------------------------------------------------------------------------
Architecture Letters_a of Letters is
-------------------------------------------------------------------------------
Type state is (Start, Space, T, E);
Signal current_s: state;
Signal Go_s, Go_s_ff: std_logic:='0';
signal data_d : std_logic_vector(6 downto 0):="1100100";
signal data_a : std_logic_vector(7 downto 0):="00000000";
Signal Error_s, New_data_s : std_logic:='0';
Signal Stop_s : std_logic:='0';
-------------------------------------------------------------------------------
BEGIN
-------------------------------------------------------------------------------
PROCESS(Clk, three_spc, seven_spc, current_s, Reset)
BEGIN
IF(Reset='1')Then
current_s<=Start;
data_d<="0000000";
data_a<="00000000";
d_out_d<="1100100";
Error_s<='0';
New_data_s<='0';
Stop_s<='0';
ELSIF(Rising_Edge(Clk))Then
IF(three_spc='1')Then
d_out_d<=data_d;
d_out_a<=data_a;
New_data_s<='1';
Stop_s<='1';
current_s<=Start;
ELSIF(seven_spc='1')Then
current_s<=Space;
d_out_d<=data_d;
d_out_a<="00100000";
New_data_s<='1';
Stop_s<='1';
current_s<=Start;
ELSIF(Go_s='1' and Go_s_ff='0')Then
Case current_s is
When Start =>
New_data_s<='0';
Stop_s<='0';
IF(Dash='1')Then
current_s<=T;
data_d<="1100100";
data_a<="01010100";
Error_s<='0';
ELSIF(Dot='1')Then
current_s<=E;
Error_s<='0';
data_d<="0000110";
data_a<="01000101";
END IF;
-------------------------------------------------------------------------------
When T =>
IF(Dash='1')Then
current_s<=M;
data_d<="1100100";
data_a<="01001101";
ELSIF(Dot='1')Then
current_s<=N;
data_d<="0101011";
data_a<="01001110";
END IF;
-------------------------------------------------------------------------------
When E =>
IF(Dash='1')Then
current_s<=A;
data_d<="0001000";
data_a<="01000001";
ELSIF(Dot='1')Then
current_s<=I;
data_d<="1111001";
data_a<="01001001";
END IF;
When OTHERS =>
current_s <= Start;
Error_s<='1'; -- Unidentified letter.
data_d<="1100100";
New_data_s<='0';
Stop_s<='0';
END Case;
END IF;
IF(Stop_s='1')Then
New_data_s<='0';
END IF;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
PROCESS(Clk, Dot, Dash, Reset)
BEGIN
Go_s<=Dash or Dot;
IF(Reset='1')Then
Go_s<='0';
Go_s_ff<='0';
ELSIF(Rising_Edge(Clk))Then
Go_s_ff<=Go_s;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
Error<=Error_s;
New_data<=New_data_s;
-------------------------------------------------------------------------------
END Letters_a;
Thank you.
I see that you've declared an enumerated type state and instantiated a signal current_s of type state. The enumerated type includes the literals, (Start, Space, T, E), but you assign literals M, N and A to signal current_s which are not members of the state type. Your compiler should complain about that. Does it?
The fsm included in your code is a bit difficult to follow because state transition code is mixed with output signal logic. So, I've rewritten it and posted it below. My fsm may not exactly represent the functionality you're looking for, however, you can use it as a template. It illustrates how to generate a one clock wide edge detector for the dot and dash signals. It also illustrates how to control the data strobe signal that you were having difficulty switching on and off.
The output logic does not take full advantage of the default signal values that proceed the output logic case statement so that it will be easier for you to see what's happening. However, many of the statements within the case could be eliminated for compactness.
Also, I haven't compiled the code, so you may find a few syntax errors, but the template should be of use to you.
-- Note, not all signals are declared here, refer to the posted code for them
Type state_t is (Idle, start_dot, start_dash, E_dot, strobe_3spc_data,
wait_1, strobe_7spc_data, wait_2, E_dash);
signal state_snoop : state_t; -- use to monitor state in simulator
signal dash_ff : std_logic;
signal dash_pulse : std_logic;
signal dot_ff : std_logic;
signal dot_pulse : std_logic;
fsm: process (clk)
variable current_s : state_t;
begin
if rising_edge(clk) then
if Reset = '1' then
current_s := Idle;
else
case Idle is
when Idle =>
if dot_pulse = '1' then
current_s := start_dot;
elsif dash_pulse = '1' then
current_s := start_dash;
end if;
-- dot related states ----------------------
when start_dot =>
current_s := E_dot;
when E_dot =>
if three_spc = '1' then
current_s := strobe_3spc_data;
end if;
when strobe_3spc_data =>
if seven_spc = '1' then -- counter strobe from external source
current_s := wait_1;
end if;
when wait_1 =>
if seven_spc = '1' then -- counter strobe from external source
current_s := strobe_7spc_data;
end if;
when strobe_7spc_data =>
current_s := wait_2;
when wait_2 =>
current_s := idle;
-- dash related states ----------------------
when start_dash =>
current_s := E_dash;
when E_dash =>
if three_spc = '1' then
current_s := strobe_3spc_data;
end if;
end case;
end if;
end if;
state_snoop <= current_s; -- monitor state in simulator. variables are hard to monitor
-------------- outputs decoded from state variable -------------------
-- default signal values
New_data_s <= '0';
data_d <= "0000000"; data_a <= "00000000"; d_out_d <= "0000000";
Stop_s <= '0'; Error_s <= '0';
case current_s is
when Idle =>
data_d <= "0000000";
data_a <= "00000000";
d_out_d <= "1100100";
Error_s <= '0';
New_data_s <= '0';
when start_dot =>
data_d <= "0000110"; --'ACK'
data_a <= "01000101"; -- ascii dash -> 'E'
Error_s <= '0';
New_data_s <= '0';
when E_dot =>
data_d <= "1111001";
data_a <= "01001001";
when strobe_3spc_data =>
d_out_d <= data_d;
d_out_a <= data_a;
New_data_s <= '1';
when wait_1 => -- switch data strobe off for first data transmission
New_data_s <= '0';
when strobe_7spc_data =>
d_out_d <= data_d;
d_out_a <= "00100000";
New_data_s <= '1';
when wait_2 => -- switch data strobe off for second data transmission
New_data_s <= '0';
-- dash related outputs
when start_dash =>
data_d <= "1100100"; --'t'
data_a <= "01010100"; --'T'
Error_s <= '0';
New_data_s <= '0';
when E_dash =>
data_d <= "0001000";
data_a <= "01000001";
when others => null;
end case;
-- rising edge detector for dash and dot input.
if Reset = '1' then
dash_pulse <= '0'
else
dash_ff << not(Dash);
dash_pulse << dash_ff and dash;
end if;
if Reset = '1' then
dot_pulse <= '0'
else
dot_ff << not(dot);
dot_pulse << dot_ff and dot;
end if;
end process fsm

Implementing a FSM in VHDL

Just wondering if I'm implementing a finite state machine in VHDL whether or not I need to state what all of the outputs are in every possible state? Even if I know that some outputs won't change from one state to the other and I know that the order of the states will also be in the same order?
For example, in this (forced) example:
entity test is
port (
clk : in std_logic;
a : in std_logic;
b: out std_logic;
c: out std_logic;
);
end test;
architecture Behavioral of test is
type executionStage is (s1,s2,s3);
signal currentstate, nextstate: executionStage;
begin
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
else
currentstate <= currentstate;
end if;
end process;
process(currentstate)
begin
case currentstate is
when s1 =>
if (a = '1') then
b <= '1';
c <= '0';
else
b <= '1';
c <= '1';
end if;
nextstate <= s2;
when s2 =>
-- b doesnt change state from s1 to here, do I need to define what it is here?
if (a = '1') then
b <= '1';
c <= '1';
else
b <= '1';
c <= '0';
end if;
nextstate <= s3;
when s3 =>
if (a = '1') then
b <= '0';
c <= '0';
else
b <= '1';
c <= '1';
end if;
nextstate <= s1;
end case;
end process;
end Behavioral;
From my understanding if I don't do this then latches are created?
It's not a big deal in something like that example but if I have a machine with more than 10 outputs and more than 10 states then my VHDL files start to look incredibly messy and I'm sure it must be bad practice to copy and paste the same thing over and over. Is there a better way of doing this?
edit: Can I define a 'default' state for an ouput? IE set b to be 1 outside of all the processes and then only define what it is in the case statements where it is 0? Would that work?
Yes, you will infer latches if you only drive signals intended to be combinatorial in some branches of the process.
However, you can define a 'default' state for the signal simply by assigning a value to it before the case statement (but within the same process). For example:
process(currentstate, a)
begin
b <= '1';
c <= '1';
case currentstate is
when s1 =>
if (a = '1') then
c <= '0';
end if;
nextstate <= s2;
when s2 =>
-- b doesnt change state from s1 to here, do I need to define what it is here?
if (a /= '1') then
c <= '0';
end if;
nextstate <= s3;
when s3 =>
if (a = '1') then
b <= '0';
c <= '0';
end if;
nextstate <= s1;
end case;
end process;
Three problems with your example code:
The last port in your port list should not have a semicolon:
port (
clk : in std_logic;
a : in std_logic;
b: out std_logic;
c: out std_logic -- no semicolon here!!!
);
In your register process, you should not have an "else" statement. While this will probably be accepted by the tools, it will confuse your fellow-VHDL designers.
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
end if;
end process;
In your combinational logic, the sensitivity list should contain all signals that you read: process(a, currentstate). In this particular case (again) things will probably work out fine, but you are bound to infer latches or cause other problems if your sensitivity list is not correct.
As for your question:
Yes, you need to assign a value (for each state) to each signal in the combinational process.
As Tomi mentions, you can easily do this by assigning a default value in the beginning of the process.
But you can also write the entire state machine in one single synchronous process. This way, you do not have to assign a value to every signal in every state.
Just a note to Philippe's response (can't comment on it directly?)..
I do prefer to write state machines in the two process style. It makes it very clear where you expect inferred flipflops and where you don't. It's also a bit more along the lines of
describing the hardware - imagine building a state machine with board level logic for example.
The registered device matches the state <= next_state process,
and the case statement maps to the and/or array in front of the state register..
Having said that, I typically use one process state machines for small simple tasks, and move over to two process machines for bigger ones.
I will even sometimes use a third process for organizing state outputs into different "task" groups.. but not often. A really large state machine tends to tell me the architecture needs work..
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
end if;
end process;
Hi
the above process is problematic but not due to the sensitivity list. It is ok to only declare clk for sequential process. Both simulation and synthesis tools won't have problems with it. clk is the fastest changing/transitioning signal after all in your code.
However, you should use an (preferrably) asynchronous reset. Of course, vendors nowadays say that for FPGA design, resets are not even necessary; they happen at boot time. Or they propose a synchronous reset.
Still, an asynchronous reset is valuable for a board-based environment.
In short: add a reset to your design and fix its behavior properly.
Kind regards
Nikolaos Kavvadias
The following VHDL code is edge sensitive state machine.
The edge sensitive process in this example will make both “out1” and “out2” in phase with “clk”.
entity main_code is
Port ( clk : in STD_LOGIC;
in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
out1 : out STD_LOGIC;
out2 : out STD_LOGIC);
end main_code;
architecture Behavioral of main_code is
-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';
signal out2_temp : std_logic := '0';
-- counter registers
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;
--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;
-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
if (counter >= 3) then
counter <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_fourth_clock;
one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
if (counter_8th_clk>=7) then
counter_8th_clk <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_eighth_clock;
-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_edge_sensitive : process (clk)
begin
if rising_edge (clk) then
case state is
when s0 =>
out1_temp <= not out1_temp;
state <= s1;
when s1 =>
out2_temp <= not out2_temp;
state <= s0;
end case;
end if;
end process state_process_edge_sensitive;
end Behavioral;
here is the test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY my_test_bench IS
END my_test_bench;
ARCHITECTURE behavior OF my_test_bench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT main_code
PORT(
clk : IN std_logic;
in1 : IN std_logic;
in2 : IN std_logic;
out1 : OUT std_logic;
out2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal in1 : std_logic := '0';
signal in2 : std_logic := '0';
--Outputs
signal out1 : std_logic;
signal out2 : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: main_code PORT MAP (
clk => clk,
in1 => in1,
in2 => in2,
out1 => out1,
out2 => out2
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
-- wait for 100 ns;
--
-- wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The following VHDL code is level sensitive state machine.
The level sensitive process in this example will make “out1” out of phase with “clk” and “out2” in phase with “clk”.
entity main_code is
Port ( clk : in STD_LOGIC;
in1 : in STD_LOGIC;
in2 : in STD_LOGIC;
out1 : out STD_LOGIC;
out2 : out STD_LOGIC);
end main_code;
architecture Behavioral of main_code is
-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';
signal out2_temp : std_logic := '0';
-- counter registers
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;
--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;
-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
if (counter >= 3) then
counter <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_fourth_clock;
one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
if (counter_8th_clk>=7) then
counter_8th_clk <= 0;
-- out2_temp <= not out2_temp;
end if;
end if;
end process one_eighth_clock;
-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_level_sensitive : process (clk)
begin
case state is
when s0 =>
out1_temp <= not out1_temp;
state <= s1;
when s1 =>
out2_temp <= not out2_temp;
state <= s0;
end case;
end process state_process_level_sensitive;
end Behavioral;
here is the test bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY my_test_bench IS
END my_test_bench;
ARCHITECTURE behavior OF my_test_bench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT main_code
PORT(
clk : IN std_logic;
in1 : IN std_logic;
in2 : IN std_logic;
out1 : OUT std_logic;
out2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal in1 : std_logic := '0';
signal in2 : std_logic := '0';
--Outputs
signal out1 : std_logic;
signal out2 : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: main_code PORT MAP (
clk => clk,
in1 => in1,
in2 => in2,
out1 => out1,
out2 => out2
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
-- wait for 100 ns;
--
-- wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;

Resources