URL
https://opencores.org/ocsvn/uart2bus/uart2bus/trunk
Subversion Repositories uart2bus
Compare Revisions
- This comparison shows the changes necessary to convert path
/uart2bus/trunk/vhdl/rtl
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/baudGen.vhd
0,0 → 1,48
----------------------------------------------------------------------------------------- |
-- baud rate generator for uart |
-- |
-- this module has been changed to receive the baud rate dividing counter from registers. |
-- the two registers should be calculated as follows: |
-- first register: |
-- baud_freq = 16*baud_rate / gcd(global_clock_freq, 16*baud_rate) |
-- second register: |
-- baud_limit = (global_clock_freq / gcd(global_clock_freq, 16*baud_rate)) - baud_freq |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity baudGen is |
port ( clr : in std_logic; -- global reset input |
clk : in std_logic; -- global clock input |
-- baudFreq = 16 * baudRate / gcd(clkFreq, 16 * baudRate) |
baudFreq : in std_logic_vector(11 downto 0); -- baud rate setting registers - see header description |
-- baudLimit = clkFreq / gcd(clkFreq, 16 * baudRate) - baudFreq |
baudLimit : in std_logic_vector(15 downto 0); -- baud rate setting registers - see header description |
ce16 : out std_logic); -- baud rate multiplyed by 16 |
end baudGen; |
|
architecture Behavioral of baudGen is |
|
signal counter : std_logic_vector(15 downto 0); |
|
begin |
-- baud divider counter |
-- clock divider output |
process (clr, clk) |
begin |
if (clr = '1') then |
counter <= (others => '0'); |
ce16 <= '0'; |
elsif (rising_edge(clk)) then |
if (counter >= baudLimit) then |
counter <= counter - baudLimit; |
ce16 <= '1'; |
else |
counter <= counter + baudFreq; |
ce16 <= '0'; |
end if; |
end if; |
end process; |
end Behavioral; |
/uartRx.vhd
0,0 → 1,111
----------------------------------------------------------------------------------------- |
-- uart receive module |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity uartRx is |
port ( clr : in std_logic; -- global reset input |
clk : in std_logic; -- global clock input |
ce16 : in std_logic; -- baud rate multiplyed by 16 - generated by baud module |
serIn : in std_logic; -- serial data input |
rxData : out std_logic_vector(7 downto 0); -- data byte received |
newRxData : out std_logic); -- signs that a new byte was received |
end uartRx; |
|
architecture Behavioral of uartRx is |
|
signal ce1 : std_logic; -- clock enable at bit rate |
signal ce1Mid : std_logic; -- clock enable at the middle of each bit - used to sample data |
signal inSync : std_logic_vector(1 downto 0); |
signal count16 : std_logic_vector(3 downto 0); |
signal rxBusy : std_logic; |
signal bitCount : std_logic_vector(3 downto 0); |
signal dataBuf : std_logic_vector(7 downto 0); |
|
begin |
-- input async input is sampled twice |
process (clr, clk) |
begin |
if (clr = '1') then |
inSync <= (others => '1'); |
elsif (rising_edge(clk)) then |
inSync <= inSync(0) & serIn; |
end if; |
end process; |
-- a counter to count 16 pulses of ce_16 to generate the ce_1 and ce_1_mid pulses. |
-- this counter is used to detect the start bit while the receiver is not receiving and |
-- signs the sampling cycle during reception. |
process (clr, clk) |
begin |
if (clr = '1') then |
count16 <= (others => '0'); |
elsif (rising_edge(clk)) then |
if (ce16 = '1') then |
if ((rxBusy = '1') or (inSync(1) = '0')) then |
count16 <= count16 + 1; |
else |
count16 <= (others => '0'); |
end if; |
end if; |
end if; |
end process; |
-- receiving busy flag |
process (clr, clk) |
begin |
if (clr = '1') then |
rxBusy <= '0'; |
elsif (rising_edge(clk)) then |
if ((rxBusy = '0') and (ce1Mid = '1')) then |
rxBusy <= '1'; |
elsif ((rxBusy = '1') and (bitCount = "1001") and (ce1 = '1')) then |
rxBusy <= '0'; |
end if; |
end if; |
end process; |
-- bit counter |
process (clr, clk) |
begin |
if (clr = '1') then |
bitCount <= (others => '0'); |
elsif (rising_edge(clk)) then |
if (rxBusy = '0') then |
bitCount <= (others => '0'); |
elsif ((rxBusy = '1') and (ce1Mid = '1')) then |
bitCount <= bitCount + 1; |
end if; |
end if; |
end process; |
-- data buffer shift register |
process (clr, clk) |
begin |
if (clr = '1') then |
dataBuf <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((rxBusy = '1') and (ce1Mid = '1')) then |
dataBuf <= inSync(1) & dataBuf(7 downto 1); |
end if; |
end if; |
end process; |
-- data output and flag |
process (clr, clk) |
begin |
if (clr = '1') then |
rxData <= (others => '0'); |
newRxData <= '0'; |
elsif (rising_edge(clk)) then |
if ((rxBusy = '1') and (bitCount = "1000") and (ce1 = '1')) then |
rxData <= dataBuf; |
newRxData <= '1'; |
else |
newRxData <= '0'; |
end if; |
end if; |
end process; |
-- ce_1 pulse indicating expected end of current bit |
ce1 <= '1' when ((count16 = "1111") and (ce16 = '1')) else '0'; |
-- ce_1_mid pulse indication the sampling clock cycle of the current data bit |
ce1Mid <= '1' when ((count16 = "0111") and (ce16 = '1')) else '0'; |
end Behavioral; |
/uartTx.vhd
0,0 → 1,96
----------------------------------------------------------------------------------------- |
-- uart transmit module |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity uartTx is |
port ( clr : in std_logic; -- global reset input |
clk : in std_logic; -- global clock input |
ce16 : in std_logic; -- baud rate multiplyed by 16 - generated by baud module |
txData : in std_logic_vector(7 downto 0); -- data byte to transmit |
newTxData : in std_logic; -- asserted to indicate that there is a new data byte for transmission |
serOut : out std_logic; -- serial data output |
txBusy : out std_logic); -- signs that transmitter is busy |
end uartTx; |
|
architecture Behavioral of uartTx is |
|
signal iTxBusy : std_logic; |
signal ce1 : std_logic; -- clock enable at bit rate |
signal count16 : std_logic_vector(3 downto 0); |
signal bitCount : std_logic_vector(3 downto 0); |
signal dataBuf : std_logic_vector(8 downto 0); |
|
begin |
-- a counter to count 16 pulses of ce_16 to generate the ce_1 pulse |
process (clr, clk) |
begin |
if (clr = '1') then |
count16 <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((iTxBusy = '1') and (ce16 = '1')) then |
count16 <= count16 + 1; |
elsif (iTxBusy = '0') then |
count16 <= (others => '0'); |
end if; |
end if; |
end process; |
-- tx_busy flag |
process (clr, clk) |
begin |
if (clr = '1') then |
iTxBusy <= '0'; |
elsif (rising_edge(clk)) then |
if ((iTxBusy = '0') and (newTxData = '1')) then |
iTxBusy <= '1'; |
elsif ((iTxBusy = '1') and (bitCount = "1010") and (ce1 = '1')) then |
iTxBusy <= '0'; |
end if; |
end if; |
end process; |
-- output bit counter |
process (clr, clk) |
begin |
if (clr = '1') then |
bitCount <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((iTxBusy = '1') and (ce1 = '1')) then |
bitCount <= bitCount + 1; |
elsif (iTxBusy = '0') then |
bitCount <= (others => '0'); |
end if; |
end if; |
end process; |
-- data shift register |
process (clr, clk) |
begin |
if (clr = '1') then |
dataBuf <= (others => '0'); |
elsif (rising_edge(clk)) then |
if (iTxBusy = '0') then |
dataBuf <= txData & '0'; |
elsif ((iTxBusy = '1') and (ce1 = '1')) then |
dataBuf <= '1' & dataBuf(8 downto 1); |
end if; |
end if; |
end process; |
-- output data bit |
process (clr, clk) |
begin |
if (clr = '1') then |
serOut <= '1'; |
elsif (rising_edge(clk)) then |
if (iTxBusy = '1') then |
serOut <= dataBuf(0); |
else |
serOut <= '1'; |
end if; |
end if; |
end process; |
-- ce_1 pulse indicating output data bit should be updated |
ce1 <= '1' when ((count16 = "1111") and (ce16 = '1')) else '0'; |
txBusy <= iTxBusy; |
end Behavioral; |
/uartParser.vhd
0,0 → 1,562
----------------------------------------------------------------------------------------- |
-- uart parser module |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
use IEEE.STD_LOGIC_UNSIGNED.ALL; |
|
entity uartParser is |
generic ( -- parameters |
AW : integer := 8); |
port ( -- global signals |
clr : in std_logic; -- global reset input |
clk : in std_logic; -- global clock input |
-- transmit and receive internal interface signals from uart interface |
txBusy : in std_logic; -- signs that transmitter is busy |
rxData : in std_logic_vector(7 downto 0); -- data byte received |
newRxData : in std_logic; -- signs that a new byte was received |
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 |
-- internal bus to 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 |
intWrData : out std_logic_vector(7 downto 0); -- write data to register file |
intWrite : out std_logic; -- write control to register file |
intRead : out std_logic); -- read control to register file |
end uartParser; |
|
architecture Behavioral of uartParser is |
|
-- internal constants |
-- main (receive) state machine states |
signal mainSm : std_logic_vector(3 downto 0); -- main state machine |
constant mainIdle : std_logic_vector(mainSm'range) := "0000"; |
constant mainWhite1 : std_logic_vector(mainSm'range) := "0001"; |
constant mainData : std_logic_vector(mainSm'range) := "0010"; |
constant mainWhite2 : std_logic_vector(mainSm'range) := "0011"; |
constant mainAddr : std_logic_vector(mainSm'range) := "0100"; |
constant mainEol : std_logic_vector(mainSm'range) := "0101"; |
-- binary mode extension states |
constant mainBinCmd : std_logic_vector(mainSm'range) := "1000"; |
constant mainBinAdrh : std_logic_vector(mainSm'range) := "1001"; |
constant mainBinAdrl : std_logic_vector(mainSm'range) := "1010"; |
constant mainBinLen : std_logic_vector(mainSm'range) := "1011"; |
constant mainBinData : std_logic_vector(mainSm'range) := "1100"; |
|
-- transmit state machine |
signal txSm : std_logic_vector(2 downto 0); -- transmit state machine |
constant txIdle : std_logic_vector(txSm'range) := "000"; |
constant txHiNib : std_logic_vector(txSm'range) := "001"; |
constant txLoNib : std_logic_vector(txSm'range) := "100"; |
constant txCharCR : std_logic_vector(txSm'range) := "101"; |
constant txCharLF : std_logic_vector(txSm'range) := "110"; |
|
-- define characters used by the parser |
constant charNul : std_logic_vector(7 downto 0) := x"00"; |
constant charTab : std_logic_vector(7 downto 0) := x"09"; |
constant charLF : std_logic_vector(7 downto 0) := x"0A"; |
constant charCR : std_logic_vector(7 downto 0) := x"0D"; |
constant charSpace : std_logic_vector(7 downto 0) := x"20"; |
constant charZero : std_logic_vector(7 downto 0) := x"30"; |
constant charOne : std_logic_vector(7 downto 0) := x"31"; |
constant charTwo : std_logic_vector(7 downto 0) := x"32"; |
constant charThree : std_logic_vector(7 downto 0) := x"33"; |
constant charFour : std_logic_vector(7 downto 0) := x"34"; |
constant charFive : std_logic_vector(7 downto 0) := x"35"; |
constant charSix : std_logic_vector(7 downto 0) := x"36"; |
constant charSeven : std_logic_vector(7 downto 0) := x"37"; |
constant charEight : std_logic_vector(7 downto 0) := x"38"; |
constant charNine : std_logic_vector(7 downto 0) := x"39"; |
constant charAHigh : std_logic_vector(7 downto 0) := x"41"; |
constant charBHigh : std_logic_vector(7 downto 0) := x"42"; |
constant charCHigh : std_logic_vector(7 downto 0) := x"43"; |
constant charDHigh : std_logic_vector(7 downto 0) := x"44"; |
constant charEHigh : std_logic_vector(7 downto 0) := x"45"; |
constant charFHigh : std_logic_vector(7 downto 0) := x"46"; |
constant charRHigh : std_logic_vector(7 downto 0) := x"52"; |
constant charWHigh : std_logic_vector(7 downto 0) := x"57"; |
constant charALow : std_logic_vector(7 downto 0) := x"61"; |
constant charBLow : std_logic_vector(7 downto 0) := x"62"; |
constant charCLow : std_logic_vector(7 downto 0) := x"63"; |
constant charDLow : std_logic_vector(7 downto 0) := x"64"; |
constant charELow : std_logic_vector(7 downto 0) := x"65"; |
constant charFLow : std_logic_vector(7 downto 0) := x"66"; |
constant charRLow : std_logic_vector(7 downto 0) := x"72"; |
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 |
constant binCmdNop : std_logic_vector(1 downto 0) := "00"; |
constant binCmdRead : std_logic_vector(1 downto 0) := "01"; |
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 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 readOp : std_logic; -- read operation flag |
signal writeOp : std_logic; -- write operation flag |
signal binReadOp : std_logic; -- binary mode read operation flag |
signal binWriteOp : std_logic; -- binary mode write operation flag |
signal sendStatFlag : std_logic; -- send status flag |
signal addrAutoInc : std_logic; -- address auto increment mode |
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 addrParam : std_logic_vector(15 downto 0); -- operation address parameter |
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 iIntAddress : std_logic_vector(intAddress'range); -- |
signal iIntWrite : std_logic; -- |
signal readDone : std_logic; -- internally generated read done flag |
signal readDoneS : std_logic; -- sampled read done |
signal readDataS : std_logic_vector(7 downto 0); -- sampled read data |
signal iIntRead : std_logic; -- |
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 txNibble : std_logic_vector(3 downto 0); -- nibble value for transmission |
|
-- module implementation |
-- main state machine |
begin |
process (clr, clk) |
begin |
if (clr = '1') then |
mainSm <= mainIdle; |
elsif (rising_edge(clk)) then |
if (newRxData = '1') then |
case mainSm is |
-- wait for a read ('r') or write ('w') command |
-- binary extension - an all zeros byte enabled binary commands |
when mainIdle => |
-- check received character |
if (rxData = charNul) then |
-- an all zeros received byte enters binary mode |
mainSm <= mainBinCmd; |
elsif ((rxData = charRLow) or (rxData = charRHigh)) then |
-- on read wait to receive only address field |
mainSm <= mainWhite2; |
elsif ((rxData = charWLow) or (rxData = charWHigh)) then |
-- on write wait to receive data and address |
mainSm <= mainWhite1; |
elsif ((rxData = charCR) or (rxData = charLF)) then |
-- on new line sta in idle |
mainSm <= mainIdle; |
else |
-- any other character wait to end of line (EOL) |
mainSm <= mainEol; |
end if; |
-- wait for white spaces till first data nibble |
when mainWhite1 => |
-- 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 |
-- return should reset the state machine to idle. |
-- any other character transitions the state machine to wait for EOL. |
if ((rxData = charSpace) or (rxData = charTab)) then |
mainSm <= mainWhite1; |
elsif (dataInHexRange = '1') then |
mainSm <= mainData; |
elsif ((rxData = charCR) or (rxData = charLF)) then |
mainSm <= mainIdle; |
else |
mainSm <= mainEol; |
end if; |
-- receive data field |
when mainData => |
-- 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 |
-- wait til end of line. |
if (dataInHexRange = '1') then |
mainSm <= mainData; |
elsif ((rxData = charSpace) or (rxData = charTab)) then |
mainSm <= mainWhite2; |
elsif ((rxData = charCR) or (rxData = charLF)) then |
mainSm <= mainIdle; |
else |
mainSm <= mainEol; |
end if; |
-- wait for white spaces till first address nibble |
when mainWhite2 => |
-- similar to MAIN_WHITE1 |
if ((rxData = charSpace) or (rxData = charTab)) then |
mainSm <= mainWhite2; |
elsif (dataInHexRange = '1') then |
mainSm <= mainAddr; |
elsif ((rxData = charCR) or (rxData = charLF)) then |
mainSm <= mainIdle; |
else |
mainSm <= mainEol; |
end if; |
-- receive address field |
when mainAddr => |
-- similar to MAIN_DATA |
if (dataInHexRange = '1') then |
mainSm <= mainAddr; |
elsif ((rxData = charCR) or (rxData = charLF)) then |
mainSm <= mainIdle; |
else |
mainSm <= mainEol; |
end if; |
-- wait to EOL |
when mainEol => |
-- wait for CR or LF to move back to idle |
if ((rxData = charCR) or (rxData = charLF)) then |
mainSm <= mainIdle; |
end if; |
-- binary extension |
-- wait for command - one byte |
when mainBinCmd => |
-- check if command is a NOP command |
if (rxData(5 downto 4) = binCmdNop) then |
-- if NOP command then switch back to idle state |
mainSm <= mainIdle; |
else |
-- not a NOP command, continue receiving parameters |
mainSm <= mainBinAdrh; |
end if; |
-- wait for address parameter - two bytes |
-- high address byte |
when mainBinAdrh => |
-- switch to next state |
mainSm <= mainBinAdrl; |
-- low address byte |
when mainBinAdrl => |
-- switch to next state |
mainSm <= mainBinLen; |
-- wait for length parameter - one byte |
when mainBinLen => |
-- check if write command else command reception ended |
if (binWriteOp = '1') then |
-- wait for write data |
mainSm <= mainBinData; |
else |
-- command reception has ended |
mainSm <= mainIdle; |
end if; |
-- on write commands wait for data till end of buffer as specified by length parameter |
when mainBinData => |
-- if this is the last data byte then return to idle |
if (binLastByte = '1') then |
mainSm <= mainIdle; |
end if; |
-- go to idle |
when others => |
mainSm <= mainIdle; |
end case; |
end if; |
end if; |
end process; |
-- read operation flag |
-- write operation flag |
-- binary mode read operation flag |
-- binary mode write operation flag |
process (clr, clk) |
begin |
if (clr = '1') then |
readOp <= '0'; |
writeOp <= '0'; |
binReadOp <= '0'; |
binWriteOp <= '0'; |
elsif (rising_edge(clk)) 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 |
-- if any other character is received during that state. |
if ((rxData = charRLow) or (rxData = charRHigh)) then |
readOp <= '1'; |
else |
readOp <= '0'; |
end if; |
-- 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 ((rxData = charWLow) or (rxData = charWHigh)) then |
writeOp <= '1'; |
else |
writeOp <= '0'; |
end if; |
end if; |
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdRead)) then |
-- read command is started on reception of a read command |
binReadOp <= '1'; |
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) then |
-- read command ends on transmission of the last byte read |
binReadOp <= '0'; |
end if; |
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdWrite)) then |
-- write command is started on reception of a write command |
binWriteOp <= '1'; |
elsif ((mainSm = mainBinData) and (newRxData = '1') and (binLastByte = '1')) then |
binWriteOp <= '0'; |
end if; |
end if; |
end process; |
-- send status flag - used only in binary extension mode |
-- address auto increment - used only in binary extension mode |
process (clr, clk) |
begin |
if (clr = '1') then |
sendStatFlag <= '0'; |
addrAutoInc <= '0'; |
elsif (rising_edge(clk)) then |
if ((mainSm = mainBinCmd) and (newRxData = '1')) then |
-- check if a status byte should be sent at the end of the command |
sendStatFlag <= rxData(0); |
-- check if address should be automatically incremented or not. |
-- Note that when rx_data[1] is set, address auto increment is disabled. |
addrAutoInc <= not(rxData(1)); |
end if; |
end if; |
end process; |
-- operation data parameter |
process (clr, clk) |
begin |
if (clr = '1') then |
dataParam <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((mainSm = mainWhite1) and (newRxData = '1') and (dataInHexRange = '1')) then |
dataParam <= "0000" & dataNibble; |
elsif ((mainSm = mainData) and (newRxData = '1') and (dataInHexRange = '1')) then |
dataParam <= dataParam(3 downto 0) & dataNibble; |
end if; |
end if; |
end process; |
-- operation address parameter |
process (clr, clk) |
begin |
if (clr = '1') then |
addrParam <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((mainSm = mainWhite2) and (newRxData = '1') and (dataInHexRange = '1')) then |
addrParam <= x"000" & dataNibble; |
elsif ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '1')) then |
addrParam <= addrParam(11 downto 0) & dataNibble; |
-- binary extension |
elsif (mainSm = mainBinAdrh) then |
addrParam(15 downto 8) <= rxData; |
elsif (mainSm = mainBinAdrl) then |
addrParam(7 downto 0) <= rxData; |
end if; |
end if; |
end process; |
-- 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. |
process (clr, clk) |
begin |
if (clr = '1') then |
binByteCount <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((mainSm = mainBinLen) and (newRxData = '1')) then |
binByteCount <= rxData; |
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 transmitted for read operations. |
binByteCount <= binByteCount - 1; |
end if; |
end if; |
end process; |
-- internal write control and data |
-- internal read control |
process (clr, clk) |
begin |
if (clr = '1') then |
iIntRead <= '0'; |
iIntWrite <= '0'; |
intWrData <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((mainSm = mainAddr) and (writeOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then |
iIntWrite <= '1'; |
intWrData <= dataParam; |
-- binary extension mode |
elsif ((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) then |
iIntWrite <= '1'; |
intWrData <= rxData; |
else |
iIntWrite <= '0'; |
end if; |
if ((mainSm = mainAddr) and (readOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then |
iIntRead <= '1'; |
-- binary extension |
elsif ((mainSm = mainBinLen) and (binReadOp = '1') and (newRxData = '1')) then |
-- the first read request is issued on reception of the length byte |
iIntRead <= '1'; |
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) then |
-- the next read requests are issued after the previous read value was transmitted and |
-- this is not the last byte to be read. |
iIntRead <= '1'; |
else |
iIntRead <= '0'; |
end if; |
end if; |
end process; |
-- internal address |
process (clr, clk) |
begin |
if (clr = '1') then |
iIntAddress <= (others => '0'); |
elsif (rising_edge(clk)) then |
if ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '0')) then |
iIntAddress <= addrParam(AW - 1 downto 0); |
-- binary extension |
elsif ((mainSm = mainBinLen) and (newRxData = '1')) then |
-- sample address parameter on reception of length byte |
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 |
-- address is incremented on every read or write if enabled |
iIntAddress <= iIntAddress + 1; |
end if; |
end if; |
end process; |
-- read done flag and sampled data read |
process (clr, clk) |
begin |
if (clr = '1') then |
readDone <= '0'; |
readDoneS <= '0'; |
readDataS <= (others => '0'); |
elsif (rising_edge(clk)) then |
-- read done flag |
readDone <= iIntRead; |
-- sampled read done |
readDoneS <= readDone; |
-- sampled data read |
if (readDone = '1') then |
readDataS <= intRdData; |
end if; |
end if; |
end process; |
-- transmit state machine and control |
process (clr, clk) |
begin |
if (clr = '1') then |
txSm <= txIdle; |
txData <= (others => '0'); |
newTxData <= '0'; |
elsif (rising_edge(clk)) then |
case txSm is |
-- wait for read done indication |
when txIdle => |
-- on end of every read operation check how the data read should be transmitted |
-- according to read type: ascii or binary. |
if (readDoneS = '1') then |
-- on binary mode read transmit byte value |
if (binReadOp = '1') then |
-- note that there is no need to change state |
txData <= readDataS; |
newTxData <= '1'; |
else |
txSm <= txHiNib; |
txData <= txChar; |
newTxData <= '1'; |
end if; |
-- 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 |
-- send status byte - currently a constant |
txData <= x"5A"; |
newTxData <= '1'; |
else |
newTxData <= '0'; |
end if; |
when txHiNib => |
-- wait for transmit to end |
if (txEndP = '1') then |
txSm <= txLoNib; |
txData <= txChar; |
newTxData <= '1'; |
else |
newTxData <= '0'; |
end if; |
-- wait for transmit to end |
when txLoNib => |
if (txEndP = '1') then |
txSm <= txCharCR; |
txData <= charCR; |
newTxData <= '1'; |
else |
newTxData <= '0'; |
end if; |
-- wait for transmit to end |
when txCharCR => |
if (txEndP = '1') then |
txSm <= txCharLF; |
txData <= charLF; |
newTxData <= '1'; |
else |
newTxData <= '0'; |
end if; |
-- wait for transmit to end |
when txCharLF => |
if (txEndP = '1') then |
txSm <= txIdle; |
end if; |
-- clear tx new data flag |
newTxData <= '0'; |
-- return to idle |
when others => |
txSm <= txIdle; |
end case; |
end if; |
end process; |
-- sampled tx_busy |
process (clr, clk) |
begin |
if (clr = '1') then |
sTxBusy <= '1'; |
elsif (rising_edge(clk)) then |
sTxBusy <= txBusy; |
end if; |
end process; |
-- indicates that the received data is in the range of hex number |
dataInHexRange <= '1' when (((rxData >= charZero) and (rxData <= charNine)) or |
((rxData >= charAHigh) and (rxData <= charFHigh)) or |
((rxData >= charALow) and (rxData <= charFLow))) else '0'; |
-- last byte in command flag |
binLastByte <= '1' when (binByteCount = x"01") else '0'; |
-- select the nibble to the nibble to character conversion |
txNibble <= readDataS(3 downto 0) when (txSm = txHiNib) else readDataS(7 downto 4); |
-- tx end pulse |
txEndP <= '1' when ((txBusy = '0') and (sTxBusy = '1')) else '0'; |
-- character to nibble conversion |
with rxData select |
dataNibble <= x"0" when charZero, |
x"1" when charOne, |
x"2" when charTwo, |
x"3" when charThree, |
x"4" when charFour, |
x"5" when charFive, |
x"6" when charSix, |
x"7" when charSeven, |
x"8" when charEight, |
x"9" when charNine, |
x"A" when charALow, |
x"A" when charAHigh, |
x"B" when charBLow, |
x"B" when charBHigh, |
x"C" when charCLow, |
x"C" when charCHigh, |
x"D" when charDLow, |
x"D" when charDHigh, |
x"E" when charELow, |
x"E" when charEHigh, |
x"F" when charFLow, |
x"F" when charFHigh, |
x"F" when others; |
-- nibble to character conversion |
with txNibble select |
txChar <= charZero when x"0", |
charOne when x"1", |
charTwo when x"2", |
charThree when x"3", |
charFour when x"4", |
charFive when x"5", |
charSix when x"6", |
charSeven when x"7", |
charEight when x"8", |
charNine when x"9", |
charAHigh when x"A", |
charBHigh when x"B", |
charCHigh when x"C", |
charDHigh when x"D", |
charEHigh when x"E", |
charFHigh when x"F", |
charFHigh when others; |
intAddress <= iIntAddress; |
intWrite <= iIntWrite; |
intRead <= iIntRead; |
end Behavioral; |
/uart2BusTop.vhd
0,0 → 1,100
----------------------------------------------------------------------------------------- |
-- uart to internal bus top module |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
|
entity uart2BusTop is |
generic ( AW : integer := 8); |
port ( -- global signals |
clr : in STD_LOGIC; -- global reset input |
clk : in STD_LOGIC; -- global clock input |
-- uart serial signals |
serIn : in STD_LOGIC; -- serial data input |
serOut : out STD_LOGIC; -- serial data output |
-- internal bus to 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 |
intWrData : out STD_LOGIC_VECTOR (7 downto 0); -- write data to register file |
intWrite : out STD_LOGIC; -- write control to register file |
intRead : out STD_LOGIC); -- read control to register file |
end uart2BusTop; |
|
architecture Behavioral of uart2BusTop is |
|
component uartTop |
port ( clr : in std_logic; |
clk : in std_logic; |
serIn : in std_logic; |
txData : in std_logic_vector(7 downto 0); |
newTxData : in std_logic; |
baudFreq : in std_logic_vector(11 downto 0); |
baudLimit : in std_logic_vector(15 downto 0); |
serOut : out std_logic; |
txBusy : out std_logic; |
rxData : out std_logic_vector(7 downto 0); |
newRxData : out std_logic; |
baudClk : out std_logic); |
end component; |
|
component uartParser |
generic ( AW : integer := 8); |
port ( clr : in std_logic; |
clk : in std_logic; |
txBusy : in std_logic; |
rxData : in std_logic_vector(7 downto 0); |
newRxData : in std_logic; |
intRdData : in std_logic_vector(7 downto 0); |
txData : out std_logic_vector(7 downto 0); |
newTxData : out std_logic; |
intAddress : out std_logic_vector(AW - 1 downto 0); |
intWrData : out std_logic_vector(7 downto 0); |
intWrite : out std_logic; |
intRead : out std_logic); |
end component; |
|
-- baud rate configuration, see baudGen.vhd for more details. |
-- baud rate generator parameters for 115200 baud on 25MHz clock |
constant baudFreq : std_logic_vector(11 downto 0) := x"480"; |
constant baudLimit : std_logic_vector(15 downto 0) := x"3889"; |
signal txData : std_logic_vector(7 downto 0); -- data byte to transmit |
signal newTxData : std_logic; -- asserted to indicate that there is a new data byte for transmission |
signal txBusy : std_logic; -- signs that transmitter is busy |
signal rxData : std_logic_vector(7 downto 0); -- data byte received |
signal newRxData : std_logic; -- signs that a new byte was received |
|
begin |
-- uart top module instance |
ut : uartTop |
port map ( |
clr => clr, |
clk => clk, |
serIn => serIn, |
txData => txData, |
newTxData => newTxData, |
baudFreq => baudFreq, |
baudLimit => baudLimit, |
serOut => serOut, |
txBusy => txBusy, |
rxData => rxData, |
newRxData => newRxData, |
baudClk => open); |
-- uart parser instance |
up : uartParser |
generic map ( |
AW => AW) |
port map ( |
clr => clr, |
clk => clk, |
txBusy => txBusy, |
rxData => rxData, |
newRxData => newRxData, |
intRdData => intRdData, |
txData => txData, |
newTxData => newTxData, |
intAddress => intAddress, |
intWrData => intWrData, |
intWrite => intWrite, |
intRead => intRead); |
end Behavioral; |
/uartTop.vhd
0,0 → 1,90
----------------------------------------------------------------------------------------- |
-- uart top level module |
-- |
----------------------------------------------------------------------------------------- |
library IEEE; |
use IEEE.STD_LOGIC_1164.ALL; |
|
entity uartTop is |
port ( -- global signals |
clr : in std_logic; -- global reset input |
clk : in std_logic; -- global clock input |
-- uart serial signals |
serIn : in std_logic; -- serial data input |
serOut : out std_logic; -- serial data output |
-- transmit and receive internal interface signals |
txData : in std_logic_vector(7 downto 0); -- data byte to transmit |
newTxData : in std_logic; -- asserted to indicate that there is a new data byte for transmission |
txBusy : out std_logic; -- signs that transmitter is busy |
rxData : out std_logic_vector(7 downto 0); -- data byte received |
newRxData : out std_logic; -- signs that a new byte was received |
-- baud rate configuration register - see baudGen.vhd for details |
baudFreq : in std_logic_vector(11 downto 0); -- baud rate setting registers - see header description |
baudLimit : in std_logic_vector(15 downto 0); -- baud rate setting registers - see header description |
baudClk : out std_logic); -- |
end uartTop; |
|
architecture Behavioral of uartTop is |
|
component baudGen |
port ( |
clr : in std_logic; |
clk : in std_logic; |
baudFreq : in std_logic_vector(11 downto 0); |
baudLimit : in std_logic_vector(15 downto 0); |
ce16 : out std_logic); |
end component; |
|
component uartTx |
port ( |
clr : in std_logic; |
clk : in std_logic; |
ce16 : in std_logic; |
txData : in std_logic_vector(7 downto 0); |
newTxData : in std_logic; |
serOut : out std_logic; |
txBusy : out std_logic); |
end component; |
|
component uartRx |
port ( |
clr : in std_logic; |
clk : in std_logic; |
ce16 : in std_logic; |
serIn : in std_logic; |
rxData : out std_logic_vector(7 downto 0); |
newRxData : out std_logic); |
end component; |
|
signal ce16 : std_logic; -- clock enable at bit rate |
|
begin |
-- baud rate generator module |
bg : baudGen |
port map ( |
clr => clr, |
clk => clk, |
baudFreq => baudFreq, |
baudLimit => baudLimit, |
ce16 => ce16); |
-- uart receiver |
ut : uartTx |
port map ( |
clr => clr, |
clk => clk, |
ce16 => ce16, |
txData => txData, |
newTxData => newTxData, |
serOut => serOut, |
txBusy => txBusy); |
-- uart transmitter |
ur : uartRx |
port map ( |
clr => clr, |
clk => clk, |
ce16 => ce16, |
serIn => serIn, |
rxData => rxData, |
newRxData => newRxData); |
baudClk <= ce16; |
end Behavioral; |