VHDL synthesis tool won't infer FSM - vhdl

I'm trying to create a FSM in VHDL. However, the synthesis tool that I'm using (Vivado) won't infer it, and instead it thinks I've created a lot of registers and mux.
The goal of the hardware I'm designing is to implement a locker onto a FPGA. I've changed a lot of things in order not to create any latch, so if you see something wrong please tell me. Also, I'm Spanish so some names are in Spanish; if you don't understand something please tell me. I don't know if you need something else like the synthesis report. (Please don't tell me to create just one process, I have to design it using one sequential and one combinational process).
Here's the code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cerrojo is
port ( boton : in std_logic;
rst : in std_logic;
clk : in std_logic;
clave : in std_logic_vector(7 downto 0);
leds : out std_logic_vector(15 downto 0);
intentos: out std_logic_vector(6 downto 0));
end cerrojo;
architecture archCerrojo of cerrojo is
signal intentos_binario : unsigned(3 downto 0);
signal sin_rebote : std_logic;
signal guardado : unsigned(7 downto 0);
type estado is(inicial, tres, dos, uno, final);
signal estado_actual, estado_siguiente : estado;
component conv_7seg is
port (x : in std_logic_vector (3 downto 0);
display : out std_logic_vector (6 downto 0));
end component conv_7seg;
component debouncer is
port (
rst : in std_logic;
clk : in std_logic;
x : in std_logic;
xdeb : out std_logic;
xdebfallingedge : out std_logic;
xdebrisingedge : out std_logic);
end component debouncer;
begin
sieteSeg : conv_7seg
port map ( x => std_logic_vector(intentos_binario(3 downto 0)),
display => intentos);
rebotes : debouncer
port map (rst => rst, clk => clk, x => boton, xdeb => sin_rebote);
p_reg : process(clk, rst)
begin
if rst = '1' then
guardado <= "00000000";
estado_actual <= inicial;
elsif rising_edge(clk) and estado_actual = inicial then
guardado <= unsigned(clave);
estado_actual <= estado_siguiente;
elsif rising_edge(clk) then
guardado <= guardado;
estado_actual <= estado_siguiente;
end if;
end process p_reg;
p_comb : process(estado_actual, sin_rebote, clave, guardado)
begin
case estado_actual is
when inicial =>
intentos_binario <= "1000";
leds <= "1111111111111111";
--guardado <= unsigned(clave);
if (sin_rebote = '1') then
estado_siguiente <= tres;
else
estado_siguiente <= inicial;
end if;
when tres =>
intentos_binario <= "0011";
leds <= "0000000000000000";
-- guardado <= guardado;
if (sin_rebote = '1' and guardado = unsigned(clave)) then
estado_siguiente <= inicial;
elsif (sin_rebote = '1' and guardado /= unsigned(clave)) then
estado_siguiente <= dos;
else
estado_siguiente <= tres;
end if;
when dos =>
intentos_binario <= "0010";
leds <= "0000000000000000";
--guardado <= guardado;
if (sin_rebote = '1' and guardado = unsigned(clave)) then
estado_siguiente <= inicial;
elsif (sin_rebote = '1' and guardado /= unsigned(clave)) then
estado_siguiente <= uno;
else
estado_siguiente <= dos;
end if;
when uno =>
intentos_binario <= "0001";
leds <= "0000000000000000";
--guardado <= guardado;
if (sin_rebote = '1' and guardado = unsigned(clave)) then
estado_siguiente <= inicial;
elsif (sin_rebote = '1' and guardado /= unsigned(clave)) then
estado_siguiente <= final;
else
estado_siguiente <= uno;
end if;
when final =>
intentos_binario <= "0000";
leds <= "0000000000000000";
--guardado <= guardado;
estado_siguiente <= final;
end case;
end process p_comb;
end architecture archCerrojo;
Thank you in advance!

Related

Undefined Initial Signals VHDL

I have to implement a mini-router in VHDL. The design requirements for this are:
I've written the implementation, and a testbench. However, looking at the simulation waveform, some of my initial signals are undefined and I'm not sure why.
This is the source code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end entity;
architecture arch of mini_router is
signal aux : std_logic_vector(9 downto 0);
signal aux1 : std_logic_vector(1 downto 0);
signal aux2 : std_logic_vector(1 downto 0);
signal aux_valid : std_logic;
signal aux_grant1 : std_logic;
signal aux_grant2 : std_logic;
begin
mini_router: process(clk)
variable r : std_logic:= '1';
begin
-- conta le volte in cui c'è stato data conflict
if rising_edge(clk) then -- chiuso
if reset = '0' then
aux <= (others => '0');
aux_valid <= '0';
aux_grant1 <= '0';
aux_grant2 <= '0';
elsif reset = '1' then
if (req1 xor req2) = '1' then --chiuso -- un solo req è alto
if req1 ='1' then --chiuso
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
else
aux <= data2;
aux_grant1 <= '0';
aux_grant2 <= '1';
aux_valid <= '1';
end if;
----entrambi i req sono alti
elsif (req1 and req2) = '1' then -- chiuso
if ((unsigned(aux1)) > (unsigned(aux2))) then
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) < (unsigned(aux2))) then
aux <= data2;
aux_grant2 <= '1';
aux_grant1 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) = (unsigned(aux2))) then -- stesso livello di priorità -- alternativa:(aux1 xnor aux2)="11"
if r = '1' then
aux <= data1;
aux_grant1<= '1';
aux_grant2 <= '0';
aux_valid <= '1';
r := not (r);
else
aux <= data2;
aux_grant2 <= '1';
aux_grant1<= '0';
aux_valid <= '1';
r := not (r);
end if;
end if;
elsif (req1 nor req2) = '1' then
aux_valid <= '0';
aux <= (others => '0');
aux_grant1 <= '0';
aux_grant2 <= '0';
end if;
end if; -- if del reset
end if; -- if del clock
end process;
data_out <= aux(9 downto 2);
aux1 <= data1 (1 downto 0);
aux2 <= data2 (1 downto 0);
valid <= aux_valid;
grant1 <= aux_grant1;
grant2 <= aux_grant2;
end architecture;
This is the testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mini_router_tb is
end mini_router_tb;
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns; --- frequenza di clock: 125 MHz
signal clk_tb : std_logic := '1';
signal reset_tb : std_logic := '0'; -- reset attivo basso sincrono
signal data1_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req1_tb : std_logic:= '0';
signal grant1_tb : std_logic;
signal data2_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req2_tb : std_logic:= '0';
signal grant2_tb : std_logic;
signal data_out_tb : std_logic_vector(7 downto 0);
signal valid_tb : std_logic;
signal end_sim : std_logic := '1'; -- signal to use to stop the simulation when there is nothing else to test
component mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end component;
begin
clk_tb <= (not(clk_tb)and(end_sim)) after T_CLK/2;
DUT : mini_router
port map (
clk => clk_tb,
reset => reset_tb,
data1 => data1_tb,
req1 => req1_tb,
grant1 => grant1_tb,
data2 => data2_tb,
req2 => req2_tb,
grant2 => grant2_tb,
data_out => data_out_tb,
valid => valid_tb
);
-- process used to make the testbench signals change synchronously with the rising edge of the clock
stimuli_process: process(clk_tb,reset_tb)
variable t : integer := 0; -- variabile che conta i cicli di clock
begin
if (rising_edge(clk_tb)) then
case (t) is
when 1 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=0 per il reset
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=1
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 3 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4;
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13; data_out=3
req1_tb <= '0' ; req2_tb<= '1';
when 4 => data1_tb <= (9 downto 5 => '0') & "11100"; --data1=28
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13; data_out=3 priorità maggiore
req1_tb <= '1' ; req2_tb<= '1';
when 5 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1 priorità maggiore
data2_tb <= (9 downto 5 => '0') & "11101"; -- data2= 29;
req1_tb <= '1' ; req2_tb<= '1';
when 6 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31;
req1_tb <= '1' ; req2_tb<= '1';
when 7 => data1_tb <= (9 downto 5 => '0') & "00111"; --data_out=0;
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
when 8 => data1_tb <= (9 downto 5 => '0') & "10111"; --data1=7; data_out non assunto=5
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31; data_out=7
req1_tb <= '1' ; req2_tb<= '1';
when 9 => end_sim <= '0'; -- stops the simulation when t = 10
when others => null; -- non accade nulla negli altri casi
end case;
t := t + 1;
end if;
end process;
end architecture;
Your reset logic is synchronous, because the outmost condition is rising_edge(clk). Therefore the internal signals are undefined until the first raising edge of the clock.
Change to an asynchronous reset like this (excerpt):
if reset = '0' then
-- reset statements
elsif rising_edge(clk) then
-- work statements
end if;
Please be aware that even with an asynchronous reset the signals will be undefined until reset is activated or the clock raises. This reflects the actual behavior of a real device.
The reason your signals are initially set to U or X is because the values of all signals, variables, etc. are initialized to the left hand side of the type definition.
From the IEEE 1076 code (see here):
-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
type STD_ULOGIC is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
--------------------------------
And std_logic is just a resolved version of std_ulogic. So any signal of type std_logic will have its default value be U, unless set otherwise.
Consider the following code:
signal A : std_logic;
signal B : std_logic := '1';
Signal A would be U until set otherwise. Signal B will be 0 until set otherwise.
This is why you are seeing U in your simulation. (As for X you see in your waveform window, many simulators that collapse vectors into a single value in the waveform view treat collections with U as X. Expand that vector and I suspect you will see several U's.)

I2Cmaster with MPU6050 in VHDL not working

For my hobby project I try to make a quadcopter which balances itself with the MPU-6050. The flight controller shall be the FPGA Altera cyclone IV, because its fun. I'm coding it in VHDL.
Anyway I'm stuck on the I2C communication with the MPU-6050. As bases I used the I2C master VHDL code from: https://www.digikey.com/eewiki/pages/viewpage.action?pageId=10125324.
I try to read the gyro registers and print them out on 8 leds just to see if I have some communication coming in.
I have tried to run with a 1Hz prescaler all the I2C phases in the state machine and light up some leds just to see if all phases are run through. This is the case. I have assigned the pins 2.5V default, I use 10k pull up resistors. The MPU6050 works perferct on an arduino.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mpu6050_2 is
port( clk_50 : in std_logic;
areset : in std_logic;
i2c_SDA : INOUT STD_LOGIC;
i2c_SCL : INOUT STD_LOGIC;
leds : out std_LOGIC_VECTOR(7 downto 0)
);
end entity mpu6050_2;
architecture struc of mpu6050_2 is
component i2c_master is
GENERIC(
input_clk : INTEGER := 50_000_000;
bus_clk : INTEGER := 400_000);
PORT(
clk : IN STD_LOGIC;
reset_n : IN STD_LOGIC;
ena : IN STD_LOGIC;
addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
rw : IN STD_LOGIC;
data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
busy : OUT STD_LOGIC;
data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
ack_error : BUFFER STD_LOGIC;
sda : INOUT STD_LOGIC;
scl : INOUT STD_LOGIC);
end component ;
type machine is (config1, config2, gyroH, gyroL);
signal state : machine:= config1; --current state
signal SDA_int : std_LOGIC;
signal SCL_int : std_LOGIC;
signal i2c_ena : std_LOGIC;
signal i2c_busy : std_LOGIC;
signal busy_prev : std_LOGIC;
signal i2c_rw : std_LOGIC;
signal i2c_data_wr : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal gyro_data : std_LOGIC_VECTOR(15 downto 0);
signal i2c_data_rd : std_LOGIC_VECTOR (7 downto 0);
signal i2c_addr : STD_LOGIC_VECTOR(6 DOWNTO 0);
begin
process(areset, clk_50)
VARIABLE busy_cnt : INTEGER := 0; --keeps track of i2c busy signals during transaction
begin
if areset = '0' then
busy_cnt := 0;
i2c_ena <= '0';
state <= config1;
elsif rising_edge(clk_50) then
case state is
when config1 =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"6B"; -- hex6B powermanagement
when 1 =>
i2c_rw <= '0'; --write
i2c_data_wr <= "00000000"; -- ON with internal clock
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
busy_cnt := 0;
state <= config2;
end if;
when others => NULL;
end case;
when config2 =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"1B"; -- Gyro config
when 1 =>
i2c_rw <= '0'; --write
i2c_data_wr <= "00000000"; -- 250 degree/sec, no self test
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
busy_cnt := 0;
state <= gyroH;
end if;
when others => NULL;
end case;
when gyroH =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"43"; -- hex43 GYRO_OUT[15:8]
when 1 =>
i2c_rw <= '1'; --read
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
gyro_data(15 downto 8) <= i2c_data_rd;
busy_cnt := 0;
state <= gyroL;
end if;
when others => NULL;
end case;
when gyroL =>
busy_prev <= i2c_busy;
if (busy_prev = '0' and i2c_busy = '1') then
busy_cnt := busy_cnt + 1;
end if;
case busy_cnt is
when 0 =>
i2c_ena <= '1';
i2c_addr <= "1101000"; --MPU6050 adress
i2c_rw <= '0'; --write
i2c_data_wr <= x"44"; -- hex44 GYRO_OUT[7:0]
when 1 =>
i2c_rw <= '1'; --read
when 2 =>
i2c_ena <= '0';
if(i2c_busy = '0') then
gyro_data(7 downto 0) <= i2c_data_rd;
busy_cnt := 0;
state <= gyroH;
end if;
when others => NULL;
end case;
end case;
end if;
end process;
u0: i2c_master
port map(clk => clk_50, reset_n => areset, ena => i2c_ena, addr => i2c_addr, rw => i2c_rw, data_wr => i2c_data_wr, busy => i2c_busy, data_rd => i2c_data_rd
, sda => SDA_int, scl => SCL_int);
leds(7) <= gyro_data(0); --D4
leds(6) <= gyro_data(1); -- D5
leds(5) <= gyro_data(4); -- D6
leds(4) <= gyro_data(7); -- D7
leds(3) <= gyro_data(8); -- D8
leds(2) <= gyro_data(11); -- D9
leds(1) <= gyro_data(13); -- D10
leds(0) <= gyro_data(15); -- D11
i2c_SDA <= SDA_int;
i2c_SCL <= SCL_int;
end struc;
Result:
all the leds dont change status despite if i rotate the MPU6050. So no communication. Can anyone help me what i'm doing wrong?
First: I'm using the same component in one of my designs and do confirm it works.
I think you are just using the wrong i2c address to begin with.
In datasheets, i2c addresses are usually given including the read/write bit (for the MPU-6050, this is 0x68/01101000 and 0x69/01101001). The i2c master component used, however, expects to build the final i2c address by itself by appending (&) the i2c rw bit to the given address (see line 124 in the original sources), thus you must pass the address from the datasheet shifted by one bit.
Try using 0x34/0110100 as i2c address for read and write instead.
I only looked very briefly into the rest of your code (so there might be other culprits as well), but this should be enough to get you going.

VHDL Parametric Division Circuit - Book: FPGA Prototyping by VHDL Examples, Pong Chu

I'm trying to follow an example on my VHDL book. Its name is FPGA Prototyping by VHDL Examples, Pong Chu. It has a Divider Circuit example in Chapter 6, Listing 5. I understood the general idea of a division operation. To verify the module I wrote a testbench and I saw that it doesn't work properly. If anyone could explain to me where the problem is, I would be very appreciated.
Here are the codes of module and testbench.
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Divider is
generic(W: integer := 8;
CBIT: integer := 4 );
Port ( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (W-1 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (W-1 downto 0));
end Divider;
architecture Behavioral of Divider is
type state_type is (idle, op, last, done);
signal state_reg, state_next: state_type;
signal rh_reg, rh_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal rl_reg, rl_next: STD_LOGIC_VECTOR(W-1 downto 0) := (others => '0');
signal rh_temp: UNSIGNED(W-1 downto 0) := (others => '0');
signal d_reg, d_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal n_reg, n_next: UNSIGNED(CBIT-1 downto 0) := (others => '0');
signal q_bit: STD_LOGIC;
begin
-- FSMD State and Data Registers
process(clk, reset)
begin
if reset = '1' then
state_reg <= idle;
rh_reg <= (others => '0');
rl_reg <= (others => '0');
d_reg <= (others => '0');
n_reg <= (others => '0');
elsif rising_edge(clk) then
state_reg <= state_next;
rh_reg <= rh_next;
rl_reg <= rl_next;
d_reg <= d_next;
n_reg <= n_next;
end if;
end process;
-- FSMD Next-State Logic and Data Path Logic
process(state_reg, n_reg, rh_reg, rl_reg, d_reg, start, dvsr, dvnd, q_bit, rh_temp, n_next)
begin
ready <= '0';
done_tick <= '0';
state_next <= state_reg;
rh_next <= rh_reg;
rl_next <= rl_reg;
d_next <= d_reg;
n_next <= n_reg;
case state_reg is
when idle =>
ready <= '1';
if start = '1' then
rh_next <= (others => '0');
rl_next <= dvnd; -- Dividend
d_next <= UNSIGNED(dvsr); -- Divisor
n_next <= TO_UNSIGNED(W+1, CBIT); -- Index
state_next <= op;
end if;
when op =>
--Shift rh and rl left
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp(W-2 downto 0) & rl_reg(W-1);
--Decrease index
n_next <= n_reg - 1;
if(n_next = 1) then
state_next <= last;
end if;
when last =>
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp;
state_next <= done;
when done =>
state_next <= idle;
done_tick <= '1';
end case;
end process;
-- Compare and Subtract
process(rh_reg, d_reg)
begin
if rh_reg <= d_reg then
rh_temp <= rh_Reg - d_reg;
q_bit <= '1';
else
rh_temp <= rh_reg;
q_bit <= '0';
end if;
end process;
-- Output
quo <= rl_reg;
rmd <= STD_LOGIC_VECTOR(rh_reg);
end Behavioral;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_Divider is
-- Port ( );
end tb_Divider;
architecture Behavioral of tb_Divider is
signal clk, reset, start, ready, done: STD_LOGIC;
signal dvsr, dvnd: STD_LOGIC_VECTOR(7 downto 0);
signal quo, rmd: STD_LOGIC_VECTOR(7 downto 0);
component Divider is
port( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (7 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (7 downto 0));
end component Divider;
begin
UUT: Divider port map( clk => clk, reset => reset, start => start, dvsr => dvsr, dvnd => dvnd,
ready => ready, done_tick => done, quo => quo, rmd => rmd);
process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
process
begin
start <= '0';
dvnd <= x"00";
dvsr <= x"00";
wait for 100 ns;
start <= '1';
dvnd <= x"C8";
dvsr <= x"0A";
wait for 10 us;
end process;
end Behavioral;
Result of Testbench:

State machine and unsigned signal

I have a few problems with a fairly simple state machine I made. No matter what I do, the signal startS1, startS2, enS and mS always stays unsigned in simulation even when I hit the reset button and I can't figure out why. There's a component in the mix, but I did test the component and it works perfectly. I hope you can help me!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity machine_etat is
generic (N_bit : integer := 8);
Port ( LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0);
RESET : in STD_LOGIC;
START : in STD_LOGIC;
CLK : in STD_LOGIC;
OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0));
end machine_etat;
architecture Behavioral of machine_etat is
TYPE machine is (IddleT, DepartT, LoadT, ShiftT, EndT);
SIGNAL Etat1, Etat2 : machine:= IddleT;
SIGNAL mS: STD_LOGIC_VECTOR (1 downto 0);
SIGNAL enS : STD_LOGIC;
SIGNAL outputS : STD_LOGIC_VECTOR (N_bit-1 downto 0);
component Reg_decal is
generic (N_bit : integer := N_bit);
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
EN : in STD_LOGIC;
M : in STD_LOGIC_VECTOR (1 downto 0);
LOAD : in STD_LOGIC_VECTOR (N_bit-1 downto 0);
OUTPUT : out STD_LOGIC_VECTOR (N_bit-1 downto 0));
end component;
SIGNAL startS1, startS2 : STD_LOGIC;
begin
OUTPUT <= outputS;
Reg_dec: Reg_decal
generic map (N_bit => N_bit)
port map (CLK => CLK,
RESET => RESET,
EN => enS,
M => mS,
LOAD => LOAD,
OUTPUT => outputS);
Machine1: process (CLK)
begin
if RESET = '1' then
enS <= '0';
mS <= "00";
startS1 <= '0';
startS2 <= '0';
Etat1 <= IddleT;
elsif rising_edge(CLK) then
CASE Etat1 is
WHEN IddleT =>
if startS1 = '1' OR START = '1' then
Etat1 <= DepartT;
else
Etat1 <= IddleT;
end if;
WHEN DepartT =>
Etat1 <= LoadT;
startS1 <= '0';
WHEN LoadT =>
mS <= "11";
enS <= '1';
Etat1 <= ShiftT;
WHEN ShiftT =>
mS <= "00";
Etat1 <= EndT;
WHEN EndT =>
enS <= '0';
startS2 <= '1';
Etat1 <= IddleT;
WHEN Others =>
Etat1 <= IddleT;
end CASE;
end if;
end process;
Machine2: process (CLK)
begin
if RESET = '1' then
Etat2 <= IddleT;
elsif rising_edge(CLK) then
CASE Etat2 is
WHEN IddleT =>
if startS2 = '1' then
Etat2 <= DepartT;
else
Etat2 <= IddleT;
end if;
WHEN DepartT =>
startS2 <= '0';
Etat2 <= LoadT;
WHEN LoadT =>
enS <= '1';
Etat2 <= ShiftT;
WHEN ShiftT =>
mS <= "01";
Etat2 <= EndT;
WHEN EndT =>
Etat2 <= IddleT;
startS1 <= '1';
WHEN Others =>
end CASE;
end if;
end process;
end Behavioral;
Add RESET to your process sensitivity list.

VHDL filtering data

I am new to VHDL. I need to write a module to do filtering of data. My module structure is:
a_rst - async reset
clk - clock
s_rst - sync reset
valid_in - 0 - no data, 1 - where is data
data_in - [7 downto 0]
Out signals:
valid_out - 0 - no data, 1 - where is data
data_out - [7 downto 0]
I write testbeanch which puts to data_in of my module: 00,01,02,03,0A,02,00,01,02,0F.
But my module returns: 00,01,AA,03,0A,02,00,01,AA,0F
insted of: 00,01,AA,03,0A,02,00,01,02,0F.
I tried to do this:
--libraries
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--entity
entity ex6_v03 is
port
(
a_rst : in std_logic;
clk : in std_logic; -- 200 MHz
s_rst : in std_logic;
valid_in : in std_logic;
data_in : in std_logic_vector (7 downto 0);
valid_out : out std_logic;
data_out : out std_logic_vector (7 downto 0)
);
end entity ex6_v03;
architecture behavior of ex6_v03 is
signal st : integer := 0;
begin
process(a_rst, clk)
begin
-- asynchronous reset
if (a_rst = '1') then
data_out <= x"00";
valid_out <= '0';
-- synchronous reset
elsif rising_edge(clk) then -- clk
if (s_rst = '1') then
valid_out <= '0';
data_out <= x"00";
else
-- normal activity
if(valid_in = '1') then
-- main logic
if(data_in = x"00") then
st <= 1;
valid_out <= '1';
data_out <= data_in;
elsif(st = 1 and data_in = x"01") then
st <= 2;
valid_out <= '1';
data_out <= data_in;
elsif(st = 2 and data_in = x"02") then
st <= 3;
valid_out <= '1';
data_out <= x"AA";
elsif(st = 3 and data_in = x"03") then
valid_out <= '1';
data_out <= data_in;
st <= 0;
else
st <= 0;
valid_out <= '1';
data_out <= data_in;
end if;
-- end main logic
else
valid_out <= '0';
data_out <= x"00";
end if;
end if;
end if;
end process;
end architecture behavior;
But my module do not wait for 0x03 and instantly sends 0xAA. How to fix this?
You need to add a 1 clock cycle buffer so you know if the next input is 03 before you choose whether to send 02 or AA. Of course, this means the output wont appear until 2 cycles after the input instead of only one. See revised code:
--libraries
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--entity
entity ex6_v03 is
port
(
a_rst : in std_logic;
clk : in std_logic; -- 200 MHz
s_rst : in std_logic;
valid_in : in std_logic;
data_in : in std_logic_vector (7 downto 0);
valid_out : out std_logic;
data_out : out std_logic_vector (7 downto 0)
);
end entity ex6_v03;
architecture behavior of ex6_v03 is
signal st : integer := 0;
signal bvalid : std_logic := '0'; --is buffer valid?
signal data_buffer : std_logic_vector (7 downto 0); --data from previous cycle
begin
process(a_rst, clk)
begin
if (a_rst = '1') then -- asynchronous reset
data_out <= x"00";
valid_out <= '0';
bvalid <= '0';
elsif rising_edge(clk) then -- clk
if (s_rst = '1') then --sync reset
valid_out <= '0';
bvalid <= '0';
data_out <= x"00";
else -- normal activity
if(valid_in = '1') then --fill buffer
if(data_in = x"00") then
st <= 1;
data_out <= data_in;
elsif(st = 1 and data_in = x"01") then
st <= 2;
data_out <= data_in;
elsif(st = 2 and data_in = x"02") then
st <= 3;
else
st <= 0;
end if;
data_buffer <= data_in;
bvalid <= '1';
else
bvalid <= '0';
end if;
if(bvalid = '1') then --use buffer to populate output
valid_out <= '1'
if(st = 3 and data_in = x"03" and valid_in = '1') then --EDIT: make sure the x"03" sitting on the input is actually valid
data_out <= x"AA"; --output for the previous cycle (buffer contains x"02")
else
data_out <= data_buffer;
end if
else
valid_out <= '0';
data_out <= x"00";
end if;
end if;
end if;
end process;
end architecture behavior;

Resources