counting clock rising edges then produce a specific signal with FSM in VHDL - vhdl

sorry for my weak english .
I want to write a VHDL code of simple Control unit or TPG controller that produce a signal like S2 , that motivated from FSM which count two rising edge of clock and then make the s2=1, so I want help to write a code wich count two rise edge then produce s2=1. then in third cycle make it zero.
here is my code that does not work :
LIBRARY ieee ;
USE ieee.std_logic_1164.all ;
USE ieee.std_logic_unsigned.all ;
ENTITY TPG_CONTROL IS
PORT ( Clock : IN STD_LOGIC ;
TPG_CONTROL_En : IN STD_LOGIC ;
--reset : IN STD_LOGIC ;
ST2 : OUT STD_LOGIC ) ;
END TPG_CONTROL ;
ARCHITECTURE behav OF TPG_CONTROL IS
SIGNAL Count : std_logic_vector(1 DOWNTO 0) := "00" ;
TYPE state IS (S0, S1, S2);
SIGNAL Moore_state: state;
SIGNAL Clear: std_logic ;
begin
U_Moore0: PROCESS (clock, Clear, TPG_CONTROL_En, Count)
BEGIN
IF(Count = "11") THEN
Moore_state <= S0;
Clear <= '1';
ELSIF ( (rising_edge (clock)) AND TPG_CONTROL_En= '1') THEN
-- IF (Count = "11") THEN Clear <= '1' THEN
IF Clear = '1' THEN
Count <= "00" ;
ELSE
Count <= Count + 1 ;
-- END IF ;
-- END IF;
-- END IF;
-- END IF;
CASE Moore_state IS
WHEN S0 =>
IF Count = "01" THEN
Moore_state <= S1;
-- ELSE
-- Moore_state <= S0;
END IF;
WHEN S1 =>
IF Count = "10" THEN
Moore_state <= S2;
-- ELSE
-- Moore_state <= S1;
END IF;
WHEN S2 =>
IF Count = "11" THEN
Moore_state <= S0;
-- ELSE
-- Moore_state <= S1;
END IF;
END CASE;
END IF;
END IF;
--ST2 <= ‘1’ WHEN Moore_state = S2 ELSE ‘0’;
END PROCESS;
U_Moore1: PROCESS (clock, TPG_CONTROL_En)
BEGIN
IF ( (rising_edge (clock)) AND TPG_CONTROL_En= '1') THEN
IF ( Moore_state = S2 ) THEN ST2 <= '1' ;
ELSE ST2 <= '0' ;
END IF;
END IF;
END PROCESS;
END behav ;

Fixing the back ticks in you're comment:
Was:
--ST2 <= ‘1’ WHEN Moore_state = S2 ELSE ‘0’;
Is:
-- st2 <= '1' when moore_state = s2 else '0';
Your code analyzes and elaborates.
Writing a simple testbench:
library ieee;
use ieee.std_logic_1164.all;
entity tpg_control_tb is
end entity;
architecture foo of tpg_control_tb is
signal clk: std_logic := '0';
signal enab: std_logic := '1';
signal st2: std_logic;
begin
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 100 ns then
wait;
end if;
end process;
DUT:
entity work.tpg_control
port map (
clock => clk,
tpg_control_en => enab,
st2 => st2
);
end architecture;
with a constant tpg_control_en emonstrates the behavior to which you allude, that you aren't reaching S2.
If you comment out the asynchronous clear of moore_state by count:
u_moore0: process (clock, clear, tpg_control_en, count)
begin
if(count = "11") then
-- moore_state <= s0;
clear <= '1';
elsif ( (rising_edge (clock)) and tpg_control_en= '1') then
-- if (count = "11") then clear <= '1' then
if clear = '1' then
count <= "00" ;
else
count <= count + 1 ;
-- end if ;
-- end if;
-- end if;
-- end if;
case moore_state is
when s0 =>
if count = "01" then
moore_state <= s1;
-- else
-- moore_state <= s0;
end if;
when s1 =>
if count = "10" then
moore_state <= s2;
-- else
-- moore_state <= s1;
end if;
when s2 =>
if count = "11" then
moore_state <= s0;
-- else
-- moore_state <= s1;
end if;
end case;
end if;
end if;
-- st2 <= '1' when moore_state = s2 else '0';
end process;
You actually get there:
I'd suspect without knowing why you have an asynchronous clear that the process statement sensitivity list could be reduced to clock.
And because unsigned/std_logic_vector "+" rolls over you can simply the heck out of what you have:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity tpg_control is
port (
clock: in std_logic;
tpg_control_en: in std_logic;
--reset: in std_logic;
st2: out std_logic
);
end tpg_control;
architecture behav of tpg_control is
signal count : std_logic_vector(1 downto 0) := "00" ;
type state is (s0, s1, s2);
signal moore_state: state;
-- signal clear: std_logic;
begin
u_moore0:
process (clock)
begin
-- if(count = "11") then
-- moore_state <= s0;
-- clear <= '1';
-- elsif ...
if rising_edge(clock) and tpg_control_en = '1' then
-- if clear = '1' then
-- count <= "00" ;
-- else
count <= count + 1;
case moore_state is
when s0 =>
if count = "01" then
moore_state <= s1;
end if;
when s1 =>
if count = "10" then
moore_state <= s2;
end if;
when s2 =>
if count = "11" then
moore_state <= s0;
end if;
end case;
-- end if;
end if;
end process;
u_moore1:
process (clock)
begin
if rising_edge(clock) and tpg_control_en = '1' then
if moore_state = s2 then
st2 <= '1' ;
else st2 <= '0' ;
end if;
end if;
end process;
end behav ;
And this shows the state roll over:
Note that count and moore_state hold the same information in two different type formats. You don't actually need both. Generally synthesis tools would be capable of producing a working implementation from moore_state alone.

Related

Quartus netlist optimization lost register fanout in a state machine

Hi guys i'm trying to implement a state machine but i have the problem that during timing simulation i get an error saying that
Info: 1 registers lost all their fanouts during netlist optimizations. The first 1 are displayed below.
Info: Register "state.STATE_I" lost all its fanouts during netlist optimizations.
and in the waveform timing simulation the output works fine but if i try to check the actual state I only get an initial state (STATE I) and an "UNDEFINED" in the rest of places where the actual state should be shown, the code is:
library ieee;
use ieee.std_logic_1164.all;
--define entity
entity pregunta1a is
port(
resetn : in std_logic;
clock : in std_logic;
w : in std_logic;
z : out std_logic
);
end pregunta1a;
--define architecture
architecture behavior of pregunta1a is
type STATE_TYPE is (STATE_A,STATE_B,STATE_C,STATE_D,STATE_E,STATE_F,STATE_I); -- todos los estados
signal state, next_state : STATE_TYPE;
begin
process(clock)
begin
if(rising_edge(clock)) then
if (resetn='0') then
state <= STATE_I;
else
state <= next_state;
end if;
end if;
end process;
process(state,w) -- complete sensitivity list
begin
z<='0';
case state is
when STATE_A =>
if (w = '1') then
next_state <= STATE_B;
else
next_state <= STATE_C;
end if;
when STATE_B =>
if (w = '1') then
next_state <= STATE_D;
else
next_state <= STATE_A;
end if;
when STATE_C =>
if (w = '1') then
next_state <= STATE_B;
else
next_state <= STATE_E;
end if;
when STATE_D =>
if (w = '1') then
next_state <= STATE_F;
else
next_state <= STATE_A;
end if;
when STATE_E =>
if (w = '1') then
next_state <= STATE_B;
else
next_state <= STATE_E;
z<='1';
end if;
when STATE_F =>
if (w = '1') then
next_state <= STATE_F;
z<='1';
else
next_state <= STATE_A;
end if;
when STATE_I =>
if (w = '1') then
next_state <= STATE_B;
else
next_state <= STATE_A;
end if;
end case;
end process;
end behavior;
This is a screenshot of the timing simulation
anyone known how to solve this ??
i´ve found a solution to my problem, it seems that i have to force some type of interaction with the register lost (state_I). I've changed some parts of the code and ordered it to make things more clear:
library ieee;
use ieee.std_logic_1164.all;
--define entity
entity pregunta1a is
port(
resetn : in std_logic;
clock : in std_logic;
w : in std_logic;
z : out std_logic
);
end pregunta1a;
--define architecture
architecture behavior of pregunta1a is
type STATE_TYPE is (STATE_A,STATE_B,STATE_C,STATE_E,STATE_F,STATE_G,STATE_R); -- todos los estados
signal state, next_state : STATE_TYPE:=state_R;
begin
process(clock)
begin
if(rising_edge(clock)) then
if (resetn='0') then
state <= STATE_R;
else
state <= next_state;
end if;
end if;
end process;
process(state,w,resetn) -- complete sensitivity list
begin
z<='0';
next_state<=state_R;
case state is
when STATE_A =>
if (w = '0') then
next_state <= STATE_B;
else
next_state <= STATE_E;
end if;
when STATE_B =>
if (w = '0') then
next_state <= STATE_C;
else
next_state <= STATE_E;
end if;
when STATE_C =>
if (w = '0') then
next_state <= STATE_C;
z<='1';
else
next_state <= STATE_E;
end if;
when STATE_E =>
if (w = '0') then
next_state <= STATE_A;
else
next_state <= STATE_F;
end if;
when STATE_F =>
if (w = '0') then
next_state <= STATE_A;
else
next_state <= STATE_G;
end if;
when STATE_G =>
if (w = '0') then
next_state <= STATE_A;
else
next_state <= STATE_G;
z<='1';
end if;
when STATE_R =>
if(resetn='1') then
if (w = '0') then
next_state <= STATE_A;
else
next_state <= STATE_E;
end if;
else
next_state<=state_R;
end if;
end case;
end process;
end behavior;
it seems that i have to force some type of interaction to establish STATE_I, the programs was working as it was, but one of the requirements was to get rid of this problem in the simulation

Finite state machine VHDL reset

I am new to VHDL and I have a question about the implementation of a FSM.
I would like the behaviour shown in the picture (where I implemented the same FSM with AHDL). When I implement it in VHDL I have a different behaviour of the reset : if it detects reset=1 and at the same time there is a rising edge the FSM does not go on but it keeps on putting PS at S0.
I know the problem is that if... elsif (it detects right the 1st condition and does not enter in the 2nd I suppose).
I have tried in many different ways but still is not working and the output stays at 00 also after the 1st rising edge.
Waveforms of AHDL implementation:
Waveforms of VHDL implementation:
LIBRARY ieee; -- Bibliotheksvereinbarung
USE ieee.std_logic_1164.all;
ENTITY sumconvol IS -- Schaltungssymbol
PORT
(
x : IN STD_LOGIC; --input of 1st FF
clk : IN STD_LOGIC; --clock of all the 3 FFs
clrn : IN STD_LOGIC;
y : OUT STD_LOGIC_VECTOR (1 downto 0) --vector of output data
);
END sumconvol;
ARCHITECTURE a OF sumconvol IS -- Creation of architecture
--SIGNAL output_tmp : STD_LOGIC_VECTOR (1 downto 0); -- temporary variables (e.g. input/output between FFs)7
TYPE state_type IS (S0,S1,S2,S3);
SIGNAL NS,PS : state_type;
SIGNAL stato : STD_LOGIC;
BEGIN
sync_proc: PROCESS (clk,clrn)
BEGIN
if ((clrn='1')) THEN
PS<=S0;
y <= "00";
elsif (rising_edge(clk)) then
PS <= NS;
CASE PS IS
when S0 =>
if ((x='0'))then
NS <= S0;
y <= "00";
else
NS <= S1;
y <= "11";
end if;
when S1 =>
if (x='0') then
NS <= S2;
y<="10";
else
NS <= S3;
y <= "01";
end if;
when S2 =>
if (x='0') then
NS <= S0;
y <="11";
else
NS <= S1;
y <= "00";
end if;
when S3 =>
if (x='0') then
NS <= S2;
y <="01";
else
NS <= S3;
y <= "10";
end if;
end case;
end if;
end process sync_proc;
END a;
One thing you might not noticed, is that you put both PS (previous state) and NS (next state) in a clocked process. That means registers are inferred for both signals. Thus, NS will be set to PS one clock later that you would probably expect. This can be solved two ways:
1) remove the PS->NS part, and just use state.
sync_proc: PROCESS (clk, clr)
BEGIN
if clr = '1' THEN
state <= S0;
y <= "00";
elsif rising_edge(clk) then
CASE state IS
when S0 =>
if x = '0' then
state <= S0;
y <= "00";
else
state <= S1;
y <= "11";
end if;
when S1 =>
if x = '0' then
state <= S2;
y<="10";
else
state <= S3;
y <= "01";
end if;
when S2 =>
if x = '0' then
state <= S0;
y <="11";
else
state <= S1;
y <= "00";
end if;
when S3 =>
if (x='0') then
state <= S2;
y <="01";
else
state <= S3;
y <= "10";
end if;
end case;
end if;
end process sync_proc;
2) separate the process into a clocked and a combinatorial process.
clk_proc: PROCESS (clk, clr)
BEGIN
if clr = '1' THEN
PS <= S0;
y <= "00";
elsif rising_edge(clk) then
PS <= NS;
y <= next_y;
end if;
end process;
comb_proc : process(PS, x)
begin
CASE PS IS
when S0 =>
if x = '0' then
NS <= S0;
next_y <= "00";
else
NS <= S1;
next_y <= "11";
end if;
when S1 =>
if x = '0' then
NS <= S2;
next_y <= "10";
else
NS <= S3;
next_y <= "01";
end if;
when S2 =>
if x = '0' then
NS <= S0;
next_y <="11";
else
NS <= S1;
next_y <= "00";
end if;
when S3 =>
if x = '0' then
NS <= S2;
next_y <="01";
else
NS <= S3;
next_y <= "10";
end if;
end case;
end process;
Next, I don't understand what you want with reset. The VHDL code is doing exactly what it should do. This is the proper way to use a reset: as long as the reset is asserted, y should display "00". Then, once it is deasserted, y should change on the next clock edge. That is proper design. What the first (AHDL) picture shows is not good: activity of y during reset.
But anyhow, if you are really stubborn, you can get the behavior that is in the first image using some tricks.
sync_proc: PROCESS (clk)
BEGIN
if (rising_edge(clk)) then
if clr = '1' THEN
state <= S0;
y <= "11";
else
case state is
[...]
p.s. you are calling the process sync_proc, as in "synchronous process". But this is not true, as the reset in your code is asynchronous...
p.s.2: give your signals some proper names, instead of e.g. x...

VHDL FSM with a counter inside

I am new here and here is my question:
I have a state machine with 3 states(s0,s1.s2) and input:(reset, clk, start) and output (done). My state machine works like this: on reset it comes to s0, and then if start = '1' goes to s2 and in this state I want it to stay there for 12 clock cycles (12 clock cycle delay) and then goes to s2 and done ='1' here and then back to s0.
My codes goes like this :
My code seems fine but my simulation result is not ok.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY fsm_count IS
port(clk : in std_logic;
reset : in std_logic;
start : in std_logic ;
don : out std_logic );
END ENTITY fsm_count;
--
ARCHITECTURE arc OF fsm_count IS
type statetype is (s0,s1,s2);
signal pr_state,nx_state : statetype;
signal s_counter : std_logic_vector (3 downto 0):=(others=>'0'); -- zero
begin
fsmcount: process(clk,reset,pr_state,start)
begin
if reset = '1'then pr_state <= s0;
elsif (clk'event and clk='1') then
case pr_state is
when s0 =>
if start ='1' then nx_state <=s1;
else nx_state <= s0;
end if;
when s1 =>
s_counter <= s_counter + '1';
if (s_counter = "1100") then
nx_state <= s2;
s_counter <=(others =>'0'); -- initializing the counter back to zero
else nx_state <=s1;
end if;
when s2 =>
nx_state<= s0;
end case;
end if;
end process fsmcount;
don <= '1' when (pr_state = s2) else '0';
END ARCHITECTURE arc;
I haven't synthetized it, but I think it should work. I you are not using VHDL2008, modify conditions so that bool types are returned:
ARCHITECTURE arc OF fsm_count IS
type statetype is (s0,s1,s2);
signal pr_state,nx_state: statetype;
signal s_counter: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if rst then pr_state <= s0; else pr_state <= nx_state; end if;
end if; end process;
process(clk) begin if rising_edge(clk) then
if pr_state/=s1 then s_counter <= (others=>'0');
else s_counter <= s_counter+1; end if;
end if; end process;
process(all) begin
case pr_state is
when s0 =>
if start then nx_state <= s1;
else nx_state <= pr_state; end if;
when s1 =>
if s_counter?=12 then nx_state <= s2;
else nx_state <= pr_state; end if;
when s2 =>
nx_state<= s0;
end case;
end process;
don <= '1' when (pr_state = s2) else '0';
END arc;
EDIT
Alternatively, you can save s2 (i replaced pr_state with sta, nx_state with stn, and s_counter with cnt:
ARCHITECTURE arc OF fsm_count IS
signal idon: std_logic;
type t_st is (s0,s1);
signal sta, stn: t_st;
signal cnt: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if rst then sta <= s0; else sta <= stn; end if;
end if; end process;
process(clk) begin if rising_edge(clk) then
if sta/=s1 then cnt <= (others=>'0');
else cnt <= cnt+1; end if;
end if; end process;
process(all) begin
case sta is
when s0 =>
if start then stn <= s1; else stn<=sta; end if;
when s1 =>
if idon then stn <= s0; else stn<=sta; end if;
end case;
end process;
idon <= cnt?=12;
don <= idon;
END arc;
Or, you can just use a flag:
ARCHITECTURE arc OF fsm_count IS
signal st, idon: std_logic;
signal cnt: std_logic_vector (3 downto 0);
begin
process(clk) begin if rising_edge(clk) then
if sta/=s1 then cnt <= (others=>'0');
else cnt <= cnt+1; end if;
end if; end process;
idon <= cnt?=12;
process(clk) begin if rising_edge(clk) then
if rst then st <= '0';
elsif not st and start then st <= '1';
elsif st and idon then st <= '0'; end if;
end if; end process;
don <= idon;
END arc;

ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description

I am trying to simulate an elevator and as a result i get the error
ERROR:Xst:827 = Signal count cannot be synthesized, bad synchronous description
I am following the code from this source [https://www.youtube.com/watch?v=i03_-NMwmDs] since mine is very similar,(i have 7 floors and two more elevators). At first i am working with the code mentioned on the video and later i am going to implement two more elevators to work together in this simulation.
Thanks in advance.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity elevator is
port (clk: in std_logic;
sensors1: out std_logic:='0'; --sensors at each level for elevator 1
a1, a2, a3, a4, a5, a6, a7: out std_logic; -- for LED display at FPGA
insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down: std_logic; -- input request for each floor
opendoor: out std_logic; -- from inside elevator
closedoor: out std_logic); -- from inside elevator
end elevator;
architecture sequence of elevator is
constant timedoorclose: integer := 3;
constant timedoorclosed: integer := 2;
constant time_nx_state: integer :=4;
signal demand: std_logic_vector(0 to 4) := "00000";
signal direction_of_elevator : integer range 0 to 2 := 0;
signal updownpassenger : std_logic := '0';
signal signalstatus: std_logic := '1';
type status is (L1, L2, L3, L4, L5);
signal pr_state, nx_state: status;
begin
main: process (clk, insideopendoor, in1, in2, in3, in4, in5, in1up, in2up, in3up, in4up, in5up, in5down, in4down, in3down, in2down, in1down)
variable digit1 : std_logic_vector (6 downto 0);
variable count : integer range 0 to (time_nx_state + timedoorclose + timedoorclosed);
variable bufferopendoor : std_logic;
variable position : integer range 0 to 4;
variable tempup : integer range 1 to 2 := 1;
variable tempdown : integer range -4 to 4;
begin
if (clk'event and clk='1') then
demand(0) <= demand(0) or in1 or in1up or in1down;
demand(1) <= demand(1) or in2 or in2up or in2down;
demand(2) <= demand(2) or in3 or in3up or in3down;
demand(3) <= demand(3) or in4 or in4up or in4down;
demand(4) <= demand(4) or in5 or in5up or in5down;
case pr_state is
when L1 => position := 0;
when L2 => position := 1;
when L3 => position := 2;
when L4 => position := 3;
when L5 => position := 4;
end case;
for i in 1 to 4 loop
if demand(i) ='1' then
tempup := i - position;
else null;
end if;
end loop;
for i in 3 downto 0 loop
bufferopendoor := '1';
closedoor <= '0';
count := 0;
end loop; --
elsif (updownpassenger = '1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
elsif count < (timedoorclose + timedoorclosed) then
opendoor <= '0';
bufferopendoor := '0';
else
closedoor <= '0';
end if;
--else null; ------
--end if; ------
-----------part main-----------------
count := count +1;
if insideopendoor = '1' then
opendoor<='1';
bufferopendoor :='1';
closedoor <= '0';
count := 0;
elsif (updownpassenger ='1') then
if (count < timedoorclose) then
opendoor <= '1';
bufferopendoor := '1';
closedoor <= '0';
elsif (count < (timedoorclose + timedoorclosed)) then
opendoor <= '0';
bufferopendoor := '0';
closedoor <= '1';
else
closedoor <= '0';
pr_state <= nx_state;
if signalstatus = '1' then
signalstatus <= '0';
else
signalstatus <= '1';
end if;
count := 0;
end if;
else null; --
end if;--
case nx_state is
when L1 =>
digit1 := "1111001";
if demand(0) = '1' then
demand(0) <= '0';
else null;
end if;
when L2 =>
digit1 := "0100100";
if demand(1) = '1' then
demand(1) <= '0';
else null;
end if;
when L3 =>
digit1 := "0110000";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L4 =>
digit1 := "0011001";
if demand(3) = '1' then
demand(3) <= '0';
else null;
end if;
when L5 =>
digit1 := "0010010";
if demand(4) = '1' then
demand(4) <= '0';
else null;
end if;
when others => null;
end case;
a1 <= digit1(0);
a2 <= digit1(1);
a3 <= digit1(2);
a4 <= digit1(3);
a5 <= digit1(4);
a6 <= digit1(5);
a7 <= digit1(6);
end if;
end process main;
step: process (pr_state, signalstatus)
begin
case pr_state is
--end if;
when L1 =>
if (demand(0)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <=L2;
elsif direction_of_elevator = 2 then
nx_state <= pr_state;
else
nx_state <= pr_state;
end if;
end if;
when L2 =>
if (demand(1)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L3;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when L3 =>
if (demand(2)= '1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L5;
elsif direction_of_elevator = 2 then
end if;
end if;
end if;
when L5 =>
if (demand(4)='1') then
nx_state <= pr_state;
updownpassenger <= '1';
else
updownpassenger <= '0';
if direction_of_elevator = 1 then
nx_state <= L4;
elsif direction_of_elevator = 2 then
nx_state <= L1;
else
nx_state <= pr_state;
end if;
end if;
when others => null;
end case;
end process step;
end sequence;
Your code seems very mixed up. There is a specific reason why it won't synthesise: think carefully when the code immediately following this line here
elsif (updownpassenger = '1') then
will be executed. It will be executed following a positive edge or negative edge on any input in the sensitivity list, apart from clk where it will be executed only following a negative edge. How would you design logic with such behaviour? Well, your synthesiser can't do it, either.
Basically, you need to refactor your code. You need to split it into sequential and combinational processes. (Combinational logic is logic whose output depends only on it's input and thus is logic that contains no latches or flip-flops. Sequential logic is logic that contains latches or flip-flops, but will also usually contain some gates too. Do not use latches - they are not synchronous design.) Whilst there are many ways to code such processes, it is wise to be consistent by sticking to a template. Here are three templates, which if followed, will give you everything you need and will keep your VHDL coding life simple:
Here is the template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Here is the template for sequential logic without an asynchronous reset:
process(clock) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if rising_edge(clock) then -- or falling_edge(clock) or clk'event and clk='1' or clk'event and clk='0'
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
And here is the corresponding template for a combinational process:
process(all inputs in the sensitivity list) -- an 'input' is a signal either on the LHS of an assignment or a signal that is tested
begin
-- combinational logic (with complete assignment and no feedback)
end process;

Bitsequence detector counter doesn't work (VHDL)

I build a 4 bit sequence detector with a 16-bit input.
I wanna now how often the sequence appears in the 16 bits.
For that I use this code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET:IN std_logic;
LOAD: IN std_logic;
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state, next_state: statetype;
SIGNAL counter: std_logic_vector(3 DOWNTO 0) :="0000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic;
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0 ;
counter <= (OTHERS => '0') ;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15) ;
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSE next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSE next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSE next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
counter <= counter + '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
END SEQ;
But neither my counter reset nor my incrementation of counter is working.
The rest is working perfect and fine.
Has somebody a hint or an idea for me?
The programm is now working fine in ModelSim, but I struggle with getting it on the board.
I simulated it several times in ModelSim, with different parameters and it works fine, so the functional part is fine.
My code looks now this way:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET: IN std_logic;
LOAD: IN std_logic;
DIGIT: OUT std_logic_vector(6 DOWNTO 0) := "1111110";
COUT: OUT std_logic_vector(2 DOWNTO 0);
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state: statetype;
SIGNAL next_state: statetype:=s0;
SIGNAL counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic := 'U';
-------------------Aktualisierung des Zustandes--------------------------------
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
---------------------Counter---------------------------------------------------
COUNT: PROCESS (state, RESET)
BEGIN
IF (RESET = '1') THEN
counter <= (OTHERS => '0');
ELSIF (state = s4) THEN
counter <= counter + '1';
COUT <= counter;
END IF;
END PROCESS COUNT;
-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15);
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
-------------------Zustandsabfrage und Berechnung------------------------------
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
-------------------Ausgang-----------------------------------------------------
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
-------------------7 Segment---------------------------------------------------
SEVEN_SEG: PROCESS (counter, CLK)
BEGIN
IF (RESET = '1') THEN
DIGIT <= "1111110";
END IF;
CASE counter IS
WHEN "000" => DIGIT <= "1111110";
WHEN "001" => DIGIT <= "0110000";
WHEN "010" => DIGIT <= "1101101";
WHEN "011" => DIGIT <= "1111001";
WHEN "100" => DIGIT <= "0110011";
WHEN "101" => DIGIT <= "1011011";
WHEN OTHERS => NULL;
END CASE;
END PROCESS SEVEN_SEG;
END SEQ;
When i put it on the board the 7-segment will show a "3".
I would assume, as the functional part seems to be good,that it has to do somethink with the timings, but i can't find any solution to it. If some experience VHDL-programmer could give me a new hint that would be great.
Best regards
Adrian

Resources