-----------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------
|
-- uart parser module
|
-- uart parser module
|
--
|
--
|
-----------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------
|
library IEEE;
|
library ieee;
|
use IEEE.STD_LOGIC_1164.ALL;
|
use ieee.std_logic_1164.ALL;
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
use ieee.std_logic_unsigned.ALL;
|
|
|
entity uartParser is
|
entity uartParser is
|
generic ( -- parameters
|
generic ( -- parameters
|
AW : integer := 8);
|
AW : integer := 8);
|
port ( -- global signals
|
port ( -- global signals
|
clr : in std_logic; -- global reset input
|
clr : in std_logic; -- global reset input
|
clk : in std_logic; -- global clock input
|
clk : in std_logic; -- global clock input
|
-- transmit and receive internal interface signals from uart interface
|
-- transmit and receive internal interface signals from uart interface
|
txBusy : in std_logic; -- signs that transmitter is busy
|
txBusy : in std_logic; -- signs that transmitter is busy
|
rxData : in std_logic_vector(7 downto 0); -- data byte received
|
rxData : in std_logic_vector(7 downto 0); -- data byte received
|
newRxData : in std_logic; -- signs that a new byte was received
|
newRxData : in std_logic; -- signs that a new byte was received
|
txData : out std_logic_vector(7 downto 0); -- data byte to transmit
|
txData : out std_logic_vector(7 downto 0); -- data byte to transmit
|
newTxData : out std_logic; -- asserted to indicate that there is a new data byte for transmission
|
newTxData : out std_logic; -- asserted to indicate that there is a new data byte for transmission
|
-- internal bus to register file
|
-- internal bus to register file
|
|
intReq : out std_logic; --
|
|
intGnt : in std_logic; --
|
intRdData : in std_logic_vector(7 downto 0); -- data read from register file
|
intRdData : in std_logic_vector(7 downto 0); -- data read from register file
|
intAddress : out std_logic_vector(AW - 1 downto 0); -- address bus to register file
|
intAddress : out std_logic_vector(AW - 1 downto 0); -- address bus to register file
|
intWrData : out std_logic_vector(7 downto 0); -- write data to register file
|
intWrData : out std_logic_vector(7 downto 0); -- write data to register file
|
intWrite : out std_logic; -- write control to register file
|
intWrite : out std_logic; -- write control to register file
|
intRead : out std_logic); -- read control to register file
|
intRead : out std_logic); -- read control to register file
|
end uartParser;
|
end uartParser;
|
|
|
architecture Behavioral of uartParser is
|
architecture Behavioral of uartParser is
|
|
|
-- internal constants
|
-- internal constants
|
-- main (receive) state machine states
|
-- main (receive) state machine states
|
signal mainSm : std_logic_vector(3 downto 0); -- main state machine
|
signal mainSm : std_logic_vector(3 downto 0); -- main state machine
|
constant mainIdle : std_logic_vector(mainSm'range) := "0000";
|
constant mainIdle : std_logic_vector(mainSm'range) := "0000";
|
constant mainWhite1 : std_logic_vector(mainSm'range) := "0001";
|
constant mainWhite1 : std_logic_vector(mainSm'range) := "0001";
|
constant mainData : std_logic_vector(mainSm'range) := "0010";
|
constant mainData : std_logic_vector(mainSm'range) := "0010";
|
constant mainWhite2 : std_logic_vector(mainSm'range) := "0011";
|
constant mainWhite2 : std_logic_vector(mainSm'range) := "0011";
|
constant mainAddr : std_logic_vector(mainSm'range) := "0100";
|
constant mainAddr : std_logic_vector(mainSm'range) := "0100";
|
constant mainEol : std_logic_vector(mainSm'range) := "0101";
|
constant mainEol : std_logic_vector(mainSm'range) := "0101";
|
-- binary mode extension states
|
-- binary mode extension states
|
constant mainBinCmd : std_logic_vector(mainSm'range) := "1000";
|
constant mainBinCmd : std_logic_vector(mainSm'range) := "1000";
|
constant mainBinAdrh : std_logic_vector(mainSm'range) := "1001";
|
constant mainBinAdrh : std_logic_vector(mainSm'range) := "1001";
|
constant mainBinAdrl : std_logic_vector(mainSm'range) := "1010";
|
constant mainBinAdrl : std_logic_vector(mainSm'range) := "1010";
|
constant mainBinLen : std_logic_vector(mainSm'range) := "1011";
|
constant mainBinLen : std_logic_vector(mainSm'range) := "1011";
|
constant mainBinData : std_logic_vector(mainSm'range) := "1100";
|
constant mainBinData : std_logic_vector(mainSm'range) := "1100";
|
|
|
-- transmit state machine
|
-- transmit state machine
|
signal txSm : std_logic_vector(2 downto 0); -- transmit state machine
|
signal txSm : std_logic_vector(2 downto 0); -- transmit state machine
|
constant txIdle : std_logic_vector(txSm'range) := "000";
|
constant txIdle : std_logic_vector(txSm'range) := "000";
|
constant txHiNib : std_logic_vector(txSm'range) := "001";
|
constant txHiNib : std_logic_vector(txSm'range) := "001";
|
constant txLoNib : std_logic_vector(txSm'range) := "100";
|
constant txLoNib : std_logic_vector(txSm'range) := "100";
|
constant txCharCR : std_logic_vector(txSm'range) := "101";
|
constant txCharCR : std_logic_vector(txSm'range) := "101";
|
constant txCharLF : std_logic_vector(txSm'range) := "110";
|
constant txCharLF : std_logic_vector(txSm'range) := "110";
|
|
|
-- define characters used by the parser
|
-- define characters used by the parser
|
constant charNul : std_logic_vector(7 downto 0) := x"00";
|
constant charNul : std_logic_vector(7 downto 0) := x"00";
|
constant charTab : std_logic_vector(7 downto 0) := x"09";
|
constant charTab : std_logic_vector(7 downto 0) := x"09";
|
constant charLF : std_logic_vector(7 downto 0) := x"0A";
|
constant charLF : std_logic_vector(7 downto 0) := x"0A";
|
constant charCR : std_logic_vector(7 downto 0) := x"0D";
|
constant charCR : std_logic_vector(7 downto 0) := x"0D";
|
constant charSpace : std_logic_vector(7 downto 0) := x"20";
|
constant charSpace : std_logic_vector(7 downto 0) := x"20";
|
constant charZero : std_logic_vector(7 downto 0) := x"30";
|
constant charZero : std_logic_vector(7 downto 0) := x"30";
|
constant charOne : std_logic_vector(7 downto 0) := x"31";
|
constant charOne : std_logic_vector(7 downto 0) := x"31";
|
constant charTwo : std_logic_vector(7 downto 0) := x"32";
|
constant charTwo : std_logic_vector(7 downto 0) := x"32";
|
constant charThree : std_logic_vector(7 downto 0) := x"33";
|
constant charThree : std_logic_vector(7 downto 0) := x"33";
|
constant charFour : std_logic_vector(7 downto 0) := x"34";
|
constant charFour : std_logic_vector(7 downto 0) := x"34";
|
constant charFive : std_logic_vector(7 downto 0) := x"35";
|
constant charFive : std_logic_vector(7 downto 0) := x"35";
|
constant charSix : std_logic_vector(7 downto 0) := x"36";
|
constant charSix : std_logic_vector(7 downto 0) := x"36";
|
constant charSeven : std_logic_vector(7 downto 0) := x"37";
|
constant charSeven : std_logic_vector(7 downto 0) := x"37";
|
constant charEight : std_logic_vector(7 downto 0) := x"38";
|
constant charEight : std_logic_vector(7 downto 0) := x"38";
|
constant charNine : std_logic_vector(7 downto 0) := x"39";
|
constant charNine : std_logic_vector(7 downto 0) := x"39";
|
constant charAHigh : std_logic_vector(7 downto 0) := x"41";
|
constant charAHigh : std_logic_vector(7 downto 0) := x"41";
|
constant charBHigh : std_logic_vector(7 downto 0) := x"42";
|
constant charBHigh : std_logic_vector(7 downto 0) := x"42";
|
constant charCHigh : std_logic_vector(7 downto 0) := x"43";
|
constant charCHigh : std_logic_vector(7 downto 0) := x"43";
|
constant charDHigh : std_logic_vector(7 downto 0) := x"44";
|
constant charDHigh : std_logic_vector(7 downto 0) := x"44";
|
constant charEHigh : std_logic_vector(7 downto 0) := x"45";
|
constant charEHigh : std_logic_vector(7 downto 0) := x"45";
|
constant charFHigh : std_logic_vector(7 downto 0) := x"46";
|
constant charFHigh : std_logic_vector(7 downto 0) := x"46";
|
constant charRHigh : std_logic_vector(7 downto 0) := x"52";
|
constant charRHigh : std_logic_vector(7 downto 0) := x"52";
|
constant charWHigh : std_logic_vector(7 downto 0) := x"57";
|
constant charWHigh : std_logic_vector(7 downto 0) := x"57";
|
constant charALow : std_logic_vector(7 downto 0) := x"61";
|
constant charALow : std_logic_vector(7 downto 0) := x"61";
|
constant charBLow : std_logic_vector(7 downto 0) := x"62";
|
constant charBLow : std_logic_vector(7 downto 0) := x"62";
|
constant charCLow : std_logic_vector(7 downto 0) := x"63";
|
constant charCLow : std_logic_vector(7 downto 0) := x"63";
|
constant charDLow : std_logic_vector(7 downto 0) := x"64";
|
constant charDLow : std_logic_vector(7 downto 0) := x"64";
|
constant charELow : std_logic_vector(7 downto 0) := x"65";
|
constant charELow : std_logic_vector(7 downto 0) := x"65";
|
constant charFLow : std_logic_vector(7 downto 0) := x"66";
|
constant charFLow : std_logic_vector(7 downto 0) := x"66";
|
constant charRLow : std_logic_vector(7 downto 0) := x"72";
|
constant charRLow : std_logic_vector(7 downto 0) := x"72";
|
constant charWLow : std_logic_vector(7 downto 0) := x"77";
|
constant charWLow : std_logic_vector(7 downto 0) := x"77";
|
|
|
-- binary extension mode commands - the command is indicated by bits 5:4 of the command byte
|
-- binary extension mode commands - the command is indicated by bits 5:4 of the command byte
|
constant binCmdNop : std_logic_vector(1 downto 0) := "00";
|
constant binCmdNop : std_logic_vector(1 downto 0) := "00";
|
constant binCmdRead : std_logic_vector(1 downto 0) := "01";
|
constant binCmdRead : std_logic_vector(1 downto 0) := "01";
|
constant binCmdWrite : std_logic_vector(1 downto 0) := "10";
|
constant binCmdWrite : std_logic_vector(1 downto 0) := "10";
|
|
|
signal dataInHexRange : std_logic; -- indicates that the received data is in the range of hex number
|
signal dataInHexRange : std_logic; -- indicates that the received data is in the range of hex number
|
signal binLastByte : std_logic; -- last byte flag indicates that the current byte in the command is the last
|
signal binLastByte : std_logic; -- last byte flag indicates that the current byte in the command is the last
|
signal txEndP : std_logic; -- transmission end pulse
|
signal txEndP : std_logic; -- transmission end pulse
|
signal readOp : std_logic; -- read operation flag
|
signal readOp : std_logic; -- read operation flag
|
signal writeOp : std_logic; -- write operation flag
|
signal writeOp : std_logic; -- write operation flag
|
signal binReadOp : std_logic; -- binary mode read operation flag
|
signal binReadOp : std_logic; -- binary mode read operation flag
|
signal binWriteOp : std_logic; -- binary mode write operation flag
|
signal binWriteOp : std_logic; -- binary mode write operation flag
|
signal sendStatFlag : std_logic; -- send status flag
|
signal sendStatFlag : std_logic; -- send status flag
|
signal addrAutoInc : std_logic; -- address auto increment mode
|
signal addrAutoInc : std_logic; -- address auto increment mode
|
signal dataParam : std_logic_vector(7 downto 0); -- operation data parameter
|
signal dataParam : std_logic_vector(7 downto 0); -- operation data parameter
|
signal dataNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
signal dataNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
signal addrParam : std_logic_vector(15 downto 0); -- operation address parameter
|
signal addrParam : std_logic_vector(15 downto 0); -- operation address parameter
|
signal addrNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
signal addrNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
signal binByteCount : std_logic_vector(7 downto 0); -- binary mode byte counter
|
signal binByteCount : std_logic_vector(7 downto 0); -- binary mode byte counter
|
signal iIntAddress : std_logic_vector(intAddress'range); --
|
signal iIntAddress : std_logic_vector(intAddress'range); --
|
|
signal iWriteReq : std_logic; --
|
signal iIntWrite : std_logic; --
|
signal iIntWrite : std_logic; --
|
signal readDone : std_logic; -- internally generated read done flag
|
signal readDone : std_logic; -- internally generated read done flag
|
signal readDoneS : std_logic; -- sampled read done
|
signal readDoneS : std_logic; -- sampled read done
|
signal readDataS : std_logic_vector(7 downto 0); -- sampled read data
|
signal readDataS : std_logic_vector(7 downto 0); -- sampled read data
|
|
signal iReadReq : std_logic; --
|
signal iIntRead : std_logic; --
|
signal iIntRead : std_logic; --
|
signal txChar : std_logic_vector(7 downto 0); -- transmit byte from nibble to character conversion
|
signal txChar : std_logic_vector(7 downto 0); -- transmit byte from nibble to character conversion
|
signal sTxBusy : std_logic; -- sampled tx_busy for falling edge detection
|
signal sTxBusy : std_logic; -- sampled tx_busy for falling edge detection
|
signal txNibble : std_logic_vector(3 downto 0); -- nibble value for transmission
|
signal txNibble : std_logic_vector(3 downto 0); -- nibble value for transmission
|
|
|
-- module implementation
|
-- module implementation
|
-- main state machine
|
-- main state machine
|
begin
|
begin
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if (newRxData = '1') then
|
if (newRxData = '1') then
|
case mainSm is
|
case mainSm is
|
-- wait for a read ('r') or write ('w') command
|
-- wait for a read ('r') or write ('w') command
|
-- binary extension - an all zeros byte enabled binary commands
|
-- binary extension - an all zeros byte enabled binary commands
|
when mainIdle =>
|
when mainIdle =>
|
-- check received character
|
-- check received character
|
if (rxData = charNul) then
|
if (rxData = charNul) then
|
-- an all zeros received byte enters binary mode
|
-- an all zeros received byte enters binary mode
|
mainSm <= mainBinCmd;
|
mainSm <= mainBinCmd;
|
elsif ((rxData = charRLow) or (rxData = charRHigh)) then
|
elsif ((rxData = charRLow) or (rxData = charRHigh)) then
|
-- on read wait to receive only address field
|
-- on read wait to receive only address field
|
mainSm <= mainWhite2;
|
mainSm <= mainWhite2;
|
elsif ((rxData = charWLow) or (rxData = charWHigh)) then
|
elsif ((rxData = charWLow) or (rxData = charWHigh)) then
|
-- on write wait to receive data and address
|
-- on write wait to receive data and address
|
mainSm <= mainWhite1;
|
mainSm <= mainWhite1;
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
-- on new line sta in idle
|
-- on new line sta in idle
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
-- any other character wait to end of line (EOL)
|
-- any other character wait to end of line (EOL)
|
mainSm <= mainEol;
|
mainSm <= mainEol;
|
end if;
|
end if;
|
-- wait for white spaces till first data nibble
|
-- wait for white spaces till first data nibble
|
when mainWhite1 =>
|
when mainWhite1 =>
|
-- wait in this case until any white space character is received. in any
|
-- wait in this case until any white space character is received. in any
|
-- valid character for data value switch to data state. a new line or carriage
|
-- valid character for data value switch to data state. a new line or carriage
|
-- return should reset the state machine to idle.
|
-- return should reset the state machine to idle.
|
-- any other character transitions the state machine to wait for EOL.
|
-- any other character transitions the state machine to wait for EOL.
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
mainSm <= mainWhite1;
|
mainSm <= mainWhite1;
|
elsif (dataInHexRange = '1') then
|
elsif (dataInHexRange = '1') then
|
mainSm <= mainData;
|
mainSm <= mainData;
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
mainSm <= mainEol;
|
mainSm <= mainEol;
|
end if;
|
end if;
|
-- receive data field
|
-- receive data field
|
when mainData =>
|
when mainData =>
|
-- wait while data in hex range. white space transition to wait white 2 state.
|
-- wait while data in hex range. white space transition to wait white 2 state.
|
-- CR and LF resets the state machine. any other value cause state machine to
|
-- CR and LF resets the state machine. any other value cause state machine to
|
-- wait til end of line.
|
-- wait til end of line.
|
if (dataInHexRange = '1') then
|
if (dataInHexRange = '1') then
|
mainSm <= mainData;
|
mainSm <= mainData;
|
elsif ((rxData = charSpace) or (rxData = charTab)) then
|
elsif ((rxData = charSpace) or (rxData = charTab)) then
|
mainSm <= mainWhite2;
|
mainSm <= mainWhite2;
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
mainSm <= mainEol;
|
mainSm <= mainEol;
|
end if;
|
end if;
|
-- wait for white spaces till first address nibble
|
-- wait for white spaces till first address nibble
|
when mainWhite2 =>
|
when mainWhite2 =>
|
-- similar to MAIN_WHITE1
|
-- similar to MAIN_WHITE1
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
mainSm <= mainWhite2;
|
mainSm <= mainWhite2;
|
elsif (dataInHexRange = '1') then
|
elsif (dataInHexRange = '1') then
|
mainSm <= mainAddr;
|
mainSm <= mainAddr;
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
mainSm <= mainEol;
|
mainSm <= mainEol;
|
end if;
|
end if;
|
-- receive address field
|
-- receive address field
|
when mainAddr =>
|
when mainAddr =>
|
-- similar to MAIN_DATA
|
-- similar to MAIN_DATA
|
if (dataInHexRange = '1') then
|
if (dataInHexRange = '1') then
|
mainSm <= mainAddr;
|
mainSm <= mainAddr;
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
mainSm <= mainEol;
|
mainSm <= mainEol;
|
end if;
|
end if;
|
-- wait to EOL
|
-- wait to EOL
|
when mainEol =>
|
when mainEol =>
|
-- wait for CR or LF to move back to idle
|
-- wait for CR or LF to move back to idle
|
if ((rxData = charCR) or (rxData = charLF)) then
|
if ((rxData = charCR) or (rxData = charLF)) then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
end if;
|
end if;
|
-- binary extension
|
-- binary extension
|
-- wait for command - one byte
|
-- wait for command - one byte
|
when mainBinCmd =>
|
when mainBinCmd =>
|
-- check if command is a NOP command
|
-- check if command is a NOP command
|
if (rxData(5 downto 4) = binCmdNop) then
|
if (rxData(5 downto 4) = binCmdNop) then
|
-- if NOP command then switch back to idle state
|
-- if NOP command then switch back to idle state
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
else
|
else
|
-- not a NOP command, continue receiving parameters
|
-- not a NOP command, continue receiving parameters
|
mainSm <= mainBinAdrh;
|
mainSm <= mainBinAdrh;
|
end if;
|
end if;
|
-- wait for address parameter - two bytes
|
-- wait for address parameter - two bytes
|
-- high address byte
|
-- high address byte
|
when mainBinAdrh =>
|
when mainBinAdrh =>
|
-- switch to next state
|
-- switch to next state
|
mainSm <= mainBinAdrl;
|
mainSm <= mainBinAdrl;
|
-- low address byte
|
-- low address byte
|
when mainBinAdrl =>
|
when mainBinAdrl =>
|
-- switch to next state
|
-- switch to next state
|
mainSm <= mainBinLen;
|
mainSm <= mainBinLen;
|
-- wait for length parameter - one byte
|
-- wait for length parameter - one byte
|
when mainBinLen =>
|
when mainBinLen =>
|
-- check if write command else command reception ended
|
-- check if write command else command reception ended
|
if (binWriteOp = '1') then
|
if (binWriteOp = '1') then
|
-- wait for write data
|
-- wait for write data
|
mainSm <= mainBinData;
|
mainSm <= mainBinData;
|
else
|
else
|
-- command reception has ended
|
-- command reception has ended
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
end if;
|
end if;
|
-- on write commands wait for data till end of buffer as specified by length parameter
|
-- on write commands wait for data till end of buffer as specified by length parameter
|
when mainBinData =>
|
when mainBinData =>
|
-- if this is the last data byte then return to idle
|
-- if this is the last data byte then return to idle
|
if (binLastByte = '1') then
|
if (binLastByte = '1') then
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
end if;
|
end if;
|
-- go to idle
|
-- go to idle
|
when others =>
|
when others =>
|
mainSm <= mainIdle;
|
mainSm <= mainIdle;
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- read operation flag
|
-- read operation flag
|
-- write operation flag
|
-- write operation flag
|
-- binary mode read operation flag
|
-- binary mode read operation flag
|
-- binary mode write operation flag
|
-- binary mode write operation flag
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
readOp <= '0';
|
readOp <= '0';
|
writeOp <= '0';
|
writeOp <= '0';
|
binReadOp <= '0';
|
binReadOp <= '0';
|
binWriteOp <= '0';
|
binWriteOp <= '0';
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainIdle) and (newRxData = '1')) then
|
if ((mainSm = mainIdle) and (newRxData = '1')) then
|
-- the read operation flag is set when a read command is received in idle state and cleared
|
-- the read operation flag is set when a read command is received in idle state and cleared
|
-- if any other character is received during that state.
|
-- if any other character is received during that state.
|
if ((rxData = charRLow) or (rxData = charRHigh)) then
|
if ((rxData = charRLow) or (rxData = charRHigh)) then
|
readOp <= '1';
|
readOp <= '1';
|
else
|
else
|
readOp <= '0';
|
readOp <= '0';
|
end if;
|
end if;
|
-- the write operation flag is set when a write command is received in idle state and cleared
|
-- the write operation flag is set when a write command is received in idle state and cleared
|
-- if any other character is received during that state.
|
-- if any other character is received during that state.
|
if ((rxData = charWLow) or (rxData = charWHigh)) then
|
if ((rxData = charWLow) or (rxData = charWHigh)) then
|
writeOp <= '1';
|
writeOp <= '1';
|
else
|
else
|
writeOp <= '0';
|
writeOp <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdRead)) then
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdRead)) then
|
-- read command is started on reception of a read command
|
-- read command is started on reception of a read command
|
binReadOp <= '1';
|
binReadOp <= '1';
|
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) then
|
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) then
|
-- read command ends on transmission of the last byte read
|
-- read command ends on transmission of the last byte read
|
binReadOp <= '0';
|
binReadOp <= '0';
|
end if;
|
end if;
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdWrite)) then
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdWrite)) then
|
-- write command is started on reception of a write command
|
-- write command is started on reception of a write command
|
binWriteOp <= '1';
|
binWriteOp <= '1';
|
elsif ((mainSm = mainBinData) and (newRxData = '1') and (binLastByte = '1')) then
|
elsif ((mainSm = mainBinData) and (newRxData = '1') and (binLastByte = '1')) then
|
binWriteOp <= '0';
|
binWriteOp <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- send status flag - used only in binary extension mode
|
-- send status flag - used only in binary extension mode
|
-- address auto increment - used only in binary extension mode
|
-- address auto increment - used only in binary extension mode
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
sendStatFlag <= '0';
|
sendStatFlag <= '0';
|
addrAutoInc <= '0';
|
addrAutoInc <= '0';
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainBinCmd) and (newRxData = '1')) then
|
if ((mainSm = mainBinCmd) and (newRxData = '1')) then
|
-- check if a status byte should be sent at the end of the command
|
-- check if a status byte should be sent at the end of the command
|
sendStatFlag <= rxData(0);
|
sendStatFlag <= rxData(0);
|
-- check if address should be automatically incremented or not.
|
-- check if address should be automatically incremented or not.
|
-- Note that when rx_data[1] is set, address auto increment is disabled.
|
-- Note that when rx_data[1] is set, address auto increment is disabled.
|
addrAutoInc <= not(rxData(1));
|
addrAutoInc <= not(rxData(1));
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- operation data parameter
|
-- operation data parameter
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
dataParam <= (others => '0');
|
dataParam <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainWhite1) and (newRxData = '1') and (dataInHexRange = '1')) then
|
if ((mainSm = mainWhite1) and (newRxData = '1') and (dataInHexRange = '1')) then
|
dataParam <= "0000" & dataNibble;
|
dataParam <= "0000" & dataNibble;
|
elsif ((mainSm = mainData) and (newRxData = '1') and (dataInHexRange = '1')) then
|
elsif ((mainSm = mainData) and (newRxData = '1') and (dataInHexRange = '1')) then
|
dataParam <= dataParam(3 downto 0) & dataNibble;
|
dataParam <= dataParam(3 downto 0) & dataNibble;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- operation address parameter
|
-- operation address parameter
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
addrParam <= (others => '0');
|
addrParam <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainWhite2) and (newRxData = '1') and (dataInHexRange = '1')) then
|
if ((mainSm = mainWhite2) and (newRxData = '1') and (dataInHexRange = '1')) then
|
addrParam <= x"000" & dataNibble;
|
addrParam <= x"000" & dataNibble;
|
elsif ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '1')) then
|
elsif ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '1')) then
|
addrParam <= addrParam(11 downto 0) & dataNibble;
|
addrParam <= addrParam(11 downto 0) & dataNibble;
|
-- binary extension
|
-- binary extension
|
elsif (mainSm = mainBinAdrh) then
|
elsif (mainSm = mainBinAdrh) then
|
addrParam(15 downto 8) <= rxData;
|
addrParam(15 downto 8) <= rxData;
|
elsif (mainSm = mainBinAdrl) then
|
elsif (mainSm = mainBinAdrl) then
|
addrParam(7 downto 0) <= rxData;
|
addrParam(7 downto 0) <= rxData;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- binary mode command byte counter is loaded with the length parameter and counts down to zero.
|
-- binary mode command byte counter is loaded with the length parameter and counts down to zero.
|
-- NOTE: a value of zero for the length parameter indicates a command of 256 bytes.
|
-- NOTE: a value of zero for the length parameter indicates a command of 256 bytes.
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
binByteCount <= (others => '0');
|
binByteCount <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainBinLen) and (newRxData = '1')) then
|
if ((mainSm = mainBinLen) and (newRxData = '1')) then
|
binByteCount <= rxData;
|
binByteCount <= rxData;
|
elsif (((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) or ((binReadOp = '1') and (txEndP = '1'))) then
|
elsif (((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) or ((binReadOp = '1') and (txEndP = '1'))) then
|
-- byte counter is updated on every new data received in write operations and for every
|
-- byte counter is updated on every new data received in write operations and for every
|
-- byte transmitted for read operations.
|
-- byte transmitted for read operations.
|
binByteCount <= binByteCount - 1;
|
binByteCount <= binByteCount - 1;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- internal write control and data
|
-- internal write control and data
|
-- internal read control
|
-- internal read control
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
|
iReadReq <= '0';
|
iIntRead <= '0';
|
iIntRead <= '0';
|
|
iWriteReq <= '0';
|
iIntWrite <= '0';
|
iIntWrite <= '0';
|
intWrData <= (others => '0');
|
intWrData <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainAddr) and (writeOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
if ((mainSm = mainAddr) and (writeOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
iIntWrite <= '1';
|
iWriteReq <= '1';
|
intWrData <= dataParam;
|
intWrData <= dataParam;
|
-- binary extension mode
|
-- binary extension mode
|
elsif ((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) then
|
elsif ((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) then
|
iIntWrite <= '1';
|
iWriteReq <= '1';
|
intWrData <= rxData;
|
intWrData <= rxData;
|
|
elsif ((intGnt = '1') and (iWriteReq = '1')) then
|
|
iWriteReq <= '0';
|
|
iIntWrite <= '1';
|
else
|
else
|
iIntWrite <= '0';
|
iIntWrite <= '0';
|
end if;
|
end if;
|
if ((mainSm = mainAddr) and (readOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
if ((mainSm = mainAddr) and (readOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
iIntRead <= '1';
|
iReadReq <= '1';
|
-- binary extension
|
-- binary extension
|
elsif ((mainSm = mainBinLen) and (binReadOp = '1') and (newRxData = '1')) then
|
elsif ((mainSm = mainBinLen) and (binReadOp = '1') and (newRxData = '1')) then
|
-- the first read request is issued on reception of the length byte
|
-- the first read request is issued on reception of the length byte
|
iIntRead <= '1';
|
iReadReq <= '1';
|
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) then
|
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) then
|
-- the next read requests are issued after the previous read value was transmitted and
|
-- the next read requests are issued after the previous read value was transmitted and
|
-- this is not the last byte to be read.
|
-- this is not the last byte to be read.
|
|
iReadReq <= '1';
|
|
elsif ((intGnt = '1') and (iReadReq = '1')) then
|
|
iReadReq <= '0';
|
iIntRead <= '1';
|
iIntRead <= '1';
|
else
|
else
|
iIntRead <= '0';
|
iIntRead <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- internal address
|
-- internal address
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
iIntAddress <= (others => '0');
|
iIntAddress <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
if ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '0')) then
|
if ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '0')) then
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
-- binary extension
|
-- binary extension
|
elsif ((mainSm = mainBinLen) and (newRxData = '1')) then
|
elsif ((mainSm = mainBinLen) and (newRxData = '1')) then
|
-- sample address parameter on reception of length byte
|
-- sample address parameter on reception of length byte
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
elsif ((addrAutoInc = '1') and (((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) or ((binWriteOp = '1') and (iIntWrite = '1')))) then
|
elsif ((addrAutoInc = '1') and (((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) or ((binWriteOp = '1') and (iIntWrite = '1')))) then
|
-- address is incremented on every read or write if enabled
|
-- address is incremented on every read or write if enabled
|
iIntAddress <= iIntAddress + 1;
|
iIntAddress <= iIntAddress + 1;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- read done flag and sampled data read
|
-- read done flag and sampled data read
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
readDone <= '0';
|
readDone <= '0';
|
readDoneS <= '0';
|
readDoneS <= '0';
|
readDataS <= (others => '0');
|
readDataS <= (others => '0');
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
-- read done flag
|
-- read done flag
|
readDone <= iIntRead;
|
readDone <= iIntRead;
|
-- sampled read done
|
-- sampled read done
|
readDoneS <= readDone;
|
readDoneS <= readDone;
|
-- sampled data read
|
-- sampled data read
|
if (readDone = '1') then
|
if (readDone = '1') then
|
readDataS <= intRdData;
|
readDataS <= intRdData;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- transmit state machine and control
|
-- transmit state machine and control
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
txSm <= txIdle;
|
txSm <= txIdle;
|
txData <= (others => '0');
|
txData <= (others => '0');
|
newTxData <= '0';
|
newTxData <= '0';
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
case txSm is
|
case txSm is
|
-- wait for read done indication
|
-- wait for read done indication
|
when txIdle =>
|
when txIdle =>
|
-- on end of every read operation check how the data read should be transmitted
|
-- on end of every read operation check how the data read should be transmitted
|
-- according to read type: ascii or binary.
|
-- according to read type: ascii or binary.
|
if (readDoneS = '1') then
|
if (readDoneS = '1') then
|
-- on binary mode read transmit byte value
|
-- on binary mode read transmit byte value
|
if (binReadOp = '1') then
|
if (binReadOp = '1') then
|
-- note that there is no need to change state
|
-- note that there is no need to change state
|
txData <= readDataS;
|
txData <= readDataS;
|
newTxData <= '1';
|
newTxData <= '1';
|
else
|
else
|
txSm <= txHiNib;
|
txSm <= txHiNib;
|
txData <= txChar;
|
txData <= txChar;
|
newTxData <= '1';
|
newTxData <= '1';
|
end if;
|
end if;
|
-- check if status byte should be transmitted
|
-- check if status byte should be transmitted
|
elsif (((sendStatFlag = '1') and (binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) or ((sendStatFlag = '1') and (binWriteOp = '1') and (newRxData = '1') and (binLastByte = '1')) or ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdNop))) then
|
elsif (((sendStatFlag = '1') and (binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) or ((sendStatFlag = '1') and (binWriteOp = '1') and (newRxData = '1') and (binLastByte = '1')) or ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdNop))) then
|
-- send status byte - currently a constant
|
-- send status byte - currently a constant
|
txData <= x"5A";
|
txData <= x"5A";
|
newTxData <= '1';
|
newTxData <= '1';
|
else
|
else
|
newTxData <= '0';
|
newTxData <= '0';
|
end if;
|
end if;
|
when txHiNib =>
|
when txHiNib =>
|
-- wait for transmit to end
|
-- wait for transmit to end
|
if (txEndP = '1') then
|
if (txEndP = '1') then
|
txSm <= txLoNib;
|
txSm <= txLoNib;
|
txData <= txChar;
|
txData <= txChar;
|
newTxData <= '1';
|
newTxData <= '1';
|
else
|
else
|
newTxData <= '0';
|
newTxData <= '0';
|
end if;
|
end if;
|
-- wait for transmit to end
|
-- wait for transmit to end
|
when txLoNib =>
|
when txLoNib =>
|
if (txEndP = '1') then
|
if (txEndP = '1') then
|
txSm <= txCharCR;
|
txSm <= txCharCR;
|
txData <= charCR;
|
txData <= charCR;
|
newTxData <= '1';
|
newTxData <= '1';
|
else
|
else
|
newTxData <= '0';
|
newTxData <= '0';
|
end if;
|
end if;
|
-- wait for transmit to end
|
-- wait for transmit to end
|
when txCharCR =>
|
when txCharCR =>
|
if (txEndP = '1') then
|
if (txEndP = '1') then
|
txSm <= txCharLF;
|
txSm <= txCharLF;
|
txData <= charLF;
|
txData <= charLF;
|
newTxData <= '1';
|
newTxData <= '1';
|
else
|
else
|
newTxData <= '0';
|
newTxData <= '0';
|
end if;
|
end if;
|
-- wait for transmit to end
|
-- wait for transmit to end
|
when txCharLF =>
|
when txCharLF =>
|
if (txEndP = '1') then
|
if (txEndP = '1') then
|
txSm <= txIdle;
|
txSm <= txIdle;
|
end if;
|
end if;
|
-- clear tx new data flag
|
-- clear tx new data flag
|
newTxData <= '0';
|
newTxData <= '0';
|
-- return to idle
|
-- return to idle
|
when others =>
|
when others =>
|
txSm <= txIdle;
|
txSm <= txIdle;
|
end case;
|
end case;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- sampled tx_busy
|
-- sampled tx_busy
|
process (clr, clk)
|
process (clr, clk)
|
begin
|
begin
|
if (clr = '1') then
|
if (clr = '1') then
|
sTxBusy <= '1';
|
sTxBusy <= '1';
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(clk)) then
|
sTxBusy <= txBusy;
|
sTxBusy <= txBusy;
|
end if;
|
end if;
|
end process;
|
end process;
|
-- indicates that the received data is in the range of hex number
|
-- indicates that the received data is in the range of hex number
|
dataInHexRange <= '1' when (((rxData >= charZero) and (rxData <= charNine)) or
|
dataInHexRange <= '1' when (((rxData >= charZero) and (rxData <= charNine)) or
|
((rxData >= charAHigh) and (rxData <= charFHigh)) or
|
((rxData >= charAHigh) and (rxData <= charFHigh)) or
|
((rxData >= charALow) and (rxData <= charFLow))) else '0';
|
((rxData >= charALow) and (rxData <= charFLow))) else '0';
|
-- last byte in command flag
|
-- last byte in command flag
|
binLastByte <= '1' when (binByteCount = x"01") else '0';
|
binLastByte <= '1' when (binByteCount = x"01") else '0';
|
-- select the nibble to the nibble to character conversion
|
-- select the nibble to the nibble to character conversion
|
txNibble <= readDataS(3 downto 0) when (txSm = txHiNib) else readDataS(7 downto 4);
|
txNibble <= readDataS(3 downto 0) when (txSm = txHiNib) else readDataS(7 downto 4);
|
-- tx end pulse
|
-- tx end pulse
|
txEndP <= '1' when ((txBusy = '0') and (sTxBusy = '1')) else '0';
|
txEndP <= '1' when ((txBusy = '0') and (sTxBusy = '1')) else '0';
|
-- character to nibble conversion
|
-- character to nibble conversion
|
with rxData select
|
with rxData select
|
dataNibble <= x"0" when charZero,
|
dataNibble <= x"0" when charZero,
|
x"1" when charOne,
|
x"1" when charOne,
|
x"2" when charTwo,
|
x"2" when charTwo,
|
x"3" when charThree,
|
x"3" when charThree,
|
x"4" when charFour,
|
x"4" when charFour,
|
x"5" when charFive,
|
x"5" when charFive,
|
x"6" when charSix,
|
x"6" when charSix,
|
x"7" when charSeven,
|
x"7" when charSeven,
|
x"8" when charEight,
|
x"8" when charEight,
|
x"9" when charNine,
|
x"9" when charNine,
|
x"A" when charALow,
|
x"A" when charALow,
|
x"A" when charAHigh,
|
x"A" when charAHigh,
|
x"B" when charBLow,
|
x"B" when charBLow,
|
x"B" when charBHigh,
|
x"B" when charBHigh,
|
x"C" when charCLow,
|
x"C" when charCLow,
|
x"C" when charCHigh,
|
x"C" when charCHigh,
|
x"D" when charDLow,
|
x"D" when charDLow,
|
x"D" when charDHigh,
|
x"D" when charDHigh,
|
x"E" when charELow,
|
x"E" when charELow,
|
x"E" when charEHigh,
|
x"E" when charEHigh,
|
x"F" when charFLow,
|
x"F" when charFLow,
|
x"F" when charFHigh,
|
x"F" when charFHigh,
|
x"F" when others;
|
x"F" when others;
|
-- nibble to character conversion
|
-- nibble to character conversion
|
with txNibble select
|
with txNibble select
|
txChar <= charZero when x"0",
|
txChar <= charZero when x"0",
|
charOne when x"1",
|
charOne when x"1",
|
charTwo when x"2",
|
charTwo when x"2",
|
charThree when x"3",
|
charThree when x"3",
|
charFour when x"4",
|
charFour when x"4",
|
charFive when x"5",
|
charFive when x"5",
|
charSix when x"6",
|
charSix when x"6",
|
charSeven when x"7",
|
charSeven when x"7",
|
charEight when x"8",
|
charEight when x"8",
|
charNine when x"9",
|
charNine when x"9",
|
charAHigh when x"A",
|
charAHigh when x"A",
|
charBHigh when x"B",
|
charBHigh when x"B",
|
charCHigh when x"C",
|
charCHigh when x"C",
|
charDHigh when x"D",
|
charDHigh when x"D",
|
charEHigh when x"E",
|
charEHigh when x"E",
|
charFHigh when x"F",
|
charFHigh when x"F",
|
charFHigh when others;
|
charFHigh when others;
|
intAddress <= iIntAddress;
|
intAddress <= iIntAddress;
|
intWrite <= iIntWrite;
|
intWrite <= iIntWrite;
|
intRead <= iIntRead;
|
intRead <= iIntRead;
|
|
intReq <= '1' when (iReadReq = '1') else
|
|
'1' when (iWriteReq = '1') else '0';
|
end Behavioral;
|
end Behavioral;
|
|
|