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

Subversion Repositories cpu_lecture

[/] [cpu_lecture/] [trunk/] [html/] [06_Data_Path.html] - Blame information for rev 8

Go to most recent revision | 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/Data_Path</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="05_Opcode_Fetch.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="07_Opcode_Decoder.html">Next Lesson</a></th></table>
11
<hr>
12
 
13
<H1><A NAME="section_1">6 DATA PATH</A></H1>
14
 
15
<P>In this lesson we will describe the data path of the CPU. We discuss
16
the basic elements of the data path, but without reference to particular
17
instructions. The implementation of instructions will be discussed in the
18
next lesson. In this lesson we are more interested in the capabilities
19
of the data path.
20
 
21
<P>The data path consists of 3 major components: a register file,
22
an ALU (arithmetic/logic unit), and the data memory:
23
 
24
<P><br>
25
 
26
<P><img src="data_path_1.png">
27
 
28
<P><br>
29
 
30
<H2><A NAME="section_1_1">6.1 Register File</A></H2>
31
 
32
<P>The AVR CPU has 32 general purpose 8-bit registers. Most opcodes use
33
individual 8-bit registers, but some that use a pair of registers. The
34
first register of a register pair is always an even register, while the
35
other register of a pair is the next higher odd register. Instead of using
36
32 8-bit registers, we use 16 16-bit register pairs. Each register pair
37
consists of two 8-bit registers.
38
 
39
<H3><A NAME="section_1_1_1">6.1.1 Register Pair</A></H3>
40
 
41
<P>A single register pair is defined as:
42
 
43
<P><br>
44
 
45
<pre class="vhdl">
46
 
47
 32     entity reg_16 is
48
 33         port (  I_CLK       : in  std_logic;
49
 34
50
 35                 I_D         : in  std_logic_vector (15 downto 0);
51
 36                 I_WE        : in  std_logic_vector ( 1 downto 0);
52
 37
53
 38                 Q           : out std_logic_vector (15 downto 0));
54
 39     end reg_16;
55
<pre class="filename">
56
reg_16.vhd
57
</pre></pre>
58
<P>
59
 
60
<P><br>
61
 
62
<P>The <STRONG>Q</STRONG> output provides the current value of the register pair. There is
63
no need for a read strobe, because (unlike I/O devices) reading the current
64
value of a register pair has no side effects.
65
 
66
<P>The register pair can be written by setting one or both bits of the <STRONG>WE</STRONG>
67
input. If both bits are set then the all 16 bits of <STRONG>D</STRONG> are written; the
68
low byte to the even register and the higher byte to the odd register of the
69
pair. If only one bit is set then the register corresponding then the bit set
70
in <STRONG>WE</STRONG> defines the register to be written (even bit = even register,
71
odd bit = odd register) and the value to be written is in the lower byte
72
of <STRONG>DIN</STRONG>:
73
 
74
<P><br>
75
 
76
<pre class="vhdl">
77
 
78
 46         process(I_CLK)
79
 47         begin
80
 48             if (rising_edge(I_CLK)) then
81
 49                 if (I_WE(1) = '1') then
82
 50                     L(15 downto 8) <= I_D(15 downto 8);
83
 51                 end if;
84
 52                 if (I_WE(0) = '1') then
85
 53                     L( 7 downto 0) <= I_D( 7 downto 0);
86
 54                 end if;
87
 55             end if;
88
 56         end process;
89
<pre class="filename">
90
src/reg_16.vhd
91
</pre></pre>
92
<P>
93
 
94
<P><br>
95
 
96
<H3><A NAME="section_1_1_2">6.1.2 The Status Register</A></H3>
97
 
98
<P>The status register is an 8-bit register. This register can be updated by
99
writing to address 0x5F. Primarily it is updated, however, as a side
100
effect of the execution of ALU operations. If, for example, an
101
arithmetic/logic instruction produces a result of 0, then the zero flag
102
(the second bit in the status register) is set. An arithmetic overflow
103
in an ADD instruction causes the carry bit to be set, and so on.
104
The status register is declared as:
105
 
106
<P><br>
107
 
108
<pre class="vhdl">
109
 
110
 32     entity status_reg is
111
 33         port (  I_CLK       : in  std_logic;
112
 34
113
 35                 I_COND      : in  std_logic_vector ( 3 downto 0);
114
 36                 I_DIN       : in  std_logic_vector ( 7 downto 0);
115
 37                 I_FLAGS     : in  std_logic_vector ( 7 downto 0);
116
 38                 I_WE_F      : in  std_logic;
117
 39                 I_WE_SR     : in  std_logic;
118
 40
119
 41                 Q           : out std_logic_vector ( 7 downto 0);
120
 42                 Q_CC        : out std_logic);
121
 43     end status_reg;
122
<pre class="filename">
123
src/status_reg.vhd
124
</pre></pre>
125
<P>
126
 
127
<P><br>
128
 
129
<P>If <STRONG>WE_FLAGS</STRONG> is '1' then the status register is updated as a result
130
of an ALU operation; the new value of the status register is provided on the
131
<STRONG>FLAGS</STRONG> input which comes from the ALU.
132
 
133
<P>If <STRONG>WE_SR</STRONG> is '1' then the status register is updated as a result
134
of an I/O write operation (like <STRONG>OUT</STRONG> or <STRONG>STS</STRONG>); the new value of the
135
status register is provided on the <STRONG>DIN</STRONG> input.
136
 
137
<P>The output <STRONG>Q</STRONG> of the status register holds the current value of the register.
138
In addition there is a <STRONG>CC</STRONG> output that is '1' when the condition
139
indicated by the <STRONG>COND</STRONG> input is fulfilled. This is used for conditional
140
branch instructions. <STRONG>COND</STRONG> comes directly from the opcode for a branch
141
instruction (bit 10 of the opcode for the "polarity" and bits 2-0 of the
142
opcode for the bit of the status register that is being tested).
143
 
144
<H3><A NAME="section_1_1_3">6.1.3 Register File Components</A></H3>
145
 
146
<P>The register file consists of 16 general purpose register pairs <STRONG>r00</STRONG> to
147
<STRONG>r30</STRONG>, a stack pointer <STRONG>sp</STRONG>, and an 8-bit status register <STRONG>sr</STRONG>:
148
 
149
<P><br>
150
 
151
<pre class="vhdl">
152
 
153
131         r00: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE( 1 downto  0), I_D => I_DIN, Q => R_R00);
154
132         r02: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE( 3 downto  2), I_D => I_DIN, Q => R_R02);
155
133         r04: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE( 5 downto  4), I_D => I_DIN, Q => R_R04);
156
134         r06: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE( 7 downto  6), I_D => I_DIN, Q => R_R06);
157
135         r08: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE( 9 downto  8), I_D => I_DIN, Q => R_R08);
158
136         r10: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(11 downto 10), I_D => I_DIN, Q => R_R10);
159
137         r12: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(13 downto 12), I_D => I_DIN, Q => R_R12);
160
138         r14: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(15 downto 14), I_D => I_DIN, Q => R_R14);
161
139         r16: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(17 downto 16), I_D => I_DIN, Q => R_R16);
162
140         r18: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(19 downto 18), I_D => I_DIN, Q => R_R18);
163
141         r20: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(21 downto 20), I_D => I_DIN, Q => R_R20);
164
142         r22: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(23 downto 22), I_D => I_DIN, Q => R_R22);
165
143         r24: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(25 downto 24), I_D => I_DIN, Q => R_R24);
166
144         r26: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(27 downto 26), I_D => L_DX,  Q => R_R26);
167
145         r28: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(29 downto 28), I_D => L_DY,  Q => R_R28);
168
146         r30: reg_16 port map(I_CLK => I_CLK, I_WE => L_WE(31 downto 30), I_D => L_DZ,  Q => R_R30);
169
<pre class="filename">
170
src/register_file.vhd
171
</pre></pre>
172
<P>
173
 
174
<pre class="vhdl">
175
 
176
147         sp:  reg_16 port map(I_CLK => I_CLK, I_WE => L_WE_SP,            I_D => L_DSP, Q => R_SP);
177
<pre class="filename">
178
src/register_file.vhd
179
</pre></pre>
180
<P>
181
 
182
<pre class="vhdl">
183
 
184
149         sr: status_reg
185
150         port map(   I_CLK       => I_CLK,
186
151                     I_COND      => I_COND,
187
152                     I_DIN       => I_DIN(7 downto 0),
188
153                     I_FLAGS     => I_FLAGS,
189
154                     I_WE_F      => I_WE_F,
190
155                     I_WE_SR     => L_WE_SR,
191
156                     Q           => S_FLAGS,
192
157                     Q_CC        => Q_CC);
193
<pre class="filename">
194
src/register_file.vhd
195
</pre></pre>
196
<P>
197
 
198
<P><br>
199
 
200
<P>Each register pair drives a 16-bit signal according to the (even) number
201
of the register pair in the register file:
202
 
203
<P><br>
204
 
205
<pre class="vhdl">
206
 
207
 71     signal R_R00            : std_logic_vector(15 downto 0);
208
 72     signal R_R02            : std_logic_vector(15 downto 0);
209
 73     signal R_R04            : std_logic_vector(15 downto 0);
210
 74     signal R_R06            : std_logic_vector(15 downto 0);
211
 75     signal R_R08            : std_logic_vector(15 downto 0);
212
 76     signal R_R10            : std_logic_vector(15 downto 0);
213
 77     signal R_R12            : std_logic_vector(15 downto 0);
214
 78     signal R_R14            : std_logic_vector(15 downto 0);
215
 79     signal R_R16            : std_logic_vector(15 downto 0);
216
 80     signal R_R18            : std_logic_vector(15 downto 0);
217
 81     signal R_R20            : std_logic_vector(15 downto 0);
218
 82     signal R_R22            : std_logic_vector(15 downto 0);
219
 83     signal R_R24            : std_logic_vector(15 downto 0);
220
 84     signal R_R26            : std_logic_vector(15 downto 0);
221
 85     signal R_R28            : std_logic_vector(15 downto 0);
222
 86     signal R_R30            : std_logic_vector(15 downto 0);
223
 87     signal R_SP             : std_logic_vector(15 downto 0);    -- stack pointer
224
<pre class="filename">
225
src/register_file.vhd
226
</pre></pre>
227
<P>
228
 
229
<P><br>
230
 
231
<H3><A NAME="section_1_1_4">6.1.4 Addressing of General Purpose Registers</A></H3>
232
 
233
<P>We address individual general purpose registers by a 5-bit value.
234
Normally an opcode using an individual general purpose 8-bit register
235
has a 5 bit field which is the address of the register. The opcode decoder
236
transfers this field to its <STRONG>DDDDD</STRONG> or <STRONG>RRRRR</STRONG> output. For some opcodes
237
not all 32 registers can be used, but only 16 (e.g. <STRONG>ANDI</STRONG>) or 8 (e.g. <STRONG>MUL</STRONG>).
238
In these cases the register field in the opcode is smaller and the opcode
239
decoder fills in the missing bits. Some opcodes imply particular registers
240
(e.g. some <STRONG>LPM</STRONG> variant), and again the opcode decoder fills in the implied
241
register number.
242
 
243
<P>An opcode may address no, one, two, or three registers or pairs.
244
If one register is addressed, then the number of that register is
245
encoded in the <STRONG>DDDDD</STRONG> signal.<BR>
246
If two (or more) registers are used, then one (normally the destination
247
register) is encoded in the <STRONG>DDDDD</STRONG> signal and the other (source) is encoded
248
in the <STRONG>RRRRR</STRONG> signal. Opcodes with 3 registers (e.g. MUL) use an implied
249
destination register pair (register pair 0) and two source registers encoded
250
in the <STRONG>DDDDD</STRONG> and <STRONG>RRRRR</STRONG> signals.
251
 
252
<H3><A NAME="section_1_1_5">6.1.5 Addressing of General Purpose Register Pairs</A></H3>
253
 
254
<P>We address register pairs by addressing the even register of the pair.
255
The address of a register pair is therefore a 5-bit value with the lowest
256
bit cleared. The opcode normally only has a 4-bit field for a register pair
257
and the lowest (cleared) bit is filled in by the opcode decoder. Like
258
for individual registers it can happen that not all 16 register pairs can
259
be addresses (e.g. <STRONG>ADIW</STRONG>). This is handles in the same way as for individual
260
registers.
261
 
262
<P>In the AVR context, the register pairs <STRONG>R26</STRONG>, <STRONG>R28</STRONG>, and <STRONG>R30</STRONG> are also called
263
(pointer registers) <STRONG>X</STRONG>, <STRONG>Y</STRONG>, and <STRONG>Z</STRONG> respectively.
264
 
265
<H3><A NAME="section_1_1_6">6.1.6 Requirements on the Register File</A></H3>
266
 
267
<P>If we go through the opcodes of the AVR CPU, then we see the
268
capabilities that the register file must provide for general purpose
269
registers (or register pairs):
270
 
271
<TABLE border="1">
272
<THEAD><TR><TH>Capability</TH><TH>Opcode (example)</TH></TR></THEAD>
273
<TBODY>
274
<TR><TD>Read one register, read/write another register</TD><TD>ADD Rd, Rr</TD></TR>
275
<TR><TD>Write one register, read/write another register</TD><TD>LD Rd, (X+)</TD></TR>
276
<TR><TD>Write one register, read another register</TD><TD>LD Rd, (X)</TD></TR>
277
<TR><TD>Read/write one register</TD><TD>ASR Rd</TD></TR>
278
<TR><TD>Read one register, read another register</TD><TD>CMP Rd, Rr</TD></TR>
279
<TR><TD>Read one register, read another register</TD><TD>LD  Rd, Rr</TD></TR>
280
<TR><TD>Read one register</TD><TD>IN  Rd, A</TD></TR>
281
<TR><TD>Write one register</TD><TD>OUT A, Rr</TD></TR>
282
</TBODY>
283
</TABLE>
284
 
285
<H3><A NAME="section_1_1_7">6.1.7 Reading Registers or Register Pairs</A></H3>
286
 
287
<P>There are 4 cases:
288
 
289
<UL>
290
  <LI>Read register or register pair addresses by <STRONG>DDDDD</STRONG>.
291
  <LI>Read register or register pair addresses by <STRONG>RRRRR</STRONG>.
292
  <LI>Read register addressed by the current I/O address.
293
  <LI>Read <STRONG>X</STRONG>, <STRONG>Y</STRONG>, or <STRONG>Z</STRONG> pointer implied by the addressing mode <STRONG>AMOD</STRONG>.
294
  <LI>Read the <STRONG>Z</STRONG> pointer implied by the instruction (<STRONG>IJMP</STRONG> or <STRONG>ICALL</STRONG>).
295
</UL>
296
<P>Some of these cases can happen simultaneously. For example the <STRONG>ICALL</STRONG>
297
instruction reads the <STRONG>Z</STRONG> register (the target address of the call) while
298
it pushed the current PC onto the stack. Likewise, <STRONG>ST</STRONG> may need the
299
<STRONG>X</STRONG>, <STRONG>Y</STRONG>, or <STRONG>Z</STRONG> for address calculations and a general purpose register that
300
is to be stored in memory. For this reason we provide 5 different outputs
301
in the register file. These outputs are addressing the general purpose
302
registers differently (and they can be used in parallel):
303
 
304
<UL>
305
  <LI><STRONG>Q_D</STRONG> is the content of the register addressed by <STRONG>DDDDD</STRONG>.
306
  <LI><STRONG>Q_R</STRONG> is the content of the register pair addressed by <STRONG>RRRR</STRONG>.
307
  <LI><STRONG>Q_S</STRONG> is the content of the register addressed by <STRONG>ADR</STRONG>.
308
  <LI><STRONG>Q_ADR</STRONG> is an address defined by <STRONG>AMOD</STRONG> (and may use <STRONG>X</STRONG>, <STRONG>Y</STRONG>, or <STRONG>Z</STRONG>).
309
  <LI><STRONG>Q_X</STRONG> is the content of the Z register.
310
</UL>
311
<P><STRONG>Q_D</STRONG> is one of the register pair signals as defined by <STRONG>DDDDD</STRONG>. We read the
312
entire pair; the selection of the even/odd register within the pair is done
313
later in the ALU based on <STRONG>DDDDD(0)</STRONG>:
314
 
315
<P><br>
316
 
317
<pre class="vhdl">
318
 
319
189         process(R_R00, R_R02, R_R04, R_R06, R_R08, R_R10, R_R12, R_R14,
320
190                 R_R16, R_R18, R_R20, R_R22, R_R24, R_R26, R_R28, R_R30,
321
191                 I_DDDDD(4 downto 1))
322
192         begin
323
193             case I_DDDDD(4 downto 1) is
324
194                 when "0000" => Q_D <= R_R00;
325
195                 when "0001" => Q_D <= R_R02;
326
196                 when "0010" => Q_D <= R_R04;
327
197                 when "0011" => Q_D <= R_R06;
328
198                 when "0100" => Q_D <= R_R08;
329
199                 when "0101" => Q_D <= R_R10;
330
200                 when "0110" => Q_D <= R_R12;
331
201                 when "0111" => Q_D <= R_R14;
332
202                 when "1000" => Q_D <= R_R16;
333
203                 when "1001" => Q_D <= R_R18;
334
204                 when "1010" => Q_D <= R_R20;
335
205                 when "1011" => Q_D <= R_R22;
336
206                 when "1100" => Q_D <= R_R24;
337
207                 when "1101" => Q_D <= R_R26;
338
208                 when "1110" => Q_D <= R_R28;
339
209                 when others => Q_D <= R_R30;
340
210             end case;
341
211         end process;
342
<pre class="filename">
343
src/register_file.vhd
344
</pre></pre>
345
<P>
346
 
347
<P><br>
348
 
349
<P><STRONG>Q_R</STRONG> is one of the register pair signals as defined by <STRONG>RRRR</STRONG>:
350
 
351
<P><br>
352
 
353
<pre class="vhdl">
354
 
355
215         process(R_R00, R_R02, R_R04,  R_R06, R_R08, R_R10, R_R12, R_R14,
356
216                 R_R16, R_R18, R_R20, R_R22, R_R24, R_R26, R_R28, R_R30, I_RRRR)
357
217         begin
358
218             case I_RRRR is
359
219                 when "0000" => Q_R <= R_R00;
360
220                 when "0001" => Q_R <= R_R02;
361
221                 when "0010" => Q_R <= R_R04;
362
222                 when "0011" => Q_R <= R_R06;
363
223                 when "0100" => Q_R <= R_R08;
364
224                 when "0101" => Q_R <= R_R10;
365
225                 when "0110" => Q_R <= R_R12;
366
226                 when "0111" => Q_R <= R_R14;
367
227                 when "1000" => Q_R <= R_R16;
368
228                 when "1001" => Q_R <= R_R18;
369
229                 when "1010" => Q_R <= R_R20;
370
230                 when "1011" => Q_R <= R_R22;
371
231                 when "1100" => Q_R <= R_R24;
372
232                 when "1101" => Q_R <= R_R26;
373
233                 when "1110" => Q_R <= R_R28;
374
234                 when others => Q_R <= R_R30;
375
235             end case;
376
236         end process;
377
<pre class="filename">
378
src/register_file.vhd
379
</pre></pre>
380
<P>
381
 
382
<P><br>
383
 
384
<P>The general purpose registers, but also the stack pointer and the status
385
register, are mapped into the data memory space:
386
 
387
<TABLE border="1">
388
<THEAD><TR><TH>Address</TH><TH>Purpose</TH></TR></THEAD>
389
<TBODY>
390
<TR><TD>0x00 - 0x1F</TD><TD>general purpose CPU registers.</TD></TR>
391
<TR><TD>0x20 - 0x5C</TD><TD>miscellaneous I/O registers.</TD></TR>
392
<TR><TD>0x5D</TD><TD>stack pointer low</TD></TR>
393
<TR><TD>0x5E</TD><TD>stack pointer high</TD></TR>
394
<TR><TD>0x5F</TD><TD>status register</TD></TR>
395
<TR><TD>0x60 - 0xFFFF</TD><TD>data memory</TD></TR>
396
</TBODY>
397
</TABLE>
398
 
399
<P>If an address corresponding to a register in the register file (i.e. a
400
general purpose register, the stack pointer, or the status register is read,
401
then the register shall be returned.<BR>
402
For example, LD Rd, R22 shall give the same result as LDS Rd, 22.
403
 
404
<P>The 8-bit <STRONG>Q_S</STRONG> output contains the register addresses by <STRONG>ADR</STRONG>:
405
 
406
<P><br>
407
 
408
<pre class="vhdl">
409
 
410
161         process(R_R00, R_R02, R_R04, R_R06, R_R08, R_R10, R_R12, R_R14,
411
162                 R_R16, R_R18, R_R20, R_R22, R_R24, R_R26, R_R28, R_R30,
412
163                 R_SP, S_FLAGS, L_ADR(6 downto 1))
413
164         begin
414
165             case L_ADR(6 downto 1) is
415
166                 when "000000" => L_S <= R_R00;
416
167                 when "000001" => L_S <= R_R02;
417
168                 when "000010" => L_S <= R_R04;
418
169                 when "000011" => L_S <= R_R06;
419
170                 when "000100" => L_S <= R_R08;
420
171                 when "000101" => L_S <= R_R10;
421
172                 when "000110" => L_S <= R_R12;
422
173                 when "000111" => L_S <= R_R14;
423
174                 when "001000" => L_S <= R_R16;
424
175                 when "001001" => L_S <= R_R18;
425
176                 when "001010" => L_S <= R_R20;
426
177                 when "001011" => L_S <= R_R22;
427
178                 when "001100" => L_S <= R_R24;
428
179                 when "001101" => L_S <= R_R26;
429
180                 when "001110" => L_S <= R_R28;
430
181                 when "001111" => L_S <= R_R30;
431
182                 when "101111" => L_S <= R_SP ( 7 downto 0) & X"00";     -- SPL
432
183                 when others   => L_S <= S_FLAGS & R_SP (15 downto 8);   -- SR/SPH
433
184             end case;
434
185         end process;
435
186
436
<pre class="filename">
437
src/register_file.vhd
438
</pre></pre>
439
<P>
440
 
441
<P><br>
442
 
443
<H3><A NAME="section_1_1_8">6.1.8 Writing Registers or Register Pairs</A></H3>
444
 
445
<P>In order to write a register, we need to select the proper input (data
446
source) and the proper <STRONG>WE</STRONG> signal. For most registers, the only possible
447
data source is <STRONG>DIN</STRONG> which comes straight from the ALU. The pointer
448
register pairs <STRONG>X</STRONG>, <STRONG>Y</STRONG>, and <STRONG>Z</STRONG>, however, can also be changed as a side effect
449
of the post-increment (<STRONG>X+</STRONG>, <STRONG>Y+</STRONG>, <STRONG>Z+</STRONG>) and pre-decrement (<STRONG>-X</STRONG>, <STRONG>-Y</STRONG>, <STRONG>-Z</STRONG>)
450
addressing modes of the <STRONG>LDS</STRONG> and <STRONG>STS</STRONG> instructions. The addressing modes are
451
discussed in more detail in the next chapter; here it suffices to note that
452
the <STRONG>X</STRONG>, <STRONG>Y</STRONG>, and #Z #registers get there data from <STRONG>DX</STRONG>, <STRONG>DY</STRONG>, and <STRONG>DZ</STRONG>,
453
respectively rather than from <STRONG>DIN</STRONG>.
454
 
455
<P>There is a total of 4 cases where general purpose registers are written.
456
Three of these cases that are applicable to all general purpose registers
457
and one case collects special cases for particular registers (the register
458
numbers are then implied).
459
 
460
<P>We compute a 32 bit write enable signal for each of the four cases and <STRONG>OR</STRONG>
461
them together.
462
 
463
<P>The first case is a write to an 8-bit register addressed by <STRONG>DDDDD</STRONG>.
464
For this case we create the signal <STRONG>WE_D</STRONG>:
465
 
466
<P><br>
467
 
468
<pre class="vhdl">
469
 
470
288         L_WE_D( 0) <= I_WE_D(0) when (I_DDDDD = "00000") else '0';
471
289         L_WE_D( 1) <= I_WE_D(0) when (I_DDDDD = "00001") else '0';
472
290         L_WE_D( 2) <= I_WE_D(0) when (I_DDDDD = "00010") else '0';
473
291         L_WE_D( 3) <= I_WE_D(0) when (I_DDDDD = "00011") else '0';
474
292         L_WE_D( 4) <= I_WE_D(0) when (I_DDDDD = "00100") else '0';
475
293         L_WE_D( 5) <= I_WE_D(0) when (I_DDDDD = "00101") else '0';
476
294         L_WE_D( 6) <= I_WE_D(0) when (I_DDDDD = "00110") else '0';
477
295         L_WE_D( 7) <= I_WE_D(0) when (I_DDDDD = "00111") else '0';
478
296         L_WE_D( 8) <= I_WE_D(0) when (I_DDDDD = "01000") else '0';
479
297         L_WE_D( 9) <= I_WE_D(0) when (I_DDDDD = "01001") else '0';
480
298         L_WE_D(10) <= I_WE_D(0) when (I_DDDDD = "01010") else '0';
481
299         L_WE_D(11) <= I_WE_D(0) when (I_DDDDD = "01011") else '0';
482
300         L_WE_D(12) <= I_WE_D(0) when (I_DDDDD = "01100") else '0';
483
301         L_WE_D(13) <= I_WE_D(0) when (I_DDDDD = "01101") else '0';
484
302         L_WE_D(14) <= I_WE_D(0) when (I_DDDDD = "01110") else '0';
485
303         L_WE_D(15) <= I_WE_D(0) when (I_DDDDD = "01111") else '0';
486
304         L_WE_D(16) <= I_WE_D(0) when (I_DDDDD = "10000") else '0';
487
305         L_WE_D(17) <= I_WE_D(0) when (I_DDDDD = "10001") else '0';
488
306         L_WE_D(18) <= I_WE_D(0) when (I_DDDDD = "10010") else '0';
489
307         L_WE_D(19) <= I_WE_D(0) when (I_DDDDD = "10011") else '0';
490
308         L_WE_D(20) <= I_WE_D(0) when (I_DDDDD = "10100") else '0';
491
309         L_WE_D(21) <= I_WE_D(0) when (I_DDDDD = "10101") else '0';
492
310         L_WE_D(22) <= I_WE_D(0) when (I_DDDDD = "10110") else '0';
493
311         L_WE_D(23) <= I_WE_D(0) when (I_DDDDD = "10111") else '0';
494
312         L_WE_D(24) <= I_WE_D(0) when (I_DDDDD = "11000") else '0';
495
313         L_WE_D(25) <= I_WE_D(0) when (I_DDDDD = "11001") else '0';
496
314         L_WE_D(26) <= I_WE_D(0) when (I_DDDDD = "11010") else '0';
497
315         L_WE_D(27) <= I_WE_D(0) when (I_DDDDD = "11011") else '0';
498
316         L_WE_D(28) <= I_WE_D(0) when (I_DDDDD = "11100") else '0';
499
317         L_WE_D(29) <= I_WE_D(0) when (I_DDDDD = "11101") else '0';
500
318         L_WE_D(30) <= I_WE_D(0) when (I_DDDDD = "11110") else '0';
501
319         L_WE_D(31) <= I_WE_D(0) when (I_DDDDD = "11111") else '0';
502
<pre class="filename">
503
src/register_file.vhd
504
</pre></pre>
505
<P>
506
 
507
<P><br>
508
 
509
<P>The second case is a write to a 16-bit register pair addressed by <STRONG>DDDD</STRONG>
510
(<STRONG>DDDD</STRONG> is the four upper bits of <STRONG>DDDDD</STRONG>).  For this case we create
511
signal <STRONG>WE_DD</STRONG>:
512
 
513
<P><br>
514
 
515
<pre class="vhdl">
516
 
517
326         L_DDDD <= I_DDDDD(4 downto 1);
518
327         L_WE_D2 <= I_WE_D(1) & I_WE_D(1);
519
328         L_WE_DD( 1 downto  0) <= L_WE_D2 when (L_DDDD = "0000") else "00";
520
329         L_WE_DD( 3 downto  2) <= L_WE_D2 when (L_DDDD = "0001") else "00";
521
330         L_WE_DD( 5 downto  4) <= L_WE_D2 when (L_DDDD = "0010") else "00";
522
331         L_WE_DD( 7 downto  6) <= L_WE_D2 when (L_DDDD = "0011") else "00";
523
332         L_WE_DD( 9 downto  8) <= L_WE_D2 when (L_DDDD = "0100") else "00";
524
333         L_WE_DD(11 downto 10) <= L_WE_D2 when (L_DDDD = "0101") else "00";
525
334         L_WE_DD(13 downto 12) <= L_WE_D2 when (L_DDDD = "0110") else "00";
526
335         L_WE_DD(15 downto 14) <= L_WE_D2 when (L_DDDD = "0111") else "00";
527
336         L_WE_DD(17 downto 16) <= L_WE_D2 when (L_DDDD = "1000") else "00";
528
337         L_WE_DD(19 downto 18) <= L_WE_D2 when (L_DDDD = "1001") else "00";
529
338         L_WE_DD(21 downto 20) <= L_WE_D2 when (L_DDDD = "1010") else "00";
530
339         L_WE_DD(23 downto 22) <= L_WE_D2 when (L_DDDD = "1011") else "00";
531
340         L_WE_DD(25 downto 24) <= L_WE_D2 when (L_DDDD = "1100") else "00";
532
341         L_WE_DD(27 downto 26) <= L_WE_D2 when (L_DDDD = "1101") else "00";
533
342         L_WE_DD(29 downto 28) <= L_WE_D2 when (L_DDDD = "1110") else "00";
534
343         L_WE_DD(31 downto 30) <= L_WE_D2 when (L_DDDD = "1111") else "00";
535
<pre class="filename">
536
src/register_file.vhd
537
</pre></pre>
538
<P>
539
 
540
<P><br>
541
 
542
<P>The third case is writing to the memory mapped I/O space of the general
543
purpose registers. It is similar to the first case, but now we select
544
the register by <STRONG>ADR</STRONG> instead of <STRONG>DDDDD</STRONG>. When reading from the I/O mapped
545
register above we did not check if <STRONG>ADR</STRONG> was completely correct (and different
546
addresses could read the same register. This was OK, since some multiplexer
547
somewhere else would discard the value read for addresses outside the range
548
from 0x00 to 0x1F. When writing we have to be more careful and check the
549
range by means of <STRONG>WE_A</STRONG>. For the third case we use signal <STRONG>WE_IO</STRONG>:
550
 
551
<P><br>
552
 
553
<pre class="vhdl">
554
 
555
350         L_WE_IO( 0) <= L_WE_A when (L_ADR(4 downto 0) = "00000") else '0';
556
351         L_WE_IO( 1) <= L_WE_A when (L_ADR(4 downto 0) = "00001") else '0';
557
352         L_WE_IO( 2) <= L_WE_A when (L_ADR(4 downto 0) = "00010") else '0';
558
353         L_WE_IO( 3) <= L_WE_A when (L_ADR(4 downto 0) = "00011") else '0';
559
354         L_WE_IO( 4) <= L_WE_A when (L_ADR(4 downto 0) = "00100") else '0';
560
355         L_WE_IO( 5) <= L_WE_A when (L_ADR(4 downto 0) = "00101") else '0';
561
356         L_WE_IO( 6) <= L_WE_A when (L_ADR(4 downto 0) = "00110") else '0';
562
357         L_WE_IO( 7) <= L_WE_A when (L_ADR(4 downto 0) = "00111") else '0';
563
358         L_WE_IO( 8) <= L_WE_A when (L_ADR(4 downto 0) = "01000") else '0';
564
359         L_WE_IO( 9) <= L_WE_A when (L_ADR(4 downto 0) = "01001") else '0';
565
360         L_WE_IO(10) <= L_WE_A when (L_ADR(4 downto 0) = "01010") else '0';
566
361         L_WE_IO(11) <= L_WE_A when (L_ADR(4 downto 0) = "01011") else '0';
567
362         L_WE_IO(12) <= L_WE_A when (L_ADR(4 downto 0) = "01100") else '0';
568
363         L_WE_IO(13) <= L_WE_A when (L_ADR(4 downto 0) = "01101") else '0';
569
364         L_WE_IO(14) <= L_WE_A when (L_ADR(4 downto 0) = "01110") else '0';
570
365         L_WE_IO(15) <= L_WE_A when (L_ADR(4 downto 0) = "01111") else '0';
571
366         L_WE_IO(16) <= L_WE_A when (L_ADR(4 downto 0) = "10000") else '0';
572
367         L_WE_IO(17) <= L_WE_A when (L_ADR(4 downto 0) = "10001") else '0';
573
368         L_WE_IO(18) <= L_WE_A when (L_ADR(4 downto 0) = "10010") else '0';
574
369         L_WE_IO(19) <= L_WE_A when (L_ADR(4 downto 0) = "10011") else '0';
575
370         L_WE_IO(20) <= L_WE_A when (L_ADR(4 downto 0) = "10100") else '0';
576
371         L_WE_IO(21) <= L_WE_A when (L_ADR(4 downto 0) = "10101") else '0';
577
372         L_WE_IO(22) <= L_WE_A when (L_ADR(4 downto 0) = "10110") else '0';
578
373         L_WE_IO(23) <= L_WE_A when (L_ADR(4 downto 0) = "10111") else '0';
579
374         L_WE_IO(24) <= L_WE_A when (L_ADR(4 downto 0) = "11000") else '0';
580
375         L_WE_IO(25) <= L_WE_A when (L_ADR(4 downto 0) = "11001") else '0';
581
376         L_WE_IO(26) <= L_WE_A when (L_ADR(4 downto 0) = "11010") else '0';
582
377         L_WE_IO(27) <= L_WE_A when (L_ADR(4 downto 0) = "11011") else '0';
583
378         L_WE_IO(28) <= L_WE_A when (L_ADR(4 downto 0) = "11100") else '0';
584
379         L_WE_IO(29) <= L_WE_A when (L_ADR(4 downto 0) = "11101") else '0';
585
380         L_WE_IO(30) <= L_WE_A when (L_ADR(4 downto 0) = "11110") else '0';
586
381         L_WE_IO(31) <= L_WE_A when (L_ADR(4 downto 0) = "11111") else '0';
587
<pre class="filename">
588
src/register_file.vhd
589
</pre></pre>
590
<P>
591
 
592
<P><br>
593
 
594
<P>The last case for writing is handled by <STRONG>WE_MISC</STRONG>.
595
The various multiplication opcodes write their result to register pair 0;
596
this case is indicated the the <STRONG>WE_01</STRONG> input. Then we have the pre-decrement
597
and post-increment addressing modes that update the <STRONG>X</STRONG>, <STRONG>Y</STRONG>, or <STRONG>Z</STRONG> register:
598
 
599
<P><br>
600
 
601
<pre class="vhdl">
602
 
603
389         L_WE_X <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WX) else '0';
604
390         L_WE_Y <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WY) else '0';
605
391         L_WE_Z <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WZ) else '0';
606
392         L_WE_MISC <= L_WE_Z & L_WE_Z &      -- -Z and Z+ address modes  r30
607
393                      L_WE_Y & L_WE_Y &      -- -Y and Y+ address modes  r28
608
394                      L_WE_X & L_WE_X &      -- -X and X+ address modes  r26
609
395                      X"000000" &            -- never                    r24 - r02
610
396                      I_WE_01 & I_WE_01;     -- multiplication result    r00
611
<pre class="filename">
612
src/register_file.vhd
613
</pre></pre>
614
<P>
615
 
616
<P><br>
617
 
618
<P>The final <STRONG>WE</STRONG> signal is then computed by <STRONG>or</STRONG>'ing the four cases above:
619
 
620
<P><br>
621
 
622
<pre class="vhdl">
623
 
624
398         L_WE <= L_WE_D or L_WE_DD or L_WE_IO or L_WE_MISC;
625
<pre class="filename">
626
src/register_file.vhd
627
</pre></pre>
628
<P>
629
 
630
<P><br>
631
 
632
<P>The stack pointer can be updated from two sources: from <STRONG>DIN</STRONG> as a memory
633
mapped I/O or implicitly from <STRONG>XYZS</STRONG> by addressing modes (e.g. for
634
<STRONG>CALL</STRONG>, <STRONG>RET</STRONG>, <STRONG>PUSH</STRONG>, and <STRONG>POP</STRONG> instructions) that write to the <STRONG>SP</STRONG> (<STRONG>AM_WS</STRONG>).
635
 
636
<P><br>
637
 
638
<pre class="vhdl">
639
 
640
280         L_DSP <= L_XYZS when (I_AMOD(3 downto 0) = AM_WS) else I_DIN;
641
<pre class="filename">
642
src/register_file.vhd
643
</pre></pre>
644
<P>
645
 
646
<P><br>
647
 
648
<P>The status register can be written as memory mapped I/O from the <STRONG>DIN</STRONG> input
649
or from the <STRONG>FLAGS</STRONG> input (from the ALU). The <STRONG>WE_SR</STRONG> input (for memory
650
mapped I/O) and the <STRONG>WE_FLAGS</STRONG> input (for flags set as side effect of
651
ALU operations) control from where the new value comes:
652
 
653
<P><br>
654
 
655
<pre class="vhdl">
656
 
657
272         L_WE_SR    <= I_WE_M when (L_ADR = X"005F") else '0';
658
<pre class="filename">
659
src/register_file.vhd
660
</pre></pre>
661
<P>
662
 
663
<P><br>
664
 
665
<pre class="vhdl">
666
 
667
152                     I_DIN       => I_DIN(7 downto 0),
668
153                     I_FLAGS     => I_FLAGS,
669
154                     I_WE_F      => I_WE_F,
670
<pre class="filename">
671
src/register_file.vhd
672
</pre></pre>
673
<P>
674
 
675
<P><br>
676
 
677
<H3><A NAME="section_1_1_9">6.1.9 Addressing Modes</A></H3>
678
 
679
<P>The CPU provides a number of addressing modes. An addressing mode is a way
680
to compute an address. The address specifies a location in the program memory,
681
the data memory, the I/O memory, or some general purpose register. Computing
682
an address can have side effects such as incrementing or decrementing a
683
pointer register.
684
 
685
<P>The addressing mode to be used (if any) is encoded in the <STRONG>AMOD</STRONG> signal.
686
The <STRONG>AMOD</STRONG> signal consists of two sub-fields: the address source and the
687
address offset.
688
 
689
<P>There are 5 possible address sources:
690
 
691
<P><br>
692
 
693
<pre class="vhdl">
694
 
695
 84         constant AS_SP  : std_logic_vector(2 downto 0) := "000";     -- SP
696
 85         constant AS_Z   : std_logic_vector(2 downto 0) := "001";     -- Z
697
 86         constant AS_Y   : std_logic_vector(2 downto 0) := "010";     -- Y
698
 87         constant AS_X   : std_logic_vector(2 downto 0) := "011";     -- X
699
 88         constant AS_IMM : std_logic_vector(2 downto 0) := "100";     -- IMM
700
<pre class="filename">
701
src/common.vhd
702
</pre></pre>
703
<P>
704
 
705
<P><br>
706
 
707
<P>The address sources <STRONG>AS_SP</STRONG>, <STRONG>AS_X</STRONG>, <STRONG>AS_Y</STRONG>, and <STRONG>AS_Z</STRONG> are the stack pointer,
708
the <STRONG>X</STRONG> register pair, the <STRONG>Y</STRONG> register pair, or the <STRONG>Z</STRONG> register pair.
709
The <STRONG>AS_IMM</STRONG> source is the <STRONG>IMM</STRONG> input (which was computed from the opcode
710
in the opcode decoder).
711
 
712
<P>There are 6 different address offsets. An address offset can imply a side
713
effect like incrementing or decrementing the address source. The lowest
714
bit of the address offset indicates whether a side effect is intended or not:
715
 
716
<P><br>
717
 
718
<pre class="vhdl">
719
 
720
 91         constant AO_0   : std_logic_vector(5 downto 3) := "000";     -- as is
721
 92         constant AO_Q   : std_logic_vector(5 downto 3) := "010";     -- +q
722
 93         constant AO_i   : std_logic_vector(5 downto 3) := "001";     -- +1
723
 94         constant AO_ii  : std_logic_vector(5 downto 3) := "011";     -- +2
724
 95         constant AO_d   : std_logic_vector(5 downto 3) := "101";     -- -1
725
 96         constant AO_dd  : std_logic_vector(5 downto 3) := "111";     -- -2
726
<pre class="filename">
727
src/common.vhd
728
</pre></pre>
729
<P>
730
 
731
<P><br>
732
 
733
<P>The address offset <STRONG>AO_0</STRONG> does nothing; the address source is not modified.
734
Address offset <STRONG>AO_Q</STRONG> adds some constant <STRONG>q</STRONG> to the address source; the constant
735
<STRONG>q</STRONG> is provided on the <STRONG>IMM</STRONG> input (thus derived from the opcode).
736
Address offsets <STRONG>AO_i</STRONG> resp. <STRONG>AO_ii</STRONG> increment the address source after the
737
operation by 1 resp. 2 bytes. The address computed is the address source.
738
Address offsets <STRONG>AO_d</STRONG> resp. <STRONG>AO_dd</STRONG> decrement the address source before the
739
operation by 1 resp. 2 bytes. The address computed is the address source
740
minus 1 or 2.
741
 
742
<P>The constants <STRONG>AM_WX</STRONG>, <STRONG>AM_WY</STRONG>, <STRONG>AM_WZ</STRONG>, and <STRONG>AM_WS</STRONG> respectively indicate if
743
the <STRONG>X</STRONG>, <STRONG>Y</STRONG>, <STRONG>Z</STRONG>, or <STRONG>SP</STRONG> registers will be updated and are used to decode
744
the <STRONG>WE_XYZS</STRONG> signal to the register concerned and to select the proper
745
inputs:
746
 
747
<P><br>
748
 
749
<pre class="vhdl">
750
 
751
389         L_WE_X <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WX) else '0';
752
390         L_WE_Y <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WY) else '0';
753
391         L_WE_Z <= I_WE_XYZS when (I_AMOD(3 downto 0) = AM_WZ) else '0';
754
392         L_WE_MISC <= L_WE_Z & L_WE_Z &      -- -Z and Z+ address modes  r30
755
393                      L_WE_Y & L_WE_Y &      -- -Y and Y+ address modes  r28
756
394                      L_WE_X & L_WE_X &      -- -X and X+ address modes  r26
757
<pre class="filename">
758
src/register_file.vhd
759
</pre></pre>
760
<P>
761
 
762
<P><br>
763
 
764
<pre class="vhdl">
765
 
766
277         L_DX  <= L_XYZS when (L_WE_MISC(26) = '1')        else I_DIN;
767
278         L_DY  <= L_XYZS when (L_WE_MISC(28) = '1')        else I_DIN;
768
279         L_DZ  <= L_XYZS when (L_WE_MISC(30) = '1')        else I_DIN;
769
280         L_DSP <= L_XYZS when (I_AMOD(3 downto 0) = AM_WS) else I_DIN;
770
<pre class="filename">
771
src/register_file.vhd
772
</pre></pre>
773
<P>
774
 
775
<P><br>
776
 
777
<P>Not all combinations of address source and address offset occur; only
778
the following combinations are needed:
779
 
780
<P><br>
781
 
782
<pre class="vhdl">
783
 
784
108         constant AMOD_ABS : std_logic_vector(5 downto 0) := AO_0  & AS_IMM; -- IMM
785
109         constant AMOD_X   : std_logic_vector(5 downto 0) := AO_0  & AS_X;   -- (X)
786
110         constant AMOD_Xq  : std_logic_vector(5 downto 0) := AO_Q  & AS_X;   -- (X+q)
787
111         constant AMOD_Xi  : std_logic_vector(5 downto 0) := AO_i  & AS_X;   -- (X++)
788
112         constant AMOD_dX  : std_logic_vector(5 downto 0) := AO_d  & AS_X;   -- (--X)
789
113         constant AMOD_Y   : std_logic_vector(5 downto 0) := AO_0  & AS_Y;   -- (Y)
790
114         constant AMOD_Yq  : std_logic_vector(5 downto 0) := AO_Q  & AS_Y;   -- (Y+q)
791
115         constant AMOD_Yi  : std_logic_vector(5 downto 0) := AO_i  & AS_Y;   -- (Y++)
792
116         constant AMOD_dY  : std_logic_vector(5 downto 0) := AO_d  & AS_Y;   -- (--Y)
793
117         constant AMOD_Z   : std_logic_vector(5 downto 0) := AO_0  & AS_Z;   -- (Z)
794
118         constant AMOD_Zq  : std_logic_vector(5 downto 0) := AO_Q  & AS_Z;   -- (Z+q)
795
119         constant AMOD_Zi  : std_logic_vector(5 downto 0) := AO_i  & AS_Z;   -- (Z++)
796
120         constant AMOD_dZ  : std_logic_vector(5 downto 0) := AO_d  & AS_Z;   -- (--Z)
797
121         constant AMOD_SPi : std_logic_vector(5 downto 0) := AO_i  & AS_SP;  -- (SP++)
798
122         constant AMOD_SPii: std_logic_vector(5 downto 0) := AO_ii & AS_SP;  -- (SP++)
799
123         constant AMOD_dSP : std_logic_vector(5 downto 0) := AO_d  & AS_SP;  -- (--SP)
800
124         constant AMOD_ddSP: std_logic_vector(5 downto 0) := AO_dd & AS_SP;  -- (--SP)
801
<pre class="filename">
802
src/common.vhd
803
</pre></pre>
804
<P>
805
 
806
<P><br>
807
 
808
<P>The following figure shows the computation of addresses:
809
 
810
<P><br>
811
 
812
<P><img src="data_path_2.png">
813
 
814
<P><br>
815
 
816
<H2><A NAME="section_1_2">6.2 Data memory</A></H2>
817
 
818
<P>The data memory is conceptually an 8-bit memory. However, some instructions
819
(e.g. CALL, RET) write two bytes to consecutive memory locations. We do the
820
same trick as for the program memory and divide the data memory into an
821
even half and an odd half. The only new thing is a multiplexer at the input:
822
 
823
<P><br>
824
 
825
<pre class="vhdl">
826
 
827
179         L_DIN_E <= I_DIN( 7 downto 0) when (I_ADR(0) = '0') else I_DIN(15 downto 8);
828
180         L_DIN_O <= I_DIN( 7 downto 0) when (I_ADR(0) = '1') else I_DIN(15 downto 8);
829
<pre class="filename">
830
src/data_mem.vhd
831
</pre></pre>
832
<P>
833
 
834
<P><br>
835
 
836
<P>The multiplexer is needed because the data memory is a read/write memory
837
while the program memory was read-only. The multiplexer swaps the upper
838
and lower bytes of <STRONG>DIN</STRONG> when writing to odd addresses.
839
 
840
<H2><A NAME="section_1_3">6.3 Arithmetic/Logic Unit (ALU)</A></H2>
841
 
842
<P>The most obvious component of a CPU is the ALU where all arithmetic and
843
logic operations are computed. We do a little trick here and implement
844
the data move instructions (<STRONG>MOV</STRONG>, <STRONG>LD</STRONG>, <STRONG>ST</STRONG>, etc.) as ALU operations
845
that simply moves the data source to the output of the ALU.
846
The data move instructions can use the same data paths as the arithmetic
847
and logic instructions.
848
 
849
<P>If we look at the instructions set of the CPU then we see that a number
850
of instructions are quite similar. We use these similarities to reduce
851
the number of different instructions that need to be implemented in the ALU.
852
 
853
<UL>
854
  <LI>Some instructions have 8-bit and 16-bit variants (e.g. <STRONG>ADD</STRONG> and <STRONG>ADIW</STRONG>).
855
  <LI>Some instructions have immediate variants (e.g. <STRONG>CMP</STRONG> and <STRONG>CMPI</STRONG>).
856
  <LI>Some instructions differ only in whether they update the destination
857
  register or not (e.g. <STRONG>CMP</STRONG> and <STRONG>SUB</STRONG>).
858
</UL>
859
<P>The ALU is a completely combinational circuit and therefore it has
860
no clock input. We can divide the ALU into a number of blocks that
861
are explained in the following.
862
 
863
<P>6.3.1 <STRONG>D</STRONG> Input Multiplexing.
864
 
865
<P>We have seen earlier that the <STRONG>D</STRONG> input of the ALU is the output of the
866
register pair addressed by <STRONG>DDDDD[4:1]</STRONG> and that the <STRONG>D0</STRONG> input of the ALU
867
is <STRONG>DDDDD[0]</STRONG>:
868
 
869
<P><br>
870
 
871
<pre class="vhdl">
872
 
873
178                     Q_D         => F_D,
874
<pre class="filename">
875
src/data_path.vhd
876
</pre></pre>
877
<P>
878
 
879
<P><br>
880
 
881
<pre class="vhdl">
882
 
883
146                     I_D         => F_D,
884
147                     I_D0        => I_DDDDD(0),
885
<pre class="filename">
886
src/data_path.vhd
887
</pre></pre>
888
<P>
889
 
890
<P><br>
891
 
892
<P>If <STRONG>D0</STRONG> is zero, then the lower byte of the ALU operation comes from
893
the even register regardless of the size (8-bit or 16-bit) of the operation.
894
If <STRONG>D0</STRONG> is odd, then the lower byte of the ALU operation comes from the
895
odd register of the pair (and must be an 8-bit operation since register pairs
896
always have the lowest bit of <STRONG>DDDDD</STRONG> cleared.
897
 
898
<P>The upper byte of the operation (if any) is always the odd register of the pair.
899
 
900
<P>We can therefore compute the lower byte, called <STRONG>D8</STRONG>, from <STRONG>D</STRONG> and <STRONG>D0</STRONG>:
901
 
902
<P><br>
903
 
904
<pre class="vhdl">
905
 
906
356         L_D8 <= I_D(15 downto 8) when (I_D0 = '1') else I_D(7 downto 0);
907
<pre class="filename">
908
src/alu.vhd
909
</pre></pre>
910
<P>
911
 
912
<P><br>
913
 
914
<P>6.3.2 <STRONG>R</STRONG> and <STRONG>IMM</STRONG> Input Multiplexing.
915
 
916
<P>Multiplexing of the <STRONG>R</STRONG> input works like multiplexing of the <STRONG>D</STRONG> input.
917
Some opcodes can have immediate operand instead of a register addressed
918
by <STRONG>RRRRR</STRONG>. We compute the signal <STRONG>R8</STRONG> for opcodes that cannot have
919
an immediate operand, and <STRONG>RI8</STRONG> for opcodes that can have an immediate
920
operand.
921
 
922
<P>This is some fine tuning of the design: the <STRONG>MULT</STRONG> opcodes can take
923
a while to compute but cannot have an immediate operand. It makes
924
therefore sense to have a path from the register addressed by <STRONG>RRRRR</STRONG>
925
to the multiplier and to put the register/immediate multiplexer
926
outside that critical path through the ALU.
927
 
928
<P><br>
929
 
930
<pre class="vhdl">
931
 
932
357         L_R8 <= I_R(15 downto 8) when (I_R0 = '1') else I_R(7 downto 0);
933
358         L_RI8 <= I_IMM           when (I_RSEL = RS_IMM) else L_R8;
934
<pre class="filename">
935
src/alu.vhd
936
</pre></pre>
937
<P>
938
 
939
<P><br>
940
 
941
<H3><A NAME="section_1_3_1">6.3.3 Arithmetic and Logic Functions</A></H3>
942
 
943
<P>The first step in the computation of the arithmetic and logic functions
944
is to compute a number of helper values. The reason for computing them
945
beforehand is that we need these values several times,
946
either for different but similar opcodes (e.g. <STRONG>CMP</STRONG> and <STRONG>SUB</STRONG>) but also
947
for the result and for the flags of the same opcode.
948
 
949
<P><br>
950
 
951
<pre class="vhdl">
952
 
953
360         L_ADIW_D  <= I_D + ("0000000000" & I_IMM(5 downto 0));
954
361         L_SBIW_D  <= I_D - ("0000000000" & I_IMM(5 downto 0));
955
362         L_ADD_DR  <= L_D8 + L_RI8;
956
363         L_ADC_DR  <= L_ADD_DR + ("0000000" & I_FLAGS(0));
957
364         L_ASR_D   <= L_D8(7) & L_D8(7 downto 1);
958
365         L_AND_DR  <= L_D8 and L_RI8;
959
366         L_DEC_D   <= L_D8 - X"01";
960
367         L_INC_D   <= L_D8 + X"01";
961
368         L_LSR_D   <= '0' & L_D8(7 downto 1);
962
369         L_NEG_D   <= X"00" - L_D8;
963
370         L_NOT_D   <= not L_D8;
964
371         L_OR_DR   <= L_D8 or L_RI8;
965
372         L_PROD    <= (L_SIGN_D & L_D8) * (L_SIGN_R & L_R8);
966
373         L_ROR_D   <= I_FLAGS(0) &  L_D8(7 downto 1);
967
374         L_SUB_DR  <= L_D8 - L_RI8;
968
375         L_SBC_DR  <= L_SUB_DR - ("0000000" & I_FLAGS(0));
969
376         L_SIGN_D  <= L_D8(7) and I_IMM(6);
970
377         L_SIGN_R  <= L_R8(7) and I_IMM(5);
971
378         L_SWAP_D  <= L_D8(3 downto 0) & L_D8(7 downto 4);
972
379         L_XOR_DR  <= L_D8 xor L_R8;
973
<pre class="filename">
974
src/alu.vhd
975
</pre></pre>
976
<P>
977
 
978
<P><br>
979
 
980
<P>Most values should be obvious, but a few deserve an explanation:
981
There is a considerable number of multiplication functions that only differ
982
in the signedness of their operands. Instead of implementing a different
983
8-bit multiplier for each opcode, we use a common signed 9-bit multiplier
984
for all opcodes. The opcode decoder sets bits 6 and/or 5 of the <STRONG>IMM</STRONG> input
985
if the <STRONG>D</STRONG> operand and/or the <STRONG>R</STRONG> operand is signed. The signs of the
986
operands are then <STRONG>SIGN_D</STRONG> and <STRONG>SIGN_R</STRONG>; they are 0 for unsigned operations.
987
Next the signs are prepended to the operands so that each operand is 9-bit
988
signed. If the operand was unsigned (and the sign was 0) then the new signed
989
9-bit operand is positive. If the operand was signed and positive (and the
990
sign was 0 again) then the new operand is positive again. If the operand was
991
signed and negative, then the sign was 1 and the new operand is also negative.
992
 
993
<H3><A NAME="section_1_3_2">6.3.4 Output and Flag Multiplexing</A></H3>
994
 
995
<P>The necessary computations in the ALU have already been made in the previous
996
section. What remains is to select the proper result and setting the flags.
997
The output <STRONG>DOUT</STRONG> and the flags are selected by <STRONG>ALU_OP</STRONG>. We take the
998
first two values of <STRONG>ALU_OP</STRONG> as an example and leave the remaining ones
999
as an exercise for the reader.
1000
 
1001
<P><br>
1002
 
1003
<pre class="vhdl">
1004
 
1005
118         process(L_ADC_DR, L_ADD_DR, L_ADIW_D, I_ALU_OP, L_AND_DR, L_ASR_D,
1006
119                 I_BIT, I_D, L_D8, L_DEC_D, I_DIN, I_FLAGS, I_IMM, L_MASK_I,
1007
120                 L_INC_D, L_LSR_D, L_NEG_D, L_NOT_D, L_OR_DR, I_PC, L_PROD,
1008
121                 I_R, L_RI8, L_RBIT, L_ROR_D, L_SBIW_D, L_SUB_DR, L_SBC_DR,
1009
122                 L_SIGN_D, L_SIGN_R, L_SWAP_D, L_XOR_DR)
1010
123         begin
1011
124             Q_FLAGS(9) <= L_RBIT xor not I_BIT(3);      -- DIN[BIT] = BIT[3]
1012
125             Q_FLAGS(8) <= ze(L_SUB_DR);                 -- D == R for CPSE
1013
126             Q_FLAGS(7 downto 0) <= I_FLAGS;
1014
127             L_DOUT <= X"0000";
1015
128
1016
129             case I_ALU_OP is
1017
130                 when ALU_ADC =>
1018
131                     L_DOUT <= L_ADC_DR & L_ADC_DR;
1019
132                     Q_FLAGS(0) <= cy(L_D8(7), L_RI8(7), L_ADC_DR(7));   -- Carry
1020
133                     Q_FLAGS(1) <= ze(L_ADC_DR);                         -- Zero
1021
134                     Q_FLAGS(2) <= L_ADC_DR(7);                          -- Negative
1022
135                     Q_FLAGS(3) <= ov(L_D8(7), L_RI8(7), L_ADC_DR(7));   -- Overflow
1023
136                     Q_FLAGS(4) <= si(L_D8(7), L_RI8(7), L_ADC_DR(7));   -- Signed
1024
137                     Q_FLAGS(5) <= cy(L_D8(3), L_RI8(3), L_ADC_DR(3));   -- Halfcarry
1025
138
1026
139                 when ALU_ADD =>
1027
140                     L_DOUT <= L_ADD_DR & L_ADD_DR;
1028
141                     Q_FLAGS(0) <= cy(L_D8(7), L_RI8(7), L_ADD_DR(7));   -- Carry
1029
142                     Q_FLAGS(1) <= ze(L_ADD_DR);                         -- Zero
1030
143                     Q_FLAGS(2) <= L_ADD_DR(7);                          -- Negative
1031
144                     Q_FLAGS(3) <= ov(L_D8(7), L_RI8(7), L_ADD_DR(7));   -- Overflow
1032
145                     Q_FLAGS(4) <= si(L_D8(7), L_RI8(7), L_ADD_DR(7));   -- Signed
1033
146                     Q_FLAGS(5) <= cy(L_D8(3), L_RI8(3), L_ADD_DR(3));   -- Halfcarry
1034
<pre class="filename">
1035
src/alu.vhd
1036
</pre></pre>
1037
<P>
1038
 
1039
<P><br>
1040
 
1041
<P>First of all, the default values for the flags and the ALU output are chosen.
1042
The default of <STRONG>L_OUT</STRONG> is 0, while the default for <STRONG>O_FLAGS</STRONG> is <STRONG>I_FLAGS</STRONG>. This
1043
means that all flags that are not explicitly changed remain the same.
1044
The upper two flag bits are set according to specific needs of certain
1045
skip instructions (CPSE, SBIC, SBIS, SBRC, and SBRS).
1046
 
1047
<P>Then comes a big case statement for which we explain only the first two cases,
1048
<STRONG>ALU_ADC</STRONG> and <STRONG>ALU_ADD</STRONG>.
1049
 
1050
<P>The expected value of <STRONG>DOUT</STRONG> was already computed as <STRONG>L_ADC_DR</STRONG>
1051
in the previous section and this value is assigned to <STRONG>DOUT</STRONG>.
1052
 
1053
<P>After that the flags that can change in the execution of the <STRONG>ADC</STRONG> opcode
1054
are computed. The computation of flags is very similar for a number of
1055
different opcodes. We have therefore defined functions <STRONG>cy()</STRONG>, <STRONG>ze()</STRONG>,
1056
<STRONG>ov()</STRONG>, and <STRONG>si()</STRONG> for the usual way of computing these flags:
1057
 
1058
<P>The half-carry flags is computed like the carry flag but on bits 3 rather
1059
than bits 7 of the operands and result.
1060
 
1061
<P>The next example is <STRONG>ADD</STRONG>. It is similar to <STRONG>ADC</STRONG>, but now <STRONG>L_ADD_DR</STRONG>
1062
is used instead of <STRONG>L_ADC_DR</STRONG>.
1063
 
1064
<H3><A NAME="section_1_3_3">6.3.5 Individual ALU Operations</A></H3>
1065
 
1066
<P>The following table briefly describes how the <STRONG>DOUT</STRONG> output of the ALU
1067
is computed for the different <STRONG>ALU_OP</STRONG> values.
1068
 
1069
<TABLE>
1070
<TR><TD><STRONG>ALU_OP</STRONG></TD><TD><STRONG>DOUT</STRONG></TD><TD ALIGN="RIGHT"><STRONG>Size</STRONG>
1071
</TD></TR><TR><TD>ALU_ADC</TD><TD>D + R + Carry</TD><TD ALIGN="RIGHT">8-bit
1072
</TD></TR><TR><TD>ALU_ADD</TD><TD>D + R</TD><TD ALIGN="RIGHT">8-bit
1073
</TD></TR><TR><TD>ALU_ADIW</TD><TD>D + IMM</TD><TD ALIGN="RIGHT">16-bit
1074
</TD></TR><TR><TD>ALU_AND</TD><TD>D and R</TD><TD ALIGN="RIGHT">8-bit
1075
</TD></TR><TR><TD>ALU_ASR</TD><TD>D &gt;&gt; 1</TD><TD ALIGN="RIGHT">8-bit
1076
</TD></TR><TR><TD>ALU_BLD</TD><TD>T-flag &lt;&lt; IMM</TD><TD ALIGN="RIGHT">8-bit
1077
</TD></TR><TR><TD>ALU_BST</TD><TD>(set T-flag)</TD><TD ALIGN="RIGHT">8-bit
1078
</TD></TR><TR><TD>ALU_COM</TD><TD>not D</TD><TD ALIGN="RIGHT">8-bit
1079
</TD></TR><TR><TD>ALU_DEC</TD><TD>D - 1</TD><TD ALIGN="RIGHT">8-bit
1080
</TD></TR><TR><TD>ALU_EOR</TD><TD>D xor R</TD><TD ALIGN="RIGHT">8-bit
1081
</TD></TR><TR><TD>ALU_IN</TD><TD>DIN</TD><TD ALIGN="RIGHT">8-bit
1082
</TD></TR><TR><TD>ALU_INC</TD><TD>D + 1</TD><TD ALIGN="RIGHT">8-bit
1083
</TD></TR><TR><TD>ALU_LSR</TD><TD>D &gt;&gt; 1</TD><TD ALIGN="RIGHT">8-bit
1084
</TD></TR><TR><TD>ALU_D_MOV_Q</TD><TD>D</TD><TD ALIGN="RIGHT">16-bit
1085
</TD></TR><TR><TD>ALU_R_MOV_Q</TD><TD>R</TD><TD ALIGN="RIGHT">16-bit
1086
</TD></TR><TR><TD>ALU_MULT</TD><TD>D * R</TD><TD ALIGN="RIGHT">16-bit
1087
</TD></TR><TR><TD>ALU_NEG</TD><TD>0 - D</TD><TD ALIGN="RIGHT">8-bit
1088
</TD></TR><TR><TD>ALU_OR</TD><TD>A or R</TD><TD ALIGN="RIGHT">8-bit
1089
</TD></TR><TR><TD>ALU_PC</TD><TD>PC</TD><TD ALIGN="RIGHT">16-bit
1090
</TD></TR><TR><TD>ALU_PC_1</TD><TD>PC + 1</TD><TD ALIGN="RIGHT">16-bit
1091
</TD></TR><TR><TD>ALU_PC_2</TD><TD>PC + 2</TD><TD ALIGN="RIGHT">16-bit
1092
</TD></TR><TR><TD>ALU_ROR</TD><TD>D rotated right</TD><TD ALIGN="RIGHT">8-bit
1093
</TD></TR><TR><TD>ALU_SBC</TD><TD>D - R - Carry</TD><TD ALIGN="RIGHT">8-bit
1094
</TD></TR><TR><TD>ALU_SBIW</TD><TD>D - IMM</TD><TD ALIGN="RIGHT">16-bit
1095
</TD></TR><TR><TD>ALU_SREG</TD><TD>(set a flag)</TD><TD ALIGN="RIGHT">8-bit
1096
</TD></TR><TR><TD>ALU_SUB</TD><TD>D - R</TD><TD ALIGN="RIGHT">8-bit
1097
</TD></TR><TR><TD>ALU_SWAP</TD><TD>D[3:0] &amp; D[7:4]</TD><TD ALIGN="RIGHT">8-bit
1098
</TD></TR>
1099
</TABLE>
1100
<P>For all 8-bit computations, the result is placed onto the upper and
1101
onto the lower byte of <STRONG>L_DOUT</STRONG>. This saves a multiplexer at the
1102
inputs of the registers.
1103
 
1104
<P>The final result of the ALU is obtained by multiplexing the local result
1105
<STRONG>L_DOUT</STRONG> and <STRONG>DIN</STRONG> based on <STRONG>I_RSEL</STRONG>.
1106
 
1107
<P><br>
1108
 
1109
<pre class="vhdl">
1110
 
1111
381         Q_DOUT <= (I_DIN & I_DIN) when (I_RSEL = RS_DIN) else L_DOUT;
1112
<pre class="filename">
1113
src/alu.vhd
1114
</pre></pre>
1115
<P>
1116
 
1117
<P><br>
1118
 
1119
<P>We could have placed this multiplexer at the <STRONG>R</STRONG> input (combined with the
1120
multiplexer for the <STRONG>DIN</STRONG> input) or at the <STRONG>DOUT</STRONG> output. Placing it at
1121
the output gives a better timing, since the opcodes using the DIN input
1122
do not perform ALU operations.
1123
 
1124
<H3><A NAME="section_1_3_4">6.3.5 Temporary Z and T Flags</A></H3>
1125
 
1126
<P>There are two opcodes that use the value of the <STRONG>Z</STRONG> flag (<STRONG>CPSE</STRONG>) or
1127
the #T flag (SBIC, SBIS) without setting them. For timing
1128
reasons, they are executed in two cycles - one cycle for performing a
1129
comparison or a bit access and a second cycle for actually making the
1130
decision to skip the next instruction or not.
1131
 
1132
<P>For this reason we have introduced copies of the <STRONG>Z</STRONG> and <STRONG>T</STRONG> flags and called
1133
them <STRONG>FLAGS_98</STRONG>. They store the values of these flags within an instruction,
1134
but without updating the status register. The two flags are computed in
1135
the ALU:
1136
 
1137
<P><br>
1138
 
1139
<pre class="vhdl">
1140
 
1141
124             Q_FLAGS(9) <= L_RBIT xor not I_BIT(3);      -- DIN[BIT] = BIT[3]
1142
125             Q_FLAGS(8) <= ze(L_SUB_DR);                 -- D == R for CPSE
1143
<pre class="filename">
1144
src/alu.vhd
1145
</pre></pre>
1146
<P>
1147
 
1148
<P><br>
1149
 
1150
<P><br>
1151
 
1152
<P>The result is stored in the data path:
1153
 
1154
<pre class="vhdl">
1155
 
1156
195         flg98: process(I_CLK)
1157
196         begin
1158
197             if (rising_edge(I_CLK)) then
1159
198                 L_FLAGS_98 <= A_FLAGS(9 downto 8);
1160
199             end if;
1161
200         end process;
1162
<pre class="filename">
1163
src/data_path.vhd
1164
</pre></pre>
1165
<P>
1166
 
1167
<P><br>
1168
 
1169
<H2><A NAME="section_1_4">6.4 Other Functions</A></H2>
1170
 
1171
<P>Most of the data path is contained in its components <STRONG>alu</STRONG>, <STRONG>register_file</STRONG>,
1172
and <STRONG>data_mem</STRONG>. A few things are written directly in VHDL and shall be
1173
explained here.
1174
 
1175
<P>Some output signals are driven directly from inputs or from instantiated
1176
components:
1177
 
1178
<P><br>
1179
 
1180
<pre class="vhdl">
1181
 
1182
231         Q_ADR     <= F_ADR;
1183
232         Q_DOUT    <= A_DOUT(7 downto 0);
1184
233         Q_INT_ENA <= A_FLAGS(7);
1185
234         Q_OPC     <= I_OPC;
1186
235         Q_PC      <= I_PC;
1187
<pre class="filename">
1188
src/data_path.vhd
1189
</pre></pre>
1190
<P>
1191
 
1192
<P><br>
1193
 
1194
<P>The address space of the data memory is spread over the register file (general
1195
purpose registers, stack pointer, and status register), the data RAM, and the
1196
external I/O registers outside of the data path. The external I/O registers
1197
reach from 0x20 to 0x5C (including) and the data RAM starts at 0x60. We
1198
generate write enable signals for these address ranges, and a read strobe for
1199
external I/O registers. We also control the multiplexer at the input of the
1200
ALU by the address output of the register file:
1201
 
1202
<P><br>
1203
 
1204
<pre class="vhdl">
1205
 
1206
237         Q_RD_IO   <= '0'                    when (F_ADR < X"20")
1207
238                 else (I_RD_M and not I_PMS) when (F_ADR < X"5D")
1208
239                 else '0';
1209
240         Q_WE_IO   <= '0'                    when (F_ADR < X"20")
1210
241                 else I_WE_M(0)              when (F_ADR < X"5D")
1211
242                 else '0';
1212
243         L_WE_SRAM <= "00"   when  (F_ADR < X"0060") else I_WE_M;
1213
244         L_DIN     <= I_DIN  when (I_PMS = '1')
1214
245                 else F_S    when  (F_ADR < X"0020")
1215
246                 else I_DIN  when  (F_ADR < X"005D")
1216
247                 else F_S    when  (F_ADR < X"0060")
1217
248                 else M_DOUT(7 downto 0);
1218
<pre class="filename">
1219
src/data_path.vhd
1220
</pre></pre>
1221
<P>
1222
 
1223
<P><br>
1224
 
1225
<P>Most instructions that modify the program counter (other than incrementing
1226
it) use addresses that are being provided on the <STRONG>IMM</STRONG> input (from the
1227
opcode decoder).<BR>
1228
The two exceptions are the <STRONG>IJMP</STRONG> instruction where the new <STRONG>PC</STRONG> value is the
1229
value of the <STRONG>Z</STRONG> register pair, and the <STRONG>RET</STRONG> and <STRONG>RETI</STRONG> instructions where the
1230
new <STRONG>PC</STRONG> value is popped from the stack. The new value of the <STRONG>PC</STRONG> (if any) is
1231
therefore:
1232
 
1233
<P><br>
1234
 
1235
<pre class="vhdl">
1236
 
1237
252         Q_NEW_PC <= F_Z    when I_PC_OP = PC_LD_Z       -- IJMP, ICALL
1238
253                else M_DOUT when I_PC_OP = PC_LD_S       -- RET, RETI
1239
254                else I_JADR;                             -- JMP adr
1240
<pre class="filename">
1241
src/data_path.vhd
1242
</pre></pre>
1243
<P>
1244
 
1245
<P><br>
1246
 
1247
<P>Conditional branches use the <STRONG>CC</STRONG> output of the register file in order to
1248
decide whether the branch shall be taken or not. The opcode decoder
1249
drives the <STRONG>COND</STRONG> input according to the relevant bit in the status register
1250
(<STRONG>I_COND[2:0]</STRONG>) and according to the expected value (<STRONG>COND[3]</STRONG>) of that bit.
1251
 
1252
<P>The <STRONG>LOAD_PC</STRONG> output is therefore '1' for unconditional branches and <STRONG>CC</STRONG>
1253
for conditional branches:
1254
 
1255
<P><br>
1256
 
1257
<pre class="vhdl">
1258
 
1259
205         process(I_PC_OP, F_CC)
1260
206         begin
1261
207             case I_PC_OP is
1262
208                 when PC_BCC  => Q_LOAD_PC <= F_CC;      -- maybe (PC on I_JADR)
1263
209                 when PC_LD_I => Q_LOAD_PC <= '1';       -- yes: new PC on I_JADR
1264
210                 when PC_LD_Z => Q_LOAD_PC <= '1';       -- yes: new PC in Z
1265
211                 when PC_LD_S => Q_LOAD_PC <= '1';       -- yes: new PC on stack
1266
212                 when others  => Q_LOAD_PC <= '0';       -- no.
1267
213             end case;
1268
214         end process;
1269
<pre class="filename">
1270
src/data_path.vhd
1271
</pre></pre>
1272
<P>
1273
 
1274
<P><br>
1275
 
1276
<P>When a branch is taken (in the execution stage of the pipeline), then the next
1277
instruction after the branch is about to be decoded in the opcode decoder
1278
stage. This instruction must not be executed, however, and we therefore
1279
invalidate it by asserting the <STRONG>SKIP</STRONG> output.
1280
Another case where instructions need to be invalidated are skip instructions
1281
(<STRONG>CPSE</STRONG>, <STRONG>SBIC</STRONG>, <STRONG>SBIS</STRONG>, <STRONG>SBRC</STRONG>, and <STRONG>SBRS</STRONG>). These instructions do not
1282
modify the <STRONG>PC</STRONG>, but they nevertheless cause the next instruction to be
1283
invalidated:
1284
 
1285
<P><br>
1286
 
1287
<pre class="vhdl">
1288
 
1289
218         process(I_PC_OP, L_FLAGS_98, F_CC)
1290
219         begin
1291
220             case I_PC_OP is
1292
221                 when PC_BCC    => Q_SKIP <= F_CC;           -- if cond met
1293
222                 when PC_LD_I   => Q_SKIP <= '1';            -- yes
1294
223                 when PC_LD_Z   => Q_SKIP <= '1';            -- yes
1295
224                 when PC_LD_S   => Q_SKIP <= '1';            -- yes
1296
225                 when PC_SKIP_Z => Q_SKIP <= L_FLAGS_98(8);  -- if Z set
1297
226                 when PC_SKIP_T => Q_SKIP <= L_FLAGS_98(9);  -- if T set
1298
227                 when others    => Q_SKIP <= '0';            -- no.
1299
228             end case;
1300
229         end process;
1301
<pre class="filename">
1302
src/data_path.vhd
1303
</pre></pre>
1304
<P>
1305
 
1306
<P><br>
1307
 
1308
<P>This concludes the discussion of the data path. We have now installed
1309
the environment that is needed to execute opcodes.
1310
 
1311
<P><hr><BR>
1312
<table class="ttop"><th class="tpre"><a href="05_Opcode_Fetch.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="07_Opcode_Decoder.html">Next Lesson</a></th></table>
1313
</BODY>
1314
</HTML>

powered by: WebSVN 2.1.0

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