Per sperimentare con le macchine a stati ho scritto un semplice modulo tx uart ma ho notato che con l'editor visuale di Quartus non è possibile utilizzare dei vettori per gli input, confermate?
Ecco il codice, non ho previsto un segnale di reset ma inizializzo le variabili nella dichiarazione port dell'entity, è una pratica scorretta?
Mi piacerebbe qualche commento che mi "smontasse" il codice che sicuramente è migliorabile.
Il funzionamento è questo: quando voglio trasmettere dei dati preparo un bit in tx_data ed imposto tx_start ad high per iniziare la trasmissione bit dopo bit aggiungendo il segnale di start e due di stop finali. Il segnale tx_busy può essere collegato ad un led e mi avverte che la trasmissione è in corso.
Ho utilizzato una semplice macchina a stati scritta a mano in quanto ho trovato la limitazione sopra descritta utilizzando l'editor visuale, si potrebbe fare anche a meno di una macchina a stati?
Ecco il codice
- Code: Select all
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity uart_tx is
Port( clock : in STD_LOGIC; -- Baudrate clock
tx_start : in STD_LOGIC := '0';
tx_data : in STD_LOGIC_vector(7 downto 0) := B"01001100";
tx_out : out STD_LOGIC;
tx_busy : out STD_LOGIC := '0'
);
end uart_tx;
architecture uart_tx_bhv of uart_tx is
TYPE type_fstate IS (TxStart,BitStart,Bit0,Bit2,Bit1,Bit3,Bit4,Bit5,Bit6,Bit7,BitStop1,BitStop2);
SIGNAL fstate : type_fstate := TxStart; -- Stato corrente
SIGNAL reg_fstate : type_fstate := TxStart; -- Stato futuro
begin
-- Ad ogni fronte di clock aggiorna lo stato
PROCESS (clock,reg_fstate)
BEGIN
IF (clock='1' AND clock'event) THEN
fstate <= reg_fstate;
END IF;
END PROCESS;
-- Ad ogni fronte di clock
PROCESS (clock, fstate)
BEGIN
IF (clock='1' AND clock'event) THEN
CASE fstate IS
-- Se tx_start='1' e lo stato è idle
-- (TxStart) inizia a spedire i dati sequenzialmente
WHEN TxStart =>
IF (tx_start='1') THEN
reg_fstate <= BitStart;
END IF;
tx_out <= '1'; -- Line idle
tx_busy <= '0';
WHEN BitStart =>
tx_out <= '1';
tx_busy <= '1';
reg_fstate <= Bit0;
WHEN Bit0 =>
tx_out <= tx_data(0);
reg_fstate <= Bit1;
WHEN Bit1 =>
tx_out <= tx_data(1);
reg_fstate <= Bit2;
WHEN Bit2 =>
tx_out <= tx_data(2);
reg_fstate <= Bit3;
WHEN Bit3 =>
tx_out <= tx_data(3);
reg_fstate <= Bit4;
WHEN Bit4 =>
tx_out <= tx_data(4);
reg_fstate <= Bit5;
WHEN Bit5 =>
tx_out <= tx_data(5);
reg_fstate <= Bit6;
WHEN Bit6 =>
tx_out <= tx_data(6);
reg_fstate <= Bit7;
WHEN Bit7 =>
tx_out <= tx_data(7);
reg_fstate <= BitStop1;
WHEN BitStop1 =>
tx_out <= '1';
reg_fstate <= BitStop2;
WHEN BitStop2 =>
tx_out <= '1';
reg_fstate <= TxStart;
WHEN OTHERS =>
reg_fstate <= TxStart;
END CASE;
END IF;
END PROCESS;
end uart_tx_bhv;
Ciao