URL
https://opencores.org/ocsvn/ssbcc/ssbcc/trunk
Subversion Repositories ssbcc
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/ssbcc/trunk/ssbccPeripheral.py
132,12 → 132,27
# |
############################################################################## |
|
def FixedPow2(self,config,lowLimit,highLimit,value): |
def IntPow2Method(self,config,value,lowLimit=1,highLimit=None): |
""" |
Check the provided constant as a power of 2 between the provided limits.\n |
Note: This differs from InpPow2 in that localparams and constants are |
permitted. |
Return the integer value of the argument if it is a power of 2 between the |
optional limits (inclusive). Otherwise throw an error.\n |
Note: Other than a lower limit of 1 for "lowLimit", IntMethod validates |
"lowLimit" and "highLimit". |
""" |
value = self.IntMethod(config,value,lowLimit,highLimit) |
if lowLimit < 1: |
raise SSBCCException('Program bug: lowLimit = %d is less than 1' % lowLimit); |
if not IsPowerOf2(value): |
raise SSBCCException('Must be a power of 2'); |
return value; |
|
def IntMethod(self,config,value,lowLimit=None,highLimit=None): |
""" |
Return the integer value of the argument. Throw an error if the argument is |
unrecognized, not an integer, or is outside the optionally specified range. |
""" |
if (lowLimit != None) and (highLimit != None) and (highLimit < lowLimit): |
raise SSBCCException('Program bug: lowLimit = %d and highLimit = %d conflict' % (lowLimit,highLimit,)); |
if re.match(r'L_\w+$',value): |
if not config.IsParameter(value): |
raise SSBCCException('Unrecognized parameter'); |
147,72 → 162,68
if not config.IsConstant(value): |
raise SSBCCException('Unrecognized constant'); |
value = config.constants[value]; |
if not IsPosInt(value): |
raise SSBCCException('Must be a constant positive integer'); |
value = ParseIntExpr(value); |
if not IsPowerOf2(value): |
raise SSBCCException('Must be a power of 2'); |
if not (lowLimit <= value <= highLimit): |
raise SSBCCException('Must be between %d and %d inclusive' % (lowLimit,highLimit,)); |
if (lowLimit != None) and value < lowLimit: |
if lowLimit == 1: |
raise SSBCCException('Must be a positive integer'); |
else: |
raise SSBCCException('Cannot be less than %d' % lowLimit); |
if (highLimit != None) and value > highLimit: |
raise SSBCCException('Cannot be more than %d' % highLimit); |
return value; |
|
def IntPow2(self,value,minValue=1): |
""" |
Return the integer value of the argument if it is a power of 2. Otherwise |
throw an error. |
""" |
if not IsPosInt(value): |
raise SSBCCException('Not a positive integer'); |
value = ParseIntExpr(value); |
if not IsPowerOf2(value): |
raise SSBCCException('Not a power of 2'); |
if value < minValue: |
raise SSBCCException('Must be at least %d' % minValue); |
return value; |
|
def PosInt(self,value,maxValue=0): |
""" |
Return the integer value of the argument unless it is out of bounds.\n |
Note: maxValue=0 means that there is no upper limit. |
""" |
if not IsPosInt(value): |
raise SSBCCException('Not a positive integer'); |
value = ParseIntExpr(value); |
if (maxValue != 0) and (value > maxValue): |
raise SSBCCException('Out of bounds -- can be at most %d' % maxValue); |
return value; |
|
def RateMethod(self,config,value): |
""" |
Return the string to evaluate the provided value or ratio of two values. |
The value can be an integer (including underscores) or a parameter. Ratios |
are restated to do rounding instead of truncation.\n |
The value can be an integer (including underscores), a constant, or a |
parameter. Ratios are restated to do rounding instead of truncation.\n |
Examples: |
123456 |
123_456 |
L_DIVISION_RATIO |
G_CLOCK_FREQUENCY_HZ/19200 |
C_CLOCK_FREQUENCY_HZ/19200 |
G_CLOCK_FREQUENCY_HZ/L_BAUD_RATE |
100_000_000/G_BAUD_RATE |
""" |
def TestAndGetValue(self,config,value,position): |
if IsIntExpr(value): |
return str(ParseIntExpr(value)); |
elif config.IsConstant(value): |
value = config.constants[value]; |
if not value > 0: |
raise SSBCCException('Constant "%s" must be positive'); |
return str(value); |
elif config.IsParameter(value): |
return value; |
else: |
raise SSBCCException('%s must be a positive integer or a previously declared positive constant or a parameter', position); |
def LocalIntMethod(self,config,value,position=None): |
try: |
if config.IsParameter(value): |
return value; |
else: |
v = self.IntMethod(config,value,lowLimit=1); |
return str(v); |
except SSBCCException, msg: |
if not position: |
raise SSBCCException(msg); |
else: |
raise SSBCCException('%s in %s' % (msg,position,)); |
if value.find('/') < 0: |
return TestAndGetValue(self,config,value,'Value'); |
return LocalIntMethod(self,config,value); |
else: |
ratearg = re.findall('([^/]+)',value); |
if len(ratearg) != 2: |
raise SSBCCException('Only one "/" allowed in expression'); |
ratearg[0] = TestAndGetValue(self,config,ratearg[0],'Numerator'); |
ratearg[1] = TestAndGetValue(self,config,ratearg[1],'Denominator'); |
ratearg[0] = LocalIntMethod(self,config,ratearg[0],'numerator'); |
ratearg[1] = LocalIntMethod(self,config,ratearg[1],'denominator'); |
return '(%s+%s/2)/%s' % (ratearg[0],ratearg[1],ratearg[1],); |
|
def TimeMethod(self,config,value,lowLimit=None,highLimit=None): |
""" |
Convert the provided time from the specified units to seconds. |
""" |
if not re.match(r'(0|[1-9]\d*)(\.\d*)?(e[+-]?\d+)?[mun]?s$',value): |
raise SSBCCException('Malformed time value'); |
if value[-2:] == 'ms': |
v = float(value[:-2]) * 1.e-3; |
elif value[-2:] == 'us': |
v = float(value[:-2]) * 1.e-6; |
elif value[-2:] == 'ns': |
v = float(value[:-2]) * 1.e-9; |
else: |
v = float(value[:-1]); |
if (lowLimit != None) and (v < lowLimit): |
raise SSBCCException('%s must be %s or greater' % (v,lowLimit,)); |
if (highLimit != None) and (v > highLimit): |
raise SSBCCException('%s must be %s or smaller' % (v,highLimit,)); |
return v; |
/ssbcc/trunk/ssbccUtil.py
105,7 → 105,7
raise SSBCCException('Malformed parameter value: "%s"' % save_v); |
ov += dv; |
if length > 0 and ov >= 2**length: |
raise SSBCCException('Paramter length and value don\'t match: "%s"' % save_v); |
raise SSBCCException('Parameter length and value don\'t match: "%s"' % save_v); |
return ov; |
|
def IsIntExpr(value): |
114,9 → 114,9
two integers. |
Allow underscores as per Verilog. |
""" |
if re.match(r'[1-9][0-9_]*',value): |
if re.match(r'-?[1-9][0-9_]*',value): |
return True; |
elif re.match(r'\([1-9][0-9_]*(\*[1-9][0-9_]*)+\)',value): |
elif re.match(r'\(-?[1-9][0-9_]*(\*[1-9][0-9_]*)+\)',value): |
return True; |
else: |
return False; |
172,6 → 172,8
Note: If this routine is called, then the value should have already been |
verified to be a well-formatted integer string. |
""" |
if type(value) == int: |
return value; |
if not IsIntExpr(value): |
raise Exception('Program Bug -- shouldn\'t call with a badly formatted integer expression'); |
return eval(re.sub('_','',value)); |
/ssbcc/trunk/doc/MemoryInitialization.html
48,6 → 48,7
top_inst/uc_inst_Mram_s_opcodeMemory_1 [0:8];<br/> |
END_BUS_BLOCK;<br/> |
END_ADDRESS_SPACE;<br/></tt><br/> |
Note: For a Spartan-3A the bit indices <tt>[0:8]</tt> may need to be reversed.<br/><br/> |
<li>Add this file to the build process.<br/><br/> |
For a command-line build this is done by adding "<tt>-bm uc.bmm</tt>" |
to the argument list for ngdbuild.<br/><br/> |
/ssbcc/trunk/core/9x8/asm
44,6 → 44,7
|
argListParser = argparse.ArgumentParser(description='SSBCC 9x8 assembler'); |
argListParser.add_argument('-C', metavar='CONSTANT=value', action='append', help='Constant definition'); |
argListParser.add_argument('-D', metavar='define', type=str, action='append', help='Define symbol (must start with "D_")'); |
argListParser.add_argument('-G', metavar='parametername', action='append', help='parameter names'); |
argListParser.add_argument('-I', metavar='PORT=index', action='append', help='Input port names'); |
argListParser.add_argument('-L', metavar='librarypath', action='append', help='Library search path'); |
64,7 → 65,7
# Record the constants in the program symbol table. |
if argList.C: |
for constant in argList.C: |
a=re.findall(r'^(C_\w+)=(\w+)$',constant); |
a=re.findall(r'^(C_\w+)=(-?[1-9]\d*|\w+)$',constant); |
if not a: |
raise asmDef.AsmException('Malformed -C argument: "%s"' % constant); |
a = list(a[0]); |
76,6 → 77,13
raise asmDef.AsmException('Command line constant "%s" already defined' % a[0]); |
ad.AddSymbol(a[0], 'constant', body=[a[1]]); |
|
# Record the defines. |
if argList.D: |
for name in argList.D: |
if not re.match('D_',name): |
raise SSBCCException('Bad define name "%s" should start with "D_"' % name); |
ad.AddSymbol(name, 'define'); |
|
# Record the input names and values in the appropriate record type |
if argList.G: |
for parameter in argList.G: |
/ssbcc/trunk/core/9x8/asmDef.py
401,7 → 401,7
if len(b.group(0)) == len(raw): |
pass; |
elif (raw[len(b.group(0))] != '(') or (raw[-1] != ')'): |
raise AsmException('Malformed macro invokaction "%" at %s:%d' % (raw,fl_loc,col+1,)); |
raise AsmException('Malformed macro invokaction "%s" at %s:%d' % (raw,fl_loc,col+1,)); |
else: |
tcol = len(b.group(0))+1; |
while tcol < len(raw): |
/ssbcc/trunk/core/9x8/ssbccGenVerilog.py
799,14 → 799,12
fp.write('// no additional signals\n'); |
return; |
maxLength = 0; |
for ix in range(len(config.signals)): |
thisSignal = config.signals[ix]; |
for thisSignal in config.signals: |
signalName = thisSignal[0]; |
if len(signalName) > maxLength: |
maxLength = len(signalName); |
maxLength = maxLength + 12; |
for ix in range(len(config.signals)): |
thisSignal = config.signals[ix]; |
for thisSignal in config.signals: |
signalName = thisSignal[0]; |
signalWidth = thisSignal[1]; |
signalInit = "%d'd0" % signalWidth if len(thisSignal) < 3 else thisSignal[2]; |
/ssbcc/trunk/core/9x8/asmDef_9x8.py
42,8 → 42,8
""" |
Add the named global symbol to the list of symbols including its mandatory |
type and an optional body.\n |
Note: Symbols include memory names, variables, constants, functions, |
parameters, inports, outports, ... |
Note: Symbols include memory names, variables, constants, defines, |
functions, parameters, inports, outports, ... |
""" |
if self.IsSymbol(name): |
raise Exception('Program Bug -- name "%s" already exists is symbols' % name); |
383,19 → 383,10
# Ensure the directive bodies are not too short. |
if (firstToken['value'] in ('.main','.interrupt',)) and not (len(rawTokens) > 1): |
raise asmDef.AsmException('"%s" missing body at %s' % (firstToken['value'],firstToken['loc'],)); |
if (firstToken['value'] in ('.macro',)) and not (len(rawTokens) == 2): |
if (firstToken['value'] in ('.define','.macro',)) and not (len(rawTokens) == 2): |
raise asmDef.AsmException('body for "%s" directive must have exactly one argument at %s' % (firstToken['value'],firstToken['loc'],)); |
if (firstToken['value'] in ('.constant','.function','.memory','.variable',)) and not (len(rawTokens) >= 3): |
raise asmDef.AsmException('body for "%s" directive too short at %s' % (firstToken['value'],firstToken['loc'],)); |
# Ensure the main body ends in a ".jump". |
lastToken = rawTokens[-1]; |
if firstToken['value'] == '.main': |
if (lastToken['type'] != 'macro') or (lastToken['value'] != '.jump'): |
raise asmDef.AsmException('.main body does not end in ".jump" at %s' % lastToken['loc']); |
# Ensure functions and interrupts end in a ".jump" or ".return". |
if firstToken['value'] in ('.function','.interrupt',): |
if (lastToken['type'] != 'macro') or (lastToken['value'] not in ('.jump','.return',)): |
raise asmDef.AsmException('Last entry in ".function" or ".interrupt" must be a ".jump" or ".return" at %s' % lastToken['loc']); |
# Ensure no macros and no instructions in non-"functions". |
# Byproduct: No labels allowed in non-"functions". |
if firstToken['value'] not in ('.function','.interrupt','.main',): |
438,6 → 429,15
for arg in token['argument'][ixFirst:]: |
if arg['type'] == 'symbol': |
self.CheckSymbolToken(arg['value'],allowableTypes,arg['loc']); |
# Ensure the main body ends in a ".jump". |
lastToken = rawTokens[-1]; |
if firstToken['value'] == '.main': |
if (lastToken['type'] != 'macro') or (lastToken['value'] != '.jump'): |
raise asmDef.AsmException('.main body does not end in ".jump" at %s' % lastToken['loc']); |
# Ensure functions and interrupts end in a ".jump" or ".return". |
if firstToken['value'] in ('.function','.interrupt',): |
if (lastToken['type'] != 'macro') or (lastToken['value'] not in ('.jump','.return',)): |
raise asmDef.AsmException('Last entry in ".function" or ".interrupt" must be a ".jump" or ".return" at %s' % lastToken['loc']); |
|
################################################################################ |
# |
450,28 → 450,31
Return either (1) a list comprised of a single token which may not be a |
byte or (2) a list comprised of multiple tokens, each of which is a single |
byte.\n |
Note: This is called by FillRawTokens. |
Note: This is called by FillRawTokens.\n |
Note: Multi-value lists must be single-byte values (i.e., in the range -128 to 255) |
""" |
if len(rawTokens) > 1: |
limit = True; |
values = list(); |
try: |
for token in rawTokens: |
if token['type'] == 'value': |
v = token['value']; |
if type(v) == int: |
if limit and not (-128 <= v < 256): |
raise Exception('Program Bug -- unexpected out-of-range value'); |
values.append(v); |
else: |
for v in token['value']: |
if not (-128 <= v < 256): |
raise Exception('Program Bug -- unexpected out-of-range value'); |
values.append(v); |
else: |
raise asmDef.AsmException('Illegal token "%s" at %s:%d:%d', (token['type'],token['loc'])); |
except: |
raise asmDef.AsmException('Out-of-range token "%s" at %s:%d:%d', (token['type'],token['loc'])); |
for token in rawTokens: |
if token['type'] == 'symbol': |
ix = self.symbols['list'].index(token['value']); |
symbolType = self.symbols['type'][ix]; |
if symbolType != 'constant': |
raise asmDef.AsmException('Illegal symbol "%s" at %s' % (token['value'],token['loc'],)); |
value = self.symbols['body'][ix]; |
elif token['type'] == 'value': |
value = token['value']; |
else: |
raise asmDef.AsmException('Illegal token "%s" with value "%s" at %s' % (token['type'],token['value'],token['loc'],)); |
if type(value) == int: |
value = [value]; |
else: |
limit = True; |
for v in value: |
if limit and not (-128 <= v < 256): |
raise asmDef.AsmException('Out-of-rarnge value "%d" at %s' % (v,token['loc'],)) |
values.append(v); |
return values; |
|
def ExpandSymbol(self,token,singleValue): |
596,6 → 599,9
if firstToken['value'] == '.constant': |
byteList = self.ByteList(rawTokens[2:]); |
self.AddSymbol(secondToken['value'],'constant',body=byteList); |
# Process ".define" directive |
elif firstToken['value'] == '.define': |
self.AddSymbol(secondToken['value'],'define'); |
# Process ".function" definition. |
elif firstToken['value'] == '.function': |
self.AddSymbol(secondToken['value'],'function',self.ExpandTokens(rawTokens[2:])); |
753,7 → 759,7
raise asmDef.AsmException('Function "%s" not defined for function "%s"' % (callName,self.functionEvaluation['list'][ix],)); |
ixName = self.symbols['list'].index(callName); |
if self.symbols['type'][ixName] != 'function': |
raise asmDef.AsmException('Function "%s" called by "%s" is not a function', (callName, self.functionEvaluation['list'][ix],)); |
raise asmDef.AsmException('Function "%s" called by "%s" is not a function' % (callName, self.functionEvaluation['list'][ix],)); |
self.functionEvaluation['list'].append(callName); |
self.functionEvaluation['length'].append(self.symbols['body'][ixName]['length']); |
self.functionEvaluation['body'].append(self.symbols['body'][ixName]['tokens']); |
1207,6 → 1213,7
|
self.directives['list']= list(); |
self.directives['list'].append('.constant'); |
self.directives['list'].append('.define'); |
self.directives['list'].append('.function'); |
self.directives['list'].append('.interrupt'); |
self.directives['list'].append('.macro'); |
/ssbcc/trunk/core/9x8/peripherals/stepper_motor.py
0,0 → 1,476
################################################################################ |
# |
# Copyright 2015, Sinclair R.F., Inc. |
# |
################################################################################ |
|
import math |
|
from ssbccPeripheral import SSBCCperipheral |
from ssbccUtil import CeilLog2 |
from ssbccUtil import SSBCCException |
|
class stepper_motor(SSBCCperipheral): |
""" |
Stepper motor driver\n |
This peripheral creates pulses to driver a stepper motor driver such as TI's |
DRV8825. It includes a buffer which can be used to store acceleration, |
motion, and deceleration profiles and returns a "completed" status to the |
micro controller.\n |
The core runs accumulators for the angle and the rate. I.e. the rate is an |
accumulated sum of the initial rate and the commanded acceleration and the |
angle is an accumulation of this possibly changing rate. The direction signal |
to the stepper motor is the sign bit from the accumulated rate. The "step" |
signal to the stepper motor driver is strobed every time the accumulated angle |
overflows or underflows and the direction bit to the driver is set according |
to whether the accumulated angle overflowed or underflowed.\n |
The motor control word consists of the following signals: |
initial rate |
acceleration |
number of steps to be performed this control word |
optional mode specification |
These control words are individually packed into one or more 8-bit bytes. The |
8-bit values from the micro controller are shifted into a buffer from which |
the control word is constructed. This completed control word is then shifted |
into a FIFO. The control words in the FIFO are then used to generate the |
timing for the step strobes to the stepper motor driver. When the FIFO |
empties, the rate and the acceleration are set to zero and the mode retains |
its most recent value. The user must ensure they do not overfill the FIFO -- |
the only FIFO status is an "empty" or control words "done" status.\n |
Usage: |
PERIPHERAL stepper_motor basename=name \\ |
outcontrol=O_name \\ |
outrecord=O_name \\ |
outrun=O_name \\ |
indone=I_name \\ |
inerror=I_name \\ |
ratemethod={CLK_FREQ_HZ/RATE_HZ|count} \\ |
ratescale=N_rate_scale \\ |
rateres=N_rate \\ |
accelscale=N_accel_scale \\ |
accelres=N_accel \\ |
[accumres=N_accum] \\ |
countwidth=N_count \\ |
[modewidth=N_mode] \\ |
[FIFO=N_fifo]\n |
Or:\n |
PERIPHERAL stepper_motor basename=name \\ |
master=mastername \\ |
outcontrol=O_name \\ |
outrecord=O_name \\ |
outrun=O_name \\ |
indone=I_name \\ |
inerror=I_name \\ |
[FIFO=N_fifo]\n |
Where: |
basename=name |
specifies the name used to contruct the I/O signals |
Note: The name must start with an alphabetic character. |
Example: "basename=stepper" results in the names "o_stepper_dir", |
"o_stepper_step", and "o_stepper_mode" for the output |
direction, step, and optional mode signals and |
"i_stepper_error" for the input error signal. |
master=mastername |
specifies a preceding stepper_motor peripheral to use for the internal |
clock and to use for the accleration, rate, angle accumulator, and mode |
sizes |
outcontrol=O_name |
specifies the port used to assemble 8-bit control values into the stepper |
motor control word |
Note: The name must start with "O_". |
outrecord=O_name |
specifies the port used to generate the strobe that pushes the assembled |
motor control word into the stepper motor FIFO |
Note: The name must start with "O_". |
outrun=O_name |
specified the port used to begin the sequence of operations specified by |
the motor control words in the buffer |
Note: The name must start with "O_". |
indone=I_name |
specifies the port used to determine whether or not the operations in the |
FIFO have finished |
Note: The name must start with "I_". |
inerror=I_name |
specifies the port used to read the error status from the stepper motor |
controller |
Note: The name must start with "I_". |
ratemethod |
specified the method to generate the internal clock rate from the |
processor clock |
1st method: CLK_FREQ_HZ/RATE_HZ |
CLK_FREQ_HZ is the frequency of "i_clk" in Hz |
a number will be interpreted as the clock frequency in Hz |
a symbol will be interpreted as a constant or a parameter |
Note: the symbol must be declared with the CONSTANT, LOCALPARARM, |
or PARAMETER configuration command. |
RATE_HZ is the desired internal clock rate |
this is specified as per "CLK_FREQ_HZ" |
2nd method: count |
specify the number of "i_clk" clock cycles per internal clock cycle |
Note: CLK_FREQ_HZ, RATE_HZ, and count can be parameters or constants. For example, |
the following uses the parameter C_CLK_FREQ_HZ for the clock |
frequency and an internal rate to 500 kHz: |
"ratemethod=C_CLK_FREQ_HZ/500_000". |
Note: The minimum value of "ratemethod" is 2. |
ratescale=N_rate_scale |
specifies the scaling for the most significant bit of the rate |
Note: See the 'a' parameter in the "Theory of Operation" section. |
rateres=N_rate |
specifies the resolution of the rate |
Note: See the 'r' parameter in the "Theory of Operation" section. |
accelscale=N_accel_scale |
specifies the scaling for the most significant bit of the acceleration |
Note: See the 'a' parameter in the "Theory of Operation" section. |
accelres=N_accel |
specifies the resolution for the acceleration |
Note: See the 'b' parameter in the "Theory of Operation" section. |
accumres=N_accum |
optionally specify the resolution for the accumulator to the summed angle |
(from which the step strobes are generated) |
Note: This must be between rateres and accelres. |
Note: The default value is accelres. |
countwidth=N_count |
specifies the width of the counter for the number of steps to be performed |
by the control word |
modewidth=N_mode |
- if not specified, there is no mode signal to the stepper motor |
controller |
- if specified then this specifies the width of the signal to the stepper |
motor controller |
FIFO=N_fifo |
optionally specify the depth of the control word FIFO |
Note: This must be a power of 2 and must be at least 16. |
Note: The default is 16.\n |
Theory of Operation: |
Define the following: |
n is the number of internal clock cycles since the control word |
started being performed (i.e., these are counted after the dlock |
rate is reduced by ratemethod) |
F is the internal clock cycle frequency (i.e., RATE_HZ in the |
second form for specifying the ratemethod |
R_0 is the initial rate command |
R_n is the accumulated rate after n internal clock cycles |
A is the commanded acceleration |
S_n is the accumulated step after n internal clock cycles |
Then |
R_n = R_0 + A * n |
S_n = R_0 * n + A * n * (n-1) / 2 |
The rate R_n can be thought of as a signed fraction with the format "s0.r" |
where 's' represents the sign bit, there are no bits to the left of the |
decimal, and there are 'r' bits to the right of the decimal. Then the rate |
can be as high as F and as low as F/2^r. Practically, the maximum rate |
cannot exceed half the internal clock frequency, otherwise the "step" |
signals will merge together and the stepper driver will not see distinct |
driver pulses.\n |
Similarly, the acceleration command A can be thought of as a signed fraction |
with the format "sa.b". Here 's' again represents the sign bit and 'b' |
represents the number of bits to the right of the decimial, but 'a' is a |
negative number representing the first bit in A. I.e., aside from the sign |
bit, A is b+a+1 bits wide. For example, the specification s-4.8 means that |
A has a sign bit with 8-4+1 = 5 bits for the value of A with the leasts |
significant bit representing a rate of F^2/2^8.\n |
The bit widths are determined as follows: Let mR be the minimum non-zero |
magnitude of the rate, mA be the minimum non-zero mangitude of the |
acceleration, and MA be the mamximum magnitude of the acceleration, all in |
step/sec or step/sec^2. Then\n |
r = ceil(-log_2(mR/F))\n |
a = floor(log_2(MA/F^2))\n |
b = ceil(-log_2(mA/f^2))\n |
Note: r and b may be increased by a few bits if accurate representations of |
the minimum rates are needed.\n |
Example: |
A micro controller with an 8 MHz clock is used to operate a DRV8825 driving |
a stepper motor assembly. The stepper motor has 200 steps per revolution, |
can be operated in full-step or a 16-step micro step mode, has a maximum |
rotation rate of 10 Hz, and has a maximum acceleration of 4 Hz/sec (i.e., |
800 full-steps/sec^2). The motor is attached to a 400mm theaded rod with a |
pitch of 4mm per revolution.\n |
The 1.9usec minimum high and low widths of the DRV8825 and the 8 MHz |
processor clock mean that the stepper motor controller can realistically be |
run at 500kHz. The rate method to divide the micro controller clock to the |
internal processing rate is specified by "ratemethod" in the PERIPHERAL |
command.\n |
The bit widths are determine by choosing:\n |
MR = 10 rev/sec * 200 full-step/rev * 16 micro-step/full-step |
= 32000 micro-step/sec |
==> R = -ceil(log_2(MR/F)) |
= -ceil(log_2((32000 micro-step/sec)/500kHz)) |
= 3 |
mR = 10 step/sec |
==> r = -floor(log_2(mR/F)) |
= -floor(log_2((10 step/sec)/500kHz) |
= 16\n |
MA = 10 rev/sec^2 = 10*16*200 step/sec^2 |
==> A = -ceil(log_2(MA/F^2)) |
= -ceil(log_2((32,000 step/sec^2)/500kHz^2)) |
= 22\n |
mA = 20 step/sec^2 (in full step mode) |
==> a = -floor(log_2(mA/F^2)) |
= 34\n |
The values R=3 and r=16 along with the sign bit mean the rate would be |
stored in a signed 14-bit value. The rate requires two 8-bit writes to the |
control word.\n |
The values A=22 and a=34 mean the acceleration would be stored in a signed |
1+(34-22) = 13 bit value. The acceleration requires two 8-bit writes to the |
control word.\n |
The accumulator width is set to the same value as the acceleration |
resolution. This avoid non-linear trunction errors and makes the motion |
profile more predictable using simple integer arithmetic.\n |
The number of full steps to move from one of the of rod to the other is |
(400mm/(4mm/rev)*(200steps/rev)=20_000 steps. In the micro-stepmode there |
are 16 micro steps per full step, so at most 320_000 micro steps can be |
performed before the full length of the rod is traversed. I.e., a 19-bit |
counter will suffice for the worst-case unidirection motion. This 19-bit |
count requires 3 8-bit writes to the control word.\n |
A "modewidth" of 1 is specifies so that the controller can be operated in |
either full step or a single hard-wired micro-step mode. If all 3 of the |
DRV8825 mode pins were connected, then "modewidth=3" would need to |
specified.\n |
The peripheral is then specified as follows:\n |
CONSTANT C_RATE_SCALE 3 |
CONSTANT C_RATE_RES 16 |
CONSTANT C_ACCEL_SCALE 22 |
CONSTANT C_ACCEL_RES 34 |
CONSTANT C_ACCUM_RES 34 |
CONSTANT C_COUNT_WIDTH 19 |
PERIPHERAL stepper_motor basename=stepper \\ |
outcontrol=O_stepper_control \\ |
outrecord=O_stepper_wr \\ |
outrun=O_stepper_go \\ |
indone=I_stepper_done \\ |
inerror=I_stepper_error \\ |
ratemethod=8_000_000/500_000 \\ |
ratescale=C_RATE_SCALE \\ |
rateres=C_RATE_RES \\ |
accelscale=C_ACCEL_SCALE \\ |
accelres=C_ACCEL_RES \\ |
accumres=C_ACCUM_RES \\ |
countwidth=C_COUNT_WIDTH \\ |
modewidth=1\n |
and the TBD byte control words are pushed into the peripheral as follows: |
R_0 14-bit initial rate stored in a 16-bit field (MSB first) |
A 13-bit acceleration stored in a 16-bit field (MSB first) |
COUNT 19-bit count stored in a 24-bit field (MSB first) |
MODE 1-bit mode stored as the lsb of an 8-bit field |
The control word is a total of 8 bytes wide.\n |
To command the peripheral to accelerate from stop to 200 steps/sec in one |
second in the forward direction using the full-step mode, the following |
seqeuence of bytes would be written to the control port: |
0x00 0x00 ; initial rate is zero |
0x00 0x0E ; 200 step/sec^2 * 2^34 / 500kHz^2 = 14 |
0x00 0x00 0x63 ; send 100 step commands (command 100-1=99) |
0x00 ; full-step mode |
Note: It will take t=sqrt(2*100*2^34/14)/F = 0.99 sec to move the commanded |
100 steps. At this time the speed will be r=t*14/2^34*F^2 = 201 step/sec. |
A more accurate match to the commanded speed could be accomplished by adding |
additional bits to the acceleration resolution at the cost of using more |
FPGA resources. Alternatively, the acceleration could be commanded for 99 |
steps and any subsequent 200 step/sec motion could be lengthened by 1 step. |
Another alternative would be to use a micro-step acceleration. Practically, |
the computed command is within 0.5% of the desired step rate.\n |
To command the peripheral to decelerate from 200 step/sec to zero in one |
second, the following sequence of bytes would be written to the control |
port: |
0x00 0x01 0xDB ; 200 step/sec * 2^23 / 500kHz |
0xFF 0x9C ; negative of the above acceleration |
0x00 0x00 0x63 ; send 100 step commands (command 100-1=99) |
0x00 ; full-step mode\n |
The first of these two control words could be assembled and transmitted to |
the peripheral as follows:\n |
0x00 ; mode |
.push24(${100-1}) ; send 100 step commands |
.push16(14) ; 200 step/sec^2 |
.push16(0) ; initial rate is zero |
${8-1} :loop swap .outport(O_stepper_control) .jumpc(loop,1-) drop |
.outstrobe(O_stepper_wr) ; push the assembed control word into the FIFO |
... |
.outstrobe(O_stepper_go) ; perform the queued control words\n |
Example: |
Slave a second stepper motor controller peripheral to the preceding |
periperal.\n |
PERIPHERAL stepper_motor basename=slave \\ |
master=stepper \\ |
outcontrol=O_slave_control \\ |
outrecord=O_slave_wr \\ |
outrun=O_slave_go \\ |
indone=I_slave_done \\ |
inerror=I_slave_error\n |
This controller will use the internal clock generated by the first |
controller and the scales, resolutions, and accumulator width will be the |
same as that master peripheral. What will be different is the four I/O |
ports used to operate and status the controller. |
""" |
|
def __init__(self,peripheralFile,config,param_list,loc): |
# Use the externally provided file name for the peripheral |
self.peripheralFile = peripheralFile |
# Get the parameters. |
allowables = ( |
( 'FIFO', r'\S+$', lambda v : self.IntPow2Method(config,v,lowLimit=16), ), |
( 'accelres', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'accelscale', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'accumres', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'basename', r'[A-Za-z]\w*$', None, ), |
( 'countwidth', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'indone', r'I_\w+$', None, ), |
( 'inerror', r'I_\w+$', None, ), |
( 'master', r'[A-Za-z]\w*$', None, ), |
( 'modewidth', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'outcontrol', r'O_\w+$', None, ), |
( 'outrecord', r'O_\w+$', None, ), |
( 'outrun', r'O_\w+$', None, ), |
( 'ratemethod', r'\S+$', lambda v : self.RateMethod(config,v), ), |
( 'rateres', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
( 'ratescale', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1), ), |
) |
names = [a[0] for a in allowables] |
for param_tuple in param_list: |
param = param_tuple[0] |
if param not in names: |
raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,)) |
param_test = allowables[names.index(param)] |
self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]) |
# Signals that can't be specified when a master is specified. |
masterExclude = ( |
'accelres', |
'accelscale', |
'accumres', |
'countwidth', |
'modewidth', |
'ratemethod', |
'rateres', |
'ratescale', |
) |
# Ensure the required parameters are provided. |
reqdParms = ( |
'basename', |
'indone', |
'inerror', |
'outcontrol', |
'outrecord', |
'outrun', |
) |
if not hasattr(self,'master'): |
reqdParms += tuple([me for me in masterExclude if me not in ('accumres','modewidth',)]) |
for paramname in reqdParms: |
if not hasattr(self,paramname): |
raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,)) |
# Ensure mutually exclusive parameters are not listed. |
if hasattr(self,'master'): |
for paramname in masterExclude: |
if hasattr(self,paramname): |
raise SSBCCException('Parameter "%s" cannot be specified alongside "master" at %s' % (paramname,loc,)) |
# Ensure basename is unique for this class of peripheral |
for p in config.peripheral: |
if (str(p.__class__) == str(self.__class__)) and (p.basename == self.basename): |
raise SSBCCException('Duplicated stepper_motor basename "%s" at %s' % (self.basename,loc,)) |
# For slaves, copy the bit widths from the master peripheral. |
if hasattr(self,'master'): |
for p in config.peripheral: |
if (str(p.__class__) == str(self.__class__)) and (p.basename == self.master): |
break |
else: |
raise SSBCCException('Can\'t find preceding stepper_motor peripheral with basename=%s at %s ' % (self.master,loc,)) |
self.master = p |
for paramname in masterExclude: |
setattr(self,paramname,getattr(self.master,paramname)) |
# Set unspecified optional parameters. |
if not hasattr(self,'accumres'): |
self.accumres = self.accelres |
if not hasattr(self,'modewidth'): |
self.modewidth = 0 |
if not hasattr(self,'FIFO'): |
self.FIFO = 16 |
# Ensure the parameters satisfy any mutual constraints. |
if not (self.rateres < self.accelres): |
raise SSBCCException('rateres should be smaller than accelres at %s' % loc) |
if not (self.rateres <= self.accumres <= self.accelres): |
raise SSBCCException('accumres must be between rateres and accelres at %s' % loc) |
# Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral. |
config.AddIO('o_%s_dir' % self.basename, 1, 'output', loc) |
config.AddIO('o_%s_step' % self.basename, 1, 'output', loc) |
if self.modewidth > 0: |
config.AddIO('o_%s_mode' % self.basename, 1, 'output', loc) |
config.AddIO('i_%s_error' % self.basename, 1, 'input', loc) |
config.AddSignal('s__%s__done' % self.basename, 1, loc) |
self.ix_outcontrol = config.NOutports() |
config.AddOutport((self.outcontrol, |
False, |
# empty list |
),loc) |
self.ix_outrecord = config.NOutports() |
config.AddOutport((self.outrecord, |
True, |
# empty list |
),loc) |
self.ix_outrun = config.NOutports() |
config.AddOutport((self.outrun, |
True, |
# empty list |
),loc) |
config.AddInport((self.inerror, |
('i_%s_error' % self.basename, 1, 'data', ), |
), loc) |
config.AddInport((self.indone, |
('s__%s__done' % self.basename, 1, 'data', ), |
), loc) |
# Compute bit widths. |
dw = config.Get('data_width') |
self.data_width = dw |
self.ratecmdwidth = 1 + self.rateres - self.ratescale |
self.ratewidth = 1 + self.accelres - self.ratescale |
self.accelwidth = 1 + self.accelres - self.accelscale |
self.accumwidth = self.accumres + 1 |
self.controlwidth = self.ratecmdwidth |
self.controlwidth += dw*int((self.accelwidth+dw-1)/dw) |
self.controlwidth += dw*int((self.countwidth+dw-1)/dw) |
self.controlwidth += dw*int((self.modewidth+dw-1)/dw) |
self.controlwidthpacked = self.ratecmdwidth + self.accelwidth + self.countwidth + self.modewidth |
# Add the 'clog2' function to the processor (if required). |
config.functions['clog2'] = True |
|
def GenVerilog(self,fp,config): |
body = self.LoadCore(self.peripheralFile,'.v') |
if hasattr(self,'master'): |
body = re.sub(r'@MASTER_BEGIN@.*?@MASTER_END@\n','',body,flags=re.DOTALL) |
else: |
body = re.sub(r'@MASTER_BEGIN@\n','',body) |
body = re.sub(r'@MASTER_END@\n','',body) |
if self.modewidth == 0: |
body = re.sub(r'@OUTMODE_BEGIN@.*?@OUTMODE_END@\n','',body,flags=re.DOTALL) |
else: |
body = re.sub(r'@OUTMODE_BEGIN@\n','',body) |
body = re.sub(r'@OUTMODE_END@\n','',body) |
for subpair in ( |
( r'@ACCEL_WIDTH@', str(self.accelwidth), ), |
( r'@ACCEL_RES@', str(self.accelres), ), |
( r'@ACCEL_SCALE@', str(self.accelscale), ), |
( r'@ACCUM_RES@', str(self.accumres), ), |
( r'@ACCUM_WIDTH@', str(self.accumwidth), ), |
( r'@CONTROL_WIDTH@', str(self.controlwidth), ), |
( r'@CONTROL_WIDTH_PACKED@', str(self.controlwidthpacked), ), |
( r'@COUNT_WIDTH@', str(self.countwidth), ), |
( r'@DW@', str(self.data_width), ), |
( r'@DWM1@', str(self.data_width-1), ), |
( r'@FIFO_DEPTH@', str(self.FIFO), ), |
( r'@IX_OUTCONTROL@', str(self.ix_outcontrol), ), |
( r'@IX_OUTRECORD@', str(self.ix_outrecord), ), |
( r'@IX_OUTRUN@', str(self.ix_outrun), ), |
( r'@MODE_WIDTH@', str(self.modewidth), ), |
( r'@NAME@', self.basename, ), |
( r'@NBITS_FIFO_DEPTH@', str(CeilLog2(self.FIFO)), ), |
( r'@OUTMODEWIDTH@', str(self.modewidth), ), |
( r'@RATECMD_WIDTH@', str(self.ratecmdwidth), ), |
( r'@RATEMETHOD@', str(self.ratemethod), ), |
( r'@RATE_RES@', str(self.rateres), ), |
( r'@RATE_SCALE@', str(self.ratescale), ), |
( r'@RATE_WIDTH@', str(self.ratewidth), ), |
( r'\bL__', 'L__%s__' % self.basename, ), |
( r'\bi__', 'i_%s_' % self.basename, ), |
( r'\bo__', 'o_%s_' % self.basename, ), |
( r'\bs__', 's__%s__' % self.basename, ), |
( r'@S__CLK_EN@', 's__%s__clk_en' % (self.basename if not hasattr(self,'master') else self.master.basename), ), |
): |
body = re.sub(subpair[0],subpair[1],body) |
body = self.GenVerilogFinal(config,body) |
fp.write(body) |
/ssbcc/trunk/core/9x8/peripherals/outFIFO_async.py
68,7 → 68,7
('data_empty', r'o_\w+$', None, ), |
('outport', r'O_\w+$', None, ), |
('infull', r'I_\w+$', None, ), |
('depth', r'[1-9]\d*$', lambda v : self.IntPow2(v,minValue=16), ), |
('depth', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v,lowLimit=16), ), |
); |
names = [a[0] for a in allowables]; |
for param_tuple in param_list: |
/ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v
File deleted
ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v
Property changes :
Deleted: svn:eol-style
## -1 +0,0 ##
-native
\ No newline at end of property
Deleted: svn:keywords
## -1 +0,0 ##
-Author Date Id Revision
\ No newline at end of property
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v-normal
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v-normal (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v-normal (revision 9)
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ *
+ * Copyright 2013, Sinclair R.F., Inc.
+ *
+ * Test bench for the UART_Rx peripheral.
+ *
+ ******************************************************************************/
+
+`timescale 1ns/1ps
+
+module tb;
+
+// 100 MHz clock
+reg s_clk = 1'b1;
+always @ (s_clk)
+ s_clk <= #5 ~s_clk;
+
+reg s_rst = 1'b1;
+initial begin
+ repeat (5) @ (posedge s_clk);
+ s_rst = 1'b0;
+end
+
+// 115200 baud, 1 stop bit
+reg [15*10:0] s_buf1 = {
+ // list last byte first
+ 1'b1, 8'h00, 1'b0, // null character (also terminates program)
+ 1'b1, 8'h0A, 1'b0, // LF
+ 1'b1, 8'h0D, 1'b0, // CR
+ 1'b1, 8'h12, 1'b0, // '!'
+ 1'b1, 8'h63, 1'b0, // 'd'
+ 1'b1, 8'h6C, 1'b0, // 'l'
+ 1'b1, 8'h72, 1'b0, // 'r'
+ 1'b1, 8'h6F, 1'b0, // 'o'
+ 1'b1, 8'h57, 1'b0, // 'W'
+ 1'b1, 8'h20, 1'b0, // ' '
+ 1'b1, 8'h6F, 1'b0, // 'o'
+ 1'b1, 8'h6C, 1'b0, // 'l'
+ 1'b1, 8'h6C, 1'b0, // 'l'
+ 1'b1, 8'h65, 1'b0, // 'e'
+ 1'b1, 8'h48, 1'b0, // 'H'
+ 1'b1
+ };
+wire s_uart = s_buf1[0];
+initial begin
+ @ (negedge s_rst);
+ #100;
+ forever begin
+ #8680.555;
+ s_buf1 <= { 1'b1, s_buf1[1+:15*10] };
+ end
+end
+
+wire [7:0] s_data;
+wire s_data_wr;
+wire s_done;
+tb_UART_Rx uut(
+ // synchronous reset and processor clock
+ .i_rst (s_rst),
+ .i_clk (s_clk),
+ .i_uart_rx (s_uart),
+ .o_data (s_data),
+ .o_data_wr (s_data_wr),
+ .o_done (s_done)
+);
+
+always @ (posedge s_clk)
+ if (s_data_wr)
+ $display("%h", s_data);
+
+always @ (posedge s_clk)
+ if (s_done)
+ $finish;
+
+endmodule
Index: ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/run
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/run (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/run (revision 9)
@@ -1,9 +1,9 @@
#!/bin/bash
-# Copyright 2013, Sinclair R.F., Inc.
+# Copyright 2013, 2015, Sinclair R.F., Inc.
NAME=UART_Rx
-cat < good
+cat < tb.good
48
65
6c
@@ -22,13 +22,14 @@
EOF
# Test +/-2.7% and 0% baud rates.
-cp tb_UART_Rx.s-normal tb_UART_Rx.s;
+cp tb_${NAME}.s-normal tb_${NAME}.s;
+cp tb.v-normal tb.v
for baud in 112089 115200 118310; do
sed -e "s/115200/${baud}/" tb_${NAME}.9x8-good > tb_${NAME}.9x8;
../../../../../ssbcc -q -P monitor_stack tb_${NAME}.9x8 || { echo "${NAME} compile failed" > /dev/stderr; exit 1; }
iverilog -o tb tb.v tb_${NAME}.v || { echo "${NAME} build failed" > /dev/stderr; exit 1; }
./tb > tb.out;
- if ! cmp -s tb.out good; then
+ if ! cmp -s tb.out tb.good; then
echo "${NAME} failed testing baud rate: ${baud}" > /dev/stderr;
exit 1;
fi
@@ -35,15 +36,34 @@
done
# Partial test for input FIFO.
-cp tb_UART_Rx.s-fifo tb_UART_Rx.s;
+cp tb_${NAME}.s-fifo tb_${NAME}.s;
+cp tb.v-normal tb.v
sed -e "s/G_BAUD$/G_BAUD inFIFO=16/" tb_${NAME}.9x8-good > tb_${NAME}.9x8;
../../../../../ssbcc -q -P monitor_stack tb_${NAME}.9x8 || { echo "${NAME} compile failed" > /dev/stderr; exit 1; }
iverilog -o tb tb.v tb_${NAME}.v || { echo "${NAME} build failed" > /dev/stderr; exit 1; }
./tb > tb.out
-if ! cmp tb.out good; then
+if ! cmp tb.out tb.good; then
echo "${NAME} FIFO test failed" > /dev/stderr;
exit 1;
fi
+# Validate RTRn signal generation
+cp tb_${NAME}.s-rtrn tb_${NAME}.s
+cp tb.v-rtrn tb.v
+for RTR_BUFFER in 1 2 4; do
+ for RTR_OVERFLOW in 0 1 2 3; do
+ if [ ${RTR_OVERFLOW} -ge ${RTR_BUFFER} ]; then continue; fi
+ sed -e "s/G_BAUD$/G_BAUD inFIFO=8 RTRn=o_uart_rtrn rtr_buffer=${RTR_BUFFER}/" tb_${NAME}.9x8-good > tb_${NAME}.9x8;
+ sed -e "s/@RTR_OVERFLOW@/${RTR_OVERFLOW}/" tb.v-rtrn > tb.v;
+ ../../../../../ssbcc -q -P monitor_stack tb_${NAME}.9x8 || { echo "${NAME} compile failed" > /dev/stderr; exit 1; }
+ iverilog -o tb tb.v tb_${NAME}.v || { echo "${NAME} build failed" > /dev/stderr; exit 1; }
+ ./tb > tb.out
+ if ! cmp tb.out tb.good; then
+ echo "${NAME} FIFO test failed" > /dev/stderr;
+ exit 1;
+ fi
+ done
+done
+
echo "Passed: ${NAME}";
exit 0;
/ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/.gitignore
1,7 → 1,8
bad-* |
good |
tb |
tb.good |
tb.out |
tb.v |
tb_UART_Rx.9x8 |
tb_UART_Rx.s |
tb_UART_Rx.v |
/ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb_UART_Rx.9x8-good
1,4 → 1,4
# Copyright 2013, Sinclair R.F., Inc. |
# Copyright 2013, 2015, Sinclair R.F., Inc. |
# Test bench for UART_Rx peripheral. |
|
ARCHITECTURE core/9x8 Verilog |
9,9 → 9,9
PARAMETER G_CLK_FREQ_HZ 100_000_000 |
PARAMETER G_BAUD 115200 |
|
PERIPHERAL UART_Rx inport=I_UART_RX \ |
inempty=I_UART_RX_EMPTY \ |
insignal=i_uart \ |
PERIPHERAL UART_Rx inport=I_UART_RX \ |
inempty=I_UART_RX_EMPTY \ |
insignal=i_uart_rx \ |
baudmethod=G_CLK_FREQ_HZ/G_BAUD |
|
OUTPORT 8-bit,strobe o_data,o_data_wr O_DATA |
/ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb.v-rtrn
0,0 → 1,95
/******************************************************************************* |
* |
* Copyright 2015, Sinclair R.F., Inc. |
* |
* Test bench for the UART_Rx peripheral. |
* |
******************************************************************************/ |
|
`timescale 1ns/1ps |
|
module tb; |
|
// 100 MHz clock |
reg s_clk = 1'b1; |
always @ (s_clk) |
s_clk <= #5 ~s_clk; |
|
reg s_rst = 1'b1; |
initial begin |
repeat (5) @ (posedge s_clk); |
s_rst = 1'b0; |
end |
|
// 115200 baud, 1 stop bit |
reg [15*10:0] s_buf1 = { |
// list last byte first |
1'b1, 8'h00, 1'b0, // null character (also terminates program) |
1'b1, 8'h0A, 1'b0, // LF |
1'b1, 8'h0D, 1'b0, // CR |
1'b1, 8'h12, 1'b0, // '!' |
1'b1, 8'h63, 1'b0, // 'd' |
1'b1, 8'h6C, 1'b0, // 'l' |
1'b1, 8'h72, 1'b0, // 'r' |
1'b1, 8'h6F, 1'b0, // 'o' |
1'b1, 8'h57, 1'b0, // 'W' |
1'b1, 8'h20, 1'b0, // ' ' |
1'b1, 8'h6F, 1'b0, // 'o' |
1'b1, 8'h6C, 1'b0, // 'l' |
1'b1, 8'h6C, 1'b0, // 'l' |
1'b1, 8'h65, 1'b0, // 'e' |
1'b1, 8'h48, 1'b0, // 'H' |
1'b1 |
}; |
`define BIT_DELAY 8680.555 |
wire s_uart = s_buf1[0]; |
wire s_rtrn; |
integer ix_bit = 0; |
task xmit_char; |
for (ix_bit=0; ix_bit<10; ix_bit=ix_bit+1) begin |
#`BIT_DELAY; |
s_buf1 <= { 1'b1, s_buf1[1+:15*10] }; |
end |
endtask |
integer ix_char = 0; |
initial begin |
@ (negedge s_rst); |
#100; |
for (ix_char=0; ix_char<15; ix_char=ix_char+1) begin |
if (s_rtrn) begin |
repeat (@RTR_OVERFLOW@) xmit_char; |
while (s_rtrn) |
#`BIT_DELAY; |
end |
xmit_char; |
end |
end |
|
wire [7:0] s_data; |
wire s_data_wr; |
wire s_done; |
tb_UART_Rx uut( |
// synchronous reset and processor clock |
.i_rst (s_rst), |
.i_clk (s_clk), |
.i_uart_rx (s_uart), |
.o_uart_rtrn (s_rtrn), |
.o_data (s_data), |
.o_data_wr (s_data_wr), |
.o_done (s_done) |
); |
|
always @ (posedge s_clk) |
if (s_data_wr) |
$display("%h", s_data); |
|
always @ (posedge s_clk) |
if (s_done) |
$finish; |
|
//initial begin |
// $dumpfile("tb.vcd"); |
// $dumpvars(); |
//end |
|
endmodule |
/ssbcc/trunk/core/9x8/peripherals/tb/UART_Rx/tb_UART_Rx.s-rtrn
0,0 → 1,24
; Copyright 2015, Sinclair R.F., Inc. |
; |
; Test bench for UART_Rx peripheral with RTRn signal output. |
|
.main |
|
; Wait for the FIFO to fill. |
0x00 0x41 >r :wait |
.jumpc(no_major_dec,1-) r> 1- >r :no_major_dec r@ -1<> .jumpc(wait) |
|
; Read from the UART Rx port until the terminating null character is encountered. |
:loop |
;If no character is available, then continue waiting. |
.inport(I_UART_RX_EMPTY) .jumpc(loop) |
; Read the next character and output it, preserving it on the data stack. |
.inport(I_UART_RX) O_DATA outport |
; If the character was not a null character, then continue running the loop. |
.jumpc(loop) |
|
; Signal program termination. |
1 .outport(O_DONE) |
|
; Wait forever. |
:infinite .jump(infinite) |
/ssbcc/trunk/core/9x8/peripherals/tb/runall
4,7 → 4,7
# |
# Run all of the test benches for the peripherals. |
|
for runname in `find -name run`; do |
for runname in `find -maxdepth 2 -name run | sort`; do |
cd ${runname:0:${#runname}-4}; |
echo -en "${runname:2:${#runname}-6}\r"; |
./run || { echo "Tests aborted"; exit 1; } |
/ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_only.gtkw
0,0 → 1,25
[*] |
[*] GTKWave Analyzer v3.3.59 (w)1999-2014 BSI |
[*] Mon Feb 2 23:42:54 2015 |
[*] |
[dumpfile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/stepper_motor/tb.vcd" |
[dumpfile_mtime] "Mon Feb 2 22:26:13 2015" |
[dumpfile_size] 6332908 |
[savefile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/stepper_motor/tb_only.gtkw" |
[timestart] 0 |
[size] 1920 1161 |
[pos] 2559 0 |
*-33.735813 52850000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 |
[sst_width] 225 |
[signals_width] 255 |
[sst_expanded] 1 |
[sst_vpaned_height] 427 |
@28 |
tb.s_rst |
tb.s_clk |
tb.s_done |
tb.s_stepper_dir |
@29 |
tb.s_stepper_step |
[pattern_trace] 1 |
[pattern_trace] 0 |
/ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.gtkw
0,0 → 1,72
[*] |
[*] GTKWave Analyzer v3.3.59 (w)1999-2014 BSI |
[*] Thu Jan 29 19:29:10 2015 |
[*] |
[dumpfile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/stepper_motor/tb.vcd" |
[dumpfile_mtime] "Thu Jan 29 19:29:10 2015" |
[dumpfile_size] 5570292036 |
[savefile] "/home/rsinclair/Projects/SSBCC/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.gtkw" |
[timestart] 107951000 |
[size] 1920 1161 |
[pos] 1279 0 |
*-19.698416 110500000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 |
[treeopen] tb. |
[sst_width] 225 |
[signals_width] 395 |
[sst_expanded] 1 |
[sst_vpaned_height] 427 |
@28 |
tb.s_clk |
tb.s_dir |
tb.s_rst |
tb.s_step |
tb.s_done |
@800200 |
-uut |
@28 |
tb.uut.s_inport |
tb.uut.s_outport |
tb.uut.s__o_step__go |
tb.uut.s__o_step__running |
tb.uut.s__o_step__done |
@200 |
-stepper_motor |
@22 |
tb.uut.s__o_step__input_control_word[63:0] |
tb.uut.s__o_step__input_control_word_packed[58:0] |
@28 |
tb.uut.s__o_step__FIFO_wr |
@22 |
tb.uut.s__o_step__FIFO_in_addr[4:0] |
@28 |
tb.uut.s__o_step__FIFO_rd |
@22 |
tb.uut.s__o_step__FIFO_out_addr[4:0] |
tb.uut.s__o_step__output_control_word[58:0] |
tb.uut.s__o_step__next_rate[23:0] |
tb.uut.s__o_step__next_accel[15:0] |
tb.uut.s__o_step__next_count[18:0] |
@28 |
tb.uut.s__o_step__FIFO_empty |
tb.uut.s__o_step__clk_en |
@22 |
tb.uut.s__o_step__clk_en_count[3:0] |
@28 |
tb.uut.s__o_step__go |
tb.uut.s__o_step__running |
tb.uut.s__o_step__load_next |
tb.uut.s__o_step__done |
tb.uut.s__o_step__step_pre |
@22 |
tb.uut.s__o_step__count[18:0] |
@28 |
tb.uut.s__o_step__count_zero |
@22 |
tb.uut.s__o_step__angle[37:0] |
tb.uut.s__o_step__rate[37:0] |
tb.uut.s__o_step__accel[15:0] |
tb.uut.s__o_step__angle_presum[37:0] |
@1000200 |
-uut |
[pattern_trace] 1 |
[pattern_trace] 0 |
/ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/run
0,0 → 1,17
#!/bin/bash |
# |
# Copyright 2015, Sinclair R.F., Inc. |
|
NAME=stepper_motor |
|
../../../../../ssbcc -q --define-clog2 -P monitor_stack tb_${NAME}.9x8 || { echo "${NAME} compile failed" > /dev/stderr; exit 1; } |
iverilog -o tb tb.v tb_${NAME}.v || { echo "${NAME} build failed" > /dev/stderr; exit 1; } |
./tb > tb.out; |
|
if ! cmp -s tb.out tb.good; then |
echo "${NAME} failed" > /dev/stderr; |
exit 1; |
fi |
|
echo "Passed: ${NAME}"; |
exit 0; |
ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/run
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/.gitignore
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/.gitignore (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/.gitignore (revision 9)
@@ -0,0 +1,3 @@
+tb
+tb.out
+tb_stepper_motor.v
Index: ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.s
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.s (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.s (revision 9)
@@ -0,0 +1,77 @@
+; Copyright 2015, Sinclair R.F., Inc.
+;
+; Test bench for stepper_motor peripheral.
+
+.macro push16
+.macro push24
+
+.main
+
+ ; Forward acceleration.
+ .push24(${10-1}) ; 10 steps
+ .push16(3436) ; 50_000 step/sec^2 (50e3*2**34/F**2 where F=5.e5)
+ .push16(0) ; initial rate = 0
+ .call(push_command)
+
+ ; Continue uniform motion.
+ .push24(${10-1}) ; 10 steps
+ .push16(0) ; no acceleration
+ .push16(131) ; 1000 step/sec (1.e3*2**16/F)
+ .call(push_command)
+
+ ; Decelerate to stop motion.
+ .push24(${10-1}) ; 10 steps
+ .push16(-3432) ; -50_000 step/sec^2 (actual -v**2/(2*10) ==> 3432.2)
+ .push16(131) ; 1000 step/sec
+ .call(push_command)
+
+ ; Accelerate in negative direction.
+ .push24(${10-1}) ; 10 steps
+ .push16(-3436) ; -50_000 step/sec^2
+ .push16(-1) ; ~0 step/sec
+ .call(push_command)
+
+ ; Continue uniform motion.
+ .push24(${10-1}) ; 10 steps
+ .push16(0) ; no acceleration
+ .push16(-131) ; 1000 step/sec (1.e3*2**23/F)
+ .call(push_command)
+
+ ; Decelerate to stop motion.
+ .push24(${10-1}) ; 10 steps
+ .push16(3432) ; -50_000 step/sec^2
+ .push16(-131) ; 1000 step/sec (1.e3*2**23/F)
+ .call(push_command)
+
+ ; Command the motion profile to run.
+ .outstrobe(O_GO)
+
+ ; Wait for the profile to finish.
+ :loop_wait .inport(I_DONE) 0= .jumpc(loop_wait)
+
+ ; Wait about 10 usec
+ ${(10*8)/3} :wait_done .jumpc(wait_done,1-) drop
+
+ ; Indicate termination to the test bench.
+ 1 .outport(O_DONE)
+
+ ; Wait forever
+ :infinite .jump(infinite)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Stepper motor utilities.
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+.constant C_RATE_WIDTH ${C_RATE_RES-C_RATE_SCALE+1}
+.constant C_ACCEL_WIDTH ${1+C_ACCEL_RES-C_ACCEL_SCALE}
+.constant C_NBYTES ${int((C_RATE_WIDTH+7)/8)+int((C_ACCEL_WIDTH+7)/8)+int((C_COUNT_WIDTH+7)/8)}
+
+; Send the control word on the stack to the stepper motor peripheral and record it in the FIFO.
+; ( u_count_LSB ... u_accel_LSB ... u_rate_MSB - )
+.function push_command
+ ${C_NBYTES-1} :loop swap .outport(O_CONTROLWORD) .jumpc(loop,1-) drop
+ .outstrobe(O_CONTROLWORD_WR)
+ .return
Index: ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.v
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.v (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.v (revision 9)
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ *
+ * Copyright 2015, Sinclair R.F., Inc.
+ *
+ * Test bench for the stepper_motor peripheral.
+ *
+ ******************************************************************************/
+
+`timescale 1ns/1ps
+
+module tb;
+
+// 2 MHz clock
+reg s_clk = 1'b1;
+always @ (s_clk)
+ s_clk <= #250 ~s_clk;
+
+reg s_rst = 1'b1;
+initial begin
+ repeat (5) @ (posedge s_clk);
+ s_rst = 1'b0;
+end
+
+wire s_stepper_dir;
+wire s_stepper_step;
+wire s_done;
+tb_stepper_motor uut(
+ // synchronous reset and processor clock
+ .i_rst (s_rst),
+ .i_clk (s_clk),
+ // stepper motor controls
+ .o_stepper_dir (s_stepper_dir),
+ .o_stepper_step (s_stepper_step),
+ .i_stepper_error (1'b0),
+ // program termination
+ .o_done (s_done)
+);
+
+always @ (posedge s_stepper_step)
+ $display("%12d : dir = %h", $time, s_stepper_dir);
+
+always @ (negedge s_clk)
+ if (s_done)
+ $finish;
+
+//initial begin
+// $dumpfile("tb.vcd");
+// $dumpvars(1,tb);
+//end
+
+endmodule
ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.v
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.good
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.good (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb.good (revision 9)
@@ -0,0 +1,60 @@
+ 6526500 : dir = 0
+ 9146500 : dir = 0
+ 11156500 : dir = 0
+ 12852500 : dir = 0
+ 14344500 : dir = 0
+ 15694500 : dir = 0
+ 16936500 : dir = 0
+ 18090500 : dir = 0
+ 19176500 : dir = 0
+ 20202500 : dir = 0
+ 21204500 : dir = 0
+ 22204500 : dir = 0
+ 23204500 : dir = 0
+ 24206500 : dir = 0
+ 25206500 : dir = 0
+ 26206500 : dir = 0
+ 27206500 : dir = 0
+ 28208500 : dir = 0
+ 29208500 : dir = 0
+ 30208500 : dir = 0
+ 31236500 : dir = 0
+ 32322500 : dir = 0
+ 33478500 : dir = 0
+ 34720500 : dir = 0
+ 36070500 : dir = 0
+ 37564500 : dir = 0
+ 39258500 : dir = 0
+ 41270500 : dir = 0
+ 43888500 : dir = 0
+ 49970500 : dir = 0
+ 56146500 : dir = 1
+ 58764500 : dir = 1
+ 60774500 : dir = 1
+ 62470500 : dir = 1
+ 63962500 : dir = 1
+ 65312500 : dir = 1
+ 66554500 : dir = 1
+ 67708500 : dir = 1
+ 68794500 : dir = 1
+ 69820500 : dir = 1
+ 70822500 : dir = 1
+ 71822500 : dir = 1
+ 72822500 : dir = 1
+ 73824500 : dir = 1
+ 74824500 : dir = 1
+ 75824500 : dir = 1
+ 76824500 : dir = 1
+ 77826500 : dir = 1
+ 78826500 : dir = 1
+ 79826500 : dir = 1
+ 80854500 : dir = 1
+ 81940500 : dir = 1
+ 83096500 : dir = 1
+ 84338500 : dir = 1
+ 85688500 : dir = 1
+ 87182500 : dir = 1
+ 88876500 : dir = 1
+ 90888500 : dir = 1
+ 93506500 : dir = 1
+ 99588500 : dir = 1
Index: ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.9x8
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.9x8 (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/stepper_motor/tb_stepper_motor.9x8 (revision 9)
@@ -0,0 +1,38 @@
+#
+# Copyright 2015, Sinclair R.F., Inc.
+#
+# Test bench for stepper_motor peripheral.
+#
+
+ARCHITECTURE core/9x8 Verilog
+ASSEMBLY tb_stepper_motor.s
+
+INSTRUCTION 256
+DATA_STACK 16
+RETURN_STACK 16
+
+CONSTANT C_CLK_FREQ_HZ 2_000_000
+
+PORTCOMMENT stepper motor controls
+CONSTANT C_RATE_SCALE 3
+CONSTANT C_RATE_RES 16
+CONSTANT C_ACCEL_SCALE 22
+CONSTANT C_ACCEL_RES 34
+CONSTANT C_ACCUM_RES 34
+CONSTANT C_COUNT_WIDTH 19
+PERIPHERAL stepper_motor basename=stepper \
+ outcontrol=O_CONTROLWORD \
+ outrecord=O_CONTROLWORD_WR \
+ outrun=O_GO \
+ indone=I_DONE \
+ inerror=I_ERROR \
+ ratemethod=C_CLK_FREQ_HZ/500_000 \
+ ratescale=C_RATE_SCALE \
+ rateres=C_RATE_RES \
+ accelscale=C_ACCEL_SCALE \
+ accelres=C_ACCEL_RES \
+ accumres=C_ACCUM_RES \
+ countwidth=C_COUNT_WIDTH
+
+PORTCOMMENT program termination
+OUTPORT 1-bit o_done O_DONE
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.s
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.s (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.s (revision 9)
@@ -0,0 +1,20 @@
+; Copyright 2015, Sinclair R.F., Inc.
+;
+; Test bench for servo_motor peripheral.
+
+.main
+
+; Wait for two cycles of the default servo settings pass.
+${2-1} :loop_startup .inport(I_triple) 0= .jumpc(loop_startup) .jumpc(loop_startup,1-) drop
+
+; Modify the servo settings and wait for two cycles.
+ 0 .outport(O_triple_0)
+125 .outport(O_triple_1)
+250 .outport(O_triple_2)
+${2-1} :loop_first .inport(I_triple) 0= .jumpc(loop_first) .jumpc(loop_first,1-) drop
+
+; Signal program termination.
+0x01 .outport(O_DONE)
+
+; Wait forever.
+:infinite .jump(infinite)
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/run
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/run (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/run (revision 9)
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright 2015, Sinclair R.F., Inc.
+
+NAME=servo_motor
+
+../../../../../ssbcc -q -P monitor_stack tb_${NAME}.9x8 || { echo "${NAME} compile failed" > /dev/stderr; exit 1; }
+iverilog -o tb tb.v tb_${NAME}.v || { echo "${NAME} build failed" > /dev/stderr; exit 1; }
+./tb > tb.out;
+
+if ! cmp -s tb.out tb.good; then
+ echo "${NAME} failed" > /dev/stderr;
+ exit 1;
+fi
+
+echo "Passed: ${NAME}";
+exit 0;
ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/run
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/.gitignore
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/.gitignore (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/.gitignore (revision 9)
@@ -0,0 +1,2 @@
+tb.out
+tb_servo_motor.v
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.v
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.v (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.v (revision 9)
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ *
+ * Copyright 2015, Sinclair R.F., Inc.
+ *
+ * Test bench for the servo_motor peripheral.
+ *
+ ******************************************************************************/
+
+`timescale 1ns/1ps
+
+module tb;
+
+// 8 MHz clock
+reg s_clk = 1'b1;
+always @ (s_clk)
+ s_clk <= #62.5 ~s_clk;
+
+reg s_rst = 1'b1;
+initial begin
+ repeat (5) @ (posedge s_clk);
+ s_rst = 1'b0;
+end
+
+wire s_triple_0;
+wire s_triple_1;
+wire s_triple_2;
+wire s_done;
+tb_servo_motor uut(
+ // synchronous reset and processor clock
+ .i_rst (s_rst),
+ .i_clk (s_clk),
+ // 3 linked servo motor
+ .o_triple_0 (s_triple_0),
+ .o_triple_1 (s_triple_1),
+ .o_triple_2 (s_triple_2),
+ // program termination
+ .o_done (s_done)
+);
+
+always @ (s_triple_0)
+ $display("%12d : s_triple_0 %h", $time, s_triple_0);
+always @ (s_triple_1)
+ $display("%12d : s_triple_1 %h", $time, s_triple_1);
+always @ (s_triple_2)
+ $display("%12d : s_triple_2 %h", $time, s_triple_2);
+
+always @ (posedge s_clk)
+ if (s_done)
+ $finish;
+
+//initial begin
+// $dumpfile("tb.vcd");
+// $dumpvars();
+//end
+
+endmodule
ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.v
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.9x8
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.9x8 (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb_servo_motor.9x8 (revision 9)
@@ -0,0 +1,39 @@
+#
+# Copyright 2015, Sinclair R.F., Inc.
+#
+# Test bench for servo_motor peripheral.
+#
+
+ARCHITECTURE core/9x8 Verilog
+ASSEMBLY tb_servo_motor.s
+
+INSTRUCTION 256
+DATA_STACK 16
+RETURN_STACK 16
+
+CONSTANT C_CLK_FREQ_HZ 8_000_000
+
+PORTCOMMENT 3 linked servo motor
+PERIPHERAL servo_motor outport=O_triple_0 \
+ outsignal=o_triple_0 \
+ freq_hz=C_CLK_FREQ_HZ \
+ min_width=1000us \
+ max_width=1500us \
+ default_width=1250us \
+ period=5ms \
+ inperiod=I_triple
+PERIPHERAL servo_motor outport=O_triple_1 \
+ outsignal=o_triple_1 \
+ freq_hz=C_CLK_FREQ_HZ \
+ min_width=1000us \
+ max_width=1500us \
+ sync=o_triple_0
+PERIPHERAL servo_motor outport=O_triple_2 \
+ outsignal=o_triple_2 \
+ freq_hz=C_CLK_FREQ_HZ \
+ min_width=1000us \
+ max_width=1500us \
+ sync=o_triple_0
+
+PORTCOMMENT program termination
+OUTPORT 1-bit o_done O_DONE
Index: ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.good
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.good (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/tb/servo_motor/tb.good (revision 9)
@@ -0,0 +1,24 @@
+ 0 : s_triple_0 0
+ 0 : s_triple_1 0
+ 0 : s_triple_2 0
+ 5000625 : s_triple_0 1
+ 5000625 : s_triple_1 1
+ 5000625 : s_triple_2 1
+ 6000625 : s_triple_1 0
+ 6000625 : s_triple_2 0
+ 6250625 : s_triple_0 0
+ 10000625 : s_triple_0 1
+ 10000625 : s_triple_1 1
+ 10000625 : s_triple_2 1
+ 11000625 : s_triple_1 0
+ 11000625 : s_triple_2 0
+ 11250625 : s_triple_0 0
+ 15000625 : s_triple_0 1
+ 15000625 : s_triple_1 1
+ 15000625 : s_triple_2 1
+ 16000625 : s_triple_0 0
+ 16250625 : s_triple_1 0
+ 16500625 : s_triple_2 0
+ 20000625 : s_triple_0 1
+ 20000625 : s_triple_1 1
+ 20000625 : s_triple_2 1
Index: ssbcc/trunk/core/9x8/peripherals/open_drain.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/open_drain.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/open_drain.py (revision 9)
@@ -60,7 +60,7 @@
( 'inport', r'I_\w+$', None, ),
( 'iosignal', r'io_\w+$', None, ),
( 'outport', r'O_\w+$', None, ),
- ( 'width', r'[1-9]\d*$', lambda v : self.PosInt(v,maxValue=config.Get('data_width')), ),
+ ( 'width', r'\S+$', lambda v : self.IntMethod(config,v,lowLimit=1,highLimit=config.Get('data_width')), ),
);
names = [a[0] for a in allowables];
for param_tuple in param_list:
Index: ssbcc/trunk/core/9x8/peripherals/timer.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/timer.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/timer.py (revision 9)
@@ -27,9 +27,9 @@
1st method: clk/rate
clk is the frequency of "i_clk" in Hz
a number will be interpreted as the clock frequency in Hz
- a symbol will be interpreted as a parameter
- Note: this parameter must have been declared with a "PARAMETER"
- command
+ a symbol will be interpreted as a constant or a parameter
+ Note: the symbol must be declared with the CONSTANT, LOCALPARARM,
+ or PARAMETER configuration command.
rate is the desired baud rate
this is specified as per "clk"
2nd method:
Index: ssbcc/trunk/core/9x8/peripherals/AXI4_Lite_Slave_DualPortRAM.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/AXI4_Lite_Slave_DualPortRAM.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/AXI4_Lite_Slave_DualPortRAM.py (revision 9)
@@ -104,7 +104,7 @@
( 'ram8', None, None, ),
( 'ram32', None, None, ),
( 'read', r'I_\w+$', None, ),
- ( 'size', r'\S+$', lambda v : self.FixedPow2(config,16,256,v), ),
+ ( 'size', r'\S+$', lambda v : self.IntPow2Method(config,v,lowLimit=16,highLimit=256), ),
( 'write', r'O_\w+$', None, ),
);
names = [a[0] for a in allowables];
Index: ssbcc/trunk/core/9x8/peripherals/PWM_8bit.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/PWM_8bit.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/PWM_8bit.py (revision 9)
@@ -30,8 +30,13 @@
Note: The name must start with "o_".
ratemethod={clk/rate|count}
specifies the frequency at which the PWM counter is incremented
+ Note: "clk," "rate," and "count" can be integers or can be declared by
+ CONSTANT, LOCALPARARM, or PARAMETER configuration commands.
Example: ratemethod=count means to increment the PWM counter once every
"count" clock cycles.
+ Example: ratemethod=G_CLK_HZ/1_000 means to use the parameter G_CLK_HZ
+ (set elsewhere) and a 1,000 Hz update rate to determine the
+ number of clock cycles between updates.
invert|noinvert
optional configuration command to invert or to not invert the PWM output
Default: don't invert the output (i.e., a command of 0 means the output is
Index: ssbcc/trunk/core/9x8/peripherals/servo_motor.v
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/servo_motor.v (nonexistent)
+++ ssbcc/trunk/core/9x8/peripherals/servo_motor.v (revision 9)
@@ -0,0 +1,96 @@
+//
+// PERIPHERAL servo_motor: @NAME@
+//
+generate
+reg [@NBITS_PWM@-1:0] s__pwm_count_init = @DEFAULT_PWM@;
+always @ (posedge i_clk)
+ if (i_rst)
+ s__pwm_count_init <= @DEFAULT_PWM@;
+ else if (s_outport && (s_T == @IX_OUTPORT@))
+ s__pwm_count_init <= @PWM_FORMULA@;
+ else
+ s__pwm_count_init <= s__pwm_count_init;
+reg [@NBITS_PWM@-1:0] s__pwm_count = @DEFAULT_PWM@;
+@SCALE_0_BEGIN@
+@SCALE_0_ELSE@
+reg s__tick = 1'b0;
+reg [@NBITS_SCALE@-1:0] s__tick_cnt = @SCALE_MINUS_ONE@;
+wire s__tick_last = (s__tick_cnt == @ONE_SCALE@);
+always @ (posedge i_clk)
+ if (i_rst) begin
+ s__tick <= 1'b0;
+ s__tick_cnt <= @SCALE_MINUS_ONE@;
+ end else begin
+ s__tick <= s__tick_last;
+ if (s__tick)
+ s__tick_cnt <= @SCALE_MINUS_ONE@;
+ else
+ s__tick_cnt <= s__tick_cnt - @ONE_SCALE@;
+ end
+@SCALE_0_END@
+@PERIOD_BEGIN@
+reg [@NBITS_PERIOD@-1:0] s__period = @PERIOD_MINUS_ONE@;
+@SCALE_0_BEGIN@
+always @ (posedge i_clk)
+ if (i_rst) begin
+ s__period <= @PERIOD_MINUS_ONE@;
+ s__period_done <= 1'b0;
+ end else begin
+ if (s__period_done)
+ s__period <= @PERIOD_MINUS_ONE@;
+ else
+ s__period <= s__period - @ONE_PERIOD@;
+ s__period_done <= (s__period == @ONE_PERIOD@);
+ end
+@SCALE_0_ELSE@
+always @ (posedge i_clk)
+ if (i_rst) begin
+ s__period <= @PERIOD_MINUS_ONE@;
+ s__period_done <= 1'b0;
+ end else begin
+ if (s__period_done)
+ s__period <= @PERIOD_MINUS_ONE@;
+ else if (s__tick)
+ s__period <= s__period - @ONE_PERIOD@;
+ else
+ s__period <= s__period;
+ s__period_done <= s__tick_last && (s__period == @NBITS_PERIOD@'d0);
+ end
+@SCALE_0_END@
+@PERIOD_END@
+@SCALE_0_BEGIN@
+always @ (posedge i_clk)
+ if (i_rst)
+ s__pwm_count <= @DEFAULT_PWM@;
+ else if (@PERIOD_SIGNAL@)
+ s__pwm_count <= s__pwm_count_init;
+ else
+ s__pwm_count <= s__pwm_count - @ONE_PWM@;
+@SCALE_0_ELSE@
+always @ (posedge i_clk)
+ if (i_rst)
+ s__pwm_count <= @DEFAULT_PWM@;
+ else if (@PERIOD_SIGNAL@)
+ s__pwm_count <= s__pwm_count_init;
+ else if (s__tick)
+ s__pwm_count <= s__pwm_count - @ONE_PWM@;
+ else
+ s__pwm_count <= s__pwm_count;
+@SCALE_0_END@
+reg s__outsignal = 1'b0;
+always @ (posedge i_clk)
+ if (i_rst)
+ s__outsignal <= 1'b0;
+ else if (@PERIOD_SIGNAL@)
+ s__outsignal <= 1'b1;
+@SCALE_0_BEGIN@
+ else if (s__pwm_count == {(@NBITS_PWM@){1'b0}})
+@SCALE_0_ELSE@
+ else if (s__tick && (s__pwm_count == {(@NBITS_PWM@){1'b0}}))
+@SCALE_0_END@
+ s__outsignal <= 1'b0;
+ else
+ s__outsignal <= s__outsignal;
+always @ (*)
+ @OUTSIGNAL@ = @INVERT@s__outsignal;
+endgenerate
ssbcc/trunk/core/9x8/peripherals/servo_motor.v
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/UART_Rx.v
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/UART_Rx.v (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/UART_Rx.v (revision 9)
@@ -1,5 +1,6 @@
//
// PERIPHERAL UART_Rx: @NAME@
+// Copyright 2013-2015 Sinclair R.F., Inc.
//
// Technique:
// - optionally synchronize the incoming signal
@@ -13,7 +14,7 @@
//
localparam L__BAUDMETHOD = ((@BAUDMETHOD@)+1)/2;
localparam L__BAUDMETHOD_MINUS = L__BAUDMETHOD - 2;
-localparam L__BAUDMETHOD_NBITS = $clog2(L__BAUDMETHOD+1);
+localparam L__BAUDMETHOD_NBITS = $clog2(L__BAUDMETHOD_MINUS+1);
localparam L__SYNC_LENGTH = @SYNC@;
localparam L__DEGLITCH_LENGTH = @DEGLITCH@;
localparam L__NSTOP = @NSTOP@;
@@ -159,7 +160,7 @@
end
// Optional FIFO
@RTR_BEGIN@
-reg s__rtr = 1'b1;
+reg s__rtrn = 1'b1; // Disable reception until the core is out of reset.
@RTR_END@
if (L__INFIFO == 0) begin : gen__nofifo
always @ (posedge i_clk)
@@ -186,9 +187,9 @@
@RTR_BEGIN@
always @ (posedge i_clk)
if (i_rst)
- s__rtr <= 1'b1;
+ s__rtrn <= 1'b1;
else
- s__rtr <= ~s__Rx_idle;
+ s__rtrn <= ~s__Rx_idle;
@RTR_END@
end else begin : gen__fifo
reg [L__INFIFO_NBITS:0] s__Rx_fifo_addr_in;
@@ -222,7 +223,7 @@
s__Rx_full <= 1'b0;
else
s__Rx_full <= (s__Rx_fifo_addr_in == (s__Rx_fifo_addr_out ^ { 1'b1, {(L__INFIFO_NBITS){1'b0}} }));
- reg [7:0] s__Rx_fifo_mem[@INFIFO@-1:0];
+ reg [7:0] s__Rx_fifo_mem[L__INFIFO-1:0];
initial s__Rx_fifo_addr_in = {(L__INFIFO_NBITS+1){1'b0}};
always @ (posedge i_clk)
if (i_rst)
@@ -245,46 +246,22 @@
s__Rx <= s__Rx;
end
@RTR_BEGIN@
- // Isn't ready to receive if the FIFO is full or if the FIFO is almost full
- // and there is incoming data (i.e., receiver is not idle).
- reg s__Rx_idle_s = 1'b0;
+ // Isn't ready to receive if the FIFO is full or if the FIFO is almost full.
+ reg [L__INFIFO_NBITS:0] s__Rx_used = {(L__INFIFO_NBITS+1){1'b0}};
always @ (posedge i_clk)
if (i_rst)
- s__Rx_idle_s <= 1'b0;
+ s__Rx_used <= {(L__INFIFO_NBITS+1){1'b0}};
else
- s__Rx_idle_s <= s__Rx_idle;
- reg s__Rx_wr_s = 1'b0;
+ s__Rx_used <= s__Rx_fifo_addr_in - s__Rx_fifo_addr_out;
always @ (posedge i_clk)
if (i_rst)
- s__Rx_wr_s <= 1'b0;
+ s__rtrn <= 1'b1;
else
- s__Rx_wr_s <= s__Rx_wr;
- reg s__Rx_busy = 1'b0;
- always @ (posedge i_clk)
- if (i_rst)
- s__Rx_busy <= 1'b0;
- else if ({s__Rx_idle_s, s__Rx_idle} == 2'b10)
- s__Rx_busy <= 1'b1;
- else if (s__Rx_wr_s)
- s__Rx_busy <= 1'b0;
- else
- s__Rx_busy <= s__Rx_busy;
- reg s__Rx_almost_full = 1'b0;
- always @ (posedge i_clk)
- if (i_rst)
- s__Rx_almost_full <= 1'b0;
- else
- s__Rx_almost_full <= (s__Rx_fifo_addr_in == (s__Rx_fifo_addr_out + { 1'b0, {(L__INFIFO_NBITS){1'b1}} }));
- always @ (posedge i_clk)
- if (i_rst)
- s__rtr <= 1'b1;
- else
-// s__rtr <= ~(s__Rx_full || (s__Rx_almost_full && ~s__Rx_idle));
- s__rtr <= ~(s__Rx_full || (s__Rx_almost_full && s__Rx_busy));
+ s__rtrn <= s__Rx_used[L__INFIFO_NBITS] || &(s__Rx_used[L__INFIFO_NBITS-1:@RTR_FIFO_COMPARE@]);
@RTR_END@
end
@RTR_BEGIN@
always @ (*)
- @RTR_SIGNAL@ <= @RTR_INVERT@s__rtr;
+ @RTR_SIGNAL@ = @RTRN_INVERT@s__rtrn;
@RTR_END@
endgenerate
Index: ssbcc/trunk/core/9x8/peripherals/UART_Tx.v
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/UART_Tx.v (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/UART_Tx.v (revision 9)
@@ -1,5 +1,6 @@
//
// PERIPHERAL UART_Tx: @NAME@
+// Copyright 2013-2015 Sinclair R.F., Inc.
//
localparam L__OUTFIFO_NBITS = $clog2(@OUTFIFO@);
localparam L__COUNT = @BAUDMETHOD@-1;
@@ -12,7 +13,7 @@
reg s__Tx_go;
reg s__Tx_uart_busy;
if (@OUTFIFO@ == 0) begin : gen__nooutfifo
- always @ (s__Tx_uart_busy)
+ always @ (s__Tx_uart_busy, s__Tx_enabled)
s__Tx_busy = s__Tx_uart_busy || !s__Tx_enabled;
always @ (s__Tx)
s__Tx_data = s__Tx;
Index: ssbcc/trunk/core/9x8/peripherals/inFIFO_async.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/inFIFO_async.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/inFIFO_async.py (revision 9)
@@ -71,7 +71,7 @@
( 'data_full', r'o_\w+$', None, ),
( 'inport', r'I_\w+$', None, ),
( 'inempty', r'I_\w+$', None, ),
- ( 'depth', r'[1-9]\d*$', lambda v : self.IntPow2(v,minValue=16), ),
+ ( 'depth', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v,lowLimit=16), ),
);
names = [a[0] for a in allowables];
for param_tuple in param_list:
Index: ssbcc/trunk/core/9x8/peripherals/UART.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/UART.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/UART.py (revision 9)
@@ -1,6 +1,6 @@
################################################################################
#
-# Copyright 2013-2014, Sinclair R.F., Inc.
+# Copyright 2013-2015, Sinclair R.F., Inc.
#
################################################################################
@@ -8,8 +8,8 @@
import re;
from ssbccPeripheral import SSBCCperipheral
-from ssbccUtil import IsPowerOf2;
-from ssbccUtil import SSBCCException;
+from ssbccUtil import CeilLog2
+from ssbccUtil import SSBCCException
class UART(SSBCCperipheral):
"""
@@ -30,7 +30,8 @@
[noInFIFO|inFIFO=n] \\
[noOutFIFO|outFIFO=n] \\
[{CTS|CTSn}=i_cts_name] \\
- [{RTR|RTRn}=i_rtr_name] \\
+ [{RTR|RTRn}=o_rtr_name] \\
+ rtr_buffer=n \\
[nStop={1|2}]\n
Where:
inport=I_inport_name
@@ -54,9 +55,9 @@
1st method: clk/rate
clk is the frequency of "i_clk" in Hz
a number will be interpreted as the clock frequency in Hz
- a symbol will be interpreted as a parameter
- Note: this parameter must have been declared with a "PARAMETER"
- command
+ a symbol will be interpreted as a constant or a parameter
+ Note: the symbol must be declared with the CONSTANT, LOCALPARARM,
+ or PARAMETER configuration command.
rate is the desired baud rate
this is specified as per "clk"
2nd method:
@@ -110,17 +111,24 @@
Note: If there is no FIFO and the CTS/CTSn handshake indicates that the
data flow is disabled, then the busy signal will be high and the
processor code must not transmit the next byte.
- RTR=i_rtr_name or RTRn=i_rtr_name
+ RTR=o_rtr_name or RTRn=o_rtr_name
optionally specify an output handshake signal to indicate that the
peripheral is ready to receive data
Note: If RTR is specified then the receiver indicates it is ready when
- i_rtr_name is high. If RTRn is specified then the transmitter
- indicates it is ready when i_rtr_name is low.
+ o_rtr_name is high. If RTRn is specified then the transmitter
+ indicates it is ready when o_rtr_name is low.
Note: The default, i.e., neither CTS nor CTSn is specified, is to always
enable the receiver.
Note: If there is no FIFO and the RTR/RTRn handshake indicates that the
receiver is not ready as soon as it starts receiving data and
until that data is read from the peripheral.
+ rtr_buffer=n
+ optionally specify the number of entries in inFIFO to reserve for data
+ received after the RTR/RTRn signal indicates to stop data flow.
+ Note: n must be a power of 2.
+ Note: This requires that inFIFO be specified.
+ Note: Some USB UARTs will transmit several characters after the RTR/RTRn
+ signal indicates to stop the data flow.
nStop=n
optionally configure the peripheral for n stop bits
default: 1 stop bit
@@ -185,7 +193,7 @@
( 'RTRn', r'o_\w+$', None, ),
( 'baudmethod', r'\S+$', lambda v : self.RateMethod(config,v), ),
( 'deglitch', r'[1-9]\d*$', int, ),
- ( 'inFIFO', r'[1-9]\d*$', lambda v : self.IntPow2(v), ),
+ ( 'inFIFO', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
( 'inempty', r'I_\w+$', None, ),
( 'inport', r'I_\w+$', None, ),
( 'insignal', r'i_\w+$', None, ),
@@ -194,10 +202,11 @@
( 'noOutFIFO', None, None, ),
( 'noSync', None, None, ),
( 'nStop', r'[12]$', int, ),
- ( 'outFIFO', r'[1-9]\d*$', lambda v : self.IntPow2(v), ),
+ ( 'outFIFO', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
( 'outport', r'O_\w+$', None, ),
( 'outsignal', r'o_\w+$', None, ),
( 'outstatus', r'I_\w+$', None, ),
+ ( 'rtr_buffer', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
( 'sync', r'[1-9]\d*$', int, ),
);
names = [a[0] for a in allowables];
@@ -225,7 +234,16 @@
):
if not hasattr(self,optionalpair[0]):
setattr(self,optionalpair[0],optionalpair[1]);
- # Ensure exclusive pair configurations are set and consistent.
+ # Ensure the rtr_buffer, if specified, is consistent with the inFIFO
+ # specification.
+ if hasattr(self,'rtr_buffer'):
+ if not hasattr(self,'inFIFO'):
+ raise SSBCCException('rtr_buffer specification requires simultaneous inFIFO specification at %s' % loc);
+ if self.rtr_buffer > self.inFIFO:
+ raise SSBCCException('rtr_buffer=%d specification cannot exceed inFIFO=%d specification at %s' % (self.rtr_buffer,self.inFIFO,loc,));
+ else:
+ self.rtr_buffer = 1;
+ # Ensure optional exclusive pair configurations are set and consistent.
for exclusivepair in (
( 'CTS', 'CTSn', None, None, ),
( 'RTR', 'RTRn', None, None, ),
@@ -261,25 +279,25 @@
):
if hasattr(self,ioEntry[0]):
config.AddIO(getattr(self,ioEntry[0]),ioEntry[1],ioEntry[2],loc);
- config.AddSignal('s__%s__Rx' % self.namestring,8,loc);
- config.AddSignal('s__%s__Rx_empty' % self.namestring,1,loc);
- config.AddSignal('s__%s__Rx_rd' % self.namestring,1,loc);
- config.AddSignal('s__%s__Tx' % self.namestring,8,loc);
- config.AddSignal('s__%s__Tx_busy' % self.namestring,1,loc);
- config.AddSignal('s__%s__Tx_wr' % self.namestring,1,loc);
+ config.AddSignal('s__%s__Rx' % self.namestring,8,loc);
+ config.AddSignal('s__%s__Rx_empty' % self.namestring,1,loc);
+ config.AddSignal('s__%s__Rx_rd' % self.namestring,1,loc);
+ config.AddSignalWithInit('s__%s__Tx' % self.namestring,8,None,loc);
+ config.AddSignal('s__%s__Tx_busy' % self.namestring,1,loc);
+ config.AddSignalWithInit('s__%s__Tx_wr' % self.namestring,1,None,loc);
config.AddInport((self.inport,
- ('s__%s__Rx' % self.namestring,8,'data',),
- ('s__%s__Rx_rd' % self.namestring,1,'strobe',),
+ ('s__%s__Rx' % self.namestring,8,'data',),
+ ('s__%s__Rx_rd' % self.namestring,1,'strobe',),
),loc);
config.AddInport((self.inempty,
- ('s__%s__Rx_empty' % self.namestring,1,'data',),
+ ('s__%s__Rx_empty' % self.namestring,1,'data',),
),loc);
config.AddOutport((self.outport,False,
- ('s__%s__Tx' % self.namestring,8,'data',),
- ('s__%s__Tx_wr' % self.namestring,1,'strobe',),
+ ('s__%s__Tx' % self.namestring,8,'data',),
+ ('s__%s__Tx_wr' % self.namestring,1,'strobe',),
),loc);
config.AddInport((self.outstatus,
- ('s__%s__Tx_busy' % self.namestring,1,'data',),
+ ('s__%s__Tx_busy' % self.namestring,1,'data',),
),loc);
# Add the 'clog2' function to the processor (if required).
config.functions['clog2'] = True;
@@ -294,20 +312,21 @@
if re.search(r'@RTR_BEGIN@',body):
body = re.sub(r'@RTR_BEGIN@.*?@RTR_END@\n','',body,flags=re.DOTALL);
for subpair in (
- ( r'@RTR_SIGNAL@', self.RTR if hasattr(self,'RTR') else self.RTRn if hasattr(self,'RTRn') else '', ),
- ( r'@RTR_INVERT@', '' if hasattr(self,'RTR') else '!', ),
- ( r'\bL__', 'L__@NAME@__', ),
- ( r'\bgen__', 'gen__@NAME@__', ),
- ( r'\bs__', 's__@NAME@__', ),
- ( r'@INPORT@', self.insignal, ),
- ( r'@BAUDMETHOD@', str(self.baudmethod), ),
- ( r'@SYNC@', str(self.sync), ),
- ( r'@DEGLITCH@', str(self.deglitch), ),
- ( r'@INFIFO@', str(self.inFIFO), ),
- ( r'@ENABLED@', self.CTS if hasattr(self,'CTS') else ('!%s' % self.CTSn) if hasattr(self,'CTSn') else '1\'b1', ),
- ( r'@NSTOP@', str(self.nStop), ),
- ( r'@OUTFIFO@', str(self.outFIFO), ),
- ( r'@NAME@', self.namestring, ),
+ ( r'@RTR_SIGNAL@', self.RTR if hasattr(self,'RTR') else self.RTRn if hasattr(self,'RTRn') else '', ),
+ ( r'@RTRN_INVERT@', '!' if hasattr(self,'RTR') else '', ),
+ ( r'\bL__', 'L__@NAME@__', ),
+ ( r'\bgen__', 'gen__@NAME@__', ),
+ ( r'\bs__', 's__@NAME@__', ),
+ ( r'@INPORT@', self.insignal, ),
+ ( r'@BAUDMETHOD@', str(self.baudmethod), ),
+ ( r'@SYNC@', str(self.sync), ),
+ ( r'@DEGLITCH@', str(self.deglitch), ),
+ ( r'@INFIFO@', str(self.inFIFO), ),
+ ( r'@ENABLED@', self.CTS if hasattr(self,'CTS') else ('!%s' % self.CTSn) if hasattr(self,'CTSn') else '1\'b1', ),
+ ( r'@NSTOP@', str(self.nStop), ),
+ ( r'@OUTFIFO@', str(self.outFIFO), ),
+ ( r'@NAME@', self.namestring, ),
+ ( r'@RTR_FIFO_COMPARE@', str(CeilLog2(self.rtr_buffer)), ),
):
if re.search(subpair[0],body):
body = re.sub(subpair[0],subpair[1],body);
/ssbcc/trunk/core/9x8/peripherals/servo_motor.py
0,0 → 1,250
################################################################################ |
# |
# Copyright 2015, Sinclair R.F., Inc. |
# |
################################################################################ |
|
import math |
|
from ssbccPeripheral import SSBCCperipheral |
from ssbccUtil import CeilLog2 |
from ssbccUtil import SSBCCException |
|
class servo_motor(SSBCCperipheral): |
""" |
Servo Motor driver:\n |
Creates PWM modulated signals to operate micro servos for UAVs and similar.\n |
Usage: |
PERIPHERAL servo_motor outport=O_name \\ |
{outsignal|outsignaln}=o_name \\ |
freq_hz=FREQ_HZ \\ |
min_width=XXX{s|ms|us|ns} \\ |
max_width=XXX{s|ms|us|ns} \\ |
[default_width=XXX{s|ms|us|ns}] \\ |
{period=XXX{s|ms|us|ns}|sync=o_name} \\ |
[inperiod=I_name] \\ |
[scale=C_name] \\ |
[scale_max=C_name]\n |
Where: |
outport=O_name |
specifies the symbol used to write the 8-bit PWM control to this |
peripheral |
Note: The name must start with "O_". |
{outsignal|outsignaln}=o_name |
specifies the name of the output PWM signal |
Note: outsignal creates a positive pulse for the PWM control and |
outsignaln creates an inverted pulse for the PWM control. |
Note: The name must start with "o_". |
freq_hz=FREQ_HZ |
specifies the processor clock speed to the peripheral |
min_width=XXX{s|ms|us|ns} |
specifies the minimum pulse width |
Note: XXX may be an integer or a real number |
Note: The minimum width must be a realizable positive value (since a |
pulse width of zero means no control is being given to the servo). |
max_width=XXX{s|ms|us|ns} |
specifies the maximum pulse width |
Note: XXX may be an integer or a real number |
default_width=XXX{s|ms|us|ns} |
optionally specifies the default width of the PWM before it is set by the |
processor |
Note: If the default width is not specified then the minimum width is |
used as the default width. |
{period=XXX{s|ms|us|ns}|sync=o_name} |
either specifies the rate at which the PWM is generated or synchronize the |
PWM generation to a preceding servo_motor peripheral with the output |
signal o_name |
Note: XXX may be an integer or a real number |
Note: When sync is specified the leading edges of the PWMs will coincide. |
inperiod=I_name |
optionally specifies an input port to receive the strobe generated by the |
associated period |
Note: This optional parameter requires that period be specified. It is |
not compatible with the sync parameter. |
scale=C_name |
optionally creates a constant named "C_name" which states how many clock |
cycles are used for each count in the 8-bit PWM control |
Note: The name must start with "C_". |
Example: A PWM range of 1000 to 1500 usec and a clock frequency of 8 MHz |
produces a value of ceil((1500-1000)*8/(256-1)) = 16 clock |
cycles per 8-bit control value count. |
scale_max=C_name |
optionally creates a constant named "C_name" wich states the upper limit |
of the continuous control range |
Note: The name must start with "C_". |
Example: For the example in "scale=C_name" the upper limit would be |
ceil((1500-1000)*8/16) = 250. I.e., control values of 251 |
through 255 inclusive will produce the same PWM width as the |
control value 250. |
Example: |
A micro servo that responds to positive PWM pulses between 1000 usec and |
1500 usec once every 20 msec and the processor clock is 8 MHz. The |
architecture file would include the following:\n |
CONSTANT C_FREQ_HZ 8_000_000 |
PORTCOMMENT servo motor control |
PERIPHERAL servo_motor outport=O_SERVO \\ |
outsignal=o_servo \\ |
freq_hz=C_FREQ_HZ \\ |
min_width=1000us \\ |
max_width=1500us \\ |
period=20ms \\ |
scale=C_servo_scale \\ |
scale_max=C_servo_scale_max\n |
will create a peripheral generating the desired PWM signal.\n |
The constants C_servo_scale and C_servo_scale_max could be reported by the |
micro controller to a controlling application to specify the sensitivity and |
upper limit for the servo motor controller.\n |
Example: |
Synchronize a second servo motor with PWM pulses between 1000 usec and 2500 |
usec to the preceding servo motor controller:\n |
PERIPHERAL servo_motor outport=O_SERVO_2 \\ |
outsignal=o_servo2 \\ |
freq_hz=C_FREQ_HZ \\ |
min_width=1.0ms \\ |
max_width=2.5ms \\ |
sync=o_servo\n |
""" |
|
def __init__(self,peripheralFile,config,param_list,loc): |
# Use the externally provided file name for the peripheral |
self.peripheralFile = peripheralFile; |
# Get the parameters. |
allowables = ( |
( 'default_width', r'\S+', lambda v : self.TimeMethod(config,v), ), |
( 'freq_hz', r'\S+$', lambda v : self.IntMethod(config,v), ), |
( 'inperiod', r'I_\w+$', None, ), |
( 'max_width', r'\S+$', lambda v : self.TimeMethod(config,v), ), |
( 'min_width', r'\S+$', lambda v : self.TimeMethod(config,v), ), |
( 'outport', r'O_\w+$', None, ), |
( 'outsignal', r'o_\w+$', None, ), |
( 'outsignaln', r'o_\w+$', None, ), |
( 'period', r'\S+$', lambda v : self.TimeMethod(config,v), ), |
( 'scale', r'C_\w+$', None, ), |
( 'scale_max', r'C_\w+$', None, ), |
( 'sync', r'o_\w+$', None, ), |
) |
names = [a[0] for a in allowables]; |
for param_tuple in param_list: |
param = param_tuple[0]; |
if param not in names: |
raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,)); |
param_test = allowables[names.index(param)]; |
self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]); |
# Ensure the required parameters are provided. |
for paramname in ( |
'outport', |
'freq_hz', |
'min_width', |
'max_width', |
): |
if not hasattr(self,paramname): |
raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,)); |
# Ensure exactly one of mandatory exclusive pairs are specified. |
for exclusivepair in ( |
( 'outsignal', 'outsignaln', ), |
( 'period', 'sync', ), |
): |
if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]): |
raise SSBCCException('One of %s or %s must be specified at %s', (exclusivepair[0], exclusivepair[1], loc, )); |
if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]): |
raise SSBCCException('Only one of %s or %s may be specified at %s', (exclusivepair[0], exclusivepair[1], loc, )); |
# Set optional signals |
if not hasattr(self,'default_width'): |
self.default_width = self.min_width; |
# Ensure signal values are reasonable. |
if self.min_width >= self.max_width: |
raise SSBCCException('min_width must be smaller than max_width at %s' % loc); |
if not self.min_width <= self.default_width <= self.max_width: |
raise SSBCCException('default_width is not between min_width and max_width at %s' % loc); |
# Ensure the optionally provided "sync" servo_motor peripheral has been specified. |
if hasattr(self,'sync'): |
for p in config.peripheral: |
if (str(p.__class__) == str(self.__class__)) and (p.outsignal == self.sync): |
break; |
else: |
raise SSBCCException('Can\'t find preceding servo_motor peripheral with outsignal=%s at %s ' % (self.sync,loc,)); |
if not hasattr(p,'period'): |
raise SSBCCException('servo_motor peripherial with outsignal=%s must have period specified to be used at %s' % (self.sync,loc,)); |
# Translate the outsignal specification into a single member for the signal |
# name and a specification as to whether or not the signal is inverted. |
if hasattr(self,'outsignaln'): |
self.outsignal = self.outsignaln; |
self.invertOutsignal = True; |
else: |
self.invertOutsignal = False; |
# Set the string used to identify signals associated with this peripheral. |
self.namestring = self.outsignal; |
# Calculate the name of the signal to start the PWM. |
self.periodSignal = 's__%s__period_done' % (self.namestring if hasattr(self,'period') else self.sync) |
# Calculate the scaling and set the optionally specified constants. |
# TODO -- ensure the realizable min_width is positive |
self.scaleValue = int(math.ceil((self.max_width-self.min_width)*self.freq_hz/2**config.Get('data_width'))); |
self.scale_maxValue = int(math.ceil((self.max_width-self.min_width)*self.freq_hz/self.scaleValue)); |
for scalingPair in ( |
( 'scaling', 'scaleValue', ), |
( 'scale_max', 'scale_maxValue', ), |
): |
if hasattr(self,scalingPair[0]): |
config.AddConstant(scalingPair[1], getAttr(self,scalingPair[1])); |
# Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral. |
config.AddIO(self.outsignal,1,'output',loc); |
if hasattr(self,'period'): |
config.AddSignal(self.periodSignal, 1, loc); |
self.ix_outport = config.NOutports(); |
config.AddOutport((self.outport, |
False, |
# empty list |
),loc); |
if hasattr(self,'inperiod'): |
config.AddSignal('s_SETRESET_%s' % self.periodSignal,1,loc); |
config.AddInport((self.inperiod, |
(self.periodSignal, 1, 'set-reset',), |
),loc); |
|
def GenVerilog(self,fp,config): |
body = self.LoadCore(self.peripheralFile,'.v'); |
if hasattr(self,'period'): |
body = re.sub(r'@PERIOD_BEGIN@\n','',body); |
body = re.sub(r'@PERIOD_END@\n','',body); |
else: |
body = re.sub(r'@PERIOD_BEGIN@.*?@PERIOD_END@\n','',body,flags=re.DOTALL); |
nbits_scale = CeilLog2(self.scaleValue); |
if nbits_scale == 0: |
body = re.sub(r'@SCALE_0_BEGIN@\n','',body); |
body = re.sub(r'@SCALE_0_ELSE@.*?@SCALE_0_END@\n','',body,flags=re.DOTALL); |
else: |
body = re.sub(r'@SCALE_0_BEGIN@.*?@SCALE_0_ELSE@\n','',body,flags=re.DOTALL); |
body = re.sub(r'@SCALE_0_END@\n','',body); |
scaled_min_width = int(math.floor(self.min_width*self.freq_hz/self.scaleValue)); |
scaled_default_width = int(math.floor(self.default_width*self.freq_hz/self.scaleValue)); |
scaled_max_width = int(math.floor(self.max_width*self.freq_hz/self.scaleValue)); |
nbits_pwm = max(config.Get('data_width')+1,CeilLog2(scaled_max_width)); |
pwm_formula = "%d'd%d + { %d'd0, s_N }" % (nbits_pwm,scaled_min_width-1,nbits_pwm-8,); |
if hasattr(self,'period'): |
period = self.period * self.freq_hz / self.scaleValue; |
nbits_period = CeilLog2(period); |
else: |
period = 1; |
nbits_period = 0; |
for subpair in ( |
( r'@DEFAULT_PWM@', "%d'd%d" % (nbits_pwm,scaled_default_width-1,), ), |
( r'@INVERT@', '!' if self.invertOutsignal else '', ), |
( r'@IX_OUTPORT@', "8'd%d" % self.ix_outport, ), |
( r'@NAME@', self.namestring, ), |
( r'@NBITS_PERIOD@', str(nbits_period), ), |
( r'@NBITS_PWM@', str(nbits_pwm), ), |
( r'@NBITS_SCALE@', str(nbits_scale), ), |
( r'@ONE_PERIOD@', "%d'd1" % nbits_period, ), |
( r'@ONE_PWM@', "%d'd1" % nbits_pwm, ), |
( r'@ONE_SCALE@', "%d'd1" % nbits_scale, ), |
( r'@OUTSIGNAL@', self.outsignal, ), |
( r'@PERIOD_MINUS_ONE@', "%d'd%d" % (nbits_period,period-1,), ), |
( r'@PWM_FORMULA@', pwm_formula, ), |
( r'@SCALE_MINUS_ONE@', "%d'd%d" % (nbits_scale,self.scaleValue-1,), ), |
( r'\bgen__', 'gen__%s__' % self.namestring, ), |
( r'\bs__', 's__%s__' % self.namestring, ), |
( r'@PERIOD_SIGNAL@', self.periodSignal, ), # must be after ( r'\bs__', ... |
): |
body = re.sub(subpair[0],subpair[1],body); |
body = self.GenVerilogFinal(config,body); |
fp.write(body); |
/ssbcc/trunk/core/9x8/peripherals/stepper_motor.v
0,0 → 1,207
// |
// PERIPHERAL stepper_motor: @NAME@ |
// Copyright 2015, Sinclair R.F., Inc. |
// |
// Assemble the byes of the control word from the input bytes. |
@MASTER_BEGIN@ |
localparam L__RATEMETHOD_MINUS_1 = @RATEMETHOD@ - 1; |
localparam L__NBITS_RATEMETHOD = clog2(L__RATEMETHOD_MINUS_1); |
@MASTER_END@ |
reg [@CONTROL_WIDTH@-1:0] s__input_control_word = {(@CONTROL_WIDTH@){1'b0}}; |
always @ (posedge i_clk) |
if (i_rst) |
s__input_control_word <= {(@CONTROL_WIDTH@){1'b0}}; |
else if (s_outport && (s_T == 8'd@IX_OUTCONTROL@)) |
s__input_control_word <= { s__input_control_word[0+:@CONTROL_WIDTH@-@DW@], s_N }; |
else |
s__input_control_word <= s__input_control_word; |
wire [@CONTROL_WIDTH_PACKED@-1:0] s__input_control_word_packed = { |
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+@DW@*((@COUNT_WIDTH@+@DWM1@)/@DW@)+@DW@*((@ACCEL_WIDTH@+@DWM1@)/@DW@)+:@RATECMD_WIDTH@], |
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+@DW@*((@COUNT_WIDTH@+@DWM1@)/@DW@)+:@ACCEL_WIDTH@], |
s__input_control_word[@DW@*((@MODE_WIDTH@+@DWM1@)/@DW@)+:@COUNT_WIDTH@] |
@OUTMODE_BEGIN@ |
, s__input_control_word[0+:@MODE_WIDTH@] |
@OUTMODE_END@ |
}; |
// Instantiate the control word FIFO and operate its input side. |
reg s__FIFO_wr = 1'b0; |
always @ (posedge i_clk) |
if (i_rst) |
s__FIFO_wr <= 1'b0; |
else |
s__FIFO_wr <= (s_outport && (s_T == 8'd@IX_OUTRECORD@)); |
reg [@NBITS_FIFO_DEPTH@:0] s__FIFO_in_addr = {(@NBITS_FIFO_DEPTH@+1){1'b0}}; |
always @ (posedge i_clk) |
if (i_rst) |
s__FIFO_in_addr <= {(@NBITS_FIFO_DEPTH@+1){1'b0}}; |
else |
s__FIFO_in_addr <= s__FIFO_in_addr + { @NBITS_FIFO_DEPTH@'d0, s__FIFO_wr }; |
reg [@CONTROL_WIDTH_PACKED@-1:0] s__FIFO[@FIFO_DEPTH@-1:0]; |
always @ (posedge i_clk) |
if (s__FIFO_wr) |
s__FIFO[s__FIFO_in_addr[0+:@NBITS_FIFO_DEPTH@]] <= s__input_control_word_packed; |
// Operate the output side of the FIFO and translate the packed controls into |
// individual signals. |
reg s__FIFO_rd = 1'b0; |
reg [@NBITS_FIFO_DEPTH@:0] s__FIFO_out_addr = {(@NBITS_FIFO_DEPTH@+1){1'b0}}; |
always @ (posedge i_clk) |
if (i_rst) |
s__FIFO_out_addr <= {(@NBITS_FIFO_DEPTH@+1){1'b0}}; |
else |
s__FIFO_out_addr <= s__FIFO_out_addr + { @NBITS_FIFO_DEPTH@'d0, s__FIFO_rd }; |
reg [@CONTROL_WIDTH_PACKED@-1:0] s__output_control_word = @CONTROL_WIDTH_PACKED@'d0; |
always @ (posedge i_clk) |
s__output_control_word <= s__FIFO[s__FIFO_out_addr[0+:@NBITS_FIFO_DEPTH@]]; |
wire [@RATECMD_WIDTH@-1:0] s__next_rate = s__output_control_word[@MODE_WIDTH@+@COUNT_WIDTH@+@ACCEL_WIDTH@+:@RATECMD_WIDTH@]; |
wire [@ACCEL_WIDTH@-1:0] s__next_accel = s__output_control_word[@MODE_WIDTH@+@COUNT_WIDTH@+:@ACCEL_WIDTH@]; |
wire [@COUNT_WIDTH@-1:0] s__next_count = s__output_control_word[@MODE_WIDTH@+:@COUNT_WIDTH@]; |
@OUTMODE_BEGIN@ |
wire [@MODE_WIDTH@-1:0] s__next_mode = s__output_control_word[0+:@MODE_WIDTH@]; |
@OUTMODE_END@ |
// Indicate whether or not the FIFO is empty. |
reg s__FIFO_empty = 1'b1; |
always @ (posedge i_clk) |
if (i_rst) |
s__FIFO_empty <=1'b1; |
else |
s__FIFO_empty <= (s__FIFO_out_addr == s__FIFO_in_addr); |
@MASTER_BEGIN@ |
// Generate the clock enable for the effective internal clock rate. |
reg s__clk_en = 1'b0; |
reg [L__NBITS_RATEMETHOD-1:0] s__clk_en_count = L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD]; |
always @ (posedge i_clk) |
if (i_rst) begin |
s__clk_en <= 1'b0; |
s__clk_en_count <= L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD]; |
end else begin |
s__clk_en <= (s__clk_en_count == { {(L__NBITS_RATEMETHOD-1){1'b0}}, 1'b1 }); |
if (s__clk_en) |
s__clk_en_count <= L__RATEMETHOD_MINUS_1[0+:L__NBITS_RATEMETHOD]; |
else |
s__clk_en_count <= s__clk_en_count - { {(L__NBITS_RATEMETHOD-1){1'b0}}, 1'b1 }; |
end |
@MASTER_END@ |
// Capture the start strobe from the micro controller. |
reg s__go = 1'b0; |
always @ (posedge i_clk) |
if (i_rst) |
s__go <= 1'b0; |
else if (s_outport && (s_T == 8'd@IX_OUTRUN@)) |
s__go <= 1'b1; |
else if (@S__CLK_EN@) |
s__go <= 1'b0; |
else |
s__go <= s__go; |
// Indicate when the controller is running. |
reg s__running = 1'b0; |
wire s__load_next; |
always @ (posedge i_clk) |
if (i_rst) |
s__running <= 1'b0; |
else if (s__go && @S__CLK_EN@) |
s__running <= 1'b1; |
else if (s__load_next && s__FIFO_empty) |
s__running <= 1'b0; |
else |
s__running <= s__running; |
always @ (posedge i_clk) |
if (i_rst) |
s__done <= 1'b1; |
else if (s_outport && (s_T == 8'd@IX_OUTRUN@)) |
s__done <= 1'b0; |
else |
s__done <= !s__go && !s__running; |
// Operate the step count |
wire s__step_pre; |
reg [@COUNT_WIDTH@-1:0] s__count = @COUNT_WIDTH@'d0; |
reg s__count_zero = 1'b1; |
always @ (posedge i_clk) |
if (i_rst) |
s__count <= @COUNT_WIDTH@'d0; |
else if (s__load_next && !s__FIFO_empty) |
s__count <= s__next_count; |
else if (@S__CLK_EN@ && s__step_pre) |
s__count <= s__count - { {(@COUNT_WIDTH@-1){1'b0}}, !s__count_zero }; |
else |
s__count <= s__count; |
always @ (posedge i_clk) |
if (i_rst) |
s__count_zero <= 1'b1; |
else |
s__count_zero <= (s__count == @COUNT_WIDTH@'d0); |
assign s__load_next = @S__CLK_EN@ && (s__go || s__running && s__step_pre && s__count_zero); |
always @ (posedge i_clk) |
if (i_rst) |
s__FIFO_rd <= 1'b0; |
else |
s__FIFO_rd <= s__load_next && !s__FIFO_empty; |
// Operate the accumulators. |
reg [@ACCUM_WIDTH@-1:0] s__angle = @ACCUM_WIDTH@'d0; |
reg [@RATE_WIDTH@-1:0] s__rate = @RATE_WIDTH@'d0; |
reg [@ACCEL_WIDTH@-1:0] s__accel = @ACCEL_WIDTH@'d0; |
@OUTMODE_BEGIN@ |
reg [@MODE_WIDTH@-1:0] s__mode = @MODE_WIDTH@'d0; |
@OUTMODE_END@ |
reg [@ACCUM_WIDTH@-1:0] s__angle_presum = @ACCUM_WIDTH@'d0; |
always @ (posedge i_clk) |
if (i_rst) |
s__angle_presum <= @ACCUM_WIDTH@'d0; |
else |
s__angle_presum <= s__angle + { {(@RATE_SCALE@){s__rate[@RATE_WIDTH@-1]}}, s__rate[@RATE_WIDTH@-1:@ACCEL_RES@-@ACCUM_RES@] }; |
always @ (posedge i_clk) |
if (i_rst) begin |
s__angle <= @ACCUM_WIDTH@'d0; |
s__rate <= @RATE_WIDTH@'d0; |
s__accel <= @ACCEL_WIDTH@'d0; |
@OUTMODE_BEGIN@ |
s__mode <= @MODE_WIDTH@'d0; |
@OUTMODE_END@ |
end else if (s__load_next && !s__FIFO_empty) begin |
s__angle <= {(@ACCUM_WIDTH@){s__next_rate[@RATECMD_WIDTH@-1]}}; |
s__rate <= { s__next_rate, {(@ACCEL_RES@-@RATE_RES@){1'b0}} }; |
s__accel <= s__next_accel; |
@OUTMODE_BEGIN@ |
s__mode <= s__next_mode; |
@OUTMODE_END@ |
end else if (!s__running || (s__load_next && s__FIFO_empty)) begin |
s__angle <= @ACCUM_WIDTH@'d0; |
s__rate <= @RATE_WIDTH@'d0; |
s__accel <= @ACCEL_WIDTH@'d0; |
@OUTMODE_BEGIN@ |
s__mode <= s__mode; |
@OUTMODE_END@ |
end else begin |
if (@S__CLK_EN@) begin |
s__angle <= s__angle_presum; |
s__rate <= s__rate + { {(@ACCEL_SCALE@-@RATE_SCALE@){s__accel[@ACCEL_WIDTH@-1]}}, s__accel }; |
end else begin |
s__angle <= s__angle; |
s__rate <= s__rate; |
end |
s__accel <= s__accel; |
@OUTMODE_BEGIN@ |
s__mode <= s__mode; |
@OUTMODE_END@ |
end |
// Generate the direction and step signals. |
assign s__step_pre = (s__angle[@ACCUM_WIDTH@-1] != s__angle_presum[@ACCUM_WIDTH@-1]); |
always @ (posedge i_clk) |
if (i_rst) begin |
o__dir <= 1'b0; |
o__step <= 1'b0; |
end else if (@S__CLK_EN@) begin |
o__dir <= s__rate[@RATE_WIDTH@-1]; |
o__step <= s__step_pre; |
end else begin |
o__dir <= o__dir; |
o__step <= o__step; |
end |
@OUTMODE_BEGIN@ |
always @ (posedge i_clk) |
if (i_rst) |
o__mode <= @OUTMODEWIDTH@'d0; |
else if (@S__CLK_EN@) |
o__mode <= s__mode; |
else |
o__mode <= o__mode; |
@OUTMODE_END@ |
ssbcc/trunk/core/9x8/peripherals/stepper_motor.v
Property changes :
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Index: ssbcc/trunk/core/9x8/peripherals/UART_Rx.py
===================================================================
--- ssbcc/trunk/core/9x8/peripherals/UART_Rx.py (revision 8)
+++ ssbcc/trunk/core/9x8/peripherals/UART_Rx.py (revision 9)
@@ -1,6 +1,6 @@
################################################################################
#
-# Copyright 2013-2014, Sinclair R.F., Inc.
+# Copyright 2013-2015, Sinclair R.F., Inc.
#
################################################################################
@@ -8,7 +8,8 @@
import re;
from ssbccPeripheral import SSBCCperipheral
-from ssbccUtil import SSBCCException;
+from ssbccUtil import CeilLog2
+from ssbccUtil import SSBCCException
class UART_Rx(SSBCCperipheral):
"""
@@ -24,7 +25,8 @@
[noSync|sync=n] \\
[noDeglitch|deglitch=n] \\
[noInFIFO|inFIFO=n] \\
- [{RTR|RTRn}=i_rtr_name] \\
+ [{RTR|RTRn}=o_rtr_name] \\
+ rtr_buffer=n \\
[nStop={1|2}] \n
Where:
inport=I_inport_name
@@ -40,9 +42,9 @@
1st method: clk/rate
clk is the frequency of "i_clk" in Hz
a number will be interpreted as the clock frequency in Hz
- a symbol will be interpreted as a parameter
- Note: this parameter must have been declared with a "PARAMETER"
- command
+ a symbol will be interpreted as a constant or a parameter
+ Note: the symbol must be declared with the CONSTANT, LOCALPARARM,
+ or PARAMETER configuration command.
rate is the desired baud rate
this is specified as per "clk"
2nd method:
@@ -52,7 +54,7 @@
frequency and a hard-wired baud rate of 9600:
"baudmethod=G_CLK_FREQ_HZ/9600".
Note: The numeric values can have Verilog-style '_' separators between
- the digits. For example, 100_000_000 represents 100 million.
+ the digits. For example, 100_000_000 represents 100 million.
insignal=i_name
optionally specifies the name of the single-bit transmit signal
Default: i_UART_Rx
@@ -76,17 +78,25 @@
inFIFO=n
optionally add a FIFO of depth n to the input side of the UART
Note: n must be a power of 2.
- RTR=i_rtr_name or RTRn=i_rtr_name
+ RTR=o_rtr_name or RTRn=o_rtr_name
optionally specify an output handshake signal to indicate that the
peripheral is ready to receive data
Note: If RTR is specified then the receiver indicates it is ready when
- i_rtr_name is high. If RTRn is specified then the transmitter
- indicates it is ready when i_rtr_name is low.
+ o_rtr_name is high. If RTRn is specified then the transmitter
+ indicates it is ready when o_rtr_name is low.
Note: The default, i.e., neither CTS nor CTSn is specified, is to always
enable the receiver.
Note: If there is no FIFO and the RTR/RTRn handshake indicates that the
receiver is not ready as soon as it starts receiving data and
until that data is read from the peripheral.
+ Default: 1
+ rtr_buffer=n
+ optionally specify the number of entries in inFIFO to reserve for data
+ received after the RTR/RTRn signal indicates to stop data flow.
+ Note: n must be a power of 2.
+ Note: This requires that inFIFO be specified.
+ Note: Some USB UARTs will transmit several characters after the RTR/RTRn
+ signal indicates to stop the data flow.
nStop=n
optionally configure the peripheral for n stop bits
default: 1 stop bit
@@ -121,7 +131,7 @@
( 'RTRn', r'o_\w+$', None, ),
( 'baudmethod', r'\S+$', lambda v : self.RateMethod(config,v), ),
( 'deglitch', r'[1-9]\d*$', int, ),
- ( 'inFIFO', r'[1-9]\d*$', lambda v : self.IntPow2(v), ),
+ ( 'inFIFO', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
( 'inempty', r'I_\w+$', None, ),
( 'inport', r'I_\w+$', None, ),
( 'insignal', r'i_\w+$', None, ),
@@ -129,6 +139,7 @@
( 'noInFIFO', None, None, ),
( 'noSync', None, None, ),
( 'nStop', r'[12]$', int, ),
+ ( 'rtr_buffer', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
( 'sync', r'[1-9]\d*$', int, ),
);
names = [a[0] for a in allowables];
@@ -153,6 +164,15 @@
):
if not hasattr(self,optionalpair[0]):
setattr(self,optionalpair[0],optionalpair[1]);
+ # Ensure the rtr_buffer, if specified, is consistent with the inFIFO
+ # specification.
+ if hasattr(self,'rtr_buffer'):
+ if not hasattr(self,'inFIFO'):
+ raise SSBCCException('rtr_buffer specification requires simultaneous inFIFO specification at %s' % loc);
+ if not self.rtr_buffer < self.inFIFO:
+ raise SSBCCException('rtr_buffer=%d specification must be less than the inFIFO=%d specification at %s' % (self.rtr_buffer,self.inFIFO,loc,));
+ else:
+ self.rtr_buffer = 1;
# Ensure exclusive pair configurations are set and consistent.
for exclusivepair in (
( 'RTR', 'RTRn', None, None, ),
@@ -206,17 +226,18 @@
body = re.sub(r'@RTR_BEGIN@.*?@RTR_END@\n','',body,flags=re.DOTALL);
for subpair in (
( r'@RTR_SIGNAL@', self.RTR if hasattr(self,'RTR') else self.RTRn if hasattr(self,'RTRn') else '', ),
- ( r'@RTR_INVERT@', '' if hasattr(self,'RTR') else '!', ),
- ( r'\bL__', 'L__@NAME@__', ),
- ( r'\bgen__', 'gen__@NAME@__', ),
- ( r'\bs__', 's__@NAME@__', ),
- ( r'@INPORT@', self.insignal, ),
- ( r'@BAUDMETHOD@', str(self.baudmethod), ),
- ( r'@SYNC@', str(self.sync), ),
- ( r'@DEGLITCH@', str(self.deglitch), ),
- ( r'@INFIFO@', str(self.inFIFO), ),
- ( r'@NSTOP@', str(self.nStop), ),
- ( r'@NAME@', self.namestring, ),
+ ( r'@RTRN_INVERT@', '!' if hasattr(self,'RTR') else '', ),
+ ( r'\bL__', 'L__@NAME@__', ),
+ ( r'\bgen__', 'gen__@NAME@__', ),
+ ( r'\bs__', 's__@NAME@__', ),
+ ( r'@INPORT@', self.insignal, ),
+ ( r'@BAUDMETHOD@', str(self.baudmethod), ),
+ ( r'@SYNC@', str(self.sync), ),
+ ( r'@DEGLITCH@', str(self.deglitch), ),
+ ( r'@INFIFO@', str(self.inFIFO), ),
+ ( r'@NSTOP@', str(self.nStop), ),
+ ( r'@NAME@', self.namestring, ),
+ ( r'@RTR_FIFO_COMPARE@', str(CeilLog2(self.rtr_buffer)), ),
):
if re.search(subpair[0],body):
body = re.sub(subpair[0],subpair[1],body);
/ssbcc/trunk/core/9x8/peripherals/UART_Tx.py
1,6 → 1,6
################################################################################ |
# |
# Copyright 2012-2014, Sinclair R.F., Inc. |
# Copyright 2012-2015, Sinclair R.F., Inc. |
# |
################################################################################ |
|
39,9 → 39,9
1st method: clk/rate |
clk is the frequency of "i_clk" in Hz |
a number will be interpreted as the clock frequency in Hz |
a symbol will be interpreted as a parameter |
Note: this parameter must have been declared with a "PARAMETER" |
command |
a symbol will be interpreted as a constant or a parameter |
Note: the symbol must be declared with the CONSTANT, LOCALPARARM, |
or PARAMETER configuration command. |
rate is the desired baud rate |
this is specified as per "clk" |
2nd method: |
118,7 → 118,7
( 'baudmethod', r'\S+$', lambda v : self.RateMethod(config,v), ), |
( 'noOutFIFO', None, None, ), |
( 'nStop', r'[12]$', int, ), |
( 'outFIFO', r'[1-9]\d*$', lambda v : self.IntPow2(v), ), |
( 'outFIFO', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ), |
( 'outport', r'O_\w+$', None, ), |
( 'outsignal', r'o_\w+$', None, ), |
( 'outstatus', r'I_\w+$', None, ), |
171,9 → 171,9
): |
if hasattr(self,ioEntry[0]): |
config.AddIO(getattr(self,ioEntry[0]),ioEntry[1],ioEntry[2],loc); |
config.AddSignal('s__%s__Tx' % self.namestring,8,loc); |
config.AddSignal('s__%s__Tx_busy' % self.namestring,1,loc); |
config.AddSignal('s__%s__Tx_wr' % self.namestring,1,loc); |
config.AddSignalWithInit('s__%s__Tx' % self.namestring,8,None,loc); |
config.AddSignal('s__%s__Tx_busy' % self.namestring,1,loc); |
config.AddSignalWithInit('s__%s__Tx_wr' % self.namestring,1,None,loc); |
config.AddOutport((self.outport,False, |
('s__%s__Tx' % self.namestring,8,'data',), |
('s__%s__Tx_wr' % self.namestring,1,'strobe',), |
188,14 → 188,14
for bodyextension in ('.v',): |
body = self.LoadCore(self.peripheralFile,bodyextension); |
for subpair in ( |
( r'\bL__', 'L__@NAME@__', ), |
( r'\bgen__', 'gen__@NAME@__', ), |
( r'\bs__', 's__@NAME@__', ), |
( r'@BAUDMETHOD@', str(self.baudmethod), ), |
( r'@ENABLED@', self.CTS if hasattr(self,'CTS') else ('!%s' % self.CTSn) if hasattr(self,'CTSn') else '1\'b1', ), |
( r'@NSTOP@', str(self.nStop), ), |
( r'@OUTFIFO@', str(self.outFIFO), ), |
( r'@NAME@', self.namestring, ), |
( r'\bL__', 'L__@NAME@__', ), |
( r'\bgen__', 'gen__@NAME@__', ), |
( r'\bs__', 's__@NAME@__', ), |
( r'@BAUDMETHOD@', str(self.baudmethod), ), |
( r'@ENABLED@', self.CTS if hasattr(self,'CTS') else ('!%s' % self.CTSn) if hasattr(self,'CTSn') else '1\'b1', ), |
( r'@NSTOP@', str(self.nStop), ), |
( r'@OUTFIFO@', str(self.outFIFO), ), |
( r'@NAME@', self.namestring, ), |
): |
body = re.sub(subpair[0],subpair[1],body); |
body = self.GenVerilogFinal(config,body); |
/ssbcc/trunk/ssbccConfig.py
26,6 → 26,7
""" |
self.config = dict(); # various settings, etc. |
self.constants = dict(); # CONSTANTs |
self.defines = dict(); # defines |
self.functions = dict(); # list of functions to define |
self.inports = list(); # INPORT definitions |
self.ios = list(); # List of I/Os |
66,6 → 67,19
raise SSBCCException('Could not evaluate expression "%s" for constant at %s' % (value,loc,)); |
self.constants[name] = ParseIntExpr(value); |
|
def AddDefine(self,name): |
""" |
Add the defined symbol.\n |
name name for the symbol (must start with "D_")\n |
Note: This is only invoked for the command line arguments so there is no |
"loc" available.\n |
Note: Defines can be declared more than once on the command line with no |
ill effects. |
""" |
if not self.IsDefine(name): |
self.AddSymbol(name); |
self.defines[name] = 1; |
|
def AddIO(self,name,nBits,iotype,loc): |
""" |
Add an I/O signal to the processor interface to the system.\n |
342,6 → 356,15
else: |
return False; |
|
def IsDefine(self,name): |
""" |
Indicate whether or not the specified symbol is a recognized define. |
""" |
if re.match(r'D_\w+$',name) and name in self.defines: |
return True; |
else: |
return False; |
|
def IsMemory(self,name): |
""" |
Indicate whether or not the specified symbol is the name of a memory. |
/ssbcc/trunk/README
48,15 → 48,15
the sizes of the instruction memory, data stack, and return stack; the input and |
output ports; RAM and ROM types and sizes; and peripherals. |
|
The instructions are all single-cycle. The instructions include |
The instructions are all single-cycle. The instructions are: |
- 4 arithmetic instructions: addition, subtraction, increment, and decrement |
- 2 carry bit instructions: +c and -c for addition and subtraction respectively |
- 3 bit-wise logical instructions: and, or, and exclusive or |
- 7 shift and rotation instructions: <<0, <<1, 0>>, 1>>, <<msb, >>msb, and >>lsb |
- 7 shift and rotation instructions: <<0, <<1, 0>>, 1>>, <<msb, msb>>, and lsb>> |
- 4 logical instructions: 0=, 0<>, -1=, -1<> |
- 6 Forth-like data stack instructions: drop, dup, nip, over, push, swap |
- 3 Forth-like return stack instructions: >r, r>, r@ |
- 2 input and output |
- 2 I/O: inport, outport |
- 6 memory read and write with optional address post increment and post decrement |
- 2 jump and conditional jump |
- 2 call and conditional call |
90,6 → 90,7
|
SPEED AND RESOURCE UTILIZATION |
================================================================================ |
|
These device speed and resource utilization results are copied from the build |
tests. The full results are listed in the core/9x8/build directories. The |
tests use a minimal processor implementation (clock, reset, and one output). |
599,7 → 600,16
dropped from the data stack so that it can be used by the subsequent conditional |
function call. |
|
The input from a set-reset INPORT is a pure flag. I.e., either all of the bits |
are zero or all of the bits are one. This can be used as part of executing a |
loop a fixed number of times. For example, the inperiod argument of the |
servo_motor peripheral can be used to receive a strobe every time the PWM goes |
high. The following loop will wait for 10 occurrences of the rising edge of the |
servo_motor PWM before proceeding to the next block of code: |
|
10 :loop .inport(I_INPERIOD) + .jumpc(loop,nop) drop |
|
|
PERIPHERAL |
================================================================================ |
|
652,6 → 662,8
open_drain for software-implemented I2C buses or similar |
outFIFO_async output FIFO with an asynchronous read clock |
PWM_8bit PWM generator with an 8-bit control |
servo_motor PWM modulation suitable for servo motor or similar control |
stepper_motor stepper motor controller with acceleration |
timer timing for polled loops or similar |
trace simulation diagnostic (see below) |
UART bidirectional UART |
1071,6 → 1083,7
|
MACROS |
================================================================================ |
|
There are 3 types of macros used by the assembler. |
|
The first kind of macros are built in to the assembler and are required to |
1153,54 → 1166,88
|
CONDITIONAL COMPILATION |
================================================================================ |
The computer compiler and assembler recognize conditional compilation as |
follows: .IFDEF, .IFNDEF, .ELSE, and .ENDIF can be used in the architecture |
file and they can be used to conditionally include functions, files, etc within |
the assembly code; .ifdef, .ifndef, .else, and .endif can be used in function |
bodies, variable bodies, etc. to conditionally include assembly code, symbols, |
or data. Conditionals cannot cross file boundaries. |
|
The computer compiler examines the list of defined symbols such as I/O ports, |
I/O signals, etc. to evaluate the true/false condition associated with the |
.IFDEF and .IFNDEF commands. The "-D" option to the computer compiler is |
provided to define symbols for enabling conditionally compiled configuration |
commands. Similarly, the assembler examines the list of I/O ports, I/O signals, |
parameters, constants, etc. to evaluate the .IFDEF, .IFNDEF, .ifdef, and .ifndef |
conditionals. |
Conditional compilation is accepted in the architecture file and in the assembly |
source files and is based on whether or not the referenced symbol is defined. |
|
For example, a diagnostic UART can be conditionally included using the |
configuration commands: |
In the architecture file, symbols are defined by CONSTANT, INPORT, OUTPORT, and |
PERIPHERAL statements, or by the "-D D_name" argument to ssbcc. The line |
|
.IFDEF ENABLE_UART |
.IFDEF name |
<statements> |
.ENDIF |
|
will then include the lines "<statements>" if the symbol "name" is defined. |
The ".IFNDEF" command is similar except that the statements included if the |
symbol is not defined. A ".ELSE" is also provided. |
|
In an assembly file directives are conditionally included using the .IFDEF and |
.IFNDEF directives, an optional .ELSE directive, and the terminating .ENDIF |
directive. Note that this is done at the directive level, i.e. function |
declarations, memory declarations, and so forth. Within a function code is |
conditionally included starting with a ".ifdef(name)" or a ".ifndef(name)", an |
optional ".else" and a terminating ".endif". |
|
For example, a diagnostic UART can be conditionally included in a program by |
including the following lines in the architecture file: |
|
.IFDEF D_ENABLE_UART |
PORTCOMMENT Diagnostic UART |
PERIPHERAL UART_Tx outport=O_UART_TX ... |
.ENDIF |
|
And the assembly code can include conditional code fragments such the following, |
where the existence of the output port is used to determine whether or not to |
send a character to that output port: |
A "uart_tx" function can be optionally created using code similar to the |
following. Note that the symbol for the .outport macro is used to determine |
whether or not the function is defined since that is more closely related to |
whether or not the function can be defined. The function definition must |
preceed any ".ifdef(uart_tx)" conditionals used to output diagnostics. |
|
.ifdef(O_UART_TX) 'A' .outport(O_UART_TX) .endif |
.IFDEF O_UART_TX |
.function uart_tx |
:loop .outport(O_UART_TX) .jumpc(loop,nop) .return(drop) |
.ENDIF |
|
Invoking the computer compiler with "-D ENABLE_UART" will generate a module with |
the UART peripheral and will enable the conditional code sending the 'A' |
character to the UART port. |
Diagnostics in the assembly code can be included using either |
|
The following code can be used to preclude multiple attempted inclusions of an |
assembly library file. |
.ifdef(D_ENABLE_UART) N"Msg\r\n" .call(uart_tx) .endif |
|
or |
|
.ifdef(uart_tx) N"Msg\r\n" .call(uart_tx) .endif |
|
Conditional compilation cannot cross file boundaries. |
|
The assembler also recognizes the ".define" directive. For example, specific |
diagnostics could be enabled if the UART is instantiated as follows: |
|
.IFDEF O_UART_TX |
.define D_DEBUG_FUNCTION_A |
.ENDIF |
|
... |
|
.ifdef(D_DEBUG_FUNCTION_A) N"Debug Msg\r\n" .call(uart_tx) .endif |
|
The following code illustrates how to preclude multiple attempted inclusions of |
an assembly library file. |
|
; put these two lines near the top of the file |
.IFNDEF C_FILENAME_INCLUDED |
.constant C_FILENAME_INCLUDED 1 |
.IFNDEF D_FILENAME_INCLUDED |
.define D_FILENAME_INCLUDED |
; put the library body here |
... |
; put this line at the bottom of the file |
.ENDIF ; .IFNDEF C_FILENAME_INCLUDED |
.ENDIF ; .IFNDEF D_FILENAME_INCLUDED |
|
The ".INCLUDE" configuration command can be used to read configuration commands |
from additional sources. |
from additional sources. For example, the following code will conditionally |
include a general UART library if the outport O_UART_TX is defined: |
|
.IFDEF O_UART_TX |
.INCLUDE uart.s |
.ENDIF |
|
|
SIMULATIONS |
================================================================================ |
|
1276,5 → 1323,3
|
The "INVERT_RESET" configuration command is used to indicate an active-low reset |
is input to the micro controller rather than an active-high reset. |
|
A VHDL package file is automatically generated by the computer compiler. |
/ssbcc/trunk/ssbcc
45,7 → 45,7
|
import argparse |
argListParser = argparse.ArgumentParser(description='SSBCC system builder'); |
argListParser.add_argument('-D', metavar='symbol', type=str, action='append', help='Define symbol'); |
argListParser.add_argument('-D', metavar='D_name', type=str, action='append', help='Define symbol (must start with "D_")'); |
argListParser.add_argument('-G', metavar='parameter_name=value', type=str, action='append', help='Override parameter value'); |
argListParser.add_argument('-I', metavar='include_dir', type=str, action='append', help='Add search directory for included files and peripherals'); |
argListParser.add_argument('-M', metavar='macropath', action='append', help='Macro search path'); |
74,13 → 74,15
config.functions['display_opcode'] = True; |
|
if argList.D: |
for symbol in argList.D: |
config.AddSymbol(symbol); |
for name in argList.D: |
if not re.match('D_',name): |
raise SSBCCException('Bad define name "%s" should start with "D_"' % name); |
config.AddDefine(name); |
|
if argList.I: |
for pathString in argList.I: |
if not os.path.isdir(pathString): |
raise SSBCCException('Bad path string: "%s"' % pathString); |
raise SSBCCException('Bad path string: "%s/%s"' % (os.getcwd(),pathString,)); |
config.AppendIncludePath(pathString); |
config.InsertPeripheralPath(pathString); |
|
199,7 → 201,7
elif re.match(r'\s*CONSTANT\b',line): |
if not config.Exists('architecture'): |
raise SSBCCException('"CONSTANT"s cannot be defined before the "ARCHITECTURE" is defined at %s' % loc); |
cmd = re.findall(r'\s*CONSTANT\s+(C_\w+)\s+(\w+)\s*$',line); |
cmd = re.findall(r'\s*CONSTANT\s+(C_\w+)\s+(-?[1-9]\d*|\w+)\s*$',line); |
if not cmd: |
raise SSBCCException('Malformed "CONSTANT" configuration command on %s: "%s"' % (loc,line,)); |
cmd = cmd[0]; |
367,8 → 369,8
################################################################################ |
|
# Generate peripheral libraries (if any). |
for ix in range(len(config.peripheral)): |
config.peripheral[ix].GenAssembly(config); |
for p in config.peripheral: |
p.GenAssembly(config); |
|
# Compute the file name to store the assembler output |
assemblerOutput = os.path.splitext(argList.filename.name)[0]+'.9x8-meta' |
379,6 → 381,8
cmd = os.path.join(config.Get('corepath'), compiler[0]); |
for name in config.constants: |
cmd += (' -C %s=%s' % (name,config.constants[name],)); |
for name in config.defines: |
cmd += (' -D %s' % name); |
for ix in range(len(config.parameters)): |
cmd += (' -G %s' % config.parameters[ix][0]); |
for ix in range(config.NInports()): |
548,10 → 552,10
elif fillCommand == 'peripherals': |
if not config.peripheral: |
fpOutCore.write('//\n// No peripherals\n//\n'); |
for ix in range(len(config.peripheral)): |
if ix != 0: |
for p in config.peripheral: |
if p != config.peripheral[0]: |
fpOutCore.write('\n'); |
config.peripheral[ix].GenHDL(fpOutCore,config); |
p.GenHDL(fpOutCore,config); |
# "s_memory" declaration |
elif fillCommand == 's_memory': |
if config.NMemories() == 0: |