OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [peripherals/] [UART.py] - Blame information for rev 9

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sinclairrf
################################################################################
2
#
3 9 sinclairrf
# Copyright 2013-2015, Sinclair R.F., Inc.
4 2 sinclairrf
#
5
################################################################################
6
 
7
import math;
8
import re;
9
 
10
from ssbccPeripheral import SSBCCperipheral
11 9 sinclairrf
from ssbccUtil import CeilLog2
12
from ssbccUtil import SSBCCException
13 2 sinclairrf
 
14
class UART(SSBCCperipheral):
15
  """
16
  Transmit/receive UART:
17
    1 start bit
18
    8 data bits
19
    1 or 2 stop bits\n
20
  Usage:
21
    PERIPHERAL UART    inport=I_inport_name        \\
22
                       outport=O_outport_name      \\
23
                       inempty=I_inempty_name      \\
24
                       outstatus=I_outstatus_name  \\
25
                       baudmethod={clk/rate|count} \\
26
                       [insignal=i_name]           \\
27
                       [outsignal=o_name]          \\
28
                       [noSync|sync=n]             \\
29
                       [noDeglitch|deglitch=n]     \\
30
                       [noInFIFO|inFIFO=n]         \\
31
                       [noOutFIFO|outFIFO=n]       \\
32 6 sinclairrf
                       [{CTS|CTSn}=i_cts_name]     \\
33 9 sinclairrf
                       [{RTR|RTRn}=o_rtr_name]     \\
34
                       rtr_buffer=n                \\
35 6 sinclairrf
                       [nStop={1|2}]\n
36 2 sinclairrf
  Where:
37
    inport=I_inport_name
38
      specifies the symbol used by the inport instruction to read a received by
39
      from the peripheral
40
      Note:  The name must start with "I_".
41
    outport=O_outport_name
42
      specifies the symbol used by the outport instruction to write a byte to
43
      the peripheral
44
      Note:  The name must start with "O_".
45
    inempty=I_inempty_name
46
      specifies the symbol used by the inport instruction to get the empty
47
      status of the input side of the peripheral
48
      Note:  The name must start with "I_".
49
    outstatus=I_outstatus_name
50
      specifies the symbol used by the inport instruction to get the status of
51
      the output side of the peripheral
52
      Note:  The name must start with "I_".
53
    baudmethod
54
      specifies the method to generate the desired bit rate:
55
      1st method:  clk/rate
56
        clk is the frequency of "i_clk" in Hz
57
          a number will be interpreted as the clock frequency in Hz
58 9 sinclairrf
          a symbol will be interpreted as a constant or a parameter
59
            Note:  the symbol must be declared with the CONSTANT, LOCALPARARM,
60
                   or PARAMETER configuration command.
61 2 sinclairrf
        rate is the desired baud rate
62
          this is specified as per "clk"
63
      2nd method:
64
        specify the number of "i_clk" clock cycles between bit edges
65
      Note:  clk, rate, and count can be parameters or constants.  For example,
66
             the following uses the parameter G_CLK_FREQ_HZ for the clock
67
             frequency and a hard-wired baud rate of 9600:
68
             "baudmethod=G_CLK_FREQ_HZ/9600".
69
      Note:  The numeric values can have Verilog-style '_' separators between
70
             the digits.  For example, 100_000_000 represents 100 million.
71
    insignal=i_name
72
      optionally specifies the name of the single-bit transmit signal
73
      Default:  i_UART_Rx
74
    outsignal=o_name
75
      optionally specifies the name of the output signal
76
      Default:  o_UART_Tx
77
    noSync
78
      optionally state no synchronization or registration is performed on the
79
      input signal.
80
    sync=n
81
      optionally state that an n-bit synchronizer will be performed on the
82
      input signal.
83
      Note:  sync=3 is the default.
84
    noDeglitch
85
      optionally state that no deglitching is performed on the input signal.
86
      Note:  This is the default.
87
    deglitching=n
88
      optionally state that an n-bit deglitcher is performed on the input signal
89
      Note:  Deglitching consists of changing the output state when n
90
             successive input bits are in the opposite state.
91
    noInFIFO
92
      optionally state that the peripheral will not have an input FIFO
93
      Note:  This is the default.
94
    inFIFO=n
95
      optionally add a FIFO of depth n to the input side of the UART
96
      Note:  n must be a power of 2.
97
    noOutFIFO
98
      optionally state that the peripheral will not have an output FIFO
99
      Note:  This is the default.
100
    outFIFO=n
101
      optionally add a FIFO of depth n to the output side of the UART
102
      Note:  n must be a power of 2.
103 6 sinclairrf
    CTS=i_cts_name or CTSn=i_cts_name
104
      optionally specify an input handshake signal to control whether or not the
105
      peripheral transmits data
106
      Note:  If CTS is specified then the transmitter is active when i_cts_name
107
             is high.  If CTSn is specified then the transmitter is active when
108
             i_cts_name is low.
109
      Note:  The default, i.e., neither CTS nor CTSn is specified, is to always
110
             enable the transmitter.
111
      Note:  If there is no FIFO and the CTS/CTSn handshake indicates that the
112
             data flow is disabled, then the busy signal will be high and the
113
             processor code must not transmit the next byte.
114 9 sinclairrf
    RTR=o_rtr_name or RTRn=o_rtr_name
115 6 sinclairrf
      optionally specify an output handshake signal to indicate that the
116
      peripheral is ready to receive data
117
      Note:  If RTR is specified then the receiver indicates it is ready when
118 9 sinclairrf
             o_rtr_name is high.  If RTRn is specified then the transmitter
119
             indicates it is ready when o_rtr_name is low.
120 6 sinclairrf
      Note:  The default, i.e., neither CTS nor CTSn is specified, is to always
121
             enable the receiver.
122
      Note:  If there is no FIFO and the RTR/RTRn handshake indicates that the
123
             receiver is not ready as soon as it starts receiving data and
124
             until that data is read from the peripheral.
125 9 sinclairrf
    rtr_buffer=n
126
      optionally specify the number of entries in inFIFO to reserve for data
127
      received after the RTR/RTRn signal indicates to stop data flow.
128
      Note:  n must be a power of 2.
129
      Note:  This requires that inFIFO be specified.
130
      Note:  Some USB UARTs  will transmit several characters after the RTR/RTRn
131
             signal indicates to stop the data flow.
132 2 sinclairrf
    nStop=n
133
      optionally configure the peripheral for n stop bits
134
      default:  1 stop bit
135
      Note:  n must be 1 or 2
136 6 sinclairrf
      Note:  the peripheral does not accept 1.5 stop bits\n
137 2 sinclairrf
  The following ports are provided by this peripheral:
138
    I_inport_name
139
      input a recieved byte from the peripheral
140
      Note:  If there is no input FIFO, then this is the last received byte.
141
             If there is an input FIFO, then this is the next byte in the FIFO.
142
      Note:  If there is an input FIFO and the read would cause a FIFO
143
             underflow, this will repeat the last received byte.
144
    O_outport_name
145
      output the next 8-bit value to transmit or to queue for transmission
146
      Note:  If there is no output FIFO or if there is an output FIFO and this
147
             write would cause a FIFO overflow, then this byte will be
148
             discarded.
149
    I_inempty_name
150
      input the empty status of the input side of the peripheral
151
      bit 0:  input empty
152
        this bit will be high when the input side of the peripheral has one or
153
        more bytes read to be read
154
        Note:  If there is no FIFO this means that a single byte is ready to be
155
               read and has not been read.  If there is an input FIFO this
156
               means that there are one or more bytes in the FIFO.
157
        Note:  "Empty" is used rather than "ready" to facilitate loops that
158
               respond when there is a new byte ready to be processed.  See the
159
               examples below.
160
    I_outstatus_name
161
      input the status of the output side of the peripheral
162
      bit 0:  output busy
163
        this bit will be high when the output side of the peripheral cannot
164
        accept more writes
165
        Note:  If there is no FIFO this means that the peripheral is still
166
               transmitting the last byte.  If there is an output FIFO it means
167
               that it is full.\n
168
        Note:  "Busy" is used rather that "ready" to facilitate loops that wait
169 6 sinclairrf
               for a not-busy status to send the next byte.  See the examples below.\n
170 2 sinclairrf
  WARNING:  The peripheral is very simple and does not protect against writing a
171
            new value in the middle of a transmition or writing to a full FIFO.
172
            Adding such logic would be contrary to the design principle of
173
            keeping the HDL small and relying on the assembly code to provide
174
            the protection.\n
175
  Example:  Configure the UART for 115200 baud using a 100 MHz clock and
176
            transmit the message "Hello World!"\n
177
    Within the processor architecture file include the configuration command:\n
178
    PERIPHERAL UART_Tx O_UART_TX I_UART_TX baudmethod=100_000_000/115200\n
179
    Use the following assembly code to transmit the message "Hello World!".
180
    This transmits the entire message whether or not the peripheral has a FIFO.\n
181
    N"Hello World!\\r\\n"
182
      :loop .outport(O_UART_TX) :wait .inport(I_UART_TX_BUSY) .jumpc(wait) .jumpc(loop,nop) drop
183
  """
184
 
185
  def __init__(self,peripheralFile,config,param_list,loc):
186
    # Use the externally provided file name for the peripheral
187
    self.peripheralFile = peripheralFile;
188
    # Get the parameters.
189 6 sinclairrf
    allowables = (
190
      ( 'CTS',          r'i_\w+$',      None,           ),
191
      ( 'CTSn',         r'i_\w+$',      None,           ),
192
      ( 'RTR',          r'o_\w+$',      None,           ),
193
      ( 'RTRn',         r'o_\w+$',      None,           ),
194
      ( 'baudmethod',   r'\S+$',        lambda v : self.RateMethod(config,v), ),
195
      ( 'deglitch',     r'[1-9]\d*$',   int,            ),
196 9 sinclairrf
      ( 'inFIFO',       r'[1-9]\d*$',   lambda v : self.IntPow2Method(config,v), ),
197 6 sinclairrf
      ( 'inempty',      r'I_\w+$',      None,           ),
198
      ( 'inport',       r'I_\w+$',      None,           ),
199
      ( 'insignal',     r'i_\w+$',      None,           ),
200
      ( 'noDeglitch',   None,           None,           ),
201
      ( 'noInFIFO',     None,           None,           ),
202
      ( 'noOutFIFO',    None,           None,           ),
203
      ( 'noSync',       None,           None,           ),
204
      ( 'nStop',        r'[12]$',       int,            ),
205 9 sinclairrf
      ( 'outFIFO',      r'[1-9]\d*$',   lambda v : self.IntPow2Method(config,v), ),
206 6 sinclairrf
      ( 'outport',      r'O_\w+$',      None,           ),
207
      ( 'outsignal',    r'o_\w+$',      None,           ),
208
      ( 'outstatus',    r'I_\w+$',      None,           ),
209 9 sinclairrf
      ( 'rtr_buffer',   r'[1-9]\d*$',   lambda v : self.IntPow2Method(config,v), ),
210 6 sinclairrf
      ( 'sync',         r'[1-9]\d*$',   int,            ),
211
    );
212
    names = [a[0] for a in allowables];
213 2 sinclairrf
    for param_tuple in param_list:
214
      param = param_tuple[0];
215 6 sinclairrf
      if param not in names:
216
        raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
217
      param_test = allowables[names.index(param)];
218
      self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
219 2 sinclairrf
    # Ensure the required parameters are provided.
220
    for paramname in (
221
        'baudmethod',
222
        'inempty',
223
        'inport',
224
        'outport',
225
        'outstatus',
226
      ):
227
      if not hasattr(self,paramname):
228
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
229
    # Set optional parameters.
230
    for optionalpair in (
231 6 sinclairrf
        ( 'insignal',   'i_UART_Rx',    ),
232
        ( 'nStop',      1,              ),
233
        ( 'outsignal',  'o_UART_Tx',    ),
234 2 sinclairrf
      ):
235
      if not hasattr(self,optionalpair[0]):
236
        setattr(self,optionalpair[0],optionalpair[1]);
237 9 sinclairrf
    # Ensure the rtr_buffer, if specified, is consistent with the inFIFO
238
    # specification.
239
    if hasattr(self,'rtr_buffer'):
240
      if not hasattr(self,'inFIFO'):
241
        raise SSBCCException('rtr_buffer specification requires simultaneous inFIFO specification at %s' % loc);
242
      if self.rtr_buffer > self.inFIFO:
243
        raise SSBCCException('rtr_buffer=%d specification cannot exceed inFIFO=%d specification at %s' % (self.rtr_buffer,self.inFIFO,loc,));
244
    else:
245
      self.rtr_buffer = 1;
246
    # Ensure optional exclusive pair configurations are set and consistent.
247 2 sinclairrf
    for exclusivepair in (
248 6 sinclairrf
        ( 'CTS',        'CTSn',         None,           None,   ),
249
        ( 'RTR',        'RTRn',         None,           None,   ),
250
        ( 'noSync',     'sync',         'sync',         3,      ),
251
        ( 'noDeglitch', 'deglitch',     'noDeglitch',   True,   ),
252
        ( 'noInFIFO',   'inFIFO',       'noInFIFO',     True,   ),
253
        ( 'noOutFIFO',  'outFIFO',      'noOutFIFO',    True,   ),
254 2 sinclairrf
      ):
255
      if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
256
        raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
257 6 sinclairrf
      if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]) and exclusivepair[2]:
258 2 sinclairrf
        setattr(self,exclusivepair[2],exclusivepair[3]);
259 6 sinclairrf
    # Convert configurations to alternative format.
260
    for equivalent in (
261
        ( 'noDeglitch', 'deglitch',     0,      ),
262
        ( 'noInFIFO',   'inFIFO',       0,      ),
263
        ( 'noOutFIFO',  'outFIFO',      0,      ),
264
        ( 'noSync',     'sync',         0,      ),
265
      ):
266
      if hasattr(self,equivalent[0]):
267
        delattr(self,equivalent[0]);
268
        setattr(self,equivalent[1],equivalent[2]);
269 2 sinclairrf
    # Set the string used to identify signals associated with this peripheral.
270
    self.namestring = self.outsignal;
271
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
272 6 sinclairrf
    for ioEntry in (
273
        ( 'insignal',   1,      'input',        ),
274
        ( 'outsignal',  1,      'output',       ),
275
        ( 'CTS',        1,      'input',        ),
276
        ( 'CTSn',       1,      'input',        ),
277
        ( 'RTR',        1,      'output',       ),
278
        ( 'RTRn',       1,      'output',       ),
279
      ):
280
      if hasattr(self,ioEntry[0]):
281
        config.AddIO(getattr(self,ioEntry[0]),ioEntry[1],ioEntry[2],loc);
282 9 sinclairrf
    config.AddSignal('s__%s__Rx'                % self.namestring,8,loc);
283
    config.AddSignal('s__%s__Rx_empty'          % self.namestring,1,loc);
284
    config.AddSignal('s__%s__Rx_rd'             % self.namestring,1,loc);
285
    config.AddSignalWithInit('s__%s__Tx'        % self.namestring,8,None,loc);
286
    config.AddSignal('s__%s__Tx_busy'           % self.namestring,1,loc);
287
    config.AddSignalWithInit('s__%s__Tx_wr'     % self.namestring,1,None,loc);
288 2 sinclairrf
    config.AddInport((self.inport,
289 9 sinclairrf
                    ('s__%s__Rx'                % self.namestring,8,'data',),
290
                    ('s__%s__Rx_rd'             % self.namestring,1,'strobe',),
291 2 sinclairrf
                   ),loc);
292
    config.AddInport((self.inempty,
293 9 sinclairrf
                   ('s__%s__Rx_empty'           % self.namestring,1,'data',),
294 2 sinclairrf
                  ),loc);
295
    config.AddOutport((self.outport,False,
296 9 sinclairrf
                   ('s__%s__Tx'                 % self.namestring,8,'data',),
297
                   ('s__%s__Tx_wr'              % self.namestring,1,'strobe',),
298 2 sinclairrf
                  ),loc);
299
    config.AddInport((self.outstatus,
300 9 sinclairrf
                   ('s__%s__Tx_busy'            % self.namestring,1,'data',),
301 2 sinclairrf
                 ),loc);
302
    # Add the 'clog2' function to the processor (if required).
303
    config.functions['clog2'] = True;
304
 
305
  def GenVerilog(self,fp,config):
306
    for bodyextension in ('_Rx.v','_Tx.v',):
307
      body = self.LoadCore(self.peripheralFile,bodyextension);
308 6 sinclairrf
      if hasattr(self,'RTR') or hasattr(self,'RTRn'):
309
        body = re.sub(r'@RTR_BEGIN@\n','',body);
310
        body = re.sub(r'@RTR_END@\n','',body);
311
      else:
312
        if re.search(r'@RTR_BEGIN@',body):
313
          body = re.sub(r'@RTR_BEGIN@.*?@RTR_END@\n','',body,flags=re.DOTALL);
314 2 sinclairrf
      for subpair in (
315 9 sinclairrf
          ( r'@RTR_SIGNAL@',            self.RTR if hasattr(self,'RTR') else self.RTRn if hasattr(self,'RTRn') else '', ),
316
          ( r'@RTRN_INVERT@',           '!' if hasattr(self,'RTR') else '', ),
317
          ( r'\bL__',                   'L__@NAME@__',          ),
318
          ( r'\bgen__',                 'gen__@NAME@__',        ),
319
          ( r'\bs__',                   's__@NAME@__',          ),
320
          ( r'@INPORT@',                self.insignal,          ),
321
          ( r'@BAUDMETHOD@',            str(self.baudmethod),   ),
322
          ( r'@SYNC@',                  str(self.sync),         ),
323
          ( r'@DEGLITCH@',              str(self.deglitch),     ),
324
          ( r'@INFIFO@',                str(self.inFIFO),       ),
325
          ( r'@ENABLED@',               self.CTS if hasattr(self,'CTS') else ('!%s' % self.CTSn) if hasattr(self,'CTSn') else '1\'b1', ),
326
          ( r'@NSTOP@',                 str(self.nStop),        ),
327
          ( r'@OUTFIFO@',               str(self.outFIFO),      ),
328
          ( r'@NAME@',                  self.namestring,        ),
329
          ( r'@RTR_FIFO_COMPARE@',      str(CeilLog2(self.rtr_buffer)), ),
330 6 sinclairrf
        ):
331
        if re.search(subpair[0],body):
332
          body = re.sub(subpair[0],subpair[1],body);
333 2 sinclairrf
      body = self.GenVerilogFinal(config,body);
334
      fp.write(body);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.