1 |
6 |
smuller |
-----------------------------------------------------------------------------------------
|
2 |
|
|
-- uart parser module
|
3 |
|
|
--
|
4 |
|
|
-----------------------------------------------------------------------------------------
|
5 |
11 |
smuller |
library ieee;
|
6 |
|
|
use ieee.std_logic_1164.ALL;
|
7 |
|
|
use ieee.std_logic_unsigned.ALL;
|
8 |
6 |
smuller |
|
9 |
|
|
entity uartParser is
|
10 |
|
|
generic ( -- parameters
|
11 |
|
|
AW : integer := 8);
|
12 |
|
|
port ( -- global signals
|
13 |
|
|
clr : in std_logic; -- global reset input
|
14 |
|
|
clk : in std_logic; -- global clock input
|
15 |
|
|
-- transmit and receive internal interface signals from uart interface
|
16 |
|
|
txBusy : in std_logic; -- signs that transmitter is busy
|
17 |
|
|
rxData : in std_logic_vector(7 downto 0); -- data byte received
|
18 |
|
|
newRxData : in std_logic; -- signs that a new byte was received
|
19 |
|
|
txData : out std_logic_vector(7 downto 0); -- data byte to transmit
|
20 |
|
|
newTxData : out std_logic; -- asserted to indicate that there is a new data byte for transmission
|
21 |
|
|
-- internal bus to register file
|
22 |
11 |
smuller |
intReq : out std_logic; --
|
23 |
|
|
intGnt : in std_logic; --
|
24 |
6 |
smuller |
intRdData : in std_logic_vector(7 downto 0); -- data read from register file
|
25 |
|
|
intAddress : out std_logic_vector(AW - 1 downto 0); -- address bus to register file
|
26 |
|
|
intWrData : out std_logic_vector(7 downto 0); -- write data to register file
|
27 |
|
|
intWrite : out std_logic; -- write control to register file
|
28 |
|
|
intRead : out std_logic); -- read control to register file
|
29 |
|
|
end uartParser;
|
30 |
|
|
|
31 |
|
|
architecture Behavioral of uartParser is
|
32 |
|
|
|
33 |
|
|
-- internal constants
|
34 |
|
|
-- main (receive) state machine states
|
35 |
|
|
signal mainSm : std_logic_vector(3 downto 0); -- main state machine
|
36 |
|
|
constant mainIdle : std_logic_vector(mainSm'range) := "0000";
|
37 |
|
|
constant mainWhite1 : std_logic_vector(mainSm'range) := "0001";
|
38 |
|
|
constant mainData : std_logic_vector(mainSm'range) := "0010";
|
39 |
|
|
constant mainWhite2 : std_logic_vector(mainSm'range) := "0011";
|
40 |
|
|
constant mainAddr : std_logic_vector(mainSm'range) := "0100";
|
41 |
|
|
constant mainEol : std_logic_vector(mainSm'range) := "0101";
|
42 |
|
|
-- binary mode extension states
|
43 |
|
|
constant mainBinCmd : std_logic_vector(mainSm'range) := "1000";
|
44 |
|
|
constant mainBinAdrh : std_logic_vector(mainSm'range) := "1001";
|
45 |
|
|
constant mainBinAdrl : std_logic_vector(mainSm'range) := "1010";
|
46 |
|
|
constant mainBinLen : std_logic_vector(mainSm'range) := "1011";
|
47 |
|
|
constant mainBinData : std_logic_vector(mainSm'range) := "1100";
|
48 |
|
|
|
49 |
|
|
-- transmit state machine
|
50 |
|
|
signal txSm : std_logic_vector(2 downto 0); -- transmit state machine
|
51 |
|
|
constant txIdle : std_logic_vector(txSm'range) := "000";
|
52 |
|
|
constant txHiNib : std_logic_vector(txSm'range) := "001";
|
53 |
|
|
constant txLoNib : std_logic_vector(txSm'range) := "100";
|
54 |
|
|
constant txCharCR : std_logic_vector(txSm'range) := "101";
|
55 |
|
|
constant txCharLF : std_logic_vector(txSm'range) := "110";
|
56 |
|
|
|
57 |
|
|
-- define characters used by the parser
|
58 |
|
|
constant charNul : std_logic_vector(7 downto 0) := x"00";
|
59 |
|
|
constant charTab : std_logic_vector(7 downto 0) := x"09";
|
60 |
|
|
constant charLF : std_logic_vector(7 downto 0) := x"0A";
|
61 |
|
|
constant charCR : std_logic_vector(7 downto 0) := x"0D";
|
62 |
|
|
constant charSpace : std_logic_vector(7 downto 0) := x"20";
|
63 |
|
|
constant charZero : std_logic_vector(7 downto 0) := x"30";
|
64 |
|
|
constant charOne : std_logic_vector(7 downto 0) := x"31";
|
65 |
|
|
constant charTwo : std_logic_vector(7 downto 0) := x"32";
|
66 |
|
|
constant charThree : std_logic_vector(7 downto 0) := x"33";
|
67 |
|
|
constant charFour : std_logic_vector(7 downto 0) := x"34";
|
68 |
|
|
constant charFive : std_logic_vector(7 downto 0) := x"35";
|
69 |
|
|
constant charSix : std_logic_vector(7 downto 0) := x"36";
|
70 |
|
|
constant charSeven : std_logic_vector(7 downto 0) := x"37";
|
71 |
|
|
constant charEight : std_logic_vector(7 downto 0) := x"38";
|
72 |
|
|
constant charNine : std_logic_vector(7 downto 0) := x"39";
|
73 |
|
|
constant charAHigh : std_logic_vector(7 downto 0) := x"41";
|
74 |
|
|
constant charBHigh : std_logic_vector(7 downto 0) := x"42";
|
75 |
|
|
constant charCHigh : std_logic_vector(7 downto 0) := x"43";
|
76 |
|
|
constant charDHigh : std_logic_vector(7 downto 0) := x"44";
|
77 |
|
|
constant charEHigh : std_logic_vector(7 downto 0) := x"45";
|
78 |
|
|
constant charFHigh : std_logic_vector(7 downto 0) := x"46";
|
79 |
|
|
constant charRHigh : std_logic_vector(7 downto 0) := x"52";
|
80 |
|
|
constant charWHigh : std_logic_vector(7 downto 0) := x"57";
|
81 |
|
|
constant charALow : std_logic_vector(7 downto 0) := x"61";
|
82 |
|
|
constant charBLow : std_logic_vector(7 downto 0) := x"62";
|
83 |
|
|
constant charCLow : std_logic_vector(7 downto 0) := x"63";
|
84 |
|
|
constant charDLow : std_logic_vector(7 downto 0) := x"64";
|
85 |
|
|
constant charELow : std_logic_vector(7 downto 0) := x"65";
|
86 |
|
|
constant charFLow : std_logic_vector(7 downto 0) := x"66";
|
87 |
|
|
constant charRLow : std_logic_vector(7 downto 0) := x"72";
|
88 |
|
|
constant charWLow : std_logic_vector(7 downto 0) := x"77";
|
89 |
|
|
|
90 |
|
|
-- binary extension mode commands - the command is indicated by bits 5:4 of the command byte
|
91 |
|
|
constant binCmdNop : std_logic_vector(1 downto 0) := "00";
|
92 |
|
|
constant binCmdRead : std_logic_vector(1 downto 0) := "01";
|
93 |
|
|
constant binCmdWrite : std_logic_vector(1 downto 0) := "10";
|
94 |
|
|
|
95 |
|
|
signal dataInHexRange : std_logic; -- indicates that the received data is in the range of hex number
|
96 |
|
|
signal binLastByte : std_logic; -- last byte flag indicates that the current byte in the command is the last
|
97 |
|
|
signal txEndP : std_logic; -- transmission end pulse
|
98 |
|
|
signal readOp : std_logic; -- read operation flag
|
99 |
|
|
signal writeOp : std_logic; -- write operation flag
|
100 |
|
|
signal binReadOp : std_logic; -- binary mode read operation flag
|
101 |
|
|
signal binWriteOp : std_logic; -- binary mode write operation flag
|
102 |
|
|
signal sendStatFlag : std_logic; -- send status flag
|
103 |
|
|
signal addrAutoInc : std_logic; -- address auto increment mode
|
104 |
|
|
signal dataParam : std_logic_vector(7 downto 0); -- operation data parameter
|
105 |
|
|
signal dataNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
106 |
|
|
signal addrParam : std_logic_vector(15 downto 0); -- operation address parameter
|
107 |
|
|
signal addrNibble : std_logic_vector(3 downto 0); -- data nibble from received character
|
108 |
|
|
signal binByteCount : std_logic_vector(7 downto 0); -- binary mode byte counter
|
109 |
|
|
signal iIntAddress : std_logic_vector(intAddress'range); --
|
110 |
11 |
smuller |
signal iWriteReq : std_logic; --
|
111 |
6 |
smuller |
signal iIntWrite : std_logic; --
|
112 |
|
|
signal readDone : std_logic; -- internally generated read done flag
|
113 |
|
|
signal readDoneS : std_logic; -- sampled read done
|
114 |
|
|
signal readDataS : std_logic_vector(7 downto 0); -- sampled read data
|
115 |
11 |
smuller |
signal iReadReq : std_logic; --
|
116 |
6 |
smuller |
signal iIntRead : std_logic; --
|
117 |
|
|
signal txChar : std_logic_vector(7 downto 0); -- transmit byte from nibble to character conversion
|
118 |
|
|
signal sTxBusy : std_logic; -- sampled tx_busy for falling edge detection
|
119 |
|
|
signal txNibble : std_logic_vector(3 downto 0); -- nibble value for transmission
|
120 |
|
|
|
121 |
|
|
-- module implementation
|
122 |
|
|
-- main state machine
|
123 |
|
|
begin
|
124 |
|
|
process (clr, clk)
|
125 |
|
|
begin
|
126 |
|
|
if (clr = '1') then
|
127 |
|
|
mainSm <= mainIdle;
|
128 |
|
|
elsif (rising_edge(clk)) then
|
129 |
|
|
if (newRxData = '1') then
|
130 |
|
|
case mainSm is
|
131 |
|
|
-- wait for a read ('r') or write ('w') command
|
132 |
|
|
-- binary extension - an all zeros byte enabled binary commands
|
133 |
|
|
when mainIdle =>
|
134 |
|
|
-- check received character
|
135 |
|
|
if (rxData = charNul) then
|
136 |
|
|
-- an all zeros received byte enters binary mode
|
137 |
|
|
mainSm <= mainBinCmd;
|
138 |
|
|
elsif ((rxData = charRLow) or (rxData = charRHigh)) then
|
139 |
|
|
-- on read wait to receive only address field
|
140 |
|
|
mainSm <= mainWhite2;
|
141 |
|
|
elsif ((rxData = charWLow) or (rxData = charWHigh)) then
|
142 |
|
|
-- on write wait to receive data and address
|
143 |
|
|
mainSm <= mainWhite1;
|
144 |
|
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
145 |
|
|
-- on new line sta in idle
|
146 |
|
|
mainSm <= mainIdle;
|
147 |
|
|
else
|
148 |
|
|
-- any other character wait to end of line (EOL)
|
149 |
|
|
mainSm <= mainEol;
|
150 |
|
|
end if;
|
151 |
|
|
-- wait for white spaces till first data nibble
|
152 |
|
|
when mainWhite1 =>
|
153 |
|
|
-- wait in this case until any white space character is received. in any
|
154 |
|
|
-- valid character for data value switch to data state. a new line or carriage
|
155 |
|
|
-- return should reset the state machine to idle.
|
156 |
|
|
-- any other character transitions the state machine to wait for EOL.
|
157 |
|
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
158 |
|
|
mainSm <= mainWhite1;
|
159 |
|
|
elsif (dataInHexRange = '1') then
|
160 |
|
|
mainSm <= mainData;
|
161 |
|
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
162 |
|
|
mainSm <= mainIdle;
|
163 |
|
|
else
|
164 |
|
|
mainSm <= mainEol;
|
165 |
|
|
end if;
|
166 |
|
|
-- receive data field
|
167 |
|
|
when mainData =>
|
168 |
|
|
-- wait while data in hex range. white space transition to wait white 2 state.
|
169 |
|
|
-- CR and LF resets the state machine. any other value cause state machine to
|
170 |
|
|
-- wait til end of line.
|
171 |
|
|
if (dataInHexRange = '1') then
|
172 |
|
|
mainSm <= mainData;
|
173 |
|
|
elsif ((rxData = charSpace) or (rxData = charTab)) then
|
174 |
|
|
mainSm <= mainWhite2;
|
175 |
|
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
176 |
|
|
mainSm <= mainIdle;
|
177 |
|
|
else
|
178 |
|
|
mainSm <= mainEol;
|
179 |
|
|
end if;
|
180 |
|
|
-- wait for white spaces till first address nibble
|
181 |
|
|
when mainWhite2 =>
|
182 |
|
|
-- similar to MAIN_WHITE1
|
183 |
|
|
if ((rxData = charSpace) or (rxData = charTab)) then
|
184 |
|
|
mainSm <= mainWhite2;
|
185 |
|
|
elsif (dataInHexRange = '1') then
|
186 |
|
|
mainSm <= mainAddr;
|
187 |
|
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
188 |
|
|
mainSm <= mainIdle;
|
189 |
|
|
else
|
190 |
|
|
mainSm <= mainEol;
|
191 |
|
|
end if;
|
192 |
|
|
-- receive address field
|
193 |
|
|
when mainAddr =>
|
194 |
|
|
-- similar to MAIN_DATA
|
195 |
|
|
if (dataInHexRange = '1') then
|
196 |
|
|
mainSm <= mainAddr;
|
197 |
|
|
elsif ((rxData = charCR) or (rxData = charLF)) then
|
198 |
|
|
mainSm <= mainIdle;
|
199 |
|
|
else
|
200 |
|
|
mainSm <= mainEol;
|
201 |
|
|
end if;
|
202 |
|
|
-- wait to EOL
|
203 |
|
|
when mainEol =>
|
204 |
|
|
-- wait for CR or LF to move back to idle
|
205 |
|
|
if ((rxData = charCR) or (rxData = charLF)) then
|
206 |
|
|
mainSm <= mainIdle;
|
207 |
|
|
end if;
|
208 |
|
|
-- binary extension
|
209 |
|
|
-- wait for command - one byte
|
210 |
|
|
when mainBinCmd =>
|
211 |
|
|
-- check if command is a NOP command
|
212 |
|
|
if (rxData(5 downto 4) = binCmdNop) then
|
213 |
|
|
-- if NOP command then switch back to idle state
|
214 |
|
|
mainSm <= mainIdle;
|
215 |
|
|
else
|
216 |
|
|
-- not a NOP command, continue receiving parameters
|
217 |
|
|
mainSm <= mainBinAdrh;
|
218 |
|
|
end if;
|
219 |
|
|
-- wait for address parameter - two bytes
|
220 |
|
|
-- high address byte
|
221 |
|
|
when mainBinAdrh =>
|
222 |
|
|
-- switch to next state
|
223 |
|
|
mainSm <= mainBinAdrl;
|
224 |
|
|
-- low address byte
|
225 |
|
|
when mainBinAdrl =>
|
226 |
|
|
-- switch to next state
|
227 |
|
|
mainSm <= mainBinLen;
|
228 |
|
|
-- wait for length parameter - one byte
|
229 |
|
|
when mainBinLen =>
|
230 |
|
|
-- check if write command else command reception ended
|
231 |
|
|
if (binWriteOp = '1') then
|
232 |
|
|
-- wait for write data
|
233 |
|
|
mainSm <= mainBinData;
|
234 |
|
|
else
|
235 |
|
|
-- command reception has ended
|
236 |
|
|
mainSm <= mainIdle;
|
237 |
|
|
end if;
|
238 |
|
|
-- on write commands wait for data till end of buffer as specified by length parameter
|
239 |
|
|
when mainBinData =>
|
240 |
|
|
-- if this is the last data byte then return to idle
|
241 |
|
|
if (binLastByte = '1') then
|
242 |
|
|
mainSm <= mainIdle;
|
243 |
|
|
end if;
|
244 |
|
|
-- go to idle
|
245 |
|
|
when others =>
|
246 |
|
|
mainSm <= mainIdle;
|
247 |
|
|
end case;
|
248 |
|
|
end if;
|
249 |
|
|
end if;
|
250 |
|
|
end process;
|
251 |
|
|
-- read operation flag
|
252 |
|
|
-- write operation flag
|
253 |
|
|
-- binary mode read operation flag
|
254 |
|
|
-- binary mode write operation flag
|
255 |
|
|
process (clr, clk)
|
256 |
|
|
begin
|
257 |
|
|
if (clr = '1') then
|
258 |
|
|
readOp <= '0';
|
259 |
|
|
writeOp <= '0';
|
260 |
|
|
binReadOp <= '0';
|
261 |
|
|
binWriteOp <= '0';
|
262 |
|
|
elsif (rising_edge(clk)) then
|
263 |
|
|
if ((mainSm = mainIdle) and (newRxData = '1')) then
|
264 |
|
|
-- the read operation flag is set when a read command is received in idle state and cleared
|
265 |
|
|
-- if any other character is received during that state.
|
266 |
|
|
if ((rxData = charRLow) or (rxData = charRHigh)) then
|
267 |
|
|
readOp <= '1';
|
268 |
|
|
else
|
269 |
|
|
readOp <= '0';
|
270 |
|
|
end if;
|
271 |
|
|
-- the write operation flag is set when a write command is received in idle state and cleared
|
272 |
|
|
-- if any other character is received during that state.
|
273 |
|
|
if ((rxData = charWLow) or (rxData = charWHigh)) then
|
274 |
|
|
writeOp <= '1';
|
275 |
|
|
else
|
276 |
|
|
writeOp <= '0';
|
277 |
|
|
end if;
|
278 |
|
|
end if;
|
279 |
|
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdRead)) then
|
280 |
|
|
-- read command is started on reception of a read command
|
281 |
|
|
binReadOp <= '1';
|
282 |
|
|
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '1')) then
|
283 |
|
|
-- read command ends on transmission of the last byte read
|
284 |
|
|
binReadOp <= '0';
|
285 |
|
|
end if;
|
286 |
|
|
if ((mainSm = mainBinCmd) and (newRxData = '1') and (rxData(5 downto 4) = binCmdWrite)) then
|
287 |
|
|
-- write command is started on reception of a write command
|
288 |
|
|
binWriteOp <= '1';
|
289 |
|
|
elsif ((mainSm = mainBinData) and (newRxData = '1') and (binLastByte = '1')) then
|
290 |
|
|
binWriteOp <= '0';
|
291 |
|
|
end if;
|
292 |
|
|
end if;
|
293 |
|
|
end process;
|
294 |
|
|
-- send status flag - used only in binary extension mode
|
295 |
|
|
-- address auto increment - used only in binary extension mode
|
296 |
|
|
process (clr, clk)
|
297 |
|
|
begin
|
298 |
|
|
if (clr = '1') then
|
299 |
|
|
sendStatFlag <= '0';
|
300 |
|
|
addrAutoInc <= '0';
|
301 |
|
|
elsif (rising_edge(clk)) then
|
302 |
|
|
if ((mainSm = mainBinCmd) and (newRxData = '1')) then
|
303 |
|
|
-- check if a status byte should be sent at the end of the command
|
304 |
|
|
sendStatFlag <= rxData(0);
|
305 |
|
|
-- check if address should be automatically incremented or not.
|
306 |
|
|
-- Note that when rx_data[1] is set, address auto increment is disabled.
|
307 |
|
|
addrAutoInc <= not(rxData(1));
|
308 |
|
|
end if;
|
309 |
|
|
end if;
|
310 |
|
|
end process;
|
311 |
|
|
-- operation data parameter
|
312 |
|
|
process (clr, clk)
|
313 |
|
|
begin
|
314 |
|
|
if (clr = '1') then
|
315 |
|
|
dataParam <= (others => '0');
|
316 |
|
|
elsif (rising_edge(clk)) then
|
317 |
|
|
if ((mainSm = mainWhite1) and (newRxData = '1') and (dataInHexRange = '1')) then
|
318 |
|
|
dataParam <= "0000" & dataNibble;
|
319 |
|
|
elsif ((mainSm = mainData) and (newRxData = '1') and (dataInHexRange = '1')) then
|
320 |
|
|
dataParam <= dataParam(3 downto 0) & dataNibble;
|
321 |
|
|
end if;
|
322 |
|
|
end if;
|
323 |
|
|
end process;
|
324 |
|
|
-- operation address parameter
|
325 |
|
|
process (clr, clk)
|
326 |
|
|
begin
|
327 |
|
|
if (clr = '1') then
|
328 |
|
|
addrParam <= (others => '0');
|
329 |
|
|
elsif (rising_edge(clk)) then
|
330 |
|
|
if ((mainSm = mainWhite2) and (newRxData = '1') and (dataInHexRange = '1')) then
|
331 |
|
|
addrParam <= x"000" & dataNibble;
|
332 |
|
|
elsif ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '1')) then
|
333 |
|
|
addrParam <= addrParam(11 downto 0) & dataNibble;
|
334 |
|
|
-- binary extension
|
335 |
|
|
elsif (mainSm = mainBinAdrh) then
|
336 |
|
|
addrParam(15 downto 8) <= rxData;
|
337 |
|
|
elsif (mainSm = mainBinAdrl) then
|
338 |
|
|
addrParam(7 downto 0) <= rxData;
|
339 |
|
|
end if;
|
340 |
|
|
end if;
|
341 |
|
|
end process;
|
342 |
|
|
-- binary mode command byte counter is loaded with the length parameter and counts down to zero.
|
343 |
|
|
-- NOTE: a value of zero for the length parameter indicates a command of 256 bytes.
|
344 |
|
|
process (clr, clk)
|
345 |
|
|
begin
|
346 |
|
|
if (clr = '1') then
|
347 |
|
|
binByteCount <= (others => '0');
|
348 |
|
|
elsif (rising_edge(clk)) then
|
349 |
|
|
if ((mainSm = mainBinLen) and (newRxData = '1')) then
|
350 |
|
|
binByteCount <= rxData;
|
351 |
|
|
elsif (((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) or ((binReadOp = '1') and (txEndP = '1'))) then
|
352 |
|
|
-- byte counter is updated on every new data received in write operations and for every
|
353 |
|
|
-- byte transmitted for read operations.
|
354 |
|
|
binByteCount <= binByteCount - 1;
|
355 |
|
|
end if;
|
356 |
|
|
end if;
|
357 |
|
|
end process;
|
358 |
|
|
-- internal write control and data
|
359 |
|
|
-- internal read control
|
360 |
|
|
process (clr, clk)
|
361 |
|
|
begin
|
362 |
|
|
if (clr = '1') then
|
363 |
11 |
smuller |
iReadReq <= '0';
|
364 |
6 |
smuller |
iIntRead <= '0';
|
365 |
11 |
smuller |
iWriteReq <= '0';
|
366 |
6 |
smuller |
iIntWrite <= '0';
|
367 |
|
|
intWrData <= (others => '0');
|
368 |
|
|
elsif (rising_edge(clk)) then
|
369 |
|
|
if ((mainSm = mainAddr) and (writeOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
370 |
11 |
smuller |
iWriteReq <= '1';
|
371 |
6 |
smuller |
intWrData <= dataParam;
|
372 |
|
|
-- binary extension mode
|
373 |
|
|
elsif ((mainSm = mainBinData) and (binWriteOp = '1') and (newRxData = '1')) then
|
374 |
11 |
smuller |
iWriteReq <= '1';
|
375 |
|
|
intWrData <= rxData;
|
376 |
|
|
elsif ((intGnt = '1') and (iWriteReq = '1')) then
|
377 |
|
|
iWriteReq <= '0';
|
378 |
6 |
smuller |
iIntWrite <= '1';
|
379 |
|
|
else
|
380 |
|
|
iIntWrite <= '0';
|
381 |
|
|
end if;
|
382 |
|
|
if ((mainSm = mainAddr) and (readOp = '1') and (newRxData = '1') and (dataInHexRange = '0')) then
|
383 |
11 |
smuller |
iReadReq <= '1';
|
384 |
6 |
smuller |
-- binary extension
|
385 |
|
|
elsif ((mainSm = mainBinLen) and (binReadOp = '1') and (newRxData = '1')) then
|
386 |
|
|
-- the first read request is issued on reception of the length byte
|
387 |
11 |
smuller |
iReadReq <= '1';
|
388 |
6 |
smuller |
elsif ((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) then
|
389 |
|
|
-- the next read requests are issued after the previous read value was transmitted and
|
390 |
|
|
-- this is not the last byte to be read.
|
391 |
11 |
smuller |
iReadReq <= '1';
|
392 |
|
|
elsif ((intGnt = '1') and (iReadReq = '1')) then
|
393 |
|
|
iReadReq <= '0';
|
394 |
6 |
smuller |
iIntRead <= '1';
|
395 |
|
|
else
|
396 |
|
|
iIntRead <= '0';
|
397 |
|
|
end if;
|
398 |
|
|
end if;
|
399 |
|
|
end process;
|
400 |
|
|
-- internal address
|
401 |
|
|
process (clr, clk)
|
402 |
|
|
begin
|
403 |
|
|
if (clr = '1') then
|
404 |
|
|
iIntAddress <= (others => '0');
|
405 |
|
|
elsif (rising_edge(clk)) then
|
406 |
|
|
if ((mainSm = mainAddr) and (newRxData = '1') and (dataInHexRange = '0')) then
|
407 |
|
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
408 |
|
|
-- binary extension
|
409 |
|
|
elsif ((mainSm = mainBinLen) and (newRxData = '1')) then
|
410 |
|
|
-- sample address parameter on reception of length byte
|
411 |
|
|
iIntAddress <= addrParam(AW - 1 downto 0);
|
412 |
|
|
elsif ((addrAutoInc = '1') and (((binReadOp = '1') and (txEndP = '1') and (binLastByte = '0')) or ((binWriteOp = '1') and (iIntWrite = '1')))) then
|
413 |
|
|
-- address is incremented on every read or write if enabled
|
414 |
|
|
iIntAddress <= iIntAddress + 1;
|
415 |
|
|
end if;
|
416 |
|
|
end if;
|
417 |
|
|
end process;
|
418 |
|
|
-- read done flag and sampled data read
|
419 |
|
|
process (clr, clk)
|
420 |
|
|
begin
|
421 |
|
|
if (clr = '1') then
|
422 |
|
|
readDone <= '0';
|
423 |
|
|
readDoneS <= '0';
|
424 |
|
|
readDataS <= (others => '0');
|
425 |
|
|
elsif (rising_edge(clk)) then
|
426 |
|
|
-- read done flag
|
427 |
|
|
readDone <= iIntRead;
|
428 |
|
|
-- sampled read done
|
429 |
|
|
readDoneS <= readDone;
|
430 |
|
|
-- sampled data read
|
431 |
|
|
if (readDone = '1') then
|
432 |
|
|
readDataS <= intRdData;
|
433 |
|
|
end if;
|
434 |
|
|
end if;
|
435 |
|
|
end process;
|
436 |
|
|
-- transmit state machine and control
|
437 |
|
|
process (clr, clk)
|
438 |
|
|
begin
|
439 |
|
|
if (clr = '1') then
|
440 |
|
|
txSm <= txIdle;
|
441 |
|
|
txData <= (others => '0');
|
442 |
|
|
newTxData <= '0';
|
443 |
|
|
elsif (rising_edge(clk)) then
|
444 |
|
|
case txSm is
|
445 |
|
|
-- wait for read done indication
|
446 |
|
|
when txIdle =>
|
447 |
|
|
-- on end of every read operation check how the data read should be transmitted
|
448 |
|
|
-- according to read type: ascii or binary.
|
449 |
|
|
if (readDoneS = '1') then
|
450 |
|
|
-- on binary mode read transmit byte value
|
451 |
|
|
if (binReadOp = '1') then
|
452 |
|
|
-- note that there is no need to change state
|
453 |
|
|
txData <= readDataS;
|
454 |
|
|
newTxData <= '1';
|
455 |
|
|
else
|
456 |
|
|
txSm <= txHiNib;
|
457 |
|
|
txData <= txChar;
|
458 |
|
|
newTxData <= '1';
|
459 |
|
|
end if;
|
460 |
|
|
-- check if status byte should be transmitted
|
461 |
|
|
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
|
462 |
|
|
-- send status byte - currently a constant
|
463 |
|
|
txData <= x"5A";
|
464 |
|
|
newTxData <= '1';
|
465 |
|
|
else
|
466 |
|
|
newTxData <= '0';
|
467 |
|
|
end if;
|
468 |
|
|
when txHiNib =>
|
469 |
|
|
-- wait for transmit to end
|
470 |
|
|
if (txEndP = '1') then
|
471 |
|
|
txSm <= txLoNib;
|
472 |
|
|
txData <= txChar;
|
473 |
|
|
newTxData <= '1';
|
474 |
|
|
else
|
475 |
|
|
newTxData <= '0';
|
476 |
|
|
end if;
|
477 |
|
|
-- wait for transmit to end
|
478 |
|
|
when txLoNib =>
|
479 |
|
|
if (txEndP = '1') then
|
480 |
|
|
txSm <= txCharCR;
|
481 |
|
|
txData <= charCR;
|
482 |
|
|
newTxData <= '1';
|
483 |
|
|
else
|
484 |
|
|
newTxData <= '0';
|
485 |
|
|
end if;
|
486 |
|
|
-- wait for transmit to end
|
487 |
|
|
when txCharCR =>
|
488 |
|
|
if (txEndP = '1') then
|
489 |
|
|
txSm <= txCharLF;
|
490 |
|
|
txData <= charLF;
|
491 |
|
|
newTxData <= '1';
|
492 |
|
|
else
|
493 |
|
|
newTxData <= '0';
|
494 |
|
|
end if;
|
495 |
|
|
-- wait for transmit to end
|
496 |
|
|
when txCharLF =>
|
497 |
|
|
if (txEndP = '1') then
|
498 |
|
|
txSm <= txIdle;
|
499 |
|
|
end if;
|
500 |
|
|
-- clear tx new data flag
|
501 |
|
|
newTxData <= '0';
|
502 |
|
|
-- return to idle
|
503 |
|
|
when others =>
|
504 |
|
|
txSm <= txIdle;
|
505 |
|
|
end case;
|
506 |
|
|
end if;
|
507 |
|
|
end process;
|
508 |
|
|
-- sampled tx_busy
|
509 |
|
|
process (clr, clk)
|
510 |
|
|
begin
|
511 |
|
|
if (clr = '1') then
|
512 |
|
|
sTxBusy <= '1';
|
513 |
|
|
elsif (rising_edge(clk)) then
|
514 |
|
|
sTxBusy <= txBusy;
|
515 |
|
|
end if;
|
516 |
|
|
end process;
|
517 |
|
|
-- indicates that the received data is in the range of hex number
|
518 |
|
|
dataInHexRange <= '1' when (((rxData >= charZero) and (rxData <= charNine)) or
|
519 |
|
|
((rxData >= charAHigh) and (rxData <= charFHigh)) or
|
520 |
|
|
((rxData >= charALow) and (rxData <= charFLow))) else '0';
|
521 |
|
|
-- last byte in command flag
|
522 |
|
|
binLastByte <= '1' when (binByteCount = x"01") else '0';
|
523 |
|
|
-- select the nibble to the nibble to character conversion
|
524 |
|
|
txNibble <= readDataS(3 downto 0) when (txSm = txHiNib) else readDataS(7 downto 4);
|
525 |
|
|
-- tx end pulse
|
526 |
|
|
txEndP <= '1' when ((txBusy = '0') and (sTxBusy = '1')) else '0';
|
527 |
|
|
-- character to nibble conversion
|
528 |
|
|
with rxData select
|
529 |
|
|
dataNibble <= x"0" when charZero,
|
530 |
|
|
x"1" when charOne,
|
531 |
|
|
x"2" when charTwo,
|
532 |
|
|
x"3" when charThree,
|
533 |
|
|
x"4" when charFour,
|
534 |
|
|
x"5" when charFive,
|
535 |
|
|
x"6" when charSix,
|
536 |
|
|
x"7" when charSeven,
|
537 |
|
|
x"8" when charEight,
|
538 |
|
|
x"9" when charNine,
|
539 |
|
|
x"A" when charALow,
|
540 |
|
|
x"A" when charAHigh,
|
541 |
|
|
x"B" when charBLow,
|
542 |
|
|
x"B" when charBHigh,
|
543 |
|
|
x"C" when charCLow,
|
544 |
|
|
x"C" when charCHigh,
|
545 |
|
|
x"D" when charDLow,
|
546 |
|
|
x"D" when charDHigh,
|
547 |
|
|
x"E" when charELow,
|
548 |
|
|
x"E" when charEHigh,
|
549 |
|
|
x"F" when charFLow,
|
550 |
|
|
x"F" when charFHigh,
|
551 |
|
|
x"F" when others;
|
552 |
|
|
-- nibble to character conversion
|
553 |
|
|
with txNibble select
|
554 |
|
|
txChar <= charZero when x"0",
|
555 |
|
|
charOne when x"1",
|
556 |
|
|
charTwo when x"2",
|
557 |
|
|
charThree when x"3",
|
558 |
|
|
charFour when x"4",
|
559 |
|
|
charFive when x"5",
|
560 |
|
|
charSix when x"6",
|
561 |
|
|
charSeven when x"7",
|
562 |
|
|
charEight when x"8",
|
563 |
|
|
charNine when x"9",
|
564 |
|
|
charAHigh when x"A",
|
565 |
|
|
charBHigh when x"B",
|
566 |
|
|
charCHigh when x"C",
|
567 |
|
|
charDHigh when x"D",
|
568 |
|
|
charEHigh when x"E",
|
569 |
|
|
charFHigh when x"F",
|
570 |
|
|
charFHigh when others;
|
571 |
|
|
intAddress <= iIntAddress;
|
572 |
|
|
intWrite <= iIntWrite;
|
573 |
|
|
intRead <= iIntRead;
|
574 |
11 |
smuller |
intReq <= '1' when (iReadReq = '1') else
|
575 |
|
|
'1' when (iWriteReq = '1') else '0';
|
576 |
6 |
smuller |
end Behavioral;
|