1 |
2 |
sinclairrf |
<html>
|
2 |
|
|
<title>
|
3 |
|
|
SSBCC -- PERIPHERAL
|
4 |
|
|
</title>
|
5 |
|
|
<body>
|
6 |
|
|
<tt>Copyright 2012, Sinclair, R.F., Inc.</tt><br/>
|
7 |
|
|
<h1>Table of Contents</h1>
|
8 |
|
|
<a href="#introduction">Introduction</a><br/>
|
9 |
|
|
<a href="#command">Command</a><br/>
|
10 |
|
|
<a href="#cores">9x8 Cores</a><br/>
|
11 |
|
|
<a href="#new">Creating new Peripherals</a><br/>
|
12 |
|
|
<a href="#recommendations">Reccomendations</a><br/>
|
13 |
|
|
<h1><a name="introduction">Introduction</a></h1>
|
14 |
|
|
Within the processor configuration command, the PERIPHERAL configuration is used
|
15 |
|
|
to incorporate peripherals such as UARTs, TBD into the micro controller
|
16 |
|
|
core.<br/><br/>
|
17 |
|
|
This document describes the general format of the peripheral configuration
|
18 |
|
|
command, lists peripherals for the 9x8 core, and documents how to add
|
19 |
|
|
additional peripherals to the computer compiler.<br/><br/>
|
20 |
|
|
<h1><a name="command">Command</a></h1>
|
21 |
|
|
TODO
|
22 |
|
|
<h1><a name="cores">9x8 Cores</a></h1>
|
23 |
|
|
TODO
|
24 |
|
|
<h1><a name="new">Creating new Peripherals</a></h1>
|
25 |
|
|
New peripherals are created using a Python class with the following member
|
26 |
|
|
functions:
|
27 |
|
|
<h2>__init__(self,config,param_list):</h2>
|
28 |
|
|
Where:<br/>
|
29 |
|
|
<ul>
|
30 |
|
|
<li><tt>config</tt> is the computer compiler configuration state when
|
31 |
|
|
the peripheral configuration command is encountered.<br/><br/></li>
|
32 |
|
|
<li><tt>param_list</tt> is a list of the space separated parameters on
|
33 |
|
|
the peripheral
|
34 |
|
|
configuration command following the name of the peripheral. This list
|
35 |
|
|
is used to provide mandatory and optional parameters to the
|
36 |
|
|
core. For example, the <tt>UART_Tx</tt> peripheral requires
|
37 |
|
|
information to generate the desired baud rate and allows an optional
|
38 |
|
|
name to facilitate distinguishing between multiple instances of the
|
39 |
|
|
same peripheral.<br/><br/>
|
40 |
|
|
For example, the parameters in the peripheral configuration
|
41 |
|
|
command<br/><br/>
|
42 |
|
|
<tt> PERIPHERAL name param1 \<br/>
|
43 |
|
|
param2=options \<br/>
|
44 |
|
|
param3="a string" \<br/>
|
45 |
|
|
param4=value</tt><br/><br/>
|
46 |
|
|
is converted to the space delimited string<br/><br/>
|
47 |
|
|
<tt> param1 param2=option param3="a string" param4=value</tt><br/><br/>
|
48 |
|
|
which is then provided to the <tt>__init__</tt> function as a
|
49 |
|
|
<tt>list()</tt> with the following four tuples:<br/><br/>
|
50 |
|
|
<tt> ('param1',)<br/>
|
51 |
|
|
('param2','option',)<br/>
|
52 |
|
|
('param3','"a string"',)<br/>
|
53 |
|
|
('param4','value',)</tt><br/><br/>
|
54 |
|
|
These tuples can then be parsed within the <tt>__init__</tt> function to
|
55 |
|
|
intialize the object.<br/>
|
56 |
|
|
</li>
|
57 |
|
|
</ul>
|
58 |
|
|
This function should store instantiation specific information in
|
59 |
|
|
<tt>self</tt>.<br/><br/>
|
60 |
|
|
Inputs from the FPGA fabric to the micro controller module are added by
|
61 |
|
|
appending a tuple describing the input. The tuple consists of the
|
62 |
|
|
following:<br/>
|
63 |
|
|
<ol>
|
64 |
|
|
<li>signal name</li>
|
65 |
|
|
<li>signal width</li>
|
66 |
|
|
<li>signal type: the string <tt>'input'</tt><br/></li>
|
67 |
|
|
</ol>
|
68 |
|
|
For example, to add an 8-bit input named "<tt>i_new_input</tt>", use the
|
69 |
|
|
following statement:<br/><br/>
|
70 |
|
|
<tt> config['ios'].append(('i_new_input',8,'input',));</tt><br/><br/>
|
71 |
|
|
Outputs from the micro controller to the FPGA fabric are added using the
|
72 |
|
|
signal type <tt>'output'</tt>. For example, to add an 8-bit output
|
73 |
|
|
named "<tt>o_new_output</tt>", use the following statement:<br/><br/>
|
74 |
|
|
<tt> config['ios'].append(('o_new_output',8,'output',));</tt><br/><br/>
|
75 |
|
|
Similarly, to add a 16-bit tri-state input/output signal, use the
|
76 |
|
|
followiing statement:<br/><br/>
|
77 |
|
|
<tt> config['ios'].append(('io_new_signal',16,'inout',));</tt><br/><br/>
|
78 |
|
|
To add a signal or a composite signal output from the micro controller
|
79 |
|
|
core to the peripheral two actions are required. These can be done in
|
80 |
|
|
either order, but it may make more sense to maintainers or subsequent
|
81 |
|
|
users to do them in the following order:<br/><br/>
|
82 |
|
|
<ol>
|
83 |
|
|
<li>Add the output port to the micro controller core:<br/><br/>
|
84 |
|
|
This consists of adding a tuple to <tt>config['outports']</tt>. The
|
85 |
|
|
first element of this tuple is the name of the outport. The
|
86 |
|
|
subsequent elements of this tuple are tuples describing the
|
87 |
|
|
signal(s) associated with the outport. These tuples have the
|
88 |
|
|
following ordered format:<br/><br/>
|
89 |
|
|
<ol>
|
90 |
|
|
<li>signal name</li>
|
91 |
|
|
<li>signal width</li>
|
92 |
|
|
<li>signal type: <tt>'data'</tt> or <tt>'strobe'</tt><br/>
|
93 |
|
|
Note: Signal type <tt>'data'</tt> is used to relay single or
|
94 |
|
|
multiple bit data from the micro controller core to the
|
95 |
|
|
peripheral. Signal type <tt>'strobe'</tt> generates a single
|
96 |
|
|
bit strobe during the clock cycle immediately following the
|
97 |
|
|
<tt>outport</tt> instruction.<br/><br/>
|
98 |
|
|
</li>
|
99 |
|
|
</ol>
|
100 |
|
|
<li>Add these same signals to <tt>config['signals']</tt>, one at a
|
101 |
|
|
time using tuples with the following ordered format:<br/><br/>
|
102 |
|
|
<ol>
|
103 |
|
|
<li>signal name</li>
|
104 |
|
|
<li>signal width<br/></li>
|
105 |
|
|
</ol>
|
106 |
|
|
</li>
|
107 |
|
|
</ol>
|
108 |
|
|
For example, to add two outputs from the micro controller core to a
|
109 |
|
|
multiplier, use the following:<br/><br/>
|
110 |
|
|
<tt> config['outports'].append(('O_MULT_A',<br/>
|
111 |
|
|
('s_mult_a',8,'data'),<br/>
|
112 |
|
|
));<br/>
|
113 |
|
|
config['outports'].append(('O_MULT_B',<br/>
|
114 |
|
|
('s_mult_b',8,'data'),<br/>
|
115 |
|
|
));<br/>
|
116 |
|
|
config['signals'].append(('s_mult_a',8,));<br/>
|
117 |
|
|
config['signals'].append(('s_mult_b',8,));</tt><br/><br/>
|
118 |
|
|
As a second example, to add an output from the micro controller core
|
119 |
|
|
to the input side of an 8-bit FIFO, use the following. Here, the signal
|
120 |
|
|
<tt>s_fifo_data</tt> will be the data to write to the FIFO and
|
121 |
|
|
<tt>s_fifo_wr</tt> will be a strobe that is set high during the clock
|
122 |
|
|
cycle immediately following the <tt>outport</tt> instruction.<br/><br/>
|
123 |
|
|
<tt> config['outports'].append(('O_FIFO',<br/>
|
124 |
|
|
('s_fifo_data',8,'data'),<br/>
|
125 |
|
|
('s_fifo_wr',1,'strobe'),<br/>
|
126 |
|
|
));<br/>
|
127 |
|
|
config['signals'].append(('s_fifo_data',8,));<br/>
|
128 |
|
|
config['signals'].append(('s_fifo_wr',1,));</tt><br/><br/>
|
129 |
|
|
Adding a signal or a composite signal from the peripheral to the micro
|
130 |
|
|
controller core requires two similar actions:<br/>
|
131 |
|
|
<ol>
|
132 |
|
|
<li>Add the input port to the micro controller core:<br/><br/>
|
133 |
|
|
This consists of adding a tuple to <tt>config['inports']</tt>. The
|
134 |
|
|
first element of this tuple is the name of the inport. The
|
135 |
|
|
subsequent elements of this tuple are tuples describing the
|
136 |
|
|
signal(s) associated with the inport. These tuples have the
|
137 |
|
|
following ordered format:<br/><br/>
|
138 |
|
|
<ol>
|
139 |
|
|
<li>signal name</li>
|
140 |
|
|
<li>signal width</li>
|
141 |
|
|
<li>signal type: <tt>'data'</tt>, <tt>'set-reset'</tt>, or
|
142 |
|
|
<tt>'strobe'</tt>
|
143 |
|
|
Note: Signal type <tt>'data'</tt> is used to relay single or
|
144 |
|
|
multiple bit data from the peripheral to the micro controller
|
145 |
|
|
core. Signal type <tt>'set-reset'</tt> latches the associated
|
146 |
|
|
input bit until the signal is read, at which time it is cleared.
|
147 |
|
|
Signal type <tt>'strobe'</tt> generates a single bit strobe
|
148 |
|
|
during the clock cycle immediately following the
|
149 |
|
|
<tt>inport</tt> instruction.<br/>
|
150 |
|
|
Note: The <tt>'set-reset'</tt> signal type is provided as a
|
151 |
|
|
signal type for the <tt>INPORT</tt> command and may not be as
|
152 |
|
|
useful for peripherals since the peripheral can include the
|
153 |
|
|
associated logic required for the latch.<br/><br/>
|
154 |
|
|
</li>
|
155 |
|
|
</ol>
|
156 |
|
|
<li>Add these same signals to <tt>config['signals']</tt>, one at a
|
157 |
|
|
time using tuples with the following ordered format:<br/><br/>
|
158 |
|
|
<ol>
|
159 |
|
|
<li>signal name</li>
|
160 |
|
|
<li>signal width<br/></li>
|
161 |
|
|
</ol>
|
162 |
|
|
</li>
|
163 |
|
|
</ol>
|
164 |
|
|
For example, to add two inport ports for the MSB and LSB from an 8 by 8 multipler, use the
|
165 |
|
|
following:<br/><br/>
|
166 |
|
|
<tt> config['inports'].append(('I_MULT_MSB',<br/>
|
167 |
|
|
('s_mult_msb',8,'data'),<br/>
|
168 |
|
|
));<br/>
|
169 |
|
|
config['inports'].append(('I_MULT_LSB',<br/>
|
170 |
|
|
('s_mult_lsb',8,'data'),<br/>
|
171 |
|
|
));<br/>
|
172 |
|
|
config['signals'].append(('s_mult_msb',8,));<br/>
|
173 |
|
|
config['signals'].append(('s_mult_lsb',8,));</tt><br/><br/>
|
174 |
|
|
As a second example, to add an input port from a FIFO in the
|
175 |
|
|
peripheral to the micro controlller core, use the following:<br/><br/>
|
176 |
|
|
<tt> config['inports'].append(('I_FIFO',<br/>
|
177 |
|
|
('s_fifo_data',8,'data'),<br/>
|
178 |
|
|
('s_fifo_ack',1,'strobe'),<br/>
|
179 |
|
|
));<br/>
|
180 |
|
|
config['signals'].append(('s_fifo_data',8,));<br/>
|
181 |
|
|
config['signals'].append(('s_fifo_ack',1,));</tt><br/><br/>
|
182 |
|
|
As a third example, to add an input port for two status bits from a
|
183 |
|
|
FIFO in the peripheral to the micro controlller core, use the
|
184 |
|
|
following:<br/><br/>
|
185 |
|
|
<tt> config['inports'].append(('I_FIFO_STATUS',<br/>
|
186 |
|
|
('s_fifo_full',1,'data'),<br/>
|
187 |
|
|
('s_fifo_empty',1,'data'),<br/>
|
188 |
|
|
));<br/>
|
189 |
|
|
config['signals'].append(('s_fifo_full',1,));<br/>
|
190 |
|
|
config['signals'].append(('s_fifo_empty',1,));</tt><br/><br/>
|
191 |
|
|
<h2>GenAssembly(self,config):</h2>
|
192 |
|
|
This is an optional function to generate an assembly file associated with
|
193 |
|
|
the peripheral.<br/>
|
194 |
|
|
TODO
|
195 |
|
|
<h2>GenHDL(self,fp,config):</h2>
|
196 |
|
|
This function examines <tt>config['hdl']</tt> to determine the HDL language
|
197 |
|
|
for generating the FPGA logic for the peripheral. The logic is written to
|
198 |
|
|
the file handle <tt>fp</tt>.<br/><br/>
|
199 |
|
|
Rather than capture all HDL languages in this function, the following type
|
200 |
|
|
of structure is recommended:<br/><br/>
|
201 |
|
|
<tt> GenHDL(self,fp,config):<br/>
|
202 |
|
|
if config['hdl'] == 'Verilog':<br/>
|
203 |
|
|
self.GenVerilog(fp,config);<br/>
|
204 |
|
|
elif config['hdl'] == 'VHDL':<br/>
|
205 |
|
|
self.GenVHDL(fp,config);<br/>
|
206 |
|
|
else:<br/>
|
207 |
|
|
raise Exception('HDL "%s" not implemented' % config['hdl']);</tt><br/><br/>
|
208 |
|
|
For example, to generate the logic for an unsigned 8 by 8 multiplier using
|
209 |
|
|
the previous inport, outport, and signal assignments, the Verilog code
|
210 |
|
|
could be generated using:<br/><br/>
|
211 |
|
|
<tt> GenVerilog(self,fp,config):<br/>
|
212 |
|
|
fp.write('initial s_mult_msb = 8\'d0;\n');<br/>
|
213 |
|
|
fp.write('initial s_mult_lsb = 8\'d0;\n');<br/>
|
214 |
|
|
fp.write('always @ (posedge i_clk)\n');<br/>
|
215 |
|
|
fp.write(' if (i_rst) begin\n');<br/>
|
216 |
|
|
fp.write(' s_mult_msb <= 8\'d0;\n');<br/>
|
217 |
|
|
fp.write(' s_mult_lsb <= 8\'d0;\n');<br/>
|
218 |
|
|
fp.write(' end else\n');<br/>
|
219 |
|
|
fp.write(' { s_mult_msb, s_mult_lsb } <= $unsigned(s_mult_a) * $unsigned(s_mult_b);\n');</tt><br/><br/>
|
220 |
|
|
Note: The results of this multiplication are available two clock cycles
|
221 |
|
|
after the <tt>outport</tt> instruction setting the <tt>s_mult_a</tt> or
|
222 |
|
|
<tt>s_mult_b</tt> value. This isn't a problem with the processor as the
|
223 |
|
|
<tt>outport</tt> is probably followed by a <tt>drop</tt>
|
224 |
|
|
instruction and the <tt>inport</tt> instruction to read either part of the
|
225 |
|
|
multiplication has to be preceded by an instruction pushing the port
|
226 |
|
|
number onto the data stack.<br/><br/>
|
227 |
|
|
Note: While Python allows the entire logic block to be written using a
|
228 |
|
|
single <tt>fp.write("""initial s_...""");</tt> statement, breaking
|
229 |
|
|
out the individual statements allows computed signal names to be included
|
230 |
|
|
more cleanly and also accomodates conditional inclusion of code.<br/><br/>
|
231 |
|
|
<h1><a name="recommendations">Recommendations</a></h1>
|
232 |
|
|
<h2>help</h2>
|
233 |
|
|
The PERIPHERAL configuration command will print the documentation string for
|
234 |
|
|
peripherals if the parameter "<tt>help</tt>" is listed. For example, to get
|
235 |
|
|
help for the <tt>monitor_stack</tt> peripheral, insert the peripheral
|
236 |
|
|
using:<br/><br/>
|
237 |
|
|
<tt> PERIPHERAL monitor_stack help</tt><br/><br/>
|
238 |
|
|
This will display the documentation string for the <tt>monitor_stack</tt>
|
239 |
|
|
peripheral and then terminate the build.<br/><br/>
|
240 |
|
|
If there is no documentation string for the peripheral, the
|
241 |
|
|
following message is printed and the build is terminated:<br/><br/>
|
242 |
|
|
<tt> No help for periperal XXX is provided</tt><br/><br/>
|
243 |
|
|
Note: The help message displays the name of the peripheral and the source
|
244 |
|
|
file.<br/><br/>
|
245 |
|
|
</body>
|
246 |
|
|
</html>
|