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

Subversion Repositories cpu_lecture

[/] [cpu_lecture/] [trunk/] [html/] [09_Toolchain_Setup.html] - Blame information for rev 9

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/Toolchain_Setup</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="08_IO.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="10_Listing_of_alu_vhd.html">Next Lesson</a></th></table>
11
<hr>
12
 
13
<H1><A NAME="section_1">9 TOOLCHAIN SETUP</A></H1>
14
 
15
<P>In this lesson we will learn how to set up a toolchain on a Linux box.
16
We will not describe, however, how the tools are downloaded and installed.
17
The installation of a tools is normally described in the documentation
18
that comes with the tool.
19
 
20
<P>Places from where tools can be downloaded were already presented in the
21
first lecture.
22
 
23
<P>The following figure gives an overview of the entire flow. We show source files
24
in yellow, temporary files in white and tools in green.
25
 
26
<P><br>
27
 
28
<P><img src="toolchain_1.png">
29
 
30
<P><br>
31
 
32
<P>We start with a C source file <STRONG>hello.c</STRONG>. This file is compiled with <STRONG>avr-gcc</STRONG>,
33
a <STRONG>gcc</STRONG> variant that generates opcodes for the AVR CPU. The compilation
34
produces 2 output files: <STRONG>hello.lss</STRONG> and <STRONG>hello.hex</STRONG>.
35
 
36
<P><STRONG>hello.lss</STRONG> is a listing file and may optionally be post-processed by the
37
tool <STRONG>end_conv</STRONG> which converts the little-endian format of <STRONG>hello.lss</STRONG> into
38
a slightly different format that is more in line with the way gtkwave shows
39
the hex values of signals.
40
 
41
<P>The main purpose of the compilation is to produce <STRONG>hello.hex</STRONG>. <STRONG>hello.hex</STRONG>
42
contains the opcodes produced from <STRONG>hello.c</STRONG> in Intel-Hex format.
43
 
44
<P><STRONG>hello.hex</STRONG> is then fed into <STRONG>make_mem</STRONG>. <STRONG>make_mem</STRONG> is a tool that converts
45
the Intel-Hex format into VHDL constants. These constants are used to
46
initialize the block RAM modules of the program memory. The output of
47
<STRONG>make_mem</STRONG> is <STRONG>memory_content.vhd</STRONG> (which, as you certainly remember,
48
was included by <STRONG>prog_mem.vhd</STRONG>).
49
 
50
<P>At this point, there are two possible ways to proceed. You could do a
51
functional simulation or a timing simulation.
52
 
53
<H2><A NAME="section_1_1">8.1 Functional Simulation</A></H2>
54
 
55
<P>Initially you will be concerned mostly with the functional simulation.
56
On this branch you debug the VHDL code until it looks functionally OK.
57
In order to perform the functional simulation, you need 3 sorts of VHDL files:
58
 
59
<OL>
60
  <LI>The VHLD source files that were discussed in the previous lessons,
61
  <LI>the <STRONG>memory_content.vhd</STRONG> just described, and
62
  <LI>a testbench that mimics the board containing the FPGA to be (<STRONG>test_tb.vhd</STRONG>,
63
   and a VHDL implementation of device specific components used (in our case
64
   this is only <STRONG>RAMB4_S4_S4.vhd</STRONG>). Both files are provided in the directory
65
   called <STRONG>test</STRONG>.
66
</OL>
67
<P>All these VHDL files are then processed by <STRONG>ghdl</STRONG>. <STRONG>ghdl</STRONG> produces a single
68
output file <STRONG>testbench</STRONG> in directory <STRONG>simu</STRONG>. <STRONG>testbench</STRONG> is an executable
69
file. <STRONG>testbench</STRONG> is then run in order to produces a gzip'ed <STRONG>vcd</STRONG> (value change
70
dump) file called <STRONG>testbench.vcdgz</STRONG>.
71
 
72
<P>The last step is visualize <STRONG>testbench.vcdgz</STRONG> by means of the tool <STRONG>gtkwave</STRONG>.
73
<STRONG>gtkwave</STRONG> is similar to the <STRONG>ModelSim</STRONG> provided by Xilinx, but it has
74
two advantages: it does not bother the user with licence installations
75
(even in the "free" versions provided by Xilinx) and it runs under Linux.
76
There are actually more advantages of the <STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG> combination;
77
after having used both tools in the past the author definitely prefers
78
<STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG>.
79
 
80
<P>An example output of the functional simulation that shows the  operation
81
our CPU:
82
 
83
<P><br>
84
 
85 9 jsauermann
<P><img src="GTKWave.PNG">
86 2 jsauermann
 
87
<P><br>
88
 
89
<P>We can compare the CPU signals shown with the assembler code being executed.
90
The CPU is executing inside the C function <STRONG>uart_puts()</STRONG>:
91
 
92
<P><br>
93
 
94
<pre class="vhdl">
95
 
96
<pre class="filename">
97
app/hello.lss1
98
</pre></pre>
99
<P>
100
 
101
<P><br>
102
 
103
<H2><A NAME="section_1_2">8.2 Timing Simulation and FPGA Configuration</A></H2>
104
 
105
<P>After the CPU functions correctly, the design can be fed into the Xilinx
106
toolchain. This toolchain is better described in the documentation that
107
comes with it, so we don't go to too much detail here.
108
 
109
<P>We used Webpack 10.1, which can be downloaded from Xilinx.
110
 
111
<P>The first step is to set up a project in the ISE project navigator with
112
the proper target device. Then the VHDL files in the <STRONG>src</STRONG> directory are
113
added to the project. Next the <STRONG>Synthesize</STRONG> and <STRONG>Implementation</STRONG> steps
114
of the design flow are run.
115
 
116
<P>If this is successful, then we can generate a programming file. There are
117
a number of ways to configure Xilinx FPGAs, and the type of programming file
118
needed depends on the particular way of configuring the device. The board
119
we used for testing the CPU had a serial PROM and therefore we generated
120
a programming file for the serial PROM on the board. The FPGA would then
121
load from the PROM on start-up. Other ways of configuring the device are
122
via JTAG, which is also quite handy during debugging.
123
 
124
<P>The entire build process is a little lengthy (and the devil is known to
125
hide in the details). We therefore go through the entire design flow in
126
a step-by-step fashion.
127
 
128
<H2><A NAME="section_1_3">8.3 Downloading and Building the Tools </A></H2>
129
 
130
<UL>
131
  <LI>Download and install <STRONG>ghdl</STRONG>.
132
  <LI>Download and install <STRONG>gtkwave</STRONG>.
133
  <LI>Download and install the Xilinx toolchain.
134
  <LI>Build the <STRONG>make_mem</STRONG> tool. The source is this:
135
</UL>
136
<P><br>
137
 
138
<pre class="vhdl">
139
 
140
  1     #include "assert.h"
141
  2     #include "stdio.h"
142
  3     #include "stdint.h"
143
  4     #include "string.h"
144
  5
145 9 jsauermann
  6     uint8_t buffer[0x10000];    // 64 k is max. for Intel hex.
146
  7     uint8_t slice [0x10000];    // 16 k is max. for Xilinx bram
147 2 jsauermann
  8
148 9 jsauermann
  9     //-----------------------------------------------------------------------------
149
 10     //
150
 11     // get a byte (from cp pointing into Intel hex file).
151
 12     //
152
 13     uint32_t
153
 14     get_byte(const char *  cp)
154
 15     {
155
 16     uint32_t value;
156
 17     const char cc[3] = { cp[0], cp[1], 0 };
157
 18     const int cnt = sscanf(cc, "%X", &value);
158
 19        assert(cnt == 1);
159
 20        return value;
160
 21     }
161
 22     //-----------------------------------------------------------------------------
162
 23     //
163
 24     // read an Intel hex file into buffer
164
 25     void
165
 26     read_file(FILE * in)
166
 27     {
167
 28        memset(buffer, 0xFF, sizeof(buffer));
168
 29     char line[200];
169
 30        for (;;)
170
 31            {
171
 32              const char * s = fgets(line, sizeof(line) - 2, in);
172
 33              if (s == 0)   return;
173
 34              assert(*s++ == ':');
174
 35              const uint32_t len     = get_byte(s);
175
 36              const uint32_t ah      = get_byte(s + 2);
176
 37              const uint32_t al      = get_byte(s + 4);
177
 38              const uint32_t rectype = get_byte(s + 6);
178
 39              const char * d = s + 8;
179
 40              const uint32_t addr = ah << 8 | al;
180
 41
181
 42              uint32_t csum = len + ah + al + rectype;
182
 43              assert((addr + len) <= 0x10000);
183
 44              for (uint32_t l = 0; l < len; ++l)
184
 45                  {
185
 46                    const uint32_t byte = get_byte(d);
186
 47                    d += 2;
187
 48                    buffer[addr + l] = byte;
188
 49                    csum += byte;
189
 50                  }
190
 51
191
 52              csum = 0xFF & -csum;
192
 53              const uint32_t sum = get_byte(d);
193
 54              assert(sum == csum);
194
 55            }
195
 56     }
196
 57     //-----------------------------------------------------------------------------
197
 58     //
198
 59     // copy a slice from buffer into slice.
199
 60     // buffer is organized as 32-bit x items.
200
 61     // slice is organized as bits x items.
201
 62     //
202
 63     void copy_slice(uint32_t slice_num, uint32_t port_bits, uint32_t mem_bits)
203
 64     {
204
 65        assert(mem_bits == 0x1000 || mem_bits == 0x4000);
205
 66
206
 67     const uint32_t items = mem_bits/port_bits;
207
 68     const uint32_t mask = (1 << port_bits) - 1;
208
 69     const uint8_t * src = buffer;
209
 70
210
 71         memset(slice, 0, sizeof(slice));
211
 72
212
 73         for (uint32_t i = 0; i < items; ++i)
213
 74             {
214
 75               // read one 32-bit value;
215
 76               const uint32_t v0 = *src++;
216
 77               const uint32_t v1 = *src++;
217
 78               const uint32_t v2 = *src++;
218
 79               const uint32_t v3 = *src++;
219
 80               const uint32_t v = (v3 << 24 |
220
 81                                   v2 << 16 |
221
 82                                   v1 <<  8 |
222
 83                                   v0       ) >> (slice_num*port_bits) & mask;
223
 84
224
 85               if (port_bits == 16)
225
 86                  {
226
 87                    assert(v < 0x10000);
227
 88                    slice[2*i]     = v;
228
 89                    slice[2*i + 1] = v >> 8;
229
 90                  }
230
 91               else if (port_bits == 8)
231
 92                  {
232
 93                    assert(v < 0x100);
233
 94                    slice[i] = v;
234
 95                  }
235
 96               else if (port_bits == 4)
236
 97                  {
237
 98                    assert(v < 0x10);
238
 99                    slice[i >> 1] |= v << (4*(i & 1));
239
100                  }
240
101               else if (port_bits == 2)
241
102                  {
242
103                    assert(v < 0x04);
243
104                    slice[i >> 2] |= v << (2*(i & 3));
244
105                  }
245
106               else if (port_bits == 1)
246
107                  {
247
108                    assert(v < 0x02);
248
109                    slice[i >> 3] |= v << ((i & 7));
249
110                  }
250
111               else assert(0 && "Bad aspect ratio.");
251
112             }
252
113     }
253
114     //-----------------------------------------------------------------------------
254
115     //
255
116     // write one initialization vector
256
117     //
257
118     void
258
119     write_vector(FILE * out, uint32_t mem, uint32_t vec, const uint8_t * data)
259
120     {
260
121        fprintf(out, "constant p%u_%2.2X : BIT_VECTOR := X\"", mem, vec);
261
122        for (int32_t d = 31; d >= 0; --d)
262
123            fprintf(out, "%2.2X", data[d]);
263
124
264
125        fprintf(out, "\";\r\n");
265
126     }
266
127     //-----------------------------------------------------------------------------
267
128     //
268
129     // write one memory
269
130     //
270
131     void
271
132     write_mem(FILE * out, uint32_t mem, uint32_t bytes)
272
133     {
273
134        fprintf(out, "-- content of p_%u --------------------------------------"
274
135                     "--------------------------------------------\r\n", mem);
275
136
276
137     const uint8_t * src = slice;
277
138        for (uint32_t v = 0; v < bytes/32; ++v)
278
139            write_vector(out, mem, v, src + 32*v);
279
140
280
141        fprintf(out, "\r\n");
281
142     }
282
143     //-----------------------------------------------------------------------------
283
144     //
284
145     // write the entire memory_contents file.
285
146     //
286
147     void
287
148     write_file(FILE * out, uint32_t bits)
288
149     {
289
150        fprintf(out,
290
151     "\r\n"
291
152     "library IEEE;\r\n"
292
153     "use IEEE.STD_LOGIC_1164.all;\r\n"
293
154     "\r\n"
294
155     "package prog_mem_content is\r\n"
295
156     "\r\n");
296
157
297
158     const uint32_t mems = 16/bits;
298
159
299
160        for (uint32_t m = 0; m < 2*mems; ++m)
300
161            {
301
162              copy_slice(m, bits, 0x1000);
302
163              write_mem(out, m, 0x200);
303
164            }
304
165
305
166        fprintf(out,
306
167     "end prog_mem_content;\r\n"
307
168     "\r\n");
308
169     }
309
170     //-----------------------------------------------------------------------------
310
171     int
311
172     main(int argc, char * argv[])
312
173     {
313
174     uint32_t bits = 4;
314
175     const char * prog = *argv++;   --argc;
315
176
316
177        if      (argc && !strcmp(*argv, "-1"))    { bits =  1;   ++argv;   --argc; }
317
178        else if (argc && !strcmp(*argv, "-2"))    { bits =  2;   ++argv;   --argc; }
318
179        else if (argc && !strcmp(*argv, "-4"))    { bits =  4;   ++argv;   --argc; }
319
180        else if (argc && !strcmp(*argv, "-8"))    { bits =  8;   ++argv;   --argc; }
320
181        else if (argc && !strcmp(*argv, "-16"))   { bits = 16;   ++argv;   --argc; }
321
182
322
183     const char * hex_file = 0;
323
184     const char * vhdl_file = 0;
324
185
325
186        if (argc)   { hex_file  = *argv++;   --argc; }
326
187        if (argc)   { vhdl_file = *argv++;   --argc; }
327
188        assert(argc == 0);
328
189
329
190     FILE * in = stdin;
330
191        if (hex_file)   in = fopen(hex_file, "r");
331
192        assert(in);
332
193        read_file(in);
333
194        fclose(in);
334
195
335
196     FILE * out = stdout;
336
197        if (vhdl_file)   out = fopen(vhdl_file, "w");
337
198        write_file(out, bits);
338
199        assert(out);
339
200     }
340
201     //-----------------------------------------------------------------------------
341 2 jsauermann
<pre class="filename">
342
tools/make_mem.cc
343
</pre></pre>
344
<P>
345
 
346
<P><br>
347
 
348
<P>The command to build the tool is:
349
 
350
<P><br>
351
 
352
<pre class="cmd">
353
 
354
# Build makemem.
355
g++ -o make_mem make_mem.cc
356
 
357
</pre>
358
<P>
359
 
360
<P><br>
361
 
362
<UL>
363
  <LI>Build the <STRONG>end_conv</STRONG> tool. The source is this:
364
</UL>
365
<P><br>
366
 
367
<pre class="vhdl">
368
 
369
  1     #include "assert.h"
370
  2     #include "ctype.h"
371
  3     #include "stdio.h"
372
  4     #include "string.h"
373
  5
374
  6     //-----------------------------------------------------------------------------
375
  7     int
376
  8     main(int argc, const char * argv)
377
  9     {
378
 10     char buffer[2000];
379
 11     int pc, val, val2;
380
 12
381
 13        for (;;)
382
 14            {
383
 15              char * s = fgets(buffer, sizeof(buffer) - 2, stdin);
384
 16              if (s == 0)   return 0;
385
 17
386
 18              // map lines '  xx:' and 'xxxxxxxx; to 2* the hex value.
387
 19              //
388
 20              if (
389
 21                  (isxdigit(s[0]) || s[0] == ' ') &&
390
 22                  (isxdigit(s[1]) || s[1] == ' ') &&
391
 23                  (isxdigit(s[2]) || s[2] == ' ') &&
392
 24                   isxdigit(s[3]) && s[4] == ':')   // '  xx:'
393
 25                 {
394
 26                   assert(1 == sscanf(s, " %x:", &pc));
395
 27                   if (pc & 1)       printf("%4X+:", pc/2);
396
 28                   else              printf("%4X:", pc/2);
397
 29                   s += 5;
398
 30                 }
399
 31              else if (isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) &&
400
 32                       isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) &&
401
 33                       isxdigit(s[6]) && isxdigit(s[7]))             // 'xxxxxxxx'
402
 34                 {
403
 35                   assert(1 == sscanf(s, "%x", &pc));
404
 36                   if (pc & 1)   printf("%8.8X+:", pc/2);
405
 37                   else          printf("%8.8X:", pc/2);
406
 38                   s += 8;
407
 39                 }
408
 40              else                             // other: copy verbatim
409
 41                 {
410
 42                   printf("%s", s);
411
 43                   continue;
412
 44                 }
413
 45
414
 46               while (isblank(*s))   printf("%c", *s++);
415
 47
416
 48               // endian swap.
417
 49               //
418
 50               while (isxdigit(s[0]) &&
419
 51                      isxdigit(s[1]) &&
420
 52                               s[2] == ' ' &&
421
 53                      isxdigit(s[3]) &&
422
 54                      isxdigit(s[4]) &&
423
 55                               s[5] == ' ')
424
 56                  {
425
 57                   assert(2 == sscanf(s, "%x %x ", &val, &val2));
426
 58                   printf("%2.2X%2.2X  ", val2, val);
427
 59                   s += 6;
428
 60                  }
429
 61
430
 62              char * s1 = strstr(s, ".+");
431
 63              char * s2 = strstr(s, ".-");
432
 64              if (s1)
433
 65                 {
434
 66                   assert(1 == sscanf(s1 + 2, "%d", &val));
435
 67                   assert((val & 1) == 0);
436
 68                   sprintf(s1, " 0x%X", (pc + val)/2 + 1);
437
 69                   printf(s);
438
 70                   s = s1 + strlen(s1) + 1;
439
 71                 }
440
 72              else if (s2)
441
 73                 {
442
 74                   assert(1 == sscanf(s2 + 2, "%d", &val));
443
 75                   assert((val & 1) == 0);
444
 76                   sprintf(s2, " 0x%X", (pc - val)/2 + 1);
445
 77                   printf(s);
446
 78                   s = s2 + strlen(s2) + 1;
447
 79                 }
448
 80
449
 81              printf("%s", s);
450
 82            }
451
 83     }
452
 84     //-----------------------------------------------------------------------------
453
<pre class="filename">
454
tools/end_conv.cc
455
</pre></pre>
456
<P>
457
 
458
<P><br>
459
 
460
<P>The command to build the tool is:
461
 
462
<P><br>
463
 
464
<pre class="cmd">
465
 
466
# Build end_conv.
467
g++ -o end_conv end_conv.cc
468
 
469
</pre>
470
<P>
471
 
472
<P><br>
473
 
474
<H2><A NAME="section_1_4">8.4 Preparing the Memory Content</A></H2>
475
 
476
<P>We write a program <STRONG>hello.c</STRONG> that prints "Hello World" to the serial line.
477
 
478
<P>The source is this:
479
 
480
<P><br>
481
 
482
<pre class="vhdl">
483
 
484
  1     #include "stdint.h"
485
  2     #include "avr/io.h"
486
  3     #include "avr/pgmspace.h"
487
  4
488
  5     #undef F_CPU
489
  6     #define F_CPU 25000000UL
490
  7     #include "util/delay.h"
491
  8
492
  9
493
 10          //----------------------------------------------------------------------//
494
 11         //                                                                      //
495
 12        //   print char cc on UART.                                             //
496
 13       //    return number of chars printed (i.e. 1).                          //
497
 14      //                                                                      //
498
 15     //----------------------------------------------------------------------//
499
 16     uint8_t
500
 17     uart_putc(uint8_t cc)
501
 18     {
502
 19         while ((UCSRA & (1 << UDRE)) == 0)      ;
503
 20         UDR = cc;
504
 21         return 1;
505
 22     }
506
 23
507
 24          //----------------------------------------------------------------------//
508
 25         //                                                                      //
509
 26        //   print char cc on 7 segment display.                                //
510
 27       //    return number of chars printed (i.e. 1).                          //
511
 28      //                                                                      //
512
 29     //----------------------------------------------------------------------//
513
 30     // The segments of the display are encoded like this:
514
 31     //
515
 32     //
516
 33     //      segment     PORT B
517
 34     //      name        Bit number
518
 35     //      ----A----   ----0----
519
 36     //      |       |   |       |
520
 37     //      F       B   5       1
521
 38     //      |       |   |       |
522
 39     //      ----G----   ----6----
523
 40     //      |       |   |       |
524
 41     //      E       C   4       2
525
 42     //      |       |   |       |
526
 43     //      ----D----   ----3----
527
 44     //
528
 45     //-----------------------------------------------------------------------------
529
 46
530
 47     #define SEG7(G, F, E, D, C, B, A)   (~(G<<6|F<<5|E<<4|D<<3|C<<2|B<<1|A))
531
 48
532
 49     uint8_t
533
 50     seg7_putc(uint8_t cc)
534
 51     {
535
 52     uint16_t t;
536
 53
537
 54         switch(cc)
538
 55         {                   //   G F E D C B A
539
 56         case ' ':   PORTB = SEG7(0,0,0,0,0,0,0);        break;
540
 57         case 'E':   PORTB = SEG7(1,1,1,1,0,0,1);        break;
541
 58         case 'H':   PORTB = SEG7(1,1,1,0,1,1,0);        break;
542
 59         case 'L':   PORTB = SEG7(0,1,1,1,0,0,0);        break;
543
 60         case 'O':   PORTB = SEG7(0,1,1,1,1,1,1);        break;
544
 61         default:    PORTB = SEG7(1,0,0,1,0,0,1);        break;
545
 62         }
546
 63
547
 64         // wait 800 + 200 ms. This can be quite boring in simulations,
548
 65         // so we wait only if DIP switch 6 is closed.
549
 66         //
550
 67         if (!(PINB & 0x20))     for (t = 0; t < 800; ++t)   _delay_ms(1);
551
 68         PORTB = SEG7(0,0,0,0,0,0,0);
552
 69         if (!(PINB & 0x20))     for (t = 0; t < 200; ++t)   _delay_ms(1);
553
 70
554
 71         return 1;
555
 72     }
556
 73
557
 74          //----------------------------------------------------------------------//
558
 75         //                                                                      //
559
 76        //   print string s on UART.                                            //
560
 77       //    return number of chars printed.                                   //
561
 78      //                                                                      //
562
 79     //----------------------------------------------------------------------//
563
 80     uint16_t
564
 81     uart_puts(const char * s)
565
 82     {
566
 83     const char * from = s;
567
 84     uint8_t cc;
568
 85         while ((cc = pgm_read_byte(s++)))   uart_putc(cc);
569
 86         return s - from - 1;
570
 87     }
571
 88
572
 89          //----------------------------------------------------------------------//
573
 90         //                                                                      //
574
 91        //   print string s on 7 segment display.                               //
575
 92       //    return number of chars printed.                                   //
576
 93      //                                                                      //
577
 94     //----------------------------------------------------------------------//
578
 95     uint16_t
579
 96     seg7_puts(const char * s)
580
 97     {
581
 98     const char * from = s;
582
 99     uint8_t cc;
583
100         while ((cc = pgm_read_byte(s++)))   seg7_putc(cc);
584
101         return s - from - 1;
585
102     }
586
103
587
104     //-----------------------------------------------------------------------------
588
105     int
589
106     main(int argc, char * argv[])
590
107     {
591
108         for (;;)
592
109         {
593
110             if (PINB & 0x40)    // DIP switch 7 open.
594
111                 {
595
112                     // print 'Hello world' on UART.
596
113                     uart_puts(PSTR("Hello, World!\r\n"));
597
114                 }
598
115             else                // DIP switch 7 closed.
599
116                 {
600
117                     // print 'HELLO' on 7-segment display
601
118                     seg7_puts(PSTR("HELLO "));
602
119                 }
603
120         }
604
121     }
605
122     //-----------------------------------------------------------------------------
606
<pre class="filename">
607
app/hello.c
608
</pre></pre>
609
<P>
610
 
611
<P><br>
612
 
613
<P>The commands to create <STRONG>hello.hex</STRONG> and <STRONG>hello.css</STRONG> are:
614
 
615
<P><br>
616
 
617
<pre class="cmd">
618
 
619
# Compile and link hello.c.
620
avr-gcc -Wall -Os -fpack-struct -fshort-enums -funsigned-char -funsigned-bitfields -mmcu=atmega8 \
621 9 jsauermann
    -DF_CPU=25000000UL -c -o"hello.o" "hello.c"
622
avr-gcc -Wl,-Map,hello.map -mmcu=atmega8 -o"hello.elf"  ./hello.o
623 2 jsauermann
 
624
# Create an opcode listing.
625 9 jsauermann
avr-objdump -h -S hello.elf  >"hello.lss"
626 2 jsauermann
 
627
# Create intel hex file.
628 9 jsauermann
avr-objcopy -R .eeprom -O ihex hello.elf  "hello.hex"
629 2 jsauermann
 
630
</pre>
631
<P>
632
 
633
<P><br>
634
 
635
<P>Create  <STRONG>hello.css1</STRONG>, a better readable from of  <STRONG>hello.css</STRONG>:
636
 
637
<P><br>
638
 
639
<pre class="cmd">
640
 
641
# Create hello.css1.
642
./end_conv < hello.css > hello.css1
643
 
644
</pre>
645
<P>
646
 
647
<P><br>
648
 
649
<P>Create <STRONG>prog_mem_content.vhd</STRONG>.
650
 
651
<P><br>
652
 
653
<pre class="cmd">
654
 
655
# Create prog_mem_content.vhd.
656
./make_mem < hello.hex > src/prog_mem_content.vhd
657
 
658
</pre>
659
<P>
660
 
661
<P><br>
662
 
663
<H2><A NAME="section_1_5">8.5 Performing the Functional Simulation</A></H2>
664
 
665
<H3><A NAME="section_1_5_1">8.5.1 Preparing a Testbench</A></H3>
666
 
667
<P>We prepare a testbench in which we instantiate the top-level FPGA design
668
of the CPU. The test bench provides a clock signal and a reset signal
669
for the CPU:
670
 
671
<P><br>
672
 
673
<pre class="vhdl">
674
 
675
  1     -------------------------------------------------------------------------------
676
  2     --
677
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
678
  4     --
679
  5     --  This code is free software: you can redistribute it and/or modify
680
  6     --  it under the terms of the GNU General Public License as published by
681
  7     --  the Free Software Foundation, either version 3 of the License, or
682
  8     --  (at your option) any later version.
683
  9     --
684
 10     --  This code is distributed in the hope that it will be useful,
685
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
686
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
687
 13     --  GNU General Public License for more details.
688
 14     --
689
 15     --  You should have received a copy of the GNU General Public License
690
 16     --  along with this code (see the file named COPYING).
691
 17     --  If not, see http://www.gnu.org/licenses/.
692
 18     --
693
 19     -------------------------------------------------------------------------------
694
 20     -------------------------------------------------------------------------------
695
 21     --
696
 22     -- Module Name:    alu - Behavioral
697
 23     -- Create Date:    16:47:24 12/29/2009
698
 24     -- Description:    arithmetic logic unit of a CPU
699
 25     --
700
 26     -------------------------------------------------------------------------------
701
 27     --
702
 28     library IEEE;
703
 29     use IEEE.STD_LOGIC_1164.ALL;
704
 30     use IEEE.STD_LOGIC_ARITH.ALL;
705
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
706
 32
707
 33     entity testbench is
708
 34     end testbench;
709
 35
710
 36     architecture Behavioral of testbench is
711
 37
712
 38     component avr_fpga
713
 39         port (  I_CLK_100   : in  std_logic;
714
 40                 I_SWITCH    : in  std_logic_vector(9 downto 0);
715
 41                 I_RX        : in  std_logic;
716
 42
717
 43                 Q_7_SEGMENT : out std_logic_vector(6 downto 0);
718
 44                 Q_LEDS      : out std_logic_vector(3 downto 0);
719
 45                 Q_TX        : out std_logic);
720
 46     end component;
721
 47
722
 48     signal L_CLK_100            : std_logic;
723
 49     signal L_LEDS               : std_logic_vector(3 downto 0);
724
 50     signal L_7_SEGMENT          : std_logic_vector(6 downto 0);
725
 51     signal L_RX                 : std_logic;
726
 52     signal L_SWITCH             : std_logic_vector(9 downto 0);
727
 53     signal L_TX                 : std_logic;
728
 54
729
 55     signal  L_CLK_COUNT         : integer := 0;
730
 56
731
 57     begin
732
 58
733
 59         fpga: avr_fpga
734
 60         port map(   I_CLK_100   => L_CLK_100,
735
 61                     I_SWITCH    => L_SWITCH,
736
 62                     I_RX        => L_RX,
737
 63
738
 64                     Q_LEDS      => L_LEDS,
739
 65                     Q_7_SEGMENT => L_7_SEGMENT,
740
 66                     Q_TX        => L_TX);
741
 67
742
 68         process -- clock process for CLK_100,
743
 69         begin
744
 70             clock_loop : loop
745
 71                 L_CLK_100 <= transport '0';
746
 72                 wait for 5 ns;
747
 73
748
 74                 L_CLK_100 <= transport '1';
749
 75                 wait for 5 ns;
750
 76             end loop clock_loop;
751
 77         end process;
752
 78
753
 79         process(L_CLK_100)
754
 80         begin
755
 81             if (rising_edge(L_CLK_100)) then
756
 82                 case L_CLK_COUNT is
757
 83                     when 0 => L_SWITCH <= "0011100000";   L_RX <= '0';
758
 84                     when 2 => L_SWITCH(9 downto 8) <= "11";
759
 85                     when others =>
760
 86                 end case;
761
 87                 L_CLK_COUNT <= L_CLK_COUNT + 1;
762
 88             end if;
763
 89         end process;
764
 90     end Behavioral;
765
 91
766
<pre class="filename">
767
test/test_tb.vhd
768
</pre></pre>
769
<P>
770
 
771
<P><br>
772
 
773
<H3><A NAME="section_1_5_2">8.5.2 Defining Memory Modules</A></H3>
774
 
775
<P>We also need a VHDL file that implements the Xilinx primitives that
776
we use. This is only one: the memory module RAMB4_S4_S4:
777
 
778
<P><br>
779
 
780
<pre class="vhdl">
781
 
782
  1     -------------------------------------------------------------------------------
783
  2     --
784
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
785
  4     --
786
  5     --  This code is free software: you can redistribute it and/or modify
787
  6     --  it under the terms of the GNU General Public License as published by
788
  7     --  the Free Software Foundation, either version 3 of the License, or
789
  8     --  (at your option) any later version.
790
  9     --
791
 10     --  This code is distributed in the hope that it will be useful,
792
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
793
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
794
 13     --  GNU General Public License for more details.
795
 14     --
796
 15     --  You should have received a copy of the GNU General Public License
797
 16     --  along with this code (see the file named COPYING).
798
 17     --  If not, see http://www.gnu.org/licenses/.
799
 18     --
800
 19     -------------------------------------------------------------------------------
801
 20     -------------------------------------------------------------------------------
802
 21     --
803
 22     -- Module Name:    prog_mem - Behavioral
804
 23     -- Create Date:    14:09:04 10/30/2009
805
 24     -- Description:    a block memory module
806
 25     --
807
 26     -------------------------------------------------------------------------------
808
 27
809
 28     library IEEE;
810
 29     use IEEE.STD_LOGIC_1164.ALL;
811
 30     use IEEE.STD_LOGIC_ARITH.ALL;
812
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
813
 32
814
 33     entity RAMB4_S4_S4 is
815
 34         generic(INIT_00 : bit_vector := X"00000000000000000000000000000000"
816
 35                                       &  "00000000000000000000000000000000";
817
 36                 INIT_01 : bit_vector := X"00000000000000000000000000000000"
818
 37                                       & X"00000000000000000000000000000000";
819
 38                 INIT_02 : bit_vector := X"00000000000000000000000000000000"
820
 39                                       & X"00000000000000000000000000000000";
821
 40                 INIT_03 : bit_vector := X"00000000000000000000000000000000"
822
 41                                       & X"00000000000000000000000000000000";
823
 42                 INIT_04 : bit_vector := X"00000000000000000000000000000000"
824
 43                                       & X"00000000000000000000000000000000";
825
 44                 INIT_05 : bit_vector := X"00000000000000000000000000000000"
826
 45                                       & X"00000000000000000000000000000000";
827
 46                 INIT_06 : bit_vector := X"00000000000000000000000000000000"
828
 47                                       & X"00000000000000000000000000000000";
829
 48                 INIT_07 : bit_vector := X"00000000000000000000000000000000"
830
 49                                       & X"00000000000000000000000000000000";
831
 50                 INIT_08 : bit_vector := X"00000000000000000000000000000000"
832
 51                                       & X"00000000000000000000000000000000";
833
 52                 INIT_09 : bit_vector := X"00000000000000000000000000000000"
834
 53                                       & X"00000000000000000000000000000000";
835
 54                 INIT_0A : bit_vector := X"00000000000000000000000000000000"
836
 55                                       & X"00000000000000000000000000000000";
837
 56                 INIT_0B : bit_vector := X"00000000000000000000000000000000"
838
 57                                       & X"00000000000000000000000000000000";
839
 58                 INIT_0C : bit_vector := X"00000000000000000000000000000000"
840
 59                                       & X"00000000000000000000000000000000";
841
 60                 INIT_0D : bit_vector := X"00000000000000000000000000000000"
842
 61                                       & X"00000000000000000000000000000000";
843
 62                 INIT_0E : bit_vector := X"00000000000000000000000000000000"
844
 63                                       & X"00000000000000000000000000000000";
845
 64                 INIT_0F : bit_vector := X"00000000000000000000000000000000"
846
 65                                       & X"00000000000000000000000000000000");
847
 66
848
 67         port(   ADDRA   : in  std_logic_vector(9 downto 0);
849
 68                 ADDRB   : in  std_logic_vector(9 downto 0);
850
 69                 CLKA    : in  std_ulogic;
851
 70                 CLKB    : in  std_ulogic;
852
 71                 DIA     : in  std_logic_vector(3 downto 0);
853
 72                 DIB     : in  std_logic_vector(3 downto 0);
854
 73                 ENA     : in  std_ulogic;
855
 74                 ENB     : in  std_ulogic;
856
 75                 RSTA    : in  std_ulogic;
857
 76                 RSTB    : in  std_ulogic;
858
 77                 WEA     : in  std_ulogic;
859
 78                 WEB     : in  std_ulogic;
860
 79
861
 80                 DOA     : out std_logic_vector(3 downto 0);
862
 81                 DOB     : out std_logic_vector(3 downto 0));
863
 82     end RAMB4_S4_S4;
864
 83
865
 84     architecture Behavioral of RAMB4_S4_S4 is
866
 85
867
 86     function cv(A : bit) return std_logic is
868
 87     begin
869
 88        if (A = '1') then return '1';
870
 89        else              return '0';
871
 90        end if;
872
 91     end;
873
 92
874
 93     function cv1(A : std_logic) return bit is
875
 94     begin
876
 95        if (A = '1') then return '1';
877
 96        else              return '0';
878
 97        end if;
879
 98     end;
880
 99
881
100     signal DATA : bit_vector(4095 downto 0) :=
882
101         INIT_0F & INIT_0E & INIT_0D & INIT_0C & INIT_0B & INIT_0A & INIT_09 & INIT_08 &
883
102         INIT_07 & INIT_06 & INIT_05 & INIT_04 & INIT_03 & INIT_02 & INIT_01 & INIT_00;
884
103
885
104     begin
886
105
887
106         process(CLKA, CLKB)
888
107         begin
889
108             if (rising_edge(CLKA)) then
890
109                 if (ENA = '1') then
891
110                     DOA(3) <= cv(DATA(conv_integer(ADDRA & "11")));
892
111                     DOA(2) <= cv(DATA(conv_integer(ADDRA & "10")));
893
112                     DOA(1) <= cv(DATA(conv_integer(ADDRA & "01")));
894
113                     DOA(0) <= cv(DATA(conv_integer(ADDRA & "00")));
895
114                     if (WEA = '1') then
896
115                         DATA(conv_integer(ADDRA & "11")) <= cv1(DIA(3));
897
116                         DATA(conv_integer(ADDRA & "10")) <= cv1(DIA(2));
898
117                         DATA(conv_integer(ADDRA & "01")) <= cv1(DIA(1));
899
118                         DATA(conv_integer(ADDRA & "00")) <= cv1(DIA(0));
900
119                     end if;
901
120                end if;
902
121             end if;
903
122
904
123             if (rising_edge(CLKB)) then
905
124                 if (ENB = '1') then
906
125                     DOB(3) <= cv(DATA(conv_integer(ADDRB & "11")));
907
126                     DOB(2) <= cv(DATA(conv_integer(ADDRB & "10")));
908
127                     DOB(1) <= cv(DATA(conv_integer(ADDRB & "01")));
909
128                     DOB(0) <= cv(DATA(conv_integer(ADDRB & "00")));
910
129                     if (WEB = '1') then
911
130                         DATA(conv_integer(ADDRB & "11")) <= cv1(DIB(3));
912
131                         DATA(conv_integer(ADDRB & "10")) <= cv1(DIB(2));
913
132                         DATA(conv_integer(ADDRB & "01")) <= cv1(DIB(1));
914
133                         DATA(conv_integer(ADDRB & "00")) <= cv1(DIB(0));
915
134                     end if;
916
135                 end if;
917
136             end if;
918
137         end process;
919
138
920
139     end Behavioral;
921
140
922
<pre class="filename">
923
test/RAMB4_S4_S4.vhd
924
</pre></pre>
925
<P>
926
 
927
<P><br>
928
 
929
<H3><A NAME="section_1_5_3">8.5.3 Creating the testbench executable</A></H3>
930
 
931
<P>We assume the following file structure:
932
 
933
<UL>
934
  <LI>a <STRONG>test</STRONG> directory that contains the testbench (<STRONG>test_tb.vhd</STRONG>) and the
935
  memory module (<STRONG>RAMB4_S4_S4.vhd</STRONG>).
936
  <LI>a <STRONG>src</STRONG> directory that contains all other VHDL files.
937
  <LI>a <STRONG>simu</STRONG> directory (empty).
938
  <LI>A <STRONG>Makefile</STRONG> like this:
939
</UL>
940
<P><br>
941
 
942
<pre class="vhdl">
943
 
944
  1     PROJECT=avr_core
945
  2
946
  3     # the vhdl source files (except testbench)
947
  4     #
948
  5     FILES           += src/*.vhd
949
  6
950
  7     # the testbench sources and binary.
951
  8     #
952 9 jsauermann
  9     SIMFILES        =  test/test_tb.vhd
953
 10     SIMFILES        += test/RAMB4_S4_S4.vhd
954
 11     SIMFILES        += test/RAM32X1S.vhd
955
 12     SIMTOP          = testbench
956
 13
957
 14     # When to stop the simulation
958
 15     #
959
 16     # GHDL_SIM_OPT  = --assert-level=error
960
 17     GHDL_SIM_OPT    = --stop-time=40us
961 2 jsauermann
 18
962 9 jsauermann
 19     SIMDIR          = simu
963 2 jsauermann
 20
964 9 jsauermann
 21     FLAGS           = --ieee=synopsys --warn-no-vital-generic -fexplicit --std=93c
965
 22
966
 23     all:
967
 24             make compile
968
 25             make run 2>& 1 | grep -v std_logic_arith
969
 26             make view
970
 27
971
 28     compile:
972
 29             @mkdir -p simu
973
 30             @echo -----------------------------------------------------------------
974
 31             ghdl -i $(FLAGS) --workdir=simu --work=work $(SIMFILES) $(FILES)
975
 32             @echo
976
 33             @echo -----------------------------------------------------------------
977
 34             ghdl -m $(FLAGS) --workdir=simu --work=work $(SIMTOP)
978
 35             @echo
979
 36             @mv $(SIMTOP) simu/$(SIMTOP)
980
 37
981
 38     run:
982
 39             @$(SIMDIR)/$(SIMTOP) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(SIMTOP).vcdgz
983
 40
984
 41     view:
985
 42             gunzip --stdout $(SIMDIR)/$(SIMTOP).vcdgz | gtkwave --vcd gtkwave.save
986
 43
987
 44     clean:
988
 45             ghdl --clean --workdir=simu
989
 46
990 2 jsauermann
<pre class="filename">
991
Makefile
992
</pre></pre>
993
<P>
994
 
995
<P><br>
996
 
997
<DL>
998
  <DT>Then</DT>
999
<DD>
1000
</DL>
1001
<P><br>
1002
 
1003
<pre class="cmd">
1004
 
1005
# Run the functional simulation.
1006
make
1007
 
1008
</pre>
1009
<P>
1010
 
1011
<P><br>
1012
 
1013
<P>It will take a moment, but then a <STRONG>gtkwave</STRONG> window like the one shown
1014
earlier in this lesson will appear. It my look a little different due
1015
due to different default settings (like background color). In that
1016
window you can add new signals from the design that you would like
1017
to investigate, remove signals you are not interested in, and so on.
1018
At the first time, no signals will be shown; you can add some by selecting
1019
a component instance at the right, selecting a signal in that component,
1020
and then pushing the <STRONG>append</STRONG> button on the right.
1021
 
1022
<P>The <STRONG>make</STRONG> command has actually made 3 things:
1023
 
1024
<UL>
1025
  <LI>make compile (compile the VHLD files)
1026
  <LI>make run (run the simulation), and
1027
  <LI>make view
1028
</UL>
1029
<P>The first two steps (which took most of the total time) need only be run
1030
after changes to the VHDL files.
1031
 
1032
<H2><A NAME="section_1_6">8.6 Building the Design</A></H2>
1033
 
1034
<P>When the functional simulation looks OK, it is time to implement the design
1035
and check the timing. We describe this only briefly, since the Xilinx
1036
documentation of the Xilinx toolchain is a much better source of
1037
information.
1038
 
1039
<H3><A NAME="section_1_6_1">8.6.1 Creating an UCF file</A></H3>
1040
 
1041
<P>Before implementing the design, we need an <STRONG>UCF</STRONG> file. That file
1042
describes timing requirements, pin properties (like pull-ups for our
1043
DIP switch), and pin-to-signal mappings:
1044
 
1045
<P><br>
1046
 
1047
<pre class="vhdl">
1048
 
1049
  1     NET     I_CLK_100       PERIOD = 10 ns;
1050 9 jsauermann
  2     NET     L_CLK           PERIOD = 45 ns;
1051 2 jsauermann
  3
1052
  4     NET     I_CLK_100       TNM_NET = I_CLK_100;
1053
  5     NET     L_CLK           TNM_NET = L_CLK;
1054
  6
1055
  7     NET     I_CLK_100       LOC = AA12;
1056
  8     NET     I_RX            LOC = M3;
1057
  9     NET     Q_TX            LOC = M4;
1058
 10
1059
 11     # 7 segment LED display
1060
 12     #
1061
 13     NET     Q_7_SEGMENT<0>  LOC = V3;
1062
 14     NET     Q_7_SEGMENT<1>  LOC = V4;
1063
 15     NET     Q_7_SEGMENT<2>  LOC = W3;
1064
 16     NET     Q_7_SEGMENT<3>  LOC = T4;
1065
 17     NET     Q_7_SEGMENT<4>  LOC = T3;
1066
 18     NET     Q_7_SEGMENT<5>  LOC = U3;
1067
 19     NET     Q_7_SEGMENT<6>  LOC = U4;
1068
 20
1069
 21     # single LEDs
1070
 22     #
1071
 23     NET     Q_LEDS<0>       LOC = N1;
1072
 24     NET     Q_LEDS<1>       LOC = N2;
1073
 25     NET     Q_LEDS<2>       LOC = P1;
1074
 26     NET     Q_LEDS<3>       LOC = P2;
1075
 27
1076
 28     # DIP switch(0 ... 7) and two pushbuttons (8, 9)
1077
 29     #
1078
 30     NET     I_SWITCH<0>     LOC = H2;
1079
 31     NET     I_SWITCH<1>     LOC = H1;
1080
 32     NET     I_SWITCH<2>     LOC = J2;
1081
 33     NET     I_SWITCH<3>     LOC = J1;
1082
 34     NET     I_SWITCH<4>     LOC = K2;
1083
 35     NET     I_SWITCH<5>     LOC = K1;
1084
 36     NET     I_SWITCH<6>     LOC = L2;
1085
 37     NET     I_SWITCH<7>     LOC = L1;
1086
 38     NET     I_SWITCH<8>     LOC = R1;
1087
 39     NET     I_SWITCH<9>     LOC = R2;
1088
 40
1089
 41     NET     I_SWITCH<*>     PULLUP;
1090
 42
1091
<pre class="filename">
1092
src/avr_fpga.ucf
1093
</pre></pre>
1094
<P>
1095
 
1096
<P><br>
1097
 
1098
<H3><A NAME="section_1_6_2">8.6.2 Synthesis and Implementation</A></H3>
1099
 
1100
<UL>
1101
  <LI>Start the ISE project manager and open a new project with the desired
1102
  FPGA device.
1103
  <LI>Add the VHDL files and the <STRONG>UCF</STRONG> file in the <STRONG>src</STRONG> directory to the
1104
  project (Project-&gt;Add Source).
1105
  <LI>Synthesize and implement the design (Process-&gt;Implement top Module).
1106
</UL>
1107
<P>This generates a number of reports, netlists, and other files.
1108
There should be no errors. There will be warnings though, including
1109
timing constraints that are not met.
1110
 
1111
<P>It is important to understand the reason for each warning. Warnings often
1112
point to faults in the design.
1113
 
1114
<P>The next thing to check is the timing reports. We were lucky:
1115
 
1116
<P><br>
1117
 
1118
<pre class="cmd">
1119
 
1120
#Timing report fragment:
1121
================================================================================
1122
Timing constraint: NET "L_CLK" PERIOD = 35 ns HIGH 50%;
1123
 
1124
 676756190 paths analyzed, 2342 endpoints analyzed, 0 failing endpoints
1125
 
1126
 Minimum period is  34.981ns.
1127
--------------------------------------------------------------------------------
1128
 
1129
================================================================================
1130
Timing constraint: NET "I_CLK_100_BUFGP/IBUFG" PERIOD = 10 ns HIGH 50%;
1131
 
1132
 19 paths analyzed, 11 endpoints analyzed, 0 failing endpoints
1133
 
1134
 Minimum period is   3.751ns.
1135
--------------------------------------------------------------------------------
1136
 
1137
 
1138
All constraints were met.
1139
 
1140
</pre>
1141
<P>
1142
 
1143
<P><br>
1144
 
1145
<P>This tells us that we have enough slack on the crystal CLK_100 signal
1146
(8.048ns would allow for up to 124 MHz). We had specified a period
1147
of 35 ns irequirement for the CPU clock:
1148
 
1149
<P><br>
1150
 
1151
<pre class="vhdl">
1152
 
1153 9 jsauermann
  2     NET     L_CLK           PERIOD = 45 ns;
1154 2 jsauermann
<pre class="filename">
1155
src/avr_fpga.ucf
1156
</pre></pre>
1157
<P>
1158
 
1159
<P><br>
1160
 
1161
<P>The CPU runs at 25 MHz, or 40 ns. The 35 ns come from the 40 ms minus
1162
a slack of 5 ns. With some tweaking of optimization options, we could
1163
have reached 33 MHz, but then the slack would have been pretty small.
1164
 
1165
<P>However, we rather stay on th safe side.
1166
 
1167
<H2><A NAME="section_1_7">8.7 Creating a Programming File</A></H2>
1168
 
1169
<P>Next we double-click "Generate Programming file" in the ISE project navigator.
1170
This generates a file <STRONG>avr_fpga.bit</STRONG> in the project directory. This can also
1171
be run from a Makefile or from the command line (the command is <STRONG>bitgen</STRONG>).
1172
 
1173
<H2><A NAME="section_1_8">8.8 Configuring the FPGA</A></H2>
1174
 
1175
<P>At this point, we have the choice between configuring the FPGA directly
1176
via JTAG, or flashing an EEPROM and then loading the FPGA from the EEPROM.
1177
 
1178
<H3><A NAME="section_1_8_1">8.8.1 Configuring the FPGA via JTAG Boundary Scan</A></H3>
1179
 
1180
<P>Configuring the FPGA can be done with the Xilinx tool called <STRONG>impact</STRONG>.
1181
The file needed by <STRONG>impact</STRONG> is <STRONG>avr_fpga.bit</STRONG> from above. The configuration
1182
loaded via JTAG will be lost when the FPGA looses power.
1183
 
1184
<P>Choose "Boundary Scan" in <STRONG>impact</STRONG>, select the FPGA and follow the instructions.
1185
 
1186
<H3><A NAME="section_1_8_2">8.8.2 Flashing PROMs</A></H3>
1187
 
1188
<P>In theory this can also be done from ISE. In practice it could (and actually
1189
did) happen that the programming cable (I use an old parallel 3 cable)
1190
is not detected by impact.
1191
 
1192
<P>Before flashing the PROM, the <STRONG>avr_fpga.bit</STRONG> from the previous step needs to
1193
translated into a format suitable for the PROM. My PROM is of the serial
1194
variety, so I start <STRONG>impact</STRONG>, choose "PROM File Formatter" and follow the
1195
instructions.
1196
 
1197
<P>After converting <STRONG>avr_fpga.bit</STRONG> into, for example, <STRONG>avr_fpga.mcs</STRONG>, the
1198
PROM can be flashed. Like before choose "Boundary Scan" in #impact. This
1199
time, however, you select the PROM and not the FPGA, and follow the
1200
instructions.
1201
 
1202
<P>This concludes the description of the design flow and also of the CPU.
1203
The remaining lessons contain the complete listings of all sources files
1204
discussed in this lectures.
1205
 
1206
<P>Thank you very much for your attention.
1207
 
1208
<P><hr><BR>
1209
<table class="ttop"><th class="tpre"><a href="08_IO.html">Previous Lesson</a></th><th class="ttop"><a href="toc.html">Table of Content</a></th><th class="tnxt"><a href="10_Listing_of_alu_vhd.html">Next Lesson</a></th></table>
1210
</BODY>
1211
</HTML>

powered by: WebSVN 2.1.0

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