SURF  1.0
UartAxiLiteMaster.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : UartAxiLiteMaster.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2016-06-09
5 -- Last update: 2016-06-29
6 -------------------------------------------------------------------------------
7 -- Description: Ties together everything needed for a full duplex UART.
8 -- This includes Baud Rate Generator, Transmitter, Receiver and FIFOs.
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_arith.all;
22 use ieee.std_logic_unsigned.all;
23 
24 use work.StdRtlPkg.all;
25 use work.TextUtilPkg.all;
26 use work.AxiLitePkg.all;
27 use work.AxiLiteMasterPkg.all;
28 
29 --! @see entity
30  --! @ingroup protocols_uart
32 
33  generic (
34  TPD_G : time := 1 ns;
35  AXIL_CLK_FREQ_G : real := 125.0e6;
36  BAUD_RATE_G : integer := 115200;
37  FIFO_BRAM_EN_G : boolean := false;
38  FIFO_ADDR_WIDTH_G : integer range 4 to 48 := 5);
39  port (
40  axilClk : in sl;
41  axilRst : in sl;
42  -- Transmit parallel interface
47  -- Serial IO
48  tx : out sl;
49  rx : in sl);
50 
51 end entity UartAxiLiteMaster;
52 
53 architecture rtl of UartAxiLiteMaster is
54 
55  type StateType is (
56  WAIT_START_S,
57  SPACE_ADDR_S,
58  ADDR_SPACE_S,
59  WR_DATA_S,
60  WAIT_EOL_S,
61  AXIL_TXN_S,
62  RD_DATA_SPACE_S,
63  RD_DATA_S,
64  DONE_S);
65 
66  type RegType is record
67  state : StateType;
68  count : slv(2 downto 0);
69  axilReq : AxiLiteMasterReqType;
70  rdData : slv(31 downto 0);
71  uartTxData : slv(7 downto 0);
72  uartTxValid : sl;
73  uartRxReady : sl;
74  end record RegType;
75 
76  constant REG_INIT_C : RegType := (
77  state => WAIT_START_S,
78  count => (others => '0'),
79  axilReq => AXI_LITE_MASTER_REQ_INIT_C,
80  rdData => (others => '0'),
81  uartTxData => (others => '0'),
82  uartTxValid => '0',
83  uartRxReady => '1');
84 
85  signal r : RegType := REG_INIT_C;
86  signal rin : RegType;
87 
88 -- signal axilReq : AxiLiteMasterReqType;
89  signal axilAck : AxiLiteMasterAckType;
90 
91  signal uartRxData : slv(7 downto 0);
92  signal uartRxValid : sl;
93 -- signal uartRxReady : sl;
94 
95 -- signal uartTxData : slv(7 downto 0);
96 -- signal uartTxValid : sl;
97  signal uartTxReady : sl;
98 
99  -- translate a hex character 0-9 A-F into an slv
100  function hexToSlv (hex : slv(7 downto 0)) return slv is
101  variable char : character;
102  begin
103  char := character'val(conv_integer(hex));
104 
105  return toSlv(int(char), 4);
106 
107  end function;
108 
109  function slvToHex (nibble : slv(3 downto 0)) return slv is
110  begin
111  return toSlv(character'pos(chr(conv_integer(nibble))), 8);
112  end function;
113 
114 begin
115 
116  -------------------------------------------------------------------------------------------------
117  -- Instantiate UART
118  -------------------------------------------------------------------------------------------------
119  U_UartWrapper_1 : entity work.UartWrapper
120  generic map (
121  TPD_G => TPD_G,
126  port map (
127  clk => axilClk, -- [in]
128  rst => axilRst, -- [in]
129  wrData => r.uartTxData, -- [in]
130  wrValid => r.uartTxValid, -- [in]
131  wrReady => uartTxReady, -- [out]
132  rdData => uartRxData, -- [out]
133  rdValid => uartRxValid, -- [out]
134  rdReady => r.uartRxReady, -- [in]
135  tx => tx, -- [out]
136  rx => rx); -- [in]
137 
138  U_AxiLiteMaster_1 : entity work.AxiLiteMaster
139  generic map (
140  TPD_G => TPD_G)
141  port map (
142  axilClk => axilClk, -- [in]
143  axilRst => axilRst, -- [in]
144  req => r.axilReq, -- [in]
145  ack => axilAck, -- [out]
146  axilWriteMaster => mAxilWriteMaster, -- [out]
147  axilWriteSlave => mAxilWriteSlave, -- [in]
148  axilReadMaster => mAxilReadMaster, -- [out]
149  axilReadSlave => mAxilReadSlave); -- [in]
150 
151  comb : process (axilAck, axilRst, r, uartRxData, uartRxValid, uartTxReady) is
152  variable v : RegType;
153 
154  procedure uartTx (byte : in slv(7 downto 0)) is
155  begin
156  v.uartTxValid := '1';
157  v.uartTxData := byte;
158  end procedure uartTx;
159 
160  procedure uartTx (char : in character) is
161  begin
162  uartTx(toSlv(character'pos(char), 8));
163  end procedure uartTx;
164 
165  function isSpace (byte : slv(7 downto 0)) return boolean is
166  begin
167  return (byte = character'pos(' '));
168  end function isSpace;
169 
170  function isEOL (byte : slv(7 downto 0)) return boolean is
171  begin
172  return (byte = character'pos(CR) or
173  byte = character'pos(LF));
174  end function isEOL;
175 
176  begin
177  v := r;
178 
179  -- Format:
180  -- "w|W ADDRHEX DATAHEX0 [DATAHEX1] [DATAHEX2]...\r|\n"
181  -- Writes echo'd back with resp code
182  -- "r|R ADDRHEX [NUMREADSHEX] \r|\n"
183  -- Resp: "r|R ADDRHEX DATAHEX0 [DATAHEX1] [DATAHEX2]...\r|\n"
184  -- Blank lines ignored
185  -- Extra words ignored.
186 
187  -- Auto clear uartTxValid upton uartTxReady
188  if (uartTxReady = '1') then
189  v.uartTxValid := '0';
190  end if;
191 
192  case r.state is
193  when WAIT_START_S =>
194  -- Any characters before 'r' or 'w' are thrown out
195  if (uartRxValid = '1') then
196  if (uartRxData = toSlv(character'pos('w'), 8) or
197  uartRxData = toSlv(character'pos('W'), 8)) then
198  -- Write op
199  v.axilReq.rnw := '0';
200  uartTx(uartRxData);
201  v.state := SPACE_ADDR_S;
202  elsif (uartRxData = toSlv(character'pos('r'), 8) or
203  uartRxData = toSlv(character'pos('R'), 8)) then
204  -- Read
205  v.axilReq.rnw := '1';
206  uartTx(uartRxData);
207  v.state := SPACE_ADDR_S;
208  end if;
209  end if;
210 
211  when SPACE_ADDR_S =>
212  -- Need to check for the space after opcode
213  if (uartRxValid = '1') then
214  uartTx(uartRxData);
215  v.state := ADDR_SPACE_S;
216  v.axilReq.address := r.axilReq.address(27 downto 0) & hexToSlv(uartRxData);
217 
218  -- Ignore character if its a space
219  if (isSpace(uartRxData)) then
220  v.axilReq.address := r.axilReq.address;
221  end if;
222 
223  -- Go back to start if EOL
224  if (isEOL(uartRxData)) then
225  v.state := WAIT_START_S;
226  end if;
227  end if;
228 
229 
230  when ADDR_SPACE_S =>
231  if (uartRxValid = '1') then
232  uartTx(uartRxData);
233  v.axilReq.address := r.axilReq.address(27 downto 0) & hexToSlv(uartRxData);
234 
235  -- Space indicates end of addr word
236  if (isSpace(uartRxData)) then
237  v.axilReq.address := r.axilReq.address;
238  if (r.axilReq.rnw = '0') then
239  v.state := WR_DATA_S;
240  else
241  v.state := WAIT_EOL_S;
242  end if;
243  end if;
244 
245  -- Go back to start if EOL and write op
246  -- Else do the read op
247  if (isEOL(uartRxData)) then
248  if (r.axilReq.rnw = '0') then
249  v.state := WAIT_START_S;
250  else
251  v.axilReq.address := r.axilReq.address;
252  uartTx(' ');
253  v.state := AXIL_TXN_S;
254  end if;
255  end if;
256 
257  end if;
258 
259  when WR_DATA_S =>
260  if (uartRxValid = '1') then
261  uartTx(uartRxData);
262  v.axilReq.wrData := r.axilReq.wrData(27 downto 0) & hexToSlv(uartRxData);
263 
264  -- Space or EOL indicates end of wrData word
265  -- If space need to wait for EOL
266  if (isSpace(uartRxData)) then
267  v.axilReq.wrData := r.axilReq.wrData;
268  v.state := WAIT_EOL_S;
269  end if;
270 
271  -- If EOL can issue AXIL txn
272  if (isEOL(uartRxData)) then
273  v.axilReq.wrData := r.axilReq.wrData;
274  uartTx(' ');
275  v.state := AXIL_TXN_S;
276  end if;
277  end if;
278 
279  when WAIT_EOL_S =>
280  -- Issue AXIL TXN once EOL seen
281  -- Any other charachters are echo'd but otherwise ignored
282  if (uartRxValid = '1') then
283  uartTx(uartRxData);
284  if (isEOL(uartRxData)) then
285  uartTx(' ');
286  v.state := AXIL_TXN_S;
287  end if;
288  end if;
289 
290  when AXIL_TXN_S =>
291  -- Transmit a space on first cycle of this state
292  if (r.axilReq.request = '0' and r.axilReq.rnw = '0') then
293  uartTx(' ');
294  end if;
295 
296  -- Assert request and wait for response
297  v.axilReq.request := '1';
298  if (axilAck.done = '1') then
299 
300  -- Done if write op, else transmit the read data
301  if (r.axilReq.rnw = '0') then
302  v.state := DONE_S;
303  else
304  --uartTx(' ');
305  v.rdData := axilAck.rdData;
306  v.state := RD_DATA_S;
307  end if;
308  end if;
309 
310 
311  when RD_DATA_S =>
312  v.count := r.count + 1;
313  uartTx(slvToHex(r.rdData(31 downto 28)));
314  v.rdData := r.rdData(27 downto 0) & "0000";
315  if (r.count = 7) then
316  v.state := RD_DATA_SPACE_S;
317  end if;
318 
319 
320  when RD_DATA_SPACE_S =>
321  uartTx(' ');
322  v.state := DONE_S;
323 
324  when DONE_S =>
325  -- Send resp code first cycle of this state
326  if (r.axilReq.request = '1') then
327  -- Send the response code
328  uartTx(slvToHex(resize(axilAck.resp, 4)));
329  end if;
330 
331  -- Release request and wait for done to fall
332  -- Send closing CR when it does
333  v.axilReq.request := '0';
334  if (axilAck.done = '0') then
335  uartTx(CR);
336  v.state := WAIT_START_S;
337  end if;
338 
339  end case;
340 
341  if (axilRst = '1') then
342  v := REG_INIT_C;
343  end if;
344 
345  rin <= v;
346  end process comb;
347 
348  seq : process (axilClk) is
349  begin
350  if (rising_edge(axilClk)) then
351  r <= rin after TPD_G;
352  end if;
353  end process seq;
354 
355 
356 end architecture rtl;
in wrValidsl
Definition: UartWrapper.vhd:41
AxiLiteMasterReqType :=(request => '0',rnw => '1',address =>( others => '0'),wrData =>( others => '0')) AXI_LITE_MASTER_REQ_INIT_C
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 5
FIFO_ADDR_WIDTH_Ginteger range 4 to 48:= 4
Definition: UartWrapper.vhd:35
out mAxilReadMasterAxiLiteReadMasterType
out axilWriteMasterAxiLiteWriteMasterType
out axilReadMasterAxiLiteReadMasterType
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
in axilWriteSlaveAxiLiteWriteSlaveType
in reqAxiLiteMasterReqType
out ackAxiLiteMasterAckType
in wrDataslv( 7 downto 0)
Definition: UartWrapper.vhd:40
slv( 1 downto 0) resp
in rdReadysl
Definition: UartWrapper.vhd:46
in mAxilWriteSlaveAxiLiteWriteSlaveType
slv( 31 downto 0) rdData
AXIL_CLK_FREQ_Greal := 125.0e6
out rdDataslv( 7 downto 0)
Definition: UartWrapper.vhd:44
FIFO_BRAM_EN_Gboolean := false
out wrReadysl
Definition: UartWrapper.vhd:42
out rdValidsl
Definition: UartWrapper.vhd:45
BAUD_RATE_Ginteger := 115200
Definition: UartWrapper.vhd:33
in mAxilReadSlaveAxiLiteReadSlaveType
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
TPD_Gtime := 1 ns
Definition: UartWrapper.vhd:31
_library_ ieeeieee
Definition: SspFramer.vhd:20
FIFO_BRAM_EN_Gboolean := false
Definition: UartWrapper.vhd:34
in axilReadSlaveAxiLiteReadSlaveType
CLK_FREQ_Greal := 125.0e6
Definition: UartWrapper.vhd:32
slv( 31 downto 0) wrData
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
slv( 31 downto 0) address
out mAxilWriteMasterAxiLiteWriteMasterType
BAUD_RATE_Ginteger := 115200
TPD_Gtime := 1 ns
std_logic_vector slv
Definition: StdRtlPkg.vhd:29