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

Subversion Repositories cpu_lecture

[/] [cpu_lecture/] [trunk/] [html/] [08_IO.html] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jsauermann
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
2
"http://www.w3.org/TR/html4/strict.dtd">
3
<HTML>
4
<HEAD>
5
<TITLE>html/IO</TITLE>
6
<META NAME="generator" CONTENT="HTML::TextToHTML v2.46">
7
<LINK REL="stylesheet" TYPE="text/css" HREF="lecture.css">
8
</HEAD>
9
<BODY>
10
<P><table class="ttop"><th class="tpre"><a href="07_Opcode_Decoder.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="09_Toolchain_Setup.html">Next Lesson</a></th></table>
11
<hr>
12
 
13
<H1><A NAME="section_1">8 INPUT/OUTPUT</A></H1>
14
 
15
<P>The last piece in the design is the input/output unit. Strictly speaking
16
it does not belong to the CPU as such, but we discuss it briefly to
17
see how it connects to the CPU.
18
 
19
<H2><A NAME="section_1_1">8.1 Interface to the CPU</A></H2>
20
 
21
<P>As we have already seen in the top level design, the I/O unit uses the same
22
clock as the CPU (which greatly simplifies its design).
23
 
24
<P>The interface towards the CPU consist of the following signals:
25
 
26
<TABLE>
27
<TR><TD>ADR_IO</TD><TD>The number of an individual I/O register
28
</TD></TR><TR><TD>DIN</TD><TD>Data to an I/O register (I/O write)
29
</TD></TR><TR><TD>RD_IO</TD><TD>Read Strobe
30
</TD></TR><TR><TD>WR_IO</TD><TD>Write Strobe
31
</TD></TR><TR><TD>DOUT</TD><TD>Data from an I/O register (I/O read cycle.
32
</TD></TR>
33
</TABLE>
34
<P>These signals are well known from other I/O devices like UARTs,
35
Ethernet Controllers, and the like.
36
 
37
<P>The CPU supports two kinds of accesses to I/O registers: I/O reads
38
(with the IN or LDS instructions, but also for the skip instructions
39
SBIC and SBIS), and I/O writes (with the OUT or STS instructions,
40
but also with the bit instructions CBI and SBI).
41
 
42
<P>The skip instructions SBIC and SBIS execute in 2 cycles; in the first
43
cycle an I/O read is performed while the skip (or not) decision is made
44
in the second cycle. The reason for this is that the combinational delay
45
for a single cycle would have been too long.
46
 
47
<P>From the I/O unit's perspective, I/O reads and writes are performed
48
in a single cycle (even if the CPU needs another cycle to complete an
49
instruction.
50
 
51
<P>The I/O unit generates an interrupt vector on its <STRONG>INTVEC</STRONG> output.
52
The upper bit of the <STRONG>INTVEC</STRONG> output is set if an interrupt is pending.
53
 
54
<H2><A NAME="section_1_2">8.2 CLR Signal</A></H2>
55
 
56
<P>Some I/O components need a <STRONG>CLR</STRONG> signal to bring them into a defined state.
57
The <STRONG>CLR</STRONG> signal of the CPU is used for this purpose.
58
 
59
<H2><A NAME="section_1_3">8.3 Connection the FPGA Pins</A></H2>
60
 
61
<P>The remaining signals into and out of the I/O unit are more or less
62
directly connected to FPGA pins.
63
 
64
<P>The <STRONG>RX</STRONG> input comes from an RS232 receiver/driver chip and is the serial
65
input for an UART (active low). The TX output (also active low) is the
66
serial output from that UART and goes back to the RS232 receiver/driver chip:
67
 
68
<P><br>
69
 
70
<pre class="vhdl">
71
 
72
 89                     I_RX       => I_RX,
73
 90
74
 91                     Q_TX       => Q_TX,
75
<pre class="filename">
76
src/io.vhd
77
</pre></pre>
78
<P>
79
 
80
<P>The <STRONG>SWITCH</STRONG> input comes from a DIP switch on the board.
81
The values of the switch can be read from I/O register <STRONG>PINB</STRONG> (0x36).
82
 
83
<P><br>
84
 
85
<pre class="vhdl">
86
 
87
132                 when X"36"  => Q_DOUT <= I_SWITCH;  -- PINB
88
<pre class="filename">
89
src/io.vhd
90
</pre></pre>
91
<P>
92
 
93
<P><br>
94
 
95
<P>The 7_<STRONG>SEGMENT</STRONG> output drives the 7 segments of a 7-segment display.
96
This output can be set from software by writing to the <STRONG>PORTB</STRONG> (0x38)
97
I/O register. The segments can also be driven by a debug function which
98
shows the current <STRONG>PC</STRONG> and the current opcode of the CPU.
99
 
100
<P><br>
101
 
102
<pre class="vhdl">
103
 
104
147                         when X"38"  => Q_7_SEGMENT <= I_DIN(6 downto 0);    -- PORTB
105
<pre class="filename">
106
src/io.vhd
107
</pre></pre>
108
<P>
109
 
110
<P><br>
111
 
112
<P>The choice between the debug display and the software controlled
113
display function is made by the DIP switch setting:
114
 
115
<P><br>
116
 
117
<pre class="vhdl">
118
 
119
183
120
<pre class="filename">
121
src/avr_fpga.vhd
122
</pre></pre>
123
<P>
124
 
125
<P><br>
126
 
127
<H2><A NAME="section_1_4">8.4 I/O Read</A></H2>
128
 
129
<P>I/O read cycles are indicated by the <STRONG>RD_IO</STRONG> signal. If <STRONG>RD_IO</STRONG> is applied,
130
then the address of the I/O register to be read is provided on the <STRONG>ADR_IO</STRONG>
131
input and the value of that register is expected on <STRONG>DOUT</STRONG> at the next
132
<STRONG>CLK</STRONG> edge.
133
 
134
<P>This is accomplished by the I/O read process:
135
 
136
<P><br>
137
 
138
<pre class="vhdl">
139
 
140
 98         iord: process(I_ADR_IO, I_SWITCH,
141
 99                       U_RX_DATA, U_RX_READY, L_RX_INT_ENABLED,
142
100                       U_TX_BUSY, L_TX_INT_ENABLED)
143
101         begin
144
102             -- addresses for mega8 device (use iom8.h or #define __AVR_ATmega8__).
145
103             --
146
104             case I_ADR_IO is
147
105                 when X"2A"  => Q_DOUT <=             -- UCSRB:
148
106                                    L_RX_INT_ENABLED  -- Rx complete int enabled.
149
107                                  & L_TX_INT_ENABLED  -- Tx complete int enabled.
150
108                                  & L_TX_INT_ENABLED  -- Tx empty int enabled.
151
109                                  & '1'               -- Rx enabled
152
110                                  & '1'               -- Tx enabled
153
111                                  & '0'               -- 8 bits/char
154
112                                  & '0'               -- Rx bit 8
155
113                                  & '0';              -- Tx bit 8
156
114                 when X"2B"  => Q_DOUT <=             -- UCSRA:
157
115                                    U_RX_READY       -- Rx complete
158
116                                  & not U_TX_BUSY    -- Tx complete
159
117                                  & not U_TX_BUSY    -- Tx ready
160
118                                  & '0'              -- frame error
161
119                                  & '0'              -- data overrun
162
120                                  & '0'              -- parity error
163
121                                  & '0'              -- double dpeed
164
122                                  & '0';             -- multiproc mode
165
123                 when X"2C"  => Q_DOUT <= U_RX_DATA; -- UDR
166
124                 when X"40"  => Q_DOUT <=            -- UCSRC
167
125                                    '1'              -- URSEL
168
126                                  & '0'              -- asynchronous
169
127                                  & "00"             -- no parity
170
128                                  & '1'              -- two stop bits
171
129                                  & "11"             -- 8 bits/char
172
130                                  & '0';             -- rising clock edge
173
131
174
132                 when X"36"  => Q_DOUT <= I_SWITCH;  -- PINB
175
133                 when others => Q_DOUT <= X"AA";
176
134             end case;
177
135         end process;
178
<pre class="filename">
179
src/io.vhd
180
</pre></pre>
181
<P>
182
 
183
<P><br>
184
 
185
<P>I/O registers that are not implemented (i.e almost all) set <STRONG>DOUT</STRONG>
186
to 0xAA as a debugging aid.
187
 
188
<P>The outputs of sub-components (like the UART) are selected in the I/O read
189
process.
190
 
191
<H2><A NAME="section_1_5">8.5 I/O Write</A></H2>
192
 
193
<P>I/O write cycles are indicated by the <STRONG>WR_IO</STRONG> signal. If <STRONG>WR_IO</STRONG> is applied,
194
then the address of the I/O register to be written is provided on the <STRONG>ADR_IO</STRONG>
195
input and the value to be written is supplied on the DIN input:
196
 
197
<P><br>
198
 
199
<pre class="vhdl">
200
 
201
139         iowr: process(I_CLK)
202
140         begin
203
141             if (rising_edge(I_CLK)) then
204
142                 if (I_CLR = '1') then
205
143                     L_RX_INT_ENABLED  <= '0';
206
144                     L_TX_INT_ENABLED  <= '0';
207
145                 elsif (I_WE_IO = '1') then
208
146                     case I_ADR_IO is
209
147                         when X"38"  => Q_7_SEGMENT <= I_DIN(6 downto 0);    -- PORTB
210
148                                        L_LEDS <= not L_LEDS;
211
149                         when X"40"  =>  -- handled by uart
212
150                         when X"41"  =>  -- handled by uart
213
151                         when X"43"  => L_RX_INT_ENABLED <= I_DIN(0);
214
152                                        L_TX_INT_ENABLED <= I_DIN(1);
215
153                         when others =>
216
154                     end case;
217
155                 end if;
218
156             end if;
219
157         end process;
220
<pre class="filename">
221
src/io.vhd
222
</pre></pre>
223
<P>
224
 
225
<P><br>
226
 
227
<P>In the I/O read process the outputs of sub-component were multiplexed
228
into the final output <STRONG>DOUT</STRONG> and hence their register numbers (like 0x2C
229
for the <STRONG>UDR</STRONG> read register) were visible, In the I/O write process, however,
230
the inputs of sub-components (again like 0x2C for the <STRONG>UDR</STRONG> write register)
231
are not visible in the write process and decoding of the <STRONG>WR</STRONG> (and <STRONG>RD</STRONG> where
232
needed)  strobes for sub components is done outside of these processes:
233
 
234
<P><br>
235
 
236
<pre class="vhdl">
237
 
238
182         L_WE_UART <= I_WE_IO when (I_ADR_IO = X"2C") else '0'; -- write UART UDR
239
183         L_RD_UART <= I_RD_IO when (I_ADR_IO = X"2C") else '0'; -- read  UART UDR
240
184
241
<pre class="filename">
242
src/io.vhd
243
</pre></pre>
244
<P>
245
 
246
<P><br>
247
 
248
<H2><A NAME="section_1_6">8.6 Interrupts</A></H2>
249
 
250
<P>Some I/O components raise interrupts, which are coordinated in the
251
I/O interrupt process:
252
 
253
<P><br>
254
 
255
<pre class="vhdl">
256
 
257
161         ioint: process(I_CLK)
258
162         begin
259
163             if (rising_edge(I_CLK)) then
260
164                 if (I_CLR = '1') then
261
165                     L_INTVEC <= "000000";
262
166                 else
263
167                     if (L_RX_INT_ENABLED and U_RX_READY) = '1' then
264
168                         if (L_INTVEC(5) = '0') then     -- no interrupt pending
265
169                             L_INTVEC <= "101011";       -- _VECTOR(11)
266
170                         end if;
267
171                     elsif (L_TX_INT_ENABLED and not U_TX_BUSY) = '1' then
268
172                         if (L_INTVEC(5) = '0') then     -- no interrupt pending
269
173                             L_INTVEC <= "101100";       -- _VECTOR(12)
270
174                         end if;
271
175                     else                                -- no interrupt
272
176                         L_INTVEC <= "000000";
273
177                     end if;
274
178                 end if;
275
179             end if;
276
180         end process;
277
<pre class="filename">
278
src/io.vhd
279
</pre></pre>
280
<P>
281
 
282
<P><br>
283
 
284
<H2><A NAME="section_1_7">8.7 The UART</A></H2>
285
 
286
<P>The UART is an important facility for debugging programs that are more
287
complex than out <STRONG>hello.c</STRONG>. We use a fixed baud rate of 38400 Baud
288
and a fixed data format of 8 data bits and 2 stop bits.
289
Therefore the corresponding bits in the UART control registers of the
290
original AVR CPU are not implemented. The fixed values are properly
291
reported, however.
292
 
293
<P>The UART consists of 3 independent sub-components: a baud rate generator,
294
a receiver, and a transmitter.
295
 
296
<H3><A NAME="section_1_7_1">8.7.1 The UART Baud Rate Generator</A></H3>
297
 
298
<P>The baud rate generator is clocked with a frequency of <STRONG>clock_freq</STRONG>
299
and is supposed to generate a x1 clock of <STRONG>baud_rate</STRONG> for the transmitter
300
and a x16 clock of 16*<STRONG>baud_rate</STRONG> for the receiver.
301
 
302
<P>The x16 clock is generated like this:
303
 
304
<P><br>
305
 
306
<pre class="vhdl">
307
 
308
 54
309
 55         baud16: process(I_CLK)
310
 56         begin
311
 57             if (rising_edge(I_CLK)) then
312
 58                 if (I_CLR = '1') then
313
 59                     L_COUNTER <= X"00000000";
314
 60                 elsif (L_COUNTER >= LIMIT) then
315
 61                     L_COUNTER <= L_COUNTER - LIMIT;
316
 62                 else
317
 63                     L_COUNTER <= L_COUNTER + BAUD_16;
318
 64                 end if;
319
 65             end if;
320
 66         end process;
321
 67
322
 68         baud1: process(I_CLK)
323
<pre class="filename">
324
src/baudgen.vhd
325
</pre></pre>
326
<P>
327
 
328
<P><br>
329
 
330
<P>We have done a little trick here. Most baud rate generators divide the
331
input clock by a fixed integer number (like the one shown below for the
332
x1 clock). That is fine if the input clock is a multiple of the output
333
clock. More often than not is the CPU clock not a multiple of the the
334
baud rate. Therefore, if an integer divider is used (like in the original
335
AVR CPU, where the integer divisor was written into the UBRR I/O register)
336
then the error in the baud rate cumulates over all bits transmitted. This can
337
cause transmission errors when many characters are sent back to back.
338
An integer divider would have set <STRONG>L_COUNTER</STRONG> to 0 after reaching <STRONG>LIMIT</STRONG>,
339
which would have cause an absolute error of <STRONG>COUNTER</STRONG> - <STRONG>LIMIT</STRONG>. What we
340
do instead is to subtract <STRONG>LIMIT</STRONG>, which does no discard the error but
341
makes the next cycle a little shorter instead.
342
 
343
<P>Instead of using a fixed baud rate interval of N times the clock interval
344
(as fixed integer dividers would), we have used a variable baud rate interval;
345
the length of the interval varies slightly over time, but the total error
346
remains bounded. The error does not cumulate as for fixed integer
347
dividers.
348
 
349
<P>If you want to make the baud rate programmable, then you can replace the
350
generic <STRONG>baud_rate</STRONG> by a signal (and the trick would still work).
351
 
352
<P>The x1 clock is generated by dividing the x16 clock by 16:
353
 
354
<P><br>
355
 
356
<pre class="vhdl">
357
 
358
 70             if (rising_edge(I_CLK)) then
359
 71                 if (I_CLR = '1') then
360
 72                     L_CNT_16 <= "0000";
361
 73                 elsif (L_CE_16 = '1') then
362
 74                     L_CNT_16 <= L_CNT_16 + "0001";
363
 75                 end if;
364
 76             end if;
365
 77         end process;
366
 78
367
 79         L_CE_16 <= '1' when (L_COUNTER >= LIMIT) else '0';
368
 80         Q_CE_16 <= L_CE_16;
369
 81         Q_CE_1 <= L_CE_16 when L_CNT_16 = "1111" else '0';
370
<pre class="filename">
371
src/baudgen.vhd
372
</pre></pre>
373
<P>
374
 
375
<P><br>
376
 
377
<H3><A NAME="section_1_7_2">8.7.2 The UART Transmitter</A></H3>
378
 
379
<P>The UART transmitter is a shift register that is loaded with
380
the character to be transmitted (prepended with a start bit):
381
 
382
<P><br>
383
 
384
<pre class="vhdl">
385
 
386
 67                     elsif (L_FLAG /= I_FLAG) then       -- new byte
387
 68                         Q_TX <= '0';                    -- start bit
388
 69                         L_BUF <= I_DATA;                -- data bits
389
 70                         L_TODO <= "1001";
390
 71                     end if;
391
<pre class="filename">
392
src/uart_tx.vhd
393
</pre></pre>
394
<P>
395
 
396
<P><br>
397
 
398
<P>The <STRONG>TODO</STRONG> signal holds the number of bits that remain to be shifted out.
399
The transmitter is clocked with the x1 baud rate:
400
 
401
<P><br>
402
 
403
<pre class="vhdl">
404
 
405
 59                 elsif (I_CE_1 = '1') then
406
 60                     if (L_TODO /= "0000") then          -- transmitting
407
 61                         Q_TX <= L_BUF(0);               -- next bit
408
 62                         L_BUF     <= '1' & L_BUF(7 downto 1);
409
 63                         if (L_TODO = "0001") then
410
 64                             L_FLAG <= I_FLAG;
411
 65                         end if;
412
 66                         L_TODO <= L_TODO - "0001";
413
 67                     elsif (L_FLAG /= I_FLAG) then       -- new byte
414
 68                         Q_TX <= '0';                    -- start bit
415
 69                         L_BUF <= I_DATA;                -- data bits
416
 70                         L_TODO <= "1001";
417
 71                     end if;
418
 72                 end if;
419
<pre class="filename">
420
src/uart_tx.vhd
421
</pre></pre>
422
<P>
423
 
424
<P><br>
425
 
426
<H3><A NAME="section_1_7_3">8.7.3 The UART Receiver</A></H3>
427
 
428
<P>The UART transmitter runs synchronously with the CPU clock; but the UART
429
receiver does not. We therefore clock the receiver input twice
430
in order to synchronize it with the CPU clock:
431
 
432
<P><br>
433
 
434
<pre class="vhdl">
435
 
436
 56         process(I_CLK)
437
 57         begin
438
 58             if (rising_edge(I_CLK)) then
439
 59                 if (I_CLR = '1') then
440
 60                     L_SERIN <= '1';
441
 61                     L_SER_HOT <= '1';
442
 62                 else
443
 63                     L_SERIN   <= I_RX;
444
 64                     L_SER_HOT <= L_SERIN;
445
 65                 end if;
446
 66             end if;
447
 67         end process;
448
<pre class="filename">
449
src/uart_rx.vhd
450
</pre></pre>
451
<P>
452
 
453
<P><br>
454
 
455
<P>The key signal in the UART receiver is <STRONG>POSITION</STRONG> which is the current
456
position within the received character in units if 1/16 bit time. When the
457
receiver is idle and a start bit is received, then <STRONG>POSITION</STRONG> is reset to
458
1:
459
 
460
<P><br>
461
 
462
<pre class="vhdl">
463
 
464
 86                     if (L_POSITION = X"00") then            -- uart idle
465
 87                         L_BUF  <= "1111111111";
466
 88                         if (L_SER_HOT = '0')  then          -- start bit received
467
 89                             L_POSITION <= X"01";
468
 90                         end if;
469
<pre class="filename">
470
src/uart_rx.vhd
471
</pre></pre>
472
<P>
473
 
474
<P><br>
475
 
476
<P>At every subsequent edge of the 16x baud rate, <STRONG>POSITION</STRONG> is incremented
477
and the receiver input (<STRONG>SER_HOT</STRONG>) input is checked at the middle of each
478
bit (i.e. when <STRONG>POSITION[3:0]</STRONG> = "0111").
479
If the start bit has disappeared at the middle of the bit, then this is
480
considered noise on the line rather than a valid start bit:
481
 
482
<P><br>
483
 
484
<pre class="vhdl">
485
 
486
 93                         if (L_POSITION(3 downto 0) = "0111") then       -- 1/2 bit
487
 94                             L_BUF <= L_SER_HOT & L_BUF(9 downto 1);     -- sample data
488
 95                             --
489
 96                             -- validate start bit
490
 97                             --
491
 98                             if (START_BIT and L_SER_HOT = '1') then     -- 1/2 start bit
492
 99                                 L_POSITION <= X"00";
493
100                             end if;
494
101
495
102                             if (STOP_BIT) then                          -- 1/2 stop bit
496
103                                 Q_DATA <= L_BUF(9 downto 2);
497
104                             end if;
498
<pre class="filename">
499
src/uart_rx.vhd
500
</pre></pre>
501
<P>
502
 
503
<P><br>
504
 
505
<P>Reception of a byte already finishes at 3/4 of the stop bit. This is to
506
allow for cumulated baud rate errors of 1/4 bit time (or about 2.5 %
507
baud rate error for 10 bit (1 start, 8 data, and 1 stop bit) transmissions).
508
The received data is stored in <STRONG>DATA</STRONG>:
509
 
510
<P><br>
511
 
512
<pre class="vhdl">
513
 
514
105                         elsif (STOP_POS) then                       -- 3/4 stop bit
515
106                             L_FLAG <= L_FLAG xor (L_BUF(9) and not L_BUF(0));
516
107                             L_POSITION <= X"00";
517
<pre class="filename">
518
src/uart_rx.vhd
519
</pre></pre>
520
<P>
521
 
522
<P><br>
523
 
524
<P>If a greater tolerance against baud rate errors is needed, then one can
525
decrease <STRONG>STOP_POS</STRONG> a little, but generally it would be safer to use 2
526
stop bits on the sender side.
527
 
528
<P>This finalizes the description of the FPGA. We will proceed with the
529
design flow in the next lesson.
530
 
531
<P><hr><BR>
532
<table class="ttop"><th class="tpre"><a href="07_Opcode_Decoder.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="09_Toolchain_Setup.html">Next Lesson</a></th></table>
533
</BODY>
534
</HTML>

powered by: WebSVN 2.1.0

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