1 |
2 |
sinclairrf |
################################################################################
|
2 |
|
|
#
|
3 |
9 |
sinclairrf |
# Copyright 2013-2015, Sinclair R.F., Inc.
|
4 |
2 |
sinclairrf |
#
|
5 |
|
|
################################################################################
|
6 |
|
|
|
7 |
|
|
import math;
|
8 |
|
|
import re;
|
9 |
|
|
|
10 |
|
|
from ssbccPeripheral import SSBCCperipheral
|
11 |
9 |
sinclairrf |
from ssbccUtil import CeilLog2
|
12 |
|
|
from ssbccUtil import SSBCCException
|
13 |
2 |
sinclairrf |
|
14 |
|
|
class UART_Rx(SSBCCperipheral):
|
15 |
|
|
"""
|
16 |
|
|
Receive UART:
|
17 |
|
|
1 start bit
|
18 |
|
|
8 data bits
|
19 |
|
|
1 or 2 stop bits\n
|
20 |
|
|
Usage:
|
21 |
|
|
PERIPHERAL UART_Rx inport=I_inport_name \\
|
22 |
|
|
inempty=I_inempty_name \\
|
23 |
|
|
baudmethod={clk/rate|count} \\
|
24 |
|
|
[insignal=i_name] \\
|
25 |
|
|
[noSync|sync=n] \\
|
26 |
|
|
[noDeglitch|deglitch=n] \\
|
27 |
|
|
[noInFIFO|inFIFO=n] \\
|
28 |
9 |
sinclairrf |
[{RTR|RTRn}=o_rtr_name] \\
|
29 |
|
|
rtr_buffer=n \\
|
30 |
2 |
sinclairrf |
[nStop={1|2}] \n
|
31 |
|
|
Where:
|
32 |
|
|
inport=I_inport_name
|
33 |
|
|
specifies the symbol used by the inport instruction to read a received by
|
34 |
|
|
from the peripheral
|
35 |
|
|
Note: The name must start with "I_".
|
36 |
|
|
inempty=I_inempty_name
|
37 |
|
|
specifies the symbol used by the inport instruction to get the empty
|
38 |
|
|
status of the input side of the peripheral
|
39 |
|
|
Note: The name must start with "I_".
|
40 |
|
|
baudmethod
|
41 |
|
|
specifies the method to generate the desired bit rate:
|
42 |
|
|
1st method: clk/rate
|
43 |
|
|
clk is the frequency of "i_clk" in Hz
|
44 |
|
|
a number will be interpreted as the clock frequency in Hz
|
45 |
9 |
sinclairrf |
a symbol will be interpreted as a constant or a parameter
|
46 |
|
|
Note: the symbol must be declared with the CONSTANT, LOCALPARARM,
|
47 |
|
|
or PARAMETER configuration command.
|
48 |
2 |
sinclairrf |
rate is the desired baud rate
|
49 |
|
|
this is specified as per "clk"
|
50 |
|
|
2nd method:
|
51 |
|
|
specify the number of "i_clk" clock cycles between bit edges
|
52 |
|
|
Note: clk, rate, and count can be parameters or constants. For example,
|
53 |
|
|
the following uses the parameter G_CLK_FREQ_HZ for the clock
|
54 |
|
|
frequency and a hard-wired baud rate of 9600:
|
55 |
|
|
"baudmethod=G_CLK_FREQ_HZ/9600".
|
56 |
|
|
Note: The numeric values can have Verilog-style '_' separators between
|
57 |
9 |
sinclairrf |
the digits. For example, 100_000_000 represents 100 million.
|
58 |
2 |
sinclairrf |
insignal=i_name
|
59 |
|
|
optionally specifies the name of the single-bit transmit signal
|
60 |
|
|
Default: i_UART_Rx
|
61 |
|
|
noSync
|
62 |
|
|
optionally state no synchronization or registration is performed on the
|
63 |
|
|
input signal.
|
64 |
|
|
sync=n
|
65 |
|
|
optionally state that an n-bit synchronizer will be performed on the
|
66 |
|
|
input signal.
|
67 |
|
|
Note: sync=3 is the default.
|
68 |
|
|
noDeglitch
|
69 |
|
|
optionally state that no deglitching is performed on the input signal.
|
70 |
|
|
Note: This is the default.
|
71 |
|
|
deglitching=n
|
72 |
|
|
optionally state that an n-bit deglitcher is performed on the input signal
|
73 |
|
|
Note: Deglitching consists of changing the output state when n
|
74 |
|
|
successive input bits are in the opposite state.
|
75 |
|
|
noInFIFO
|
76 |
|
|
optionally state that the peripheral will not have an input FIFO
|
77 |
|
|
Note: This is the default.
|
78 |
|
|
inFIFO=n
|
79 |
|
|
optionally add a FIFO of depth n to the input side of the UART
|
80 |
|
|
Note: n must be a power of 2.
|
81 |
9 |
sinclairrf |
RTR=o_rtr_name or RTRn=o_rtr_name
|
82 |
6 |
sinclairrf |
optionally specify an output handshake signal to indicate that the
|
83 |
|
|
peripheral is ready to receive data
|
84 |
|
|
Note: If RTR is specified then the receiver indicates it is ready when
|
85 |
9 |
sinclairrf |
o_rtr_name is high. If RTRn is specified then the transmitter
|
86 |
|
|
indicates it is ready when o_rtr_name is low.
|
87 |
6 |
sinclairrf |
Note: The default, i.e., neither CTS nor CTSn is specified, is to always
|
88 |
|
|
enable the receiver.
|
89 |
|
|
Note: If there is no FIFO and the RTR/RTRn handshake indicates that the
|
90 |
|
|
receiver is not ready as soon as it starts receiving data and
|
91 |
|
|
until that data is read from the peripheral.
|
92 |
9 |
sinclairrf |
Default: 1
|
93 |
|
|
rtr_buffer=n
|
94 |
|
|
optionally specify the number of entries in inFIFO to reserve for data
|
95 |
|
|
received after the RTR/RTRn signal indicates to stop data flow.
|
96 |
|
|
Note: n must be a power of 2.
|
97 |
|
|
Note: This requires that inFIFO be specified.
|
98 |
|
|
Note: Some USB UARTs will transmit several characters after the RTR/RTRn
|
99 |
|
|
signal indicates to stop the data flow.
|
100 |
2 |
sinclairrf |
nStop=n
|
101 |
|
|
optionally configure the peripheral for n stop bits
|
102 |
|
|
default: 1 stop bit
|
103 |
|
|
Note: n must be 1 or 2
|
104 |
|
|
Note: the peripheral does not accept 1.5 stop bits
|
105 |
|
|
The following ports are provided by this peripheral:
|
106 |
|
|
I_inport_name
|
107 |
|
|
input a recieved byte from the peripheral
|
108 |
|
|
Note: If there is no input FIFO, then this is the last received byte.
|
109 |
|
|
If there is an input FIFO, then this is the next byte in the FIFO.
|
110 |
|
|
Note: If there is an input FIFO and the read would cause a FIFO
|
111 |
|
|
underflow, this will repeat the last received byte.
|
112 |
|
|
I_inempty_name
|
113 |
|
|
input the empty status of the input side of the peripheral
|
114 |
|
|
bit 0: input empty
|
115 |
|
|
this bit will be high when the input side of the peripheral has one or
|
116 |
|
|
more bytes read to be read
|
117 |
|
|
Note: If there is no FIFO this means that a single byte is ready to be
|
118 |
|
|
read and has not been read. If there is an input FIFO this
|
119 |
|
|
means that there are one or more bytes in the FIFO.
|
120 |
|
|
Note: "Empty" is used rather than "ready" to facilitate loops that
|
121 |
|
|
respond when there is a new byte ready to be processed. See the
|
122 |
|
|
examples below.
|
123 |
|
|
"""
|
124 |
|
|
|
125 |
|
|
def __init__(self,peripheralFile,config,param_list,loc):
|
126 |
|
|
# Use the externally provided file name for the peripheral
|
127 |
|
|
self.peripheralFile = peripheralFile;
|
128 |
|
|
# Get the parameters.
|
129 |
6 |
sinclairrf |
allowables = (
|
130 |
|
|
( 'RTR', r'o_\w+$', None, ),
|
131 |
|
|
( 'RTRn', r'o_\w+$', None, ),
|
132 |
|
|
( 'baudmethod', r'\S+$', lambda v : self.RateMethod(config,v), ),
|
133 |
|
|
( 'deglitch', r'[1-9]\d*$', int, ),
|
134 |
9 |
sinclairrf |
( 'inFIFO', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
|
135 |
6 |
sinclairrf |
( 'inempty', r'I_\w+$', None, ),
|
136 |
|
|
( 'inport', r'I_\w+$', None, ),
|
137 |
|
|
( 'insignal', r'i_\w+$', None, ),
|
138 |
|
|
( 'noDeglitch', None, None, ),
|
139 |
|
|
( 'noInFIFO', None, None, ),
|
140 |
|
|
( 'noSync', None, None, ),
|
141 |
|
|
( 'nStop', r'[12]$', int, ),
|
142 |
9 |
sinclairrf |
( 'rtr_buffer', r'[1-9]\d*$', lambda v : self.IntPow2Method(config,v), ),
|
143 |
6 |
sinclairrf |
( 'sync', r'[1-9]\d*$', int, ),
|
144 |
|
|
);
|
145 |
|
|
names = [a[0] for a in allowables];
|
146 |
2 |
sinclairrf |
for param_tuple in param_list:
|
147 |
|
|
param = param_tuple[0];
|
148 |
6 |
sinclairrf |
if param not in names:
|
149 |
|
|
raise SSBCCException('Unrecognized parameter "%s" at %s' % (param,loc,));
|
150 |
|
|
param_test = allowables[names.index(param)];
|
151 |
|
|
self.AddAttr(config,param,param_tuple[1],param_test[1],loc,param_test[2]);
|
152 |
2 |
sinclairrf |
# Ensure the required parameters are provided.
|
153 |
|
|
for paramname in (
|
154 |
|
|
'baudmethod',
|
155 |
|
|
'inempty',
|
156 |
|
|
'inport',
|
157 |
|
|
):
|
158 |
|
|
if not hasattr(self,paramname):
|
159 |
|
|
raise SSBCCException('Required parameter "%s" is missing at %s' % (paramname,loc,));
|
160 |
|
|
# Set optional parameters.
|
161 |
|
|
for optionalpair in (
|
162 |
6 |
sinclairrf |
( 'insignal', 'i_UART_Rx', ),
|
163 |
|
|
( 'nStop', 1, ),
|
164 |
2 |
sinclairrf |
):
|
165 |
|
|
if not hasattr(self,optionalpair[0]):
|
166 |
|
|
setattr(self,optionalpair[0],optionalpair[1]);
|
167 |
9 |
sinclairrf |
# Ensure the rtr_buffer, if specified, is consistent with the inFIFO
|
168 |
|
|
# specification.
|
169 |
|
|
if hasattr(self,'rtr_buffer'):
|
170 |
|
|
if not hasattr(self,'inFIFO'):
|
171 |
|
|
raise SSBCCException('rtr_buffer specification requires simultaneous inFIFO specification at %s' % loc);
|
172 |
|
|
if not self.rtr_buffer < self.inFIFO:
|
173 |
|
|
raise SSBCCException('rtr_buffer=%d specification must be less than the inFIFO=%d specification at %s' % (self.rtr_buffer,self.inFIFO,loc,));
|
174 |
|
|
else:
|
175 |
|
|
self.rtr_buffer = 1;
|
176 |
2 |
sinclairrf |
# Ensure exclusive pair configurations are set and consistent.
|
177 |
|
|
for exclusivepair in (
|
178 |
6 |
sinclairrf |
( 'RTR', 'RTRn', None, None, ),
|
179 |
|
|
( 'noSync', 'sync', 'sync', 3, ),
|
180 |
|
|
( 'noDeglitch', 'deglitch', 'noDeglitch', True, ),
|
181 |
|
|
( 'noInFIFO', 'inFIFO', 'noInFIFO', True, ),
|
182 |
2 |
sinclairrf |
):
|
183 |
|
|
if hasattr(self,exclusivepair[0]) and hasattr(self,exclusivepair[1]):
|
184 |
|
|
raise SSBCCException('Only one of "%s" and "%s" can be specified at %s' % (exclusivepair[0],exclusivepair[1],loc,));
|
185 |
6 |
sinclairrf |
if not hasattr(self,exclusivepair[0]) and not hasattr(self,exclusivepair[1]) and exclusivepair[2]:
|
186 |
2 |
sinclairrf |
setattr(self,exclusivepair[2],exclusivepair[3]);
|
187 |
6 |
sinclairrf |
# Convert configurations to alternate format.
|
188 |
|
|
for equivalent in (
|
189 |
|
|
( 'noDeglitch', 'deglitch', 0, ),
|
190 |
|
|
( 'noInFIFO', 'inFIFO', 0, ),
|
191 |
|
|
( 'noSync', 'sync', 0, ),
|
192 |
|
|
):
|
193 |
|
|
if hasattr(self,equivalent[0]):
|
194 |
|
|
delattr(self,equivalent[0]);
|
195 |
|
|
setattr(self,equivalent[1],equivalent[2]);
|
196 |
|
|
# Set the value used to identify signals associated with this peripheral.
|
197 |
2 |
sinclairrf |
self.namestring = self.insignal;
|
198 |
|
|
# Add the I/O port, internal signals, and the INPORT and OUTPORT symbols for this peripheral.
|
199 |
6 |
sinclairrf |
for ioEntry in (
|
200 |
|
|
( 'insignal', 1, 'input', ),
|
201 |
|
|
( 'RTR', 1, 'output', ),
|
202 |
|
|
( 'RTRn', 1, 'output', ),
|
203 |
|
|
):
|
204 |
|
|
if hasattr(self,ioEntry[0]):
|
205 |
|
|
config.AddIO(getattr(self,ioEntry[0]),ioEntry[1],ioEntry[2],loc);
|
206 |
2 |
sinclairrf |
config.AddSignal('s__%s__Rx' % self.namestring,8,loc);
|
207 |
|
|
config.AddSignal('s__%s__Rx_empty' % self.namestring,1,loc);
|
208 |
|
|
config.AddSignal('s__%s__Rx_rd' % self.namestring,1,loc);
|
209 |
|
|
config.AddInport((self.inport,
|
210 |
|
|
('s__%s__Rx' % self.namestring,8,'data',),
|
211 |
|
|
('s__%s__Rx_rd' % self.namestring,1,'strobe',),
|
212 |
|
|
),loc);
|
213 |
|
|
config.AddInport((self.inempty,
|
214 |
6 |
sinclairrf |
('s__%s__Rx_empty' % self.namestring,1,'data',),
|
215 |
|
|
),loc);
|
216 |
2 |
sinclairrf |
# Add the 'clog2' function to the processor (if required).
|
217 |
|
|
config.functions['clog2'] = True;
|
218 |
|
|
|
219 |
|
|
def GenVerilog(self,fp,config):
|
220 |
|
|
for bodyextension in ('.v',):
|
221 |
|
|
body = self.LoadCore(self.peripheralFile,bodyextension);
|
222 |
6 |
sinclairrf |
if hasattr(self,'RTR') or hasattr(self,'RTRn'):
|
223 |
|
|
body = re.sub(r'@RTR_BEGIN@\n','',body);
|
224 |
|
|
body = re.sub(r'@RTR_END@\n','',body);
|
225 |
|
|
else:
|
226 |
|
|
body = re.sub(r'@RTR_BEGIN@.*?@RTR_END@\n','',body,flags=re.DOTALL);
|
227 |
2 |
sinclairrf |
for subpair in (
|
228 |
6 |
sinclairrf |
( r'@RTR_SIGNAL@', self.RTR if hasattr(self,'RTR') else self.RTRn if hasattr(self,'RTRn') else '', ),
|
229 |
9 |
sinclairrf |
( r'@RTRN_INVERT@', '!' if hasattr(self,'RTR') else '', ),
|
230 |
|
|
( r'\bL__', 'L__@NAME@__', ),
|
231 |
|
|
( r'\bgen__', 'gen__@NAME@__', ),
|
232 |
|
|
( r'\bs__', 's__@NAME@__', ),
|
233 |
|
|
( r'@INPORT@', self.insignal, ),
|
234 |
|
|
( r'@BAUDMETHOD@', str(self.baudmethod), ),
|
235 |
|
|
( r'@SYNC@', str(self.sync), ),
|
236 |
|
|
( r'@DEGLITCH@', str(self.deglitch), ),
|
237 |
|
|
( r'@INFIFO@', str(self.inFIFO), ),
|
238 |
|
|
( r'@NSTOP@', str(self.nStop), ),
|
239 |
|
|
( r'@NAME@', self.namestring, ),
|
240 |
|
|
( r'@RTR_FIFO_COMPARE@', str(CeilLog2(self.rtr_buffer)), ),
|
241 |
6 |
sinclairrf |
):
|
242 |
|
|
if re.search(subpair[0],body):
|
243 |
|
|
body = re.sub(subpair[0],subpair[1],body);
|
244 |
2 |
sinclairrf |
body = self.GenVerilogFinal(config,body);
|
245 |
|
|
fp.write(body);
|