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

Subversion Repositories ssbcc

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

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

Line No. Rev Author Line
1 2 sinclairrf
################################################################################
2
#
3
# Copyright 2013, Sinclair R.F., Inc.
4
#
5
################################################################################
6
 
7
import math;
8
import re;
9
 
10
from ssbccPeripheral import SSBCCperipheral
11
from ssbccUtil import IsPowerOf2;
12
from ssbccUtil import SSBCCException;
13
 
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
                       [nStop={1|2}]               \n
33
  Where:
34
    inport=I_inport_name
35
      specifies the symbol used by the inport instruction to read a received by
36
      from the peripheral
37
      Note:  The name must start with "I_".
38
    outport=O_outport_name
39
      specifies the symbol used by the outport instruction to write a byte to
40
      the peripheral
41
      Note:  The name must start with "O_".
42
    inempty=I_inempty_name
43
      specifies the symbol used by the inport instruction to get the empty
44
      status of the input side of the peripheral
45
      Note:  The name must start with "I_".
46
    outstatus=I_outstatus_name
47
      specifies the symbol used by the inport instruction to get the status of
48
      the output side of the peripheral
49
      Note:  The name must start with "I_".
50
    baudmethod
51
      specifies the method to generate the desired bit rate:
52
      1st method:  clk/rate
53
        clk is the frequency of "i_clk" in Hz
54
          a number will be interpreted as the clock frequency in Hz
55
          a symbol will be interpreted as a parameter
56
            Note:  this parameter must have been declared with a "PARAMETER"
57
            command
58
        rate is the desired baud rate
59
          this is specified as per "clk"
60
      2nd method:
61
        specify the number of "i_clk" clock cycles between bit edges
62
      Note:  clk, rate, and count can be parameters or constants.  For example,
63
             the following uses the parameter G_CLK_FREQ_HZ for the clock
64
             frequency and a hard-wired baud rate of 9600:
65
             "baudmethod=G_CLK_FREQ_HZ/9600".
66
      Note:  The numeric values can have Verilog-style '_' separators between
67
             the digits.  For example, 100_000_000 represents 100 million.
68
    insignal=i_name
69
      optionally specifies the name of the single-bit transmit signal
70
      Default:  i_UART_Rx
71
    outsignal=o_name
72
      optionally specifies the name of the output signal
73
      Default:  o_UART_Tx
74
    noSync
75
      optionally state no synchronization or registration is performed on the
76
      input signal.
77
    sync=n
78
      optionally state that an n-bit synchronizer will be performed on the
79
      input signal.
80
      Note:  sync=3 is the default.
81
    noDeglitch
82
      optionally state that no deglitching is performed on the input signal.
83
      Note:  This is the default.
84
    deglitching=n
85
      optionally state that an n-bit deglitcher is performed on the input signal
86
      Note:  Deglitching consists of changing the output state when n
87
             successive input bits are in the opposite state.
88
    noInFIFO
89
      optionally state that the peripheral will not have an input FIFO
90
      Note:  This is the default.
91
    inFIFO=n
92
      optionally add a FIFO of depth n to the input side of the UART
93
      Note:  n must be a power of 2.
94
    noOutFIFO
95
      optionally state that the peripheral will not have an output FIFO
96
      Note:  This is the default.
97
    outFIFO=n
98
      optionally add a FIFO of depth n to the output side of the UART
99
      Note:  n must be a power of 2.
100
    nStop=n
101
      optionally configure the peripheral for n stop bits
102
      default:  1 stop bit
103
      Note:  n must be 1 or 2
104
      Note:  the peripheral does not accept 1.5 stop bits
105
  The following ports are provided by this peripheral:
106
    I_inport_name
107
      input a recieved byte from the peripheral
108
      Note:  If there is no input FIFO, then this is the last received byte.
109
             If there is an input FIFO, then this is the next byte in the FIFO.
110
      Note:  If there is an input FIFO and the read would cause a FIFO
111
             underflow, this will repeat the last received byte.
112
    O_outport_name
113
      output the next 8-bit value to transmit or to queue for transmission
114
      Note:  If there is no output FIFO or if there is an output FIFO and this
115
             write would cause a FIFO overflow, then this byte will be
116
             discarded.
117
    I_inempty_name
118
      input the empty status of the input side of the peripheral
119
      bit 0:  input empty
120
        this bit will be high when the input side of the peripheral has one or
121
        more bytes read to be read
122
        Note:  If there is no FIFO this means that a single byte is ready to be
123
               read and has not been read.  If there is an input FIFO this
124
               means that there are one or more bytes in the FIFO.
125
        Note:  "Empty" is used rather than "ready" to facilitate loops that
126
               respond when there is a new byte ready to be processed.  See the
127
               examples below.
128
    I_outstatus_name
129
      input the status of the output side of the peripheral
130
      bit 0:  output busy
131
        this bit will be high when the output side of the peripheral cannot
132
        accept more writes
133
        Note:  If there is no FIFO this means that the peripheral is still
134
               transmitting the last byte.  If there is an output FIFO it means
135
               that it is full.\n
136
        Note:  "Busy" is used rather that "ready" to facilitate loops that wait
137
               for a not-busy status to send the next byte.  See the examples below.
138
  WARNING:  The peripheral is very simple and does not protect against writing a
139
            new value in the middle of a transmition or writing to a full FIFO.
140
            Adding such logic would be contrary to the design principle of
141
            keeping the HDL small and relying on the assembly code to provide
142
            the protection.\n
143
  Example:  Configure the UART for 115200 baud using a 100 MHz clock and
144
            transmit the message "Hello World!"\n
145
    Within the processor architecture file include the configuration command:\n
146
    PERIPHERAL UART_Tx O_UART_TX I_UART_TX baudmethod=100_000_000/115200\n
147
    Use the following assembly code to transmit the message "Hello World!".
148
    This transmits the entire message whether or not the peripheral has a FIFO.\n
149
    N"Hello World!\\r\\n"
150
      :loop .outport(O_UART_TX) :wait .inport(I_UART_TX_BUSY) .jumpc(wait) .jumpc(loop,nop) drop
151
  """
152
 
153
  def __init__(self,peripheralFile,config,param_list,loc):
154
    # Use the externally provided file name for the peripheral
155
    self.peripheralFile = peripheralFile;
156
    # Get the parameters.
157
    for param_tuple in param_list:
158
      param = param_tuple[0];
159
      param_arg = param_tuple[1];
160
      for param_test in (
161
          ('deglitch',   r'[1-9]\d*$', int,   ),
162
          ('inempty',    r'I_\w+$',    None,  ),
163
          ('inport',     r'I_\w+$',    None,  ),
164
          ('insignal',   r'i_\w+$',    None,  ),
165
          ('noDeglitch', None,         None,  ),
166
          ('noInFIFO',   None,         None,  ),
167
          ('noOutFIFO',  None,         None,  ),
168
          ('noSync',     None,         None,  ),
169
          ('nStop',      r'[12]$',     int,   ),
170
          ('outport',    r'O_\w+$',    None,  ),
171
          ('outsignal',  r'o_\w+$',    None,  ),
172
          ('outstatus',  r'I_\w+$',    None,  ),
173
          ('sync',       r'[1-9]\d*$', int,   ),
174
        ):
175
        if param == param_test[0]:
176
          self.AddAttr(config,param,param_arg,param_test[1],loc,param_test[2]);
177
          break;
178
      else:
179
        if param == 'baudmethod':
180
          self.AddRateMethod(config,param,param_arg,loc);
181
        elif param in ('inFIFO','outFIFO',):
182
          self.AddAttr(config,param,param_arg,r'[1-9]\d*$',loc,int);
183
          x = getattr(self,param);
184
          if not IsPowerOf2(x):
185
            raise SSBCCException('%s=%d must be a power of 2 at %s' % (param,x,loc,));
186
        else:
187
          raise SSBCCException('Unrecognized parameter at %s: %s' % (loc,param,));
188
    # Ensure the required parameters are provided.
189
    for paramname in (
190
        'baudmethod',
191
        'inempty',
192
        'inport',
193
        'outport',
194
        'outstatus',
195
      ):
196
      if not hasattr(self,paramname):
197
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
198
    # Set optional parameters.
199
    for optionalpair in (
200
        ('insignal',  'i_UART_Rx', ),
201
        ('nStop',     1,           ),
202
        ('outsignal', 'o_UART_Tx', ),
203
      ):
204
      if not hasattr(self,optionalpair[0]):
205
        setattr(self,optionalpair[0],optionalpair[1]);
206
    # Ensure exclusive pair configurations are set and consistent.
207
    for exclusivepair in (
208
        ('noSync',     'sync',     'sync',       3,    ),
209
        ('noDeglitch', 'deglitch', 'noDeglitch', True, ),
210
        ('noInFIFO',   'inFIFO',   'noInFIFO',   True, ),
211
        ('noOutFIFO',  'outFIFO',  'noOutFIFO',  True, ),
212
      ):
213
      if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
214
        raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
215
      if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]):
216
        setattr(self,exclusivepair[2],exclusivepair[3]);
217
      if hasattr(self,exclusivepair[0]):
218
        delattr(self,exclusivepair[0]);
219
        setattr(self,exclusivepair[1],0);
220
    # Set the string used to identify signals associated with this peripheral.
221
    self.namestring = self.outsignal;
222
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
223
    config.AddIO(self.insignal,1,'input',loc);
224
    config.AddIO(self.outsignal,1,'output',loc);
225
    config.AddSignal('s__%s__Rx'          % self.namestring,8,loc);
226
    config.AddSignal('s__%s__Rx_empty'    % self.namestring,1,loc);
227
    config.AddSignal('s__%s__Rx_rd'       % self.namestring,1,loc);
228
    config.AddSignal('s__%s__Tx'          % self.namestring,8,loc);
229
    config.AddSignal('s__%s__Tx_busy'     % self.namestring,1,loc);
230
    config.AddSignal('s__%s__Tx_wr'       % self.namestring,1,loc);
231
    config.AddInport((self.inport,
232
                    ('s__%s__Rx'          % self.namestring,8,'data',),
233
                    ('s__%s__Rx_rd'       % self.namestring,1,'strobe',),
234
                   ),loc);
235
    config.AddInport((self.inempty,
236
                   ('s__%s__Rx_empty'     % self.namestring,1,'data',),
237
                  ),loc);
238
    config.AddOutport((self.outport,False,
239
                   ('s__%s__Tx'           % self.namestring,8,'data',),
240
                   ('s__%s__Tx_wr'        % self.namestring,1,'strobe',),
241
                  ),loc);
242
    config.AddInport((self.outstatus,
243
                   ('s__%s__Tx_busy'      % self.namestring,1,'data',),
244
                 ),loc);
245
    # Add the 'clog2' function to the processor (if required).
246
    config.functions['clog2'] = True;
247
 
248
  def GenVerilog(self,fp,config):
249
    for bodyextension in ('_Rx.v','_Tx.v',):
250
      body = self.LoadCore(self.peripheralFile,bodyextension);
251
      for subpair in (
252
                    (r'\bL__',          'L__@NAME@__', ),
253
                    (r'\bgen__',        'gen__@NAME@__', ),
254
                    (r'\bs__',          's__@NAME@__', ),
255
                    (r'@INPORT@',       self.insignal, ),
256
                    (r'@BAUDMETHOD@',   str(self.baudmethod), ),
257
                    (r'@SYNC@',         str(self.sync), ),
258
                    (r'@DEGLITCH@',     str(self.deglitch), ),
259
                    (r'@INFIFO@',       str(self.inFIFO), ),
260
                    (r'@NSTOP@',        str(self.nStop), ),
261
                    (r'@OUTFIFO@',      str(self.outFIFO), ),
262
                    (r'@NAME@',         self.namestring, ),
263
                  ):
264
        body = re.sub(subpair[0],subpair[1],body);
265
      body = self.GenVerilogFinal(config,body);
266
      fp.write(body);

powered by: WebSVN 2.1.0

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