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

Subversion Repositories ssbcc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 sinclairrf
################################################################################
2
#
3
# Copyright 2015, Sinclair R.F., Inc.
4
#
5
################################################################################
6
 
7
import math
8
 
9
from ssbccPeripheral import SSBCCperipheral
10
from ssbccUtil import CeilLog2
11
from ssbccUtil import SSBCCException
12
 
13
class stepper_motor(SSBCCperipheral):
14
  """
15
  Stepper motor driver\n
16
  This peripheral creates pulses to driver a stepper motor driver such as TI's
17
  DRV8825.  It includes a buffer which can be used to store acceleration,
18
  motion, and deceleration profiles and returns a "completed" status to the
19
  micro controller.\n
20
  The core runs accumulators for the angle and the rate.  I.e. the rate is an
21
  accumulated sum of the initial rate and the commanded acceleration and the
22 11 sinclairrf
  angle is an accumulation of this possibly changing rate.  The direction
23
  signal (if present) to the stepper motor is the sign bit from the accumulated
24
  rate.  The "step" signal to the stepper motor driver is strobed every time
25
  the accumulated angle overflows or underflows and the direction bit to the
26
  driver is set according to whether the accumulated angle overflowed or
27
  underflowed.\n
28 9 sinclairrf
  The motor control word consists of the following signals:
29
    initial rate
30
    acceleration
31
    number of steps to be performed this control word
32
    optional mode specification
33
  These control words are individually packed into one or more 8-bit bytes.  The
34
  8-bit values from the micro controller are shifted into a buffer from which
35
  the control word is constructed.  This completed control word is then shifted
36
  into a FIFO.  The control words in the FIFO are then used to generate the
37
  timing for the step strobes to the stepper motor driver.  When the FIFO
38
  empties, the rate and the acceleration are set to zero and the mode retains
39
  its most recent value.  The user must ensure they do not overfill the FIFO --
40
  the only FIFO status is an "empty" or control words "done" status.\n
41
  Usage:
42
    PERIPHERAL stepper_motor    basename=name                           \\
43
                                outcontrol=O_name                       \\
44
                                outrecord=O_name                        \\
45
                                outrun=O_name                           \\
46
                                indone=I_name                           \\
47 11 sinclairrf
                                [inerror=I_name]                        \\
48
                                [nodir]                                 \\
49 9 sinclairrf
                                ratemethod={CLK_FREQ_HZ/RATE_HZ|count}  \\
50
                                ratescale=N_rate_scale                  \\
51
                                rateres=N_rate                          \\
52
                                accelscale=N_accel_scale                \\
53
                                accelres=N_accel                        \\
54
                                [accumres=N_accum]                      \\
55
                                countwidth=N_count                      \\
56
                                [modewidth=N_mode]                      \\
57
                                [FIFO=N_fifo]\n
58
  Or:\n
59
    PERIPHERAL stepper_motor    basename=name                           \\
60
                                master=mastername                       \\
61
                                outrecord=O_name                        \\
62
                                outrun=O_name                           \\
63
                                indone=I_name                           \\
64 11 sinclairrf
                                [nodir]                                 \\
65
                                [inerror=I_name]                        \\
66 9 sinclairrf
                                [FIFO=N_fifo]\n
67
  Where:
68
    basename=name
69
      specifies the name used to contruct the I/O signals
70
      Note:  The name must start with an alphabetic character.
71
      Example:  "basename=stepper" results in the names "o_stepper_dir",
72
                "o_stepper_step", and "o_stepper_mode" for the output
73
                direction, step, and optional mode signals and
74
                "i_stepper_error" for the input error signal.
75
    master=mastername
76
      specifies a preceding stepper_motor peripheral to use for the internal
77
      clock and to use for the accleration, rate, angle accumulator, and mode
78
      sizes
79 10 sinclairrf
      Note:  The "outcontrol" port from the master peripheral is used to queue
80
             the control words for its slaves.
81 9 sinclairrf
    outcontrol=O_name
82
      specifies the port used to assemble 8-bit control values into the stepper
83
      motor control word
84
      Note:  The name must start with "O_".
85
    outrecord=O_name
86
      specifies the port used to generate the strobe that pushes the assembled
87
      motor control word into the stepper motor FIFO
88
      Note:  The name must start with "O_".
89
    outrun=O_name
90
      specified the port used to begin the sequence of operations specified by
91
      the motor control words in the buffer
92
      Note:  The name must start with "O_".
93
    indone=I_name
94
      specifies the port used to determine whether or not the operations in the
95
      FIFO have finished
96
      Note:  The name must start with "I_".
97
    inerror=I_name
98 11 sinclairrf
      optionally specifies the port used to read the error status from the
99
      stepper motor controller
100 9 sinclairrf
      Note:  The name must start with "I_".
101 11 sinclairrf
    nodir
102
      optionally specify that the stepper motor does not generate a direction
103
      bit
104 9 sinclairrf
    ratemethod
105
      specified the method to generate the internal clock rate from the
106
      processor clock
107
      1st method:  CLK_FREQ_HZ/RATE_HZ
108
        CLK_FREQ_HZ is the frequency of "i_clk" in Hz
109
          a number will be interpreted as the clock frequency in Hz
110
          a symbol will be interpreted as a constant or a parameter
111
            Note:  the symbol must be declared with the CONSTANT, LOCALPARARM,
112
                   or PARAMETER configuration command.
113
        RATE_HZ is the desired internal clock rate
114
          this is specified as per "CLK_FREQ_HZ"
115
      2nd method:  count
116
        specify the number of "i_clk" clock cycles per internal clock cycle
117
      Note:  CLK_FREQ_HZ, RATE_HZ, and count can be parameters or constants.  For example,
118
             the following uses the parameter C_CLK_FREQ_HZ for the clock
119
             frequency and an internal rate to 500 kHz:
120
             "ratemethod=C_CLK_FREQ_HZ/500_000".
121
      Note:  The minimum value of "ratemethod" is 2.
122
    ratescale=N_rate_scale
123
      specifies the scaling for the most significant bit of the rate
124
      Note:  See the 'a' parameter in the "Theory of Operation" section.
125
    rateres=N_rate
126
      specifies the resolution of the rate
127
      Note:  See the 'r' parameter in the "Theory of Operation" section.
128
    accelscale=N_accel_scale
129
      specifies the scaling for the most significant bit of the acceleration
130
      Note:  See the 'a' parameter in the "Theory of Operation" section.
131
    accelres=N_accel
132
      specifies the resolution for the acceleration
133
      Note:  See the 'b' parameter in the "Theory of Operation" section.
134
    accumres=N_accum
135
      optionally specify the resolution for the accumulator to the summed angle
136
      (from which the step strobes are generated)
137
      Note:  This must be between rateres and accelres.
138
      Note:  The default value is accelres.
139
    countwidth=N_count
140
      specifies the width of the counter for the number of steps to be performed
141
      by the control word
142
    modewidth=N_mode
143
      - if not specified, there is no mode signal to the stepper motor
144
        controller
145
      - if specified then this specifies the width of the signal to the stepper
146
        motor controller
147
    FIFO=N_fifo
148
      optionally specify the depth of the control word FIFO
149
      Note:  This must be a power of 2 and must be at least 16.
150
      Note:  The default is 16.\n
151
  Theory of Operation:
152
    Define the following:
153
      n         is the number of internal clock cycles since the control word
154
                started being performed (i.e., these are counted after the dlock
155
                rate is reduced by ratemethod)
156
      F         is the internal clock cycle frequency (i.e., RATE_HZ in the
157
                second form for specifying the ratemethod
158
      R_0       is the initial rate command
159
      R_n       is the accumulated rate after n internal clock cycles
160
      A         is the commanded acceleration
161
      S_n       is the accumulated step after n internal clock cycles
162
    Then
163
      R_n = R_0 + A * n
164
      S_n = R_0 * n + A * n * (n-1) / 2
165
    The rate R_n can be thought of as a signed fraction with the format "s0.r"
166
    where 's' represents the sign bit, there are no bits to the left of the
167
    decimal, and there are 'r' bits to the right of the decimal.  Then the rate
168
    can be as high as F and as low as F/2^r.  Practically, the maximum rate
169
    cannot exceed half the internal clock frequency, otherwise the "step"
170
    signals will merge together and the stepper driver will not see distinct
171
    driver pulses.\n
172
    Similarly, the acceleration command A can be thought of as a signed fraction
173
    with the format "sa.b".  Here 's' again represents the sign bit and 'b'
174
    represents the number of bits to the right of the decimial, but 'a' is a
175
    negative number representing the first bit in A.  I.e., aside from the sign
176
    bit, A is b+a+1 bits wide.  For example, the specification s-4.8 means that
177
    A has a sign bit with 8-4+1 = 5 bits for the value of A with the leasts
178
    significant bit representing a rate of F^2/2^8.\n
179
    The bit widths are determined as follows: Let mR be the minimum non-zero
180
    magnitude of the rate, mA be the minimum non-zero mangitude of the
181
    acceleration, and MA be the mamximum magnitude of the acceleration, all in
182
    step/sec or step/sec^2.  Then\n
183
      r = ceil(-log_2(mR/F))\n
184
      a = floor(log_2(MA/F^2))\n
185
      b = ceil(-log_2(mA/f^2))\n
186
    Note:  r and b may be increased by a few bits if accurate representations of
187
    the minimum rates are needed.\n
188
  Example:
189
    A micro controller with an 8 MHz clock is used to operate a DRV8825 driving
190
    a stepper motor assembly.  The stepper motor has 200 steps per revolution,
191
    can be operated in full-step or a 16-step micro step mode, has a maximum
192
    rotation rate of 10 Hz, and has a maximum acceleration of 4 Hz/sec (i.e.,
193
    800 full-steps/sec^2).  The motor is attached to a 400mm theaded rod with a
194
    pitch of 4mm per revolution.\n
195
    The 1.9usec minimum high and low widths of the DRV8825 and the 8 MHz
196
    processor clock mean that the stepper motor controller can realistically be
197
    run at 500kHz.  The rate method to divide the micro controller clock to the
198
    internal processing rate is specified by "ratemethod" in the PERIPHERAL
199
    command.\n
200
    The bit widths are determine by choosing:\n
201
      MR = 10 rev/sec * 200 full-step/rev * 16 micro-step/full-step
202
         = 32000 micro-step/sec
203
        ==> R = -ceil(log_2(MR/F))
204
              = -ceil(log_2((32000 micro-step/sec)/500kHz))
205
              = 3
206
      mR = 10 step/sec
207
        ==> r = -floor(log_2(mR/F))
208
              = -floor(log_2((10 step/sec)/500kHz)
209
              = 16\n
210
      MA = 10 rev/sec^2 = 10*16*200 step/sec^2
211
        ==> A = -ceil(log_2(MA/F^2))
212
              = -ceil(log_2((32,000 step/sec^2)/500kHz^2))
213
              = 22\n
214
      mA = 20 step/sec^2 (in full step mode)
215
        ==> a = -floor(log_2(mA/F^2))
216
              = 34\n
217
    The values R=3 and r=16 along with the sign bit mean the rate would be
218
    stored in a signed 14-bit value.  The rate requires two 8-bit writes to the
219
    control word.\n
220
    The values A=22 and a=34 mean the acceleration would be stored in a signed
221
    1+(34-22) = 13 bit value.  The acceleration requires two 8-bit writes to the
222
    control word.\n
223
    The accumulator width is set to the same value as the acceleration
224
    resolution.  This avoid non-linear trunction errors and makes the motion
225
    profile more predictable using simple integer arithmetic.\n
226
    The number of full steps to move from one of the of rod to the other is
227
    (400mm/(4mm/rev)*(200steps/rev)=20_000 steps.  In the micro-stepmode there
228
    are 16 micro steps per full step, so at most 320_000 micro steps can be
229
    performed before the full length of the rod is traversed.  I.e., a 19-bit
230
    counter will suffice for the worst-case unidirection motion.  This 19-bit
231
    count requires 3 8-bit writes to the control word.\n
232
    A "modewidth" of 1 is specifies so that the controller can be operated in
233
    either full step or a single hard-wired micro-step mode.  If all 3 of the
234
    DRV8825 mode pins were connected, then "modewidth=3" would need to
235
    specified.\n
236
    The peripheral is then specified as follows:\n
237
      CONSTANT          C_RATE_SCALE     3
238
      CONSTANT          C_RATE_RES      16
239
      CONSTANT          C_ACCEL_SCALE   22
240
      CONSTANT          C_ACCEL_RES     34
241
      CONSTANT          C_ACCUM_RES     34
242
      CONSTANT          C_COUNT_WIDTH   19
243
      PERIPHERAL        stepper_motor   basename=stepper                \\
244
                                        outcontrol=O_stepper_control    \\
245
                                        outrecord=O_stepper_wr          \\
246
                                        outrun=O_stepper_go             \\
247
                                        indone=I_stepper_done           \\
248
                                        inerror=I_stepper_error         \\
249
                                        ratemethod=8_000_000/500_000    \\
250
                                        ratescale=C_RATE_SCALE          \\
251
                                        rateres=C_RATE_RES              \\
252
                                        accelscale=C_ACCEL_SCALE        \\
253
                                        accelres=C_ACCEL_RES            \\
254
                                        accumres=C_ACCUM_RES            \\
255
                                        countwidth=C_COUNT_WIDTH        \\
256
                                        modewidth=1\n
257
    and the TBD byte control words are pushed into the peripheral as follows:
258
      R_0       14-bit initial rate stored in a 16-bit field (MSB first)
259
      A         13-bit acceleration stored in a 16-bit field (MSB first)
260
      COUNT     19-bit count stored in a 24-bit field (MSB first)
261
      MODE      1-bit mode stored as the lsb of an 8-bit field
262
    The control word is a total of 8 bytes wide.\n
263
    To command the peripheral to accelerate from stop to 200 steps/sec in one
264
    second in the forward direction using the full-step mode, the following
265
    seqeuence of bytes would be written to the control port:
266
      0x00 0x00         ; initial rate is zero
267
      0x00 0x0E         ; 200 step/sec^2 * 2^34 / 500kHz^2 = 14
268
      0x00 0x00 0x63    ; send 100 step commands (command 100-1=99)
269
      0x00              ; full-step mode
270
    Note:  It will take t=sqrt(2*100*2^34/14)/F = 0.99 sec to move the commanded
271
    100 steps.  At this time the speed will be r=t*14/2^34*F^2 = 201 step/sec.
272
    A more accurate match to the commanded speed could be accomplished by adding
273
    additional bits to the acceleration resolution at the cost of using more
274
    FPGA resources.  Alternatively, the acceleration could be commanded for 99
275
    steps and any subsequent 200 step/sec motion could be lengthened by 1 step.
276
    Another alternative would be to use a micro-step acceleration.  Practically,
277
    the computed command is within 0.5% of the desired step rate.\n
278
    To command the peripheral to decelerate from 200 step/sec to zero in one
279
    second, the following sequence of bytes would be written to the control
280
    port:
281
      0x00 0x01 0xDB    ; 200 step/sec * 2^23 / 500kHz
282
      0xFF 0x9C         ; negative of the above acceleration
283
      0x00 0x00 0x63    ; send 100 step commands (command 100-1=99)
284
      0x00              ; full-step mode\n
285
    The first of these two control words could be assembled and transmitted to
286
    the peripheral as follows:\n
287
      0x00                      ; mode
288
      .push24(${100-1})         ; send 100 step commands
289
      .push16(14)               ; 200 step/sec^2
290
      .push16(0)                ; initial rate is zero
291
      ${8-1} :loop swap .outport(O_stepper_control) .jumpc(loop,1-) drop
292
      .outstrobe(O_stepper_wr)  ; push the assembed control word into the FIFO
293
      ...
294
      .outstrobe(O_stepper_go)  ; perform the queued control words\n
295
    Example:
296
      Slave a second stepper motor controller peripheral to the preceding
297
      periperal.\n
298
      PERIPHERAL        stepper_motor   basename=slave                  \\
299
                                        master=stepper                  \\
300
                                        outrecord=O_slave_wr            \\
301
                                        outrun=O_slave_go               \\
302
                                        indone=I_slave_done             \\
303
                                        inerror=I_slave_error\n
304
      This controller will use the internal clock generated by the first
305
      controller and the scales, resolutions, and accumulator width will be the
306
      same as that master peripheral.  What will be different is the four I/O
307
      ports used to operate and status the controller.
308
    """
309
 
310
  def __init__(self,peripheralFile,config,param_list,loc):
311
    # Use the externally provided file name for the peripheral
312
    self.peripheralFile = peripheralFile
313
    # Get the parameters.
314
    allowables = (
315 11 sinclairrf
      ( 'FIFO',         r'\S+$',                lambda v : self.IntPow2Method(config,v,lowLimit=16),    ),
316
      ( 'accelres',     r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
317
      ( 'accelscale',   r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
318
      ( 'accumres',     r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
319
      ( 'basename',     r'[A-Za-z]\w*$',        None,                                                   ),
320
      ( 'countwidth',   r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
321
      ( 'indone',       r'I_\w+$',              None,                                                   ),
322
      ( 'inerror',      r'I_\w+$',              None,                                                   ),
323
      ( 'master',       r'[A-Za-z]\w*$',        None,                                                   ),
324
      ( 'modewidth',    r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
325
      ( 'nodir',        None,                   None,                                                   ),
326
      ( 'outcontrol',   r'O_\w+$',              None,                                                   ),
327
      ( 'outrecord',    r'O_\w+$',              None,                                                   ),
328
      ( 'outrun',       r'O_\w+$',              None,                                                   ),
329
      ( 'ratemethod',   r'\S+$',                lambda v : self.RateMethod(config,v),                   ),
330
      ( 'rateres',      r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
331
      ( 'ratescale',    r'\S+$',                lambda v : self.IntMethod(config,v,lowLimit=1),         ),
332 9 sinclairrf
    )
333
    names = [a[0] for a in allowables]
334
    for param_tuple in param_list:
335
      param = param_tuple[0]
336
      if param not in names:
337
        raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,))
338
      param_test = allowables[names.index(param)]
339
      self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2])
340
    # Signals that can't be specified when a master is specified.
341
    masterExclude = (
342
      'accelres',
343
      'accelscale',
344
      'accumres',
345
      'countwidth',
346
      'modewidth',
347 10 sinclairrf
      'outcontrol',
348 9 sinclairrf
      'ratemethod',
349
      'rateres',
350
      'ratescale',
351
    )
352
    # Ensure the required parameters are provided.
353
    reqdParms = (
354
      'basename',
355
      'indone',
356
      'outrecord',
357
      'outrun',
358
    )
359
    if not hasattr(self,'master'):
360
      reqdParms += tuple([me for me in masterExclude if me not in ('accumres','modewidth',)])
361
    for paramname in reqdParms:
362
      if not hasattr(self,paramname):
363
        raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,))
364
    # Ensure mutually exclusive parameters are not listed.
365
    if hasattr(self,'master'):
366
      for paramname in masterExclude:
367
        if hasattr(self,paramname):
368
          raise SSBCCException('Parameter "%s" cannot be specified alongside "master" at %s' % (paramname,loc,))
369
    # Ensure basename is unique for this class of peripheral
370
    for p in config.peripheral:
371
      if (str(p.__class__) == str(self.__class__)) and (p.basename == self.basename):
372
        raise SSBCCException('Duplicated stepper_motor basename "%s" at %s' % (self.basename,loc,))
373
    # For slaves, copy the bit widths from the master peripheral.
374
    if hasattr(self,'master'):
375
      for p in config.peripheral:
376
        if (str(p.__class__) == str(self.__class__)) and (p.basename == self.master):
377
          break
378
      else:
379
        raise SSBCCException('Can\'t find preceding stepper_motor peripheral with basename=%s at %s ' % (self.master,loc,))
380
      self.master = p
381
      for paramname in masterExclude:
382
        setattr(self,paramname,getattr(self.master,paramname))
383
    # Set unspecified optional parameters.
384
    if not hasattr(self,'accumres'):
385
      self.accumres = self.accelres
386
    if not hasattr(self,'modewidth'):
387
      self.modewidth = 0
388
    if not hasattr(self,'FIFO'):
389
      self.FIFO = 16
390
    # Ensure the parameters satisfy any mutual constraints.
391
    if not (self.rateres < self.accelres):
392
      raise SSBCCException('rateres should be smaller than accelres at %s' % loc)
393
    if not (self.rateres <= self.accumres <= self.accelres):
394
      raise SSBCCException('accumres must be between rateres and accelres at %s' % loc)
395
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
396 11 sinclairrf
    if not hasattr(self,'nodir'):
397
      config.AddIO('o_%s_dir'   % self.basename, 1, 'output', loc)
398
    config.AddIO('o_%s_step'    % self.basename, 1, 'output', loc)
399 9 sinclairrf
    if self.modewidth > 0:
400 11 sinclairrf
      config.AddIO('o_%s_mode'  % self.basename, 1, 'output', loc)
401
    if hasattr(self,'inerror'):
402
      config.AddIO('i_%s_error' % self.basename, 1, 'input',  loc)
403 9 sinclairrf
    config.AddSignal('s__%s__done' % self.basename, 1, loc)
404
    self.ix_outcontrol = config.NOutports()
405 10 sinclairrf
    if not hasattr(self,'master'):
406
      config.AddOutport((self.outcontrol,
407
                         False,
408
                         # empty list
409
                        ),loc)
410 9 sinclairrf
    self.ix_outrecord = config.NOutports()
411
    config.AddOutport((self.outrecord,
412
                       True,
413
                       # empty list
414
                      ),loc)
415
    self.ix_outrun = config.NOutports()
416
    config.AddOutport((self.outrun,
417
                       True,
418
                       # empty list
419
                      ),loc)
420 11 sinclairrf
    if hasattr(self,'inerror'):
421
      config.AddInport((self.inerror,
422 9 sinclairrf
                      ('i_%s_error' % self.basename, 1, 'data', ),
423
                     ), loc)
424
    config.AddInport((self.indone,
425
                      ('s__%s__done' % self.basename, 1, 'data', ),
426
                     ), loc)
427
    # Compute bit widths.
428
    dw = config.Get('data_width')
429
    self.data_width = dw
430
    self.ratecmdwidth = 1 + self.rateres - self.ratescale
431
    self.ratewidth = 1 + self.accelres - self.ratescale
432
    self.accelwidth = 1 + self.accelres - self.accelscale
433
    self.accumwidth = self.accumres + 1
434
    self.controlwidth = self.ratecmdwidth
435
    self.controlwidth += dw*int((self.accelwidth+dw-1)/dw)
436
    self.controlwidth += dw*int((self.countwidth+dw-1)/dw)
437
    self.controlwidth += dw*int((self.modewidth+dw-1)/dw)
438
    self.controlwidthpacked = self.ratecmdwidth + self.accelwidth + self.countwidth + self.modewidth
439
    # Add the 'clog2' function to the processor (if required).
440
    config.functions['clog2'] = True
441
 
442
  def GenVerilog(self,fp,config):
443
    body = self.LoadCore(self.peripheralFile,'.v')
444
    if hasattr(self,'master'):
445
      body = re.sub(r'@MASTER_BEGIN@.*?@MASTER_END@\n','',body,flags=re.DOTALL)
446
    else:
447
      body = re.sub(r'@MASTER_BEGIN@\n','',body)
448
      body = re.sub(r'@MASTER_END@\n','',body)
449
    if self.modewidth == 0:
450
      body = re.sub(r'@OUTMODE_BEGIN@.*?@OUTMODE_END@\n','',body,flags=re.DOTALL)
451
    else:
452
      body = re.sub(r'@OUTMODE_BEGIN@\n','',body)
453
      body = re.sub(r'@OUTMODE_END@\n','',body)
454 11 sinclairrf
    if hasattr(self,'nodir'):
455
      body = re.sub(r' *o__dir.*?\n','',body)
456 10 sinclairrf
    masterBasename = self.basename if not hasattr(self,'master') else self.master.basename
457 9 sinclairrf
    for subpair in (
458
      ( r'@ACCEL_WIDTH@',               str(self.accelwidth),           ),
459
      ( r'@ACCEL_RES@',                 str(self.accelres),             ),
460
      ( r'@ACCEL_SCALE@',               str(self.accelscale),           ),
461
      ( r'@ACCUM_RES@',                 str(self.accumres),             ),
462
      ( r'@ACCUM_WIDTH@',               str(self.accumwidth),           ),
463
      ( r'@CONTROL_WIDTH@',             str(self.controlwidth),         ),
464
      ( r'@CONTROL_WIDTH_PACKED@',      str(self.controlwidthpacked),   ),
465
      ( r'@COUNT_WIDTH@',               str(self.countwidth),           ),
466
      ( r'@DW@',                        str(self.data_width),           ),
467
      ( r'@DWM1@',                      str(self.data_width-1),         ),
468
      ( r'@FIFO_DEPTH@',                str(self.FIFO),                 ),
469
      ( r'@IX_OUTCONTROL@',             str(self.ix_outcontrol),        ),
470
      ( r'@IX_OUTRECORD@',              str(self.ix_outrecord),         ),
471
      ( r'@IX_OUTRUN@',                 str(self.ix_outrun),            ),
472
      ( r'@MODE_WIDTH@',                str(self.modewidth),            ),
473
      ( r'@NAME@',                      self.basename,                  ),
474
      ( r'@NBITS_FIFO_DEPTH@',          str(CeilLog2(self.FIFO)),       ),
475
      ( r'@OUTMODEWIDTH@',              str(self.modewidth),            ),
476
      ( r'@RATECMD_WIDTH@',             str(self.ratecmdwidth),         ),
477
      ( r'@RATEMETHOD@',                str(self.ratemethod),           ),
478
      ( r'@RATE_RES@',                  str(self.rateres),              ),
479
      ( r'@RATE_SCALE@',                str(self.ratescale),            ),
480
      ( r'@RATE_WIDTH@',                str(self.ratewidth),            ),
481
      ( r'\bL__',                       'L__%s__' % self.basename,      ),
482
      ( r'\bi__',                       'i_%s_' % self.basename,        ),
483
      ( r'\bo__',                       'o_%s_' % self.basename,        ),
484
      ( r'\bs__',                       's__%s__' % self.basename,      ),
485 10 sinclairrf
      ( r'@S__CLK_EN@',                 's__%s__clk_en' % masterBasename, ),
486
      ( r'@S__INPUT_CONTROL_WORD_PACKED@', 's__%s__input_control_word_packed' % masterBasename, ),
487 9 sinclairrf
    ):
488
      body = re.sub(subpair[0],subpair[1],body)
489
    body = self.GenVerilogFinal(config,body)
490
    fp.write(body)

powered by: WebSVN 2.1.0

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