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

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [core/] [9x8/] [peripherals/] [PWM_8bit.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 2012-2013, Sinclair R.F., Inc.
4
#
5
################################################################################
6
 
7
from ssbccPeripheral import SSBCCperipheral
8
from ssbccUtil import SSBCCException;
9
 
10
class PWM_8bit(SSBCCperipheral):
11
  """
12
  Pulse Width Modulator (PWM) with 8-bit control.\n
13
  This peripheral creates one or more PWMs.  The PWM is designed so that it is
14
  allways off when the control is 0 and it is always on when the control is
15
  0xFF.\n
16
  Usage:
17
    PERIPHERAL PWM_8bit   outport=O_name \\
18
                          outsignal=o_name \\
19
                          ratemethod={clk/rate|count} \\
20
                          [invert|noinvert] \\
21
                          [instances=n] \\
22
                          [norunt]\n
23
  Where:
24
    outport=O_name
25
      specifies the symbol used by the outport instruction to write a byte to
26
      the peripheral
27
      Note:  The name must start with "O_".
28
    outsignal=o_name
29
      specifies the name of the output signal
30
      Note:  The name must start with "o_".
31
    ratemethod={clk/rate|count}
32
      specifies the frequency at which the PWM counter is incremented
33
      Example:  ratemethod=count means to increment the PWM counter once every
34
                "count" clock cycles.
35
    invert|noinvert
36
      optional configuration command to invert or to not invert the PWM output
37
      Default:  don't invert the output (i.e., a command of 0 means the output is
38
                always low)
39
      Note:  "invert" should be used when pulling the external signal to ground
40
             means the device is "on"
41
    instances=n
42
      specifies the number of PWMs for the peripheral
43
      Default:  The default is one PWM control and output.
44
    norunt
45
      optionally add logic to ensure "runt" pulses are not generated by
46
      incorporating new PWM commands at the start of the counting cycle
47
      Default:  "runt" pulses are allowed.\n
48
  The following OUTPORT is provided by this peripheral when instances=1:
49
    O_name
50
      output the next 8-bit value to transmit or to queue for transmission\n
51
  The following OUTPORT is provided by this peripheral when instances=n is larger
52
  than 1:
53
    O_name_0, O_name_1, ..., O_name_{n-1}
54
      output the next 8-bit value to transmit on the specified PWM
55
      Note:  O_name_i = ${O_name_0+i) where 0<=i<n.
56
      Note:  The PWM for o_name[i] is controlled by the outport O_name_i
57
      Example:  If "instances=3" is specified, then the following outports are
58
                provided:  O_name_0, O_name_1, and O_name_2.  The assembly
59
                sequence "5 .outport(O_name_1)" will change the PWM control for
60
                the second of these three PWMs to 5.\n
61
  Note:  The PWM counter is an 8-bit count that ranges from 1 to 255.  Each PWM
62
         output is '1' when this count is less than or equal to the commanded
63
         count.  The signal for a commanded count of 0 will never be on while
64
         the signal for a commanded count of 255 will always be on.\n
65
  Example:  Control the intensity of an LED through a PWM.  The LED must flicker
66
            at a frequency greater than about 30 Hz in order for the flickering
67
            to not be visible by human eyes.  The LED is turned on when the
68
            signal to the LED is at ground.  The processor clock frequency is
69
            provided by the parameter G_CLK_FREQ_HZ.\n
70
    Within the processor architecture file include the configuration command:\n
71
    PERIPHERAL PWM_8bit   outport=O_PWM_LED                     \\
72
                          outsignal=o_led                       \\
73
                          ratemethod=G_CLK_FREQ_HZ/(30*255)     \\
74
                          invert\n
75
    Use the following assembly to set the LED to about 1/4 intensity:\n
76
    0x40 .outport(O_PWM_LED)\n
77
  Example:  Similarly to obove, but for the three controls of a tri-color LED:\n
78
    Within the processor architecture file include the configuration command:\n
79
    PERIPHERAL PWM_8bit   outport=O_PWM_LED                     \\
80
                          outsignal=o_led                       \\
81
                          ratemethod=G_CLK_FREQ_HZ/(30*255)     \\
82
                          invert                                \\
83
                          instances=3\n
84
    Use the following assembly to set the LED intensities to 0x10 0x20 and 0x55:\n
85
    0x10 .outport(O_PWM_LED_0)
86
    0x20 .outport(O_PWM_LED_1)
87
    0x55 .outport(O_PWM_LED_2)\n
88
    or use the following function to send the three values on the stack where
89
    the top of the stack is 0x55 0x20 0x10 (this isn't less code, but it
90
    illustrates how to increment the outport index):\n
91
    ; ( u_pwm_led_2 u_pwm_led_1 u_pwm_led_0 - )
92
    .function set_pwm_led
93
      O_PWM_LED_0 ${3-1} :loop r> swap over outport drop 1+ r> .jumpc(loop,1-) drop
94
    .return(drop)
95
  """
96
 
97
  def __init__(self,peripheralFile,config,param_list,loc):
98
    # Use the externally provided file name for the peripheral
99
    self.peripheralFile = peripheralFile;
100
    # Get the parameters.
101
    for param_tuple in param_list:
102
      param = param_tuple[0];
103
      param_arg = param_tuple[1];
104
      if param == 'outport':
105
        self.AddAttr(config,param,param_arg,r'O_\w+$',loc);
106
      elif param == 'outsignal':
107
        self.AddAttr(config,param,param_arg,r'o_\w+$',loc);
108
      elif param == 'ratemethod':
109
        self.ProcessRateMethod(config,param_arg,loc);
110
      elif param == 'invert':
111
        self.AddAttr(config,param,param_arg,None,loc);
112
      elif param == 'noinvert':
113
        self.AddAttr(config,param,param_arg,None,loc);
114
      elif param == 'instances':
115
        self.AddAttr(config,param,param_arg,r'[1-9]\d*$',loc,int);
116
      elif param == 'norunt':
117
        self.AddAttr(config,param,param_arg,None,loc);
118
      else:
119
        raise SSBCCException('Unrecognized parameter at %s: %s' % (loc,param,));
120
    # Ensure the required parameters are provided.
121
    if not hasattr(self,'instances'):
122
      self.instances = 1;
123
    # Set optional parameters.
124
    if not hasattr(self,'invert') and not hasattr(self,'noinvert'):
125
      self.noinvert = True;
126
    if not hasattr(self,'norunt'):
127
      self.norunt = False;
128
    # Ensure parameters do not conflict.
129
    if hasattr(self,'invert') and hasattr(self,'noinvert'):
130
      raise SSBCCException('Only one of "invert" or "noinvert" can be specified at %s' % loc);
131
    # Use only one of mutually exclusive configuration settings.
132
    if hasattr(self,'noinvert'):
133
      self.invert = False;
134
    # Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
135
    config.AddIO(self.outsignal,self.instances,'output',loc);
136
    self.ix_outport_0 = config.NOutports();
137
    if self.instances == 1:
138
      tmpOutport = self.outport;
139
      config.AddOutport((tmpOutport,False,),loc);
140
    else:
141
      for ixOutPort in range(self.instances):
142
        tmpOutport = '%s_%d' % (self.outport,ixOutPort,);
143
        config.AddOutport((tmpOutport,False,),loc);
144
    # Add the 'clog2' function to the processor (if required).
145
    config.functions['clog2'] = True;
146
 
147
  def ProcessRateMethod(self,config,param_arg,loc):
148
    if hasattr(self,'ratemethod'):
149
      raise SSBCCException('ratemethod repeated at %s' % loc);
150
    if param_arg.find('/') < 0:
151
      if self.IsIntExpr(param_arg):
152
        self.ratemethod = str(self.ParseIntExpr(param_arg));
153
      elif self.IsParameter(config,param_arg):
154
        self.ratemethod = param_arg;
155
      else:
156
        raise SSBCCException('ratemethod with no "/" must be an integer or a previously declared parameter at %s' % loc);
157
    else:
158
      baudarg = re.findall('([^/]+)',param_arg);
159
      if len(baudarg) == 2:
160
        if not self.IsIntExpr(baudarg[0]) and not self.IsParameter(config,baudarg[0]):
161
          raise SSBCCException('Numerator in ratemethod must be an integer or a previously declared parameter at %s' % loc);
162
        if not self.IsIntExpr(baudarg[1]) and not self.IsParameter(config,baudarg[1]):
163
          raise SSBCCException('Denominator in ratemethod must be an integer or a previously declared parameter at %s' % loc);
164
        for ix in range(2):
165
          if self.IsIntExpr(baudarg[ix]):
166
            baudarg[ix] = str(self.ParseIntExpr(baudarg[ix]));
167
        self.ratemethod = '('+baudarg[0]+'+'+baudarg[1]+'/2)/'+baudarg[1];
168
    if not hasattr(self,'ratemethod'):
169
      raise SSBCCException('Bad ratemethod value at %s:  "%s"' % (loc,param_arg,));
170
 
171
  def GenVerilog(self,fp,config):
172
    body = self.LoadCore(self.peripheralFile,'.v');
173
    output_on = "1'b1";
174
    output_off = "1'b0";
175
    if self.invert:
176
      output_on = "1'b0";
177
      output_off = "1'b1";
178
    norunt = "1'b0";
179
    if self.norunt:
180
      norunt = "1'b1";
181
    for subs in (
182
                  (r'\bL__',            'L__@NAME@__',),
183
                  (r'\bgen__',          'gen__@NAME@__',),
184
                  (r'\bs__',            's__@NAME@__',),
185
                  (r'\bix\b',           'ix__@NAME@',),
186
                  (r'@COUNT@',          self.ratemethod,),
187
                  (r'@INSTANCES@',      str(self.instances),),
188
                  (r'@IX_OUTPORT_0@',   str(self.ix_outport_0),),
189
                  (r'@OFF@',            output_off,),
190
                  (r'@ON@',             output_on,),
191
                  (r'@NAME@',           self.outsignal,),
192
                  (r'@NORUNT@',         norunt,),
193
                ):
194
      body = re.sub(subs[0],subs[1],body);
195
    body = self.GenVerilogFinal(config,body);
196
    fp.write(body);

powered by: WebSVN 2.1.0

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