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

Subversion Repositories cpu_lecture

[/] [cpu_lecture/] [trunk/] [html/] [09_Toolchain_Setup.html] - Diff between revs 2 and 9

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 9
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
"http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HTML>
<HEAD>
<HEAD>
<TITLE>html/Toolchain_Setup</TITLE>
<TITLE>html/Toolchain_Setup</TITLE>
<META NAME="generator" CONTENT="HTML::TextToHTML v2.46">
<META NAME="generator" CONTENT="HTML::TextToHTML v2.46">
<LINK REL="stylesheet" TYPE="text/css" HREF="lecture.css">
<LINK REL="stylesheet" TYPE="text/css" HREF="lecture.css">
</HEAD>
</HEAD>
<BODY>
<BODY>
<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>
<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>
<hr>
<hr>
 
 
<H1><A NAME="section_1">9 TOOLCHAIN SETUP</A></H1>
<H1><A NAME="section_1">9 TOOLCHAIN SETUP</A></H1>
 
 
<P>In this lesson we will learn how to set up a toolchain on a Linux box.
<P>In this lesson we will learn how to set up a toolchain on a Linux box.
We will not describe, however, how the tools are downloaded and installed.
We will not describe, however, how the tools are downloaded and installed.
The installation of a tools is normally described in the documentation
The installation of a tools is normally described in the documentation
that comes with the tool.
that comes with the tool.
 
 
<P>Places from where tools can be downloaded were already presented in the
<P>Places from where tools can be downloaded were already presented in the
first lecture.
first lecture.
 
 
<P>The following figure gives an overview of the entire flow. We show source files
<P>The following figure gives an overview of the entire flow. We show source files
in yellow, temporary files in white and tools in green.
in yellow, temporary files in white and tools in green.
 
 
<P><br>
<P><br>
 
 
<P><img src="toolchain_1.png">
<P><img src="toolchain_1.png">
 
 
<P><br>
<P><br>
 
 
<P>We start with a C source file <STRONG>hello.c</STRONG>. This file is compiled with <STRONG>avr-gcc</STRONG>,
<P>We start with a C source file <STRONG>hello.c</STRONG>. This file is compiled with <STRONG>avr-gcc</STRONG>,
a <STRONG>gcc</STRONG> variant that generates opcodes for the AVR CPU. The compilation
a <STRONG>gcc</STRONG> variant that generates opcodes for the AVR CPU. The compilation
produces 2 output files: <STRONG>hello.lss</STRONG> and <STRONG>hello.hex</STRONG>.
produces 2 output files: <STRONG>hello.lss</STRONG> and <STRONG>hello.hex</STRONG>.
 
 
<P><STRONG>hello.lss</STRONG> is a listing file and may optionally be post-processed by the
<P><STRONG>hello.lss</STRONG> is a listing file and may optionally be post-processed by the
tool <STRONG>end_conv</STRONG> which converts the little-endian format of <STRONG>hello.lss</STRONG> into
tool <STRONG>end_conv</STRONG> which converts the little-endian format of <STRONG>hello.lss</STRONG> into
a slightly different format that is more in line with the way gtkwave shows
a slightly different format that is more in line with the way gtkwave shows
the hex values of signals.
the hex values of signals.
 
 
<P>The main purpose of the compilation is to produce <STRONG>hello.hex</STRONG>. <STRONG>hello.hex</STRONG>
<P>The main purpose of the compilation is to produce <STRONG>hello.hex</STRONG>. <STRONG>hello.hex</STRONG>
contains the opcodes produced from <STRONG>hello.c</STRONG> in Intel-Hex format.
contains the opcodes produced from <STRONG>hello.c</STRONG> in Intel-Hex format.
 
 
<P><STRONG>hello.hex</STRONG> is then fed into <STRONG>make_mem</STRONG>. <STRONG>make_mem</STRONG> is a tool that converts
<P><STRONG>hello.hex</STRONG> is then fed into <STRONG>make_mem</STRONG>. <STRONG>make_mem</STRONG> is a tool that converts
the Intel-Hex format into VHDL constants. These constants are used to
the Intel-Hex format into VHDL constants. These constants are used to
initialize the block RAM modules of the program memory. The output of
initialize the block RAM modules of the program memory. The output of
<STRONG>make_mem</STRONG> is <STRONG>memory_content.vhd</STRONG> (which, as you certainly remember,
<STRONG>make_mem</STRONG> is <STRONG>memory_content.vhd</STRONG> (which, as you certainly remember,
was included by <STRONG>prog_mem.vhd</STRONG>).
was included by <STRONG>prog_mem.vhd</STRONG>).
 
 
<P>At this point, there are two possible ways to proceed. You could do a
<P>At this point, there are two possible ways to proceed. You could do a
functional simulation or a timing simulation.
functional simulation or a timing simulation.
 
 
<H2><A NAME="section_1_1">8.1 Functional Simulation</A></H2>
<H2><A NAME="section_1_1">8.1 Functional Simulation</A></H2>
 
 
<P>Initially you will be concerned mostly with the functional simulation.
<P>Initially you will be concerned mostly with the functional simulation.
On this branch you debug the VHDL code until it looks functionally OK.
On this branch you debug the VHDL code until it looks functionally OK.
In order to perform the functional simulation, you need 3 sorts of VHDL files:
In order to perform the functional simulation, you need 3 sorts of VHDL files:
 
 
<OL>
<OL>
  <LI>The VHLD source files that were discussed in the previous lessons,
  <LI>The VHLD source files that were discussed in the previous lessons,
  <LI>the <STRONG>memory_content.vhd</STRONG> just described, and
  <LI>the <STRONG>memory_content.vhd</STRONG> just described, and
  <LI>a testbench that mimics the board containing the FPGA to be (<STRONG>test_tb.vhd</STRONG>,
  <LI>a testbench that mimics the board containing the FPGA to be (<STRONG>test_tb.vhd</STRONG>,
   and a VHDL implementation of device specific components used (in our case
   and a VHDL implementation of device specific components used (in our case
   this is only <STRONG>RAMB4_S4_S4.vhd</STRONG>). Both files are provided in the directory
   this is only <STRONG>RAMB4_S4_S4.vhd</STRONG>). Both files are provided in the directory
   called <STRONG>test</STRONG>.
   called <STRONG>test</STRONG>.
</OL>
</OL>
<P>All these VHDL files are then processed by <STRONG>ghdl</STRONG>. <STRONG>ghdl</STRONG> produces a single
<P>All these VHDL files are then processed by <STRONG>ghdl</STRONG>. <STRONG>ghdl</STRONG> produces a single
output file <STRONG>testbench</STRONG> in directory <STRONG>simu</STRONG>. <STRONG>testbench</STRONG> is an executable
output file <STRONG>testbench</STRONG> in directory <STRONG>simu</STRONG>. <STRONG>testbench</STRONG> is an executable
file. <STRONG>testbench</STRONG> is then run in order to produces a gzip'ed <STRONG>vcd</STRONG> (value change
file. <STRONG>testbench</STRONG> is then run in order to produces a gzip'ed <STRONG>vcd</STRONG> (value change
dump) file called <STRONG>testbench.vcdgz</STRONG>.
dump) file called <STRONG>testbench.vcdgz</STRONG>.
 
 
<P>The last step is visualize <STRONG>testbench.vcdgz</STRONG> by means of the tool <STRONG>gtkwave</STRONG>.
<P>The last step is visualize <STRONG>testbench.vcdgz</STRONG> by means of the tool <STRONG>gtkwave</STRONG>.
<STRONG>gtkwave</STRONG> is similar to the <STRONG>ModelSim</STRONG> provided by Xilinx, but it has
<STRONG>gtkwave</STRONG> is similar to the <STRONG>ModelSim</STRONG> provided by Xilinx, but it has
two advantages: it does not bother the user with licence installations
two advantages: it does not bother the user with licence installations
(even in the "free" versions provided by Xilinx) and it runs under Linux.
(even in the "free" versions provided by Xilinx) and it runs under Linux.
There are actually more advantages of the <STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG> combination;
There are actually more advantages of the <STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG> combination;
after having used both tools in the past the author definitely prefers
after having used both tools in the past the author definitely prefers
<STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG>.
<STRONG>ghdl</STRONG>/<STRONG>gtkwave</STRONG>.
 
 
<P>An example output of the functional simulation that shows the  operation
<P>An example output of the functional simulation that shows the  operation
our CPU:
our CPU:
 
 
<P><br>
<P><br>
 
 
<P><img src="GTKWave.png">
<P><img src="GTKWave.PNG">
 
 
<P><br>
<P><br>
 
 
<P>We can compare the CPU signals shown with the assembler code being executed.
<P>We can compare the CPU signals shown with the assembler code being executed.
The CPU is executing inside the C function <STRONG>uart_puts()</STRONG>:
The CPU is executing inside the C function <STRONG>uart_puts()</STRONG>:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
156     00000095: (uart_puts):
 
157       95:   01AC            movw    r20, r24
 
158       96:   C003            rjmp     0x9A           ; 0x134 <uart_puts+0xa>
 
159       97:   9B5D            sbis    0x0b, 5 ; 11
 
160       98:   CFFE            rjmp     0x97           ; 0x12e <uart_puts+0x4>
 
161       99:   B92C            out     0x0c, r18       ; 12
 
162       9A:   01FC            movw    r30, r24
 
163       9B:   9601            adiw    r24, 0x01       ; 1
 
164       9C:   9124            lpm     r18, Z
 
165       9D:   2322            and     r18, r18
 
166       9E:   F7C1            brne     0x97           ; 0x12e <uart_puts+0x4>
 
167       9F:   1B84            sub     r24, r20
 
168       A0:   0B95            sbc     r25, r21
 
169       A1:   9701            sbiw    r24, 0x01       ; 1
 
170       A2:   9508            ret
 
<pre class="filename">
<pre class="filename">
app/hello.lss1
app/hello.lss1
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H2><A NAME="section_1_2">8.2 Timing Simulation and FPGA Configuration</A></H2>
<H2><A NAME="section_1_2">8.2 Timing Simulation and FPGA Configuration</A></H2>
 
 
<P>After the CPU functions correctly, the design can be fed into the Xilinx
<P>After the CPU functions correctly, the design can be fed into the Xilinx
toolchain. This toolchain is better described in the documentation that
toolchain. This toolchain is better described in the documentation that
comes with it, so we don't go to too much detail here.
comes with it, so we don't go to too much detail here.
 
 
<P>We used Webpack 10.1, which can be downloaded from Xilinx.
<P>We used Webpack 10.1, which can be downloaded from Xilinx.
 
 
<P>The first step is to set up a project in the ISE project navigator with
<P>The first step is to set up a project in the ISE project navigator with
the proper target device. Then the VHDL files in the <STRONG>src</STRONG> directory are
the proper target device. Then the VHDL files in the <STRONG>src</STRONG> directory are
added to the project. Next the <STRONG>Synthesize</STRONG> and <STRONG>Implementation</STRONG> steps
added to the project. Next the <STRONG>Synthesize</STRONG> and <STRONG>Implementation</STRONG> steps
of the design flow are run.
of the design flow are run.
 
 
<P>If this is successful, then we can generate a programming file. There are
<P>If this is successful, then we can generate a programming file. There are
a number of ways to configure Xilinx FPGAs, and the type of programming file
a number of ways to configure Xilinx FPGAs, and the type of programming file
needed depends on the particular way of configuring the device. The board
needed depends on the particular way of configuring the device. The board
we used for testing the CPU had a serial PROM and therefore we generated
we used for testing the CPU had a serial PROM and therefore we generated
a programming file for the serial PROM on the board. The FPGA would then
a programming file for the serial PROM on the board. The FPGA would then
load from the PROM on start-up. Other ways of configuring the device are
load from the PROM on start-up. Other ways of configuring the device are
via JTAG, which is also quite handy during debugging.
via JTAG, which is also quite handy during debugging.
 
 
<P>The entire build process is a little lengthy (and the devil is known to
<P>The entire build process is a little lengthy (and the devil is known to
hide in the details). We therefore go through the entire design flow in
hide in the details). We therefore go through the entire design flow in
a step-by-step fashion.
a step-by-step fashion.
 
 
<H2><A NAME="section_1_3">8.3 Downloading and Building the Tools </A></H2>
<H2><A NAME="section_1_3">8.3 Downloading and Building the Tools </A></H2>
 
 
<UL>
<UL>
  <LI>Download and install <STRONG>ghdl</STRONG>.
  <LI>Download and install <STRONG>ghdl</STRONG>.
  <LI>Download and install <STRONG>gtkwave</STRONG>.
  <LI>Download and install <STRONG>gtkwave</STRONG>.
  <LI>Download and install the Xilinx toolchain.
  <LI>Download and install the Xilinx toolchain.
  <LI>Build the <STRONG>make_mem</STRONG> tool. The source is this:
  <LI>Build the <STRONG>make_mem</STRONG> tool. The source is this:
</UL>
</UL>
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     #include "assert.h"
  1     #include "assert.h"
  2     #include "stdio.h"
  2     #include "stdio.h"
  3     #include "stdint.h"
  3     #include "stdint.h"
  4     #include "string.h"
  4     #include "string.h"
  5
  5
  6     const char * hex_file = 0;
  6     uint8_t buffer[0x10000];    // 64 k is max. for Intel hex.
  7     const char * vhdl_file = 0;
  7     uint8_t slice [0x10000];    // 16 k is max. for Xilinx bram
  8
  8
  9     uint8_t buffer[0x10000];
  9     //-----------------------------------------------------------------------------
 10
 10     //
 11     //-----------------------------------------------------------------------------
 11     // get a byte (from cp pointing into Intel hex file).
 12     uint32_t
 12     //
 13     get_byte(const char *  cp)
 13     uint32_t
 14     {
 14     get_byte(const char *  cp)
 15     uint32_t value;
 15     {
 16     const char cc[3] = { cp[0], cp[1], 0 };
 16     uint32_t value;
 17     const int cnt = sscanf(cc, "%X", &value);
 17     const char cc[3] = { cp[0], cp[1], 0 };
 18        assert(cnt == 1);
 18     const int cnt = sscanf(cc, "%X", &value);
 19        return value;
 19        assert(cnt == 1);
 20     }
 20        return value;
 21     //-----------------------------------------------------------------------------
 21     }
 22     void
 22     //-----------------------------------------------------------------------------
 23     read_file(FILE * in)
 23     //
 24     {
 24     // read an Intel hex file into buffer
 25        memset(buffer, 0xFF, sizeof(buffer));
 25     void
 26     char line[200];
 26     read_file(FILE * in)
 27        for (;;)
 27     {
 28            {
 28        memset(buffer, 0xFF, sizeof(buffer));
 29              const char * s = fgets(line, sizeof(line) - 2, in);
 29     char line[200];
 30              if (s == 0)   return;
 30        for (;;)
 31              assert(*s++ == ':');
 31            {
 32              const uint32_t len     = get_byte(s);
 32              const char * s = fgets(line, sizeof(line) - 2, in);
 33              const uint32_t ah      = get_byte(s + 2);
 33              if (s == 0)   return;
 34              const uint32_t al      = get_byte(s + 4);
 34              assert(*s++ == ':');
 35              const uint32_t rectype = get_byte(s + 6);
 35              const uint32_t len     = get_byte(s);
 36              const char * d = s + 8;
 36              const uint32_t ah      = get_byte(s + 2);
 37              const uint32_t addr = ah << 8 | al;
 37              const uint32_t al      = get_byte(s + 4);
 38
 38              const uint32_t rectype = get_byte(s + 6);
 39              uint32_t csum = len + ah + al + rectype;
 39              const char * d = s + 8;
 40              assert((addr + len) <= 0x10000);
 40              const uint32_t addr = ah << 8 | al;
 41              for (uint32_t l = 0; l < len; ++l)
 41
 42                  {
 42              uint32_t csum = len + ah + al + rectype;
 43                    const uint32_t byte = get_byte(d);
 43              assert((addr + len) <= 0x10000);
 44                    d += 2;
 44              for (uint32_t l = 0; l < len; ++l)
 45                    buffer[addr + l] = byte;
 45                  {
 46                    csum += byte;
 46                    const uint32_t byte = get_byte(d);
 47                  }
 47                    d += 2;
 48
 48                    buffer[addr + l] = byte;
 49              csum = 0xFF & -csum;
 49                    csum += byte;
 50              const uint32_t sum = get_byte(d);
 50                  }
 51              assert(sum == csum);
 51
 52            }
 52              csum = 0xFF & -csum;
 53     }
 53              const uint32_t sum = get_byte(d);
 54     //-----------------------------------------------------------------------------
 54              assert(sum == csum);
 55     void
 55            }
 56     write_vector(FILE * out, bool odd, uint32_t mem, uint32_t v)
 56     }
 57     {
 57     //-----------------------------------------------------------------------------
 58     const uint8_t * base = buffer;
 58     //
 59
 59     // copy a slice from buffer into slice.
 60        // total memory is 2 even bytes, 2 odd bytes, 2 even bytes, ...
 60     // buffer is organized as 32-bit x items.
 61        //
 61     // slice is organized as bits x items.
 62        if (odd)   base += 2;
 62     //
 63
 63     void copy_slice(uint32_t slice_num, uint32_t port_bits, uint32_t mem_bits)
 64        // total memory is 4 kByte organized into 8 memories.
 64     {
 65        // thus each of the 16 vectors covers 256 bytes.
 65        assert(mem_bits == 0x1000 || mem_bits == 0x4000);
 66        //
 66
 67        base += v*256;
 67     const uint32_t items = mem_bits/port_bits;
 68
 68     const uint32_t mask = (1 << port_bits) - 1;
 69        // memories 0 and 1 are the low byte of the opcode while
 69     const uint8_t * src = buffer;
 70        // memories 2 and 3 are the high byte.
 70
 71        //
 71         memset(slice, 0, sizeof(slice));
 72        if (mem >= 2)   ++base;
 72
 73
 73         for (uint32_t i = 0; i < items; ++i)
 74     const char * px = odd ? "po" : "pe";
 74             {
 75        fprintf(out, "constant %s_%u_%2.2X : BIT_VECTOR := X\"", px, mem, v);
 75               // read one 32-bit value;
 76        for (int32_t d = 63; d >= 0; --d)
 76               const uint32_t v0 = *src++;
 77            {
 77               const uint32_t v1 = *src++;
 78              uint32_t q = base[4*d];
 78               const uint32_t v2 = *src++;
 79              if (mem & 1)   q >>= 4;     // high nibble
 79               const uint32_t v3 = *src++;
 80              else           q &= 0x0F;   // low nibble
 80               const uint32_t v = (v3 << 24 |
 81              fprintf(out, "%X", q);
 81                                   v2 << 16 |
 82            }
 82                                   v1 <<  8 |
 83
 83                                   v0       ) >> (slice_num*port_bits) & mask;
 84        fprintf(out, "\";\r\n");
 84
 85     }
 85               if (port_bits == 16)
 86     //-----------------------------------------------------------------------------
 86                  {
 87     void
 87                    assert(v < 0x10000);
 88     write_mem(FILE * out, bool odd, uint32_t mem)
 88                    slice[2*i]     = v;
 89     {
 89                    slice[2*i + 1] = v >> 8;
 90     const char * px = odd ? "po" : "pe";
 90                  }
 91
 91               else if (port_bits == 8)
 92        fprintf(out, "-- content of %s_%u --------------------------------------"
 92                  {
 93                     "--------------------------------------------\r\n", px, mem);
 93                    assert(v < 0x100);
 94
 94                    slice[i] = v;
 95        for (uint32_t v = 0; v < 16; ++v)
 95                  }
 96            write_vector(out, odd, mem, v);
 96               else if (port_bits == 4)
 97
 97                  {
 98        fprintf(out, "\r\n");
 98                    assert(v < 0x10);
 99     }
 99                    slice[i >> 1] |= v << (4*(i & 1));
100     //-----------------------------------------------------------------------------
100                  }
101     void
101               else if (port_bits == 2)
102     write_file(FILE * out)
102                  {
103     {
103                    assert(v < 0x04);
104        fprintf(out,
104                    slice[i >> 2] |= v << (2*(i & 3));
105     "\r\n"
105                  }
106     "library IEEE;\r\n"
106               else if (port_bits == 1)
107     "use IEEE.STD_LOGIC_1164.all;\r\n"
107                  {
108     "\r\n"
108                    assert(v < 0x02);
109     "package prog_mem_content is\r\n"
109                    slice[i >> 3] |= v << ((i & 7));
110     "\r\n");
110                  }
111
111               else assert(0 && "Bad aspect ratio.");
112        for (uint32_t m = 0; m < 4; ++m)
112             }
113            write_mem(out, false, m);
113     }
114
114     //-----------------------------------------------------------------------------
115        for (uint32_t m = 0; m < 4; ++m)
115     //
116            write_mem(out, true,  m);
116     // write one initialization vector
117
117     //
118        fprintf(out,
118     void
119     "end prog_mem_content;\r\n"
119     write_vector(FILE * out, uint32_t mem, uint32_t vec, const uint8_t * data)
120     "\r\n");
120     {
121     }
121        fprintf(out, "constant p%u_%2.2X : BIT_VECTOR := X\"", mem, vec);
122     //-----------------------------------------------------------------------------
122        for (int32_t d = 31; d >= 0; --d)
123     int
123            fprintf(out, "%2.2X", data[d]);
124     main(int argc, char * argv[])
124
125     {
125        fprintf(out, "\";\r\n");
126        if (argc > 1)   hex_file = argv[1];
126     }
127        if (argc > 2)   vhdl_file = argv[2];
127     //-----------------------------------------------------------------------------
128
128     //
129     FILE * in = stdin;
129     // write one memory
130        if (hex_file)   in = fopen(hex_file, "r");
130     //
131        assert(in);
131     void
132        read_file(in);
132     write_mem(FILE * out, uint32_t mem, uint32_t bytes)
133        fclose(in);
133     {
134
134        fprintf(out, "-- content of p_%u --------------------------------------"
135     FILE * out = stdout;
135                     "--------------------------------------------\r\n", mem);
136        if (vhdl_file)   out = fopen(vhdl_file, "w");
136
137        write_file(out);
137     const uint8_t * src = slice;
138        assert(out);
138        for (uint32_t v = 0; v < bytes/32; ++v)
139     }
139            write_vector(out, mem, v, src + 32*v);
140     //-----------------------------------------------------------------------------
140
 
141        fprintf(out, "\r\n");
 
142     }
 
143     //-----------------------------------------------------------------------------
 
144     //
 
145     // write the entire memory_contents file.
 
146     //
 
147     void
 
148     write_file(FILE * out, uint32_t bits)
 
149     {
 
150        fprintf(out,
 
151     "\r\n"
 
152     "library IEEE;\r\n"
 
153     "use IEEE.STD_LOGIC_1164.all;\r\n"
 
154     "\r\n"
 
155     "package prog_mem_content is\r\n"
 
156     "\r\n");
 
157
 
158     const uint32_t mems = 16/bits;
 
159
 
160        for (uint32_t m = 0; m < 2*mems; ++m)
 
161            {
 
162              copy_slice(m, bits, 0x1000);
 
163              write_mem(out, m, 0x200);
 
164            }
 
165
 
166        fprintf(out,
 
167     "end prog_mem_content;\r\n"
 
168     "\r\n");
 
169     }
 
170     //-----------------------------------------------------------------------------
 
171     int
 
172     main(int argc, char * argv[])
 
173     {
 
174     uint32_t bits = 4;
 
175     const char * prog = *argv++;   --argc;
 
176
 
177        if      (argc && !strcmp(*argv, "-1"))    { bits =  1;   ++argv;   --argc; }
 
178        else if (argc && !strcmp(*argv, "-2"))    { bits =  2;   ++argv;   --argc; }
 
179        else if (argc && !strcmp(*argv, "-4"))    { bits =  4;   ++argv;   --argc; }
 
180        else if (argc && !strcmp(*argv, "-8"))    { bits =  8;   ++argv;   --argc; }
 
181        else if (argc && !strcmp(*argv, "-16"))   { bits = 16;   ++argv;   --argc; }
 
182
 
183     const char * hex_file = 0;
 
184     const char * vhdl_file = 0;
 
185
 
186        if (argc)   { hex_file  = *argv++;   --argc; }
 
187        if (argc)   { vhdl_file = *argv++;   --argc; }
 
188        assert(argc == 0);
 
189
 
190     FILE * in = stdin;
 
191        if (hex_file)   in = fopen(hex_file, "r");
 
192        assert(in);
 
193        read_file(in);
 
194        fclose(in);
 
195
 
196     FILE * out = stdout;
 
197        if (vhdl_file)   out = fopen(vhdl_file, "w");
 
198        write_file(out, bits);
 
199        assert(out);
 
200     }
 
201     //-----------------------------------------------------------------------------
<pre class="filename">
<pre class="filename">
tools/make_mem.cc
tools/make_mem.cc
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>The command to build the tool is:
<P>The command to build the tool is:
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Build makemem.
# Build makemem.
g++ -o make_mem make_mem.cc
g++ -o make_mem make_mem.cc
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<UL>
<UL>
  <LI>Build the <STRONG>end_conv</STRONG> tool. The source is this:
  <LI>Build the <STRONG>end_conv</STRONG> tool. The source is this:
</UL>
</UL>
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     #include "assert.h"
  1     #include "assert.h"
  2     #include "ctype.h"
  2     #include "ctype.h"
  3     #include "stdio.h"
  3     #include "stdio.h"
  4     #include "string.h"
  4     #include "string.h"
  5
  5
  6     //-----------------------------------------------------------------------------
  6     //-----------------------------------------------------------------------------
  7     int
  7     int
  8     main(int argc, const char * argv)
  8     main(int argc, const char * argv)
  9     {
  9     {
 10     char buffer[2000];
 10     char buffer[2000];
 11     int pc, val, val2;
 11     int pc, val, val2;
 12
 12
 13        for (;;)
 13        for (;;)
 14            {
 14            {
 15              char * s = fgets(buffer, sizeof(buffer) - 2, stdin);
 15              char * s = fgets(buffer, sizeof(buffer) - 2, stdin);
 16              if (s == 0)   return 0;
 16              if (s == 0)   return 0;
 17
 17
 18              // map lines '  xx:' and 'xxxxxxxx; to 2* the hex value.
 18              // map lines '  xx:' and 'xxxxxxxx; to 2* the hex value.
 19              //
 19              //
 20              if (
 20              if (
 21                  (isxdigit(s[0]) || s[0] == ' ') &&
 21                  (isxdigit(s[0]) || s[0] == ' ') &&
 22                  (isxdigit(s[1]) || s[1] == ' ') &&
 22                  (isxdigit(s[1]) || s[1] == ' ') &&
 23                  (isxdigit(s[2]) || s[2] == ' ') &&
 23                  (isxdigit(s[2]) || s[2] == ' ') &&
 24                   isxdigit(s[3]) && s[4] == ':')   // '  xx:'
 24                   isxdigit(s[3]) && s[4] == ':')   // '  xx:'
 25                 {
 25                 {
 26                   assert(1 == sscanf(s, " %x:", &pc));
 26                   assert(1 == sscanf(s, " %x:", &pc));
 27                   if (pc & 1)       printf("%4X+:", pc/2);
 27                   if (pc & 1)       printf("%4X+:", pc/2);
 28                   else              printf("%4X:", pc/2);
 28                   else              printf("%4X:", pc/2);
 29                   s += 5;
 29                   s += 5;
 30                 }
 30                 }
 31              else if (isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) &&
 31              else if (isxdigit(s[0]) && isxdigit(s[1]) && isxdigit(s[2]) &&
 32                       isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) &&
 32                       isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) &&
 33                       isxdigit(s[6]) && isxdigit(s[7]))             // 'xxxxxxxx'
 33                       isxdigit(s[6]) && isxdigit(s[7]))             // 'xxxxxxxx'
 34                 {
 34                 {
 35                   assert(1 == sscanf(s, "%x", &pc));
 35                   assert(1 == sscanf(s, "%x", &pc));
 36                   if (pc & 1)   printf("%8.8X+:", pc/2);
 36                   if (pc & 1)   printf("%8.8X+:", pc/2);
 37                   else          printf("%8.8X:", pc/2);
 37                   else          printf("%8.8X:", pc/2);
 38                   s += 8;
 38                   s += 8;
 39                 }
 39                 }
 40              else                             // other: copy verbatim
 40              else                             // other: copy verbatim
 41                 {
 41                 {
 42                   printf("%s", s);
 42                   printf("%s", s);
 43                   continue;
 43                   continue;
 44                 }
 44                 }
 45
 45
 46               while (isblank(*s))   printf("%c", *s++);
 46               while (isblank(*s))   printf("%c", *s++);
 47
 47
 48               // endian swap.
 48               // endian swap.
 49               //
 49               //
 50               while (isxdigit(s[0]) &&
 50               while (isxdigit(s[0]) &&
 51                      isxdigit(s[1]) &&
 51                      isxdigit(s[1]) &&
 52                               s[2] == ' ' &&
 52                               s[2] == ' ' &&
 53                      isxdigit(s[3]) &&
 53                      isxdigit(s[3]) &&
 54                      isxdigit(s[4]) &&
 54                      isxdigit(s[4]) &&
 55                               s[5] == ' ')
 55                               s[5] == ' ')
 56                  {
 56                  {
 57                   assert(2 == sscanf(s, "%x %x ", &val, &val2));
 57                   assert(2 == sscanf(s, "%x %x ", &val, &val2));
 58                   printf("%2.2X%2.2X  ", val2, val);
 58                   printf("%2.2X%2.2X  ", val2, val);
 59                   s += 6;
 59                   s += 6;
 60                  }
 60                  }
 61
 61
 62              char * s1 = strstr(s, ".+");
 62              char * s1 = strstr(s, ".+");
 63              char * s2 = strstr(s, ".-");
 63              char * s2 = strstr(s, ".-");
 64              if (s1)
 64              if (s1)
 65                 {
 65                 {
 66                   assert(1 == sscanf(s1 + 2, "%d", &val));
 66                   assert(1 == sscanf(s1 + 2, "%d", &val));
 67                   assert((val & 1) == 0);
 67                   assert((val & 1) == 0);
 68                   sprintf(s1, " 0x%X", (pc + val)/2 + 1);
 68                   sprintf(s1, " 0x%X", (pc + val)/2 + 1);
 69                   printf(s);
 69                   printf(s);
 70                   s = s1 + strlen(s1) + 1;
 70                   s = s1 + strlen(s1) + 1;
 71                 }
 71                 }
 72              else if (s2)
 72              else if (s2)
 73                 {
 73                 {
 74                   assert(1 == sscanf(s2 + 2, "%d", &val));
 74                   assert(1 == sscanf(s2 + 2, "%d", &val));
 75                   assert((val & 1) == 0);
 75                   assert((val & 1) == 0);
 76                   sprintf(s2, " 0x%X", (pc - val)/2 + 1);
 76                   sprintf(s2, " 0x%X", (pc - val)/2 + 1);
 77                   printf(s);
 77                   printf(s);
 78                   s = s2 + strlen(s2) + 1;
 78                   s = s2 + strlen(s2) + 1;
 79                 }
 79                 }
 80
 80
 81              printf("%s", s);
 81              printf("%s", s);
 82            }
 82            }
 83     }
 83     }
 84     //-----------------------------------------------------------------------------
 84     //-----------------------------------------------------------------------------
<pre class="filename">
<pre class="filename">
tools/end_conv.cc
tools/end_conv.cc
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>The command to build the tool is:
<P>The command to build the tool is:
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Build end_conv.
# Build end_conv.
g++ -o end_conv end_conv.cc
g++ -o end_conv end_conv.cc
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H2><A NAME="section_1_4">8.4 Preparing the Memory Content</A></H2>
<H2><A NAME="section_1_4">8.4 Preparing the Memory Content</A></H2>
 
 
<P>We write a program <STRONG>hello.c</STRONG> that prints "Hello World" to the serial line.
<P>We write a program <STRONG>hello.c</STRONG> that prints "Hello World" to the serial line.
 
 
<P>The source is this:
<P>The source is this:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     #include "stdint.h"
  1     #include "stdint.h"
  2     #include "avr/io.h"
  2     #include "avr/io.h"
  3     #include "avr/pgmspace.h"
  3     #include "avr/pgmspace.h"
  4
  4
  5     #undef F_CPU
  5     #undef F_CPU
  6     #define F_CPU 25000000UL
  6     #define F_CPU 25000000UL
  7     #include "util/delay.h"
  7     #include "util/delay.h"
  8
  8
  9
  9
 10          //----------------------------------------------------------------------//
 10          //----------------------------------------------------------------------//
 11         //                                                                      //
 11         //                                                                      //
 12        //   print char cc on UART.                                             //
 12        //   print char cc on UART.                                             //
 13       //    return number of chars printed (i.e. 1).                          //
 13       //    return number of chars printed (i.e. 1).                          //
 14      //                                                                      //
 14      //                                                                      //
 15     //----------------------------------------------------------------------//
 15     //----------------------------------------------------------------------//
 16     uint8_t
 16     uint8_t
 17     uart_putc(uint8_t cc)
 17     uart_putc(uint8_t cc)
 18     {
 18     {
 19         while ((UCSRA & (1 << UDRE)) == 0)      ;
 19         while ((UCSRA & (1 << UDRE)) == 0)      ;
 20         UDR = cc;
 20         UDR = cc;
 21         return 1;
 21         return 1;
 22     }
 22     }
 23
 23
 24          //----------------------------------------------------------------------//
 24          //----------------------------------------------------------------------//
 25         //                                                                      //
 25         //                                                                      //
 26        //   print char cc on 7 segment display.                                //
 26        //   print char cc on 7 segment display.                                //
 27       //    return number of chars printed (i.e. 1).                          //
 27       //    return number of chars printed (i.e. 1).                          //
 28      //                                                                      //
 28      //                                                                      //
 29     //----------------------------------------------------------------------//
 29     //----------------------------------------------------------------------//
 30     // The segments of the display are encoded like this:
 30     // The segments of the display are encoded like this:
 31     //
 31     //
 32     //
 32     //
 33     //      segment     PORT B
 33     //      segment     PORT B
 34     //      name        Bit number
 34     //      name        Bit number
 35     //      ----A----   ----0----
 35     //      ----A----   ----0----
 36     //      |       |   |       |
 36     //      |       |   |       |
 37     //      F       B   5       1
 37     //      F       B   5       1
 38     //      |       |   |       |
 38     //      |       |   |       |
 39     //      ----G----   ----6----
 39     //      ----G----   ----6----
 40     //      |       |   |       |
 40     //      |       |   |       |
 41     //      E       C   4       2
 41     //      E       C   4       2
 42     //      |       |   |       |
 42     //      |       |   |       |
 43     //      ----D----   ----3----
 43     //      ----D----   ----3----
 44     //
 44     //
 45     //-----------------------------------------------------------------------------
 45     //-----------------------------------------------------------------------------
 46
 46
 47     #define SEG7(G, F, E, D, C, B, A)   (~(G<<6|F<<5|E<<4|D<<3|C<<2|B<<1|A))
 47     #define SEG7(G, F, E, D, C, B, A)   (~(G<<6|F<<5|E<<4|D<<3|C<<2|B<<1|A))
 48
 48
 49     uint8_t
 49     uint8_t
 50     seg7_putc(uint8_t cc)
 50     seg7_putc(uint8_t cc)
 51     {
 51     {
 52     uint16_t t;
 52     uint16_t t;
 53
 53
 54         switch(cc)
 54         switch(cc)
 55         {                   //   G F E D C B A
 55         {                   //   G F E D C B A
 56         case ' ':   PORTB = SEG7(0,0,0,0,0,0,0);        break;
 56         case ' ':   PORTB = SEG7(0,0,0,0,0,0,0);        break;
 57         case 'E':   PORTB = SEG7(1,1,1,1,0,0,1);        break;
 57         case 'E':   PORTB = SEG7(1,1,1,1,0,0,1);        break;
 58         case 'H':   PORTB = SEG7(1,1,1,0,1,1,0);        break;
 58         case 'H':   PORTB = SEG7(1,1,1,0,1,1,0);        break;
 59         case 'L':   PORTB = SEG7(0,1,1,1,0,0,0);        break;
 59         case 'L':   PORTB = SEG7(0,1,1,1,0,0,0);        break;
 60         case 'O':   PORTB = SEG7(0,1,1,1,1,1,1);        break;
 60         case 'O':   PORTB = SEG7(0,1,1,1,1,1,1);        break;
 61         default:    PORTB = SEG7(1,0,0,1,0,0,1);        break;
 61         default:    PORTB = SEG7(1,0,0,1,0,0,1);        break;
 62         }
 62         }
 63
 63
 64         // wait 800 + 200 ms. This can be quite boring in simulations,
 64         // wait 800 + 200 ms. This can be quite boring in simulations,
 65         // so we wait only if DIP switch 6 is closed.
 65         // so we wait only if DIP switch 6 is closed.
 66         //
 66         //
 67         if (!(PINB & 0x20))     for (t = 0; t < 800; ++t)   _delay_ms(1);
 67         if (!(PINB & 0x20))     for (t = 0; t < 800; ++t)   _delay_ms(1);
 68         PORTB = SEG7(0,0,0,0,0,0,0);
 68         PORTB = SEG7(0,0,0,0,0,0,0);
 69         if (!(PINB & 0x20))     for (t = 0; t < 200; ++t)   _delay_ms(1);
 69         if (!(PINB & 0x20))     for (t = 0; t < 200; ++t)   _delay_ms(1);
 70
 70
 71         return 1;
 71         return 1;
 72     }
 72     }
 73
 73
 74          //----------------------------------------------------------------------//
 74          //----------------------------------------------------------------------//
 75         //                                                                      //
 75         //                                                                      //
 76        //   print string s on UART.                                            //
 76        //   print string s on UART.                                            //
 77       //    return number of chars printed.                                   //
 77       //    return number of chars printed.                                   //
 78      //                                                                      //
 78      //                                                                      //
 79     //----------------------------------------------------------------------//
 79     //----------------------------------------------------------------------//
 80     uint16_t
 80     uint16_t
 81     uart_puts(const char * s)
 81     uart_puts(const char * s)
 82     {
 82     {
 83     const char * from = s;
 83     const char * from = s;
 84     uint8_t cc;
 84     uint8_t cc;
 85         while ((cc = pgm_read_byte(s++)))   uart_putc(cc);
 85         while ((cc = pgm_read_byte(s++)))   uart_putc(cc);
 86         return s - from - 1;
 86         return s - from - 1;
 87     }
 87     }
 88
 88
 89          //----------------------------------------------------------------------//
 89          //----------------------------------------------------------------------//
 90         //                                                                      //
 90         //                                                                      //
 91        //   print string s on 7 segment display.                               //
 91        //   print string s on 7 segment display.                               //
 92       //    return number of chars printed.                                   //
 92       //    return number of chars printed.                                   //
 93      //                                                                      //
 93      //                                                                      //
 94     //----------------------------------------------------------------------//
 94     //----------------------------------------------------------------------//
 95     uint16_t
 95     uint16_t
 96     seg7_puts(const char * s)
 96     seg7_puts(const char * s)
 97     {
 97     {
 98     const char * from = s;
 98     const char * from = s;
 99     uint8_t cc;
 99     uint8_t cc;
100         while ((cc = pgm_read_byte(s++)))   seg7_putc(cc);
100         while ((cc = pgm_read_byte(s++)))   seg7_putc(cc);
101         return s - from - 1;
101         return s - from - 1;
102     }
102     }
103
103
104     //-----------------------------------------------------------------------------
104     //-----------------------------------------------------------------------------
105     int
105     int
106     main(int argc, char * argv[])
106     main(int argc, char * argv[])
107     {
107     {
108         for (;;)
108         for (;;)
109         {
109         {
110             if (PINB & 0x40)    // DIP switch 7 open.
110             if (PINB & 0x40)    // DIP switch 7 open.
111                 {
111                 {
112                     // print 'Hello world' on UART.
112                     // print 'Hello world' on UART.
113                     uart_puts(PSTR("Hello, World!\r\n"));
113                     uart_puts(PSTR("Hello, World!\r\n"));
114                 }
114                 }
115             else                // DIP switch 7 closed.
115             else                // DIP switch 7 closed.
116                 {
116                 {
117                     // print 'HELLO' on 7-segment display
117                     // print 'HELLO' on 7-segment display
118                     seg7_puts(PSTR("HELLO "));
118                     seg7_puts(PSTR("HELLO "));
119                 }
119                 }
120         }
120         }
121     }
121     }
122     //-----------------------------------------------------------------------------
122     //-----------------------------------------------------------------------------
<pre class="filename">
<pre class="filename">
app/hello.c
app/hello.c
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>The commands to create <STRONG>hello.hex</STRONG> and <STRONG>hello.css</STRONG> are:
<P>The commands to create <STRONG>hello.hex</STRONG> and <STRONG>hello.css</STRONG> are:
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Compile and link hello.c.
# Compile and link hello.c.
avr-gcc -Wall -Os -fpack-struct -fshort-enums -funsigned-char -funsigned-bitfields -mmcu=atmega8 \
avr-gcc -Wall -Os -fpack-struct -fshort-enums -funsigned-char -funsigned-bitfields -mmcu=atmega8 \
    -DF_CPU=33333333UL -MMD -MP -MF"main.d" -MT"main.d" -c -o"main.o" "main.c"
    -DF_CPU=25000000UL -c -o"hello.o" "hello.c"
avr-gcc -Wl,-Map,AVR_FPGA.map -mmcu=atmega8 -o"AVR_FPGA.elf"  ./main.o
avr-gcc -Wl,-Map,hello.map -mmcu=atmega8 -o"hello.elf"  ./hello.o
 
 
# Create an opcode listing.
# Create an opcode listing.
avr-objdump -h -S AVR_FPGA.elf  >"AVR_FPGA.lss"
avr-objdump -h -S hello.elf  >"hello.lss"
 
 
# Create intel hex file.
# Create intel hex file.
avr-objcopy -R .eeprom -O ihex AVR_FPGA.elf  "AVR_FPGA.hex"
avr-objcopy -R .eeprom -O ihex hello.elf  "hello.hex"
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>Create  <STRONG>hello.css1</STRONG>, a better readable from of  <STRONG>hello.css</STRONG>:
<P>Create  <STRONG>hello.css1</STRONG>, a better readable from of  <STRONG>hello.css</STRONG>:
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Create hello.css1.
# Create hello.css1.
./end_conv < hello.css > hello.css1
./end_conv < hello.css > hello.css1
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>Create <STRONG>prog_mem_content.vhd</STRONG>.
<P>Create <STRONG>prog_mem_content.vhd</STRONG>.
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Create prog_mem_content.vhd.
# Create prog_mem_content.vhd.
./make_mem < hello.hex > src/prog_mem_content.vhd
./make_mem < hello.hex > src/prog_mem_content.vhd
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H2><A NAME="section_1_5">8.5 Performing the Functional Simulation</A></H2>
<H2><A NAME="section_1_5">8.5 Performing the Functional Simulation</A></H2>
 
 
<H3><A NAME="section_1_5_1">8.5.1 Preparing a Testbench</A></H3>
<H3><A NAME="section_1_5_1">8.5.1 Preparing a Testbench</A></H3>
 
 
<P>We prepare a testbench in which we instantiate the top-level FPGA design
<P>We prepare a testbench in which we instantiate the top-level FPGA design
of the CPU. The test bench provides a clock signal and a reset signal
of the CPU. The test bench provides a clock signal and a reset signal
for the CPU:
for the CPU:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     -------------------------------------------------------------------------------
  1     -------------------------------------------------------------------------------
  2     --
  2     --
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
  4     --
  4     --
  5     --  This code is free software: you can redistribute it and/or modify
  5     --  This code is free software: you can redistribute it and/or modify
  6     --  it under the terms of the GNU General Public License as published by
  6     --  it under the terms of the GNU General Public License as published by
  7     --  the Free Software Foundation, either version 3 of the License, or
  7     --  the Free Software Foundation, either version 3 of the License, or
  8     --  (at your option) any later version.
  8     --  (at your option) any later version.
  9     --
  9     --
 10     --  This code is distributed in the hope that it will be useful,
 10     --  This code is distributed in the hope that it will be useful,
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13     --  GNU General Public License for more details.
 13     --  GNU General Public License for more details.
 14     --
 14     --
 15     --  You should have received a copy of the GNU General Public License
 15     --  You should have received a copy of the GNU General Public License
 16     --  along with this code (see the file named COPYING).
 16     --  along with this code (see the file named COPYING).
 17     --  If not, see http://www.gnu.org/licenses/.
 17     --  If not, see http://www.gnu.org/licenses/.
 18     --
 18     --
 19     -------------------------------------------------------------------------------
 19     -------------------------------------------------------------------------------
 20     -------------------------------------------------------------------------------
 20     -------------------------------------------------------------------------------
 21     --
 21     --
 22     -- Module Name:    alu - Behavioral
 22     -- Module Name:    alu - Behavioral
 23     -- Create Date:    16:47:24 12/29/2009
 23     -- Create Date:    16:47:24 12/29/2009
 24     -- Description:    arithmetic logic unit of a CPU
 24     -- Description:    arithmetic logic unit of a CPU
 25     --
 25     --
 26     -------------------------------------------------------------------------------
 26     -------------------------------------------------------------------------------
 27     --
 27     --
 28     library IEEE;
 28     library IEEE;
 29     use IEEE.STD_LOGIC_1164.ALL;
 29     use IEEE.STD_LOGIC_1164.ALL;
 30     use IEEE.STD_LOGIC_ARITH.ALL;
 30     use IEEE.STD_LOGIC_ARITH.ALL;
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
 32
 32
 33     entity testbench is
 33     entity testbench is
 34     end testbench;
 34     end testbench;
 35
 35
 36     architecture Behavioral of testbench is
 36     architecture Behavioral of testbench is
 37
 37
 38     component avr_fpga
 38     component avr_fpga
 39         port (  I_CLK_100   : in  std_logic;
 39         port (  I_CLK_100   : in  std_logic;
 40                 I_SWITCH    : in  std_logic_vector(9 downto 0);
 40                 I_SWITCH    : in  std_logic_vector(9 downto 0);
 41                 I_RX        : in  std_logic;
 41                 I_RX        : in  std_logic;
 42
 42
 43                 Q_7_SEGMENT : out std_logic_vector(6 downto 0);
 43                 Q_7_SEGMENT : out std_logic_vector(6 downto 0);
 44                 Q_LEDS      : out std_logic_vector(3 downto 0);
 44                 Q_LEDS      : out std_logic_vector(3 downto 0);
 45                 Q_TX        : out std_logic);
 45                 Q_TX        : out std_logic);
 46     end component;
 46     end component;
 47
 47
 48     signal L_CLK_100            : std_logic;
 48     signal L_CLK_100            : std_logic;
 49     signal L_LEDS               : std_logic_vector(3 downto 0);
 49     signal L_LEDS               : std_logic_vector(3 downto 0);
 50     signal L_7_SEGMENT          : std_logic_vector(6 downto 0);
 50     signal L_7_SEGMENT          : std_logic_vector(6 downto 0);
 51     signal L_RX                 : std_logic;
 51     signal L_RX                 : std_logic;
 52     signal L_SWITCH             : std_logic_vector(9 downto 0);
 52     signal L_SWITCH             : std_logic_vector(9 downto 0);
 53     signal L_TX                 : std_logic;
 53     signal L_TX                 : std_logic;
 54
 54
 55     signal  L_CLK_COUNT         : integer := 0;
 55     signal  L_CLK_COUNT         : integer := 0;
 56
 56
 57     begin
 57     begin
 58
 58
 59         fpga: avr_fpga
 59         fpga: avr_fpga
 60         port map(   I_CLK_100   => L_CLK_100,
 60         port map(   I_CLK_100   => L_CLK_100,
 61                     I_SWITCH    => L_SWITCH,
 61                     I_SWITCH    => L_SWITCH,
 62                     I_RX        => L_RX,
 62                     I_RX        => L_RX,
 63
 63
 64                     Q_LEDS      => L_LEDS,
 64                     Q_LEDS      => L_LEDS,
 65                     Q_7_SEGMENT => L_7_SEGMENT,
 65                     Q_7_SEGMENT => L_7_SEGMENT,
 66                     Q_TX        => L_TX);
 66                     Q_TX        => L_TX);
 67
 67
 68         process -- clock process for CLK_100,
 68         process -- clock process for CLK_100,
 69         begin
 69         begin
 70             clock_loop : loop
 70             clock_loop : loop
 71                 L_CLK_100 <= transport '0';
 71                 L_CLK_100 <= transport '0';
 72                 wait for 5 ns;
 72                 wait for 5 ns;
 73
 73
 74                 L_CLK_100 <= transport '1';
 74                 L_CLK_100 <= transport '1';
 75                 wait for 5 ns;
 75                 wait for 5 ns;
 76             end loop clock_loop;
 76             end loop clock_loop;
 77         end process;
 77         end process;
 78
 78
 79         process(L_CLK_100)
 79         process(L_CLK_100)
 80         begin
 80         begin
 81             if (rising_edge(L_CLK_100)) then
 81             if (rising_edge(L_CLK_100)) then
 82                 case L_CLK_COUNT is
 82                 case L_CLK_COUNT is
 83                     when 0 => L_SWITCH <= "0011100000";   L_RX <= '0';
 83                     when 0 => L_SWITCH <= "0011100000";   L_RX <= '0';
 84                     when 2 => L_SWITCH(9 downto 8) <= "11";
 84                     when 2 => L_SWITCH(9 downto 8) <= "11";
 85                     when others =>
 85                     when others =>
 86                 end case;
 86                 end case;
 87                 L_CLK_COUNT <= L_CLK_COUNT + 1;
 87                 L_CLK_COUNT <= L_CLK_COUNT + 1;
 88             end if;
 88             end if;
 89         end process;
 89         end process;
 90     end Behavioral;
 90     end Behavioral;
 91
 91
<pre class="filename">
<pre class="filename">
test/test_tb.vhd
test/test_tb.vhd
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H3><A NAME="section_1_5_2">8.5.2 Defining Memory Modules</A></H3>
<H3><A NAME="section_1_5_2">8.5.2 Defining Memory Modules</A></H3>
 
 
<P>We also need a VHDL file that implements the Xilinx primitives that
<P>We also need a VHDL file that implements the Xilinx primitives that
we use. This is only one: the memory module RAMB4_S4_S4:
we use. This is only one: the memory module RAMB4_S4_S4:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     -------------------------------------------------------------------------------
  1     -------------------------------------------------------------------------------
  2     --
  2     --
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
  3     -- Copyright (C) 2009, 2010 Dr. Juergen Sauermann
  4     --
  4     --
  5     --  This code is free software: you can redistribute it and/or modify
  5     --  This code is free software: you can redistribute it and/or modify
  6     --  it under the terms of the GNU General Public License as published by
  6     --  it under the terms of the GNU General Public License as published by
  7     --  the Free Software Foundation, either version 3 of the License, or
  7     --  the Free Software Foundation, either version 3 of the License, or
  8     --  (at your option) any later version.
  8     --  (at your option) any later version.
  9     --
  9     --
 10     --  This code is distributed in the hope that it will be useful,
 10     --  This code is distributed in the hope that it will be useful,
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
 11     --  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12     --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13     --  GNU General Public License for more details.
 13     --  GNU General Public License for more details.
 14     --
 14     --
 15     --  You should have received a copy of the GNU General Public License
 15     --  You should have received a copy of the GNU General Public License
 16     --  along with this code (see the file named COPYING).
 16     --  along with this code (see the file named COPYING).
 17     --  If not, see http://www.gnu.org/licenses/.
 17     --  If not, see http://www.gnu.org/licenses/.
 18     --
 18     --
 19     -------------------------------------------------------------------------------
 19     -------------------------------------------------------------------------------
 20     -------------------------------------------------------------------------------
 20     -------------------------------------------------------------------------------
 21     --
 21     --
 22     -- Module Name:    prog_mem - Behavioral
 22     -- Module Name:    prog_mem - Behavioral
 23     -- Create Date:    14:09:04 10/30/2009
 23     -- Create Date:    14:09:04 10/30/2009
 24     -- Description:    a block memory module
 24     -- Description:    a block memory module
 25     --
 25     --
 26     -------------------------------------------------------------------------------
 26     -------------------------------------------------------------------------------
 27
 27
 28     library IEEE;
 28     library IEEE;
 29     use IEEE.STD_LOGIC_1164.ALL;
 29     use IEEE.STD_LOGIC_1164.ALL;
 30     use IEEE.STD_LOGIC_ARITH.ALL;
 30     use IEEE.STD_LOGIC_ARITH.ALL;
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
 31     use IEEE.STD_LOGIC_UNSIGNED.ALL;
 32
 32
 33     entity RAMB4_S4_S4 is
 33     entity RAMB4_S4_S4 is
 34         generic(INIT_00 : bit_vector := X"00000000000000000000000000000000"
 34         generic(INIT_00 : bit_vector := X"00000000000000000000000000000000"
 35                                       &  "00000000000000000000000000000000";
 35                                       &  "00000000000000000000000000000000";
 36                 INIT_01 : bit_vector := X"00000000000000000000000000000000"
 36                 INIT_01 : bit_vector := X"00000000000000000000000000000000"
 37                                       & X"00000000000000000000000000000000";
 37                                       & X"00000000000000000000000000000000";
 38                 INIT_02 : bit_vector := X"00000000000000000000000000000000"
 38                 INIT_02 : bit_vector := X"00000000000000000000000000000000"
 39                                       & X"00000000000000000000000000000000";
 39                                       & X"00000000000000000000000000000000";
 40                 INIT_03 : bit_vector := X"00000000000000000000000000000000"
 40                 INIT_03 : bit_vector := X"00000000000000000000000000000000"
 41                                       & X"00000000000000000000000000000000";
 41                                       & X"00000000000000000000000000000000";
 42                 INIT_04 : bit_vector := X"00000000000000000000000000000000"
 42                 INIT_04 : bit_vector := X"00000000000000000000000000000000"
 43                                       & X"00000000000000000000000000000000";
 43                                       & X"00000000000000000000000000000000";
 44                 INIT_05 : bit_vector := X"00000000000000000000000000000000"
 44                 INIT_05 : bit_vector := X"00000000000000000000000000000000"
 45                                       & X"00000000000000000000000000000000";
 45                                       & X"00000000000000000000000000000000";
 46                 INIT_06 : bit_vector := X"00000000000000000000000000000000"
 46                 INIT_06 : bit_vector := X"00000000000000000000000000000000"
 47                                       & X"00000000000000000000000000000000";
 47                                       & X"00000000000000000000000000000000";
 48                 INIT_07 : bit_vector := X"00000000000000000000000000000000"
 48                 INIT_07 : bit_vector := X"00000000000000000000000000000000"
 49                                       & X"00000000000000000000000000000000";
 49                                       & X"00000000000000000000000000000000";
 50                 INIT_08 : bit_vector := X"00000000000000000000000000000000"
 50                 INIT_08 : bit_vector := X"00000000000000000000000000000000"
 51                                       & X"00000000000000000000000000000000";
 51                                       & X"00000000000000000000000000000000";
 52                 INIT_09 : bit_vector := X"00000000000000000000000000000000"
 52                 INIT_09 : bit_vector := X"00000000000000000000000000000000"
 53                                       & X"00000000000000000000000000000000";
 53                                       & X"00000000000000000000000000000000";
 54                 INIT_0A : bit_vector := X"00000000000000000000000000000000"
 54                 INIT_0A : bit_vector := X"00000000000000000000000000000000"
 55                                       & X"00000000000000000000000000000000";
 55                                       & X"00000000000000000000000000000000";
 56                 INIT_0B : bit_vector := X"00000000000000000000000000000000"
 56                 INIT_0B : bit_vector := X"00000000000000000000000000000000"
 57                                       & X"00000000000000000000000000000000";
 57                                       & X"00000000000000000000000000000000";
 58                 INIT_0C : bit_vector := X"00000000000000000000000000000000"
 58                 INIT_0C : bit_vector := X"00000000000000000000000000000000"
 59                                       & X"00000000000000000000000000000000";
 59                                       & X"00000000000000000000000000000000";
 60                 INIT_0D : bit_vector := X"00000000000000000000000000000000"
 60                 INIT_0D : bit_vector := X"00000000000000000000000000000000"
 61                                       & X"00000000000000000000000000000000";
 61                                       & X"00000000000000000000000000000000";
 62                 INIT_0E : bit_vector := X"00000000000000000000000000000000"
 62                 INIT_0E : bit_vector := X"00000000000000000000000000000000"
 63                                       & X"00000000000000000000000000000000";
 63                                       & X"00000000000000000000000000000000";
 64                 INIT_0F : bit_vector := X"00000000000000000000000000000000"
 64                 INIT_0F : bit_vector := X"00000000000000000000000000000000"
 65                                       & X"00000000000000000000000000000000");
 65                                       & X"00000000000000000000000000000000");
 66
 66
 67         port(   ADDRA   : in  std_logic_vector(9 downto 0);
 67         port(   ADDRA   : in  std_logic_vector(9 downto 0);
 68                 ADDRB   : in  std_logic_vector(9 downto 0);
 68                 ADDRB   : in  std_logic_vector(9 downto 0);
 69                 CLKA    : in  std_ulogic;
 69                 CLKA    : in  std_ulogic;
 70                 CLKB    : in  std_ulogic;
 70                 CLKB    : in  std_ulogic;
 71                 DIA     : in  std_logic_vector(3 downto 0);
 71                 DIA     : in  std_logic_vector(3 downto 0);
 72                 DIB     : in  std_logic_vector(3 downto 0);
 72                 DIB     : in  std_logic_vector(3 downto 0);
 73                 ENA     : in  std_ulogic;
 73                 ENA     : in  std_ulogic;
 74                 ENB     : in  std_ulogic;
 74                 ENB     : in  std_ulogic;
 75                 RSTA    : in  std_ulogic;
 75                 RSTA    : in  std_ulogic;
 76                 RSTB    : in  std_ulogic;
 76                 RSTB    : in  std_ulogic;
 77                 WEA     : in  std_ulogic;
 77                 WEA     : in  std_ulogic;
 78                 WEB     : in  std_ulogic;
 78                 WEB     : in  std_ulogic;
 79
 79
 80                 DOA     : out std_logic_vector(3 downto 0);
 80                 DOA     : out std_logic_vector(3 downto 0);
 81                 DOB     : out std_logic_vector(3 downto 0));
 81                 DOB     : out std_logic_vector(3 downto 0));
 82     end RAMB4_S4_S4;
 82     end RAMB4_S4_S4;
 83
 83
 84     architecture Behavioral of RAMB4_S4_S4 is
 84     architecture Behavioral of RAMB4_S4_S4 is
 85
 85
 86     function cv(A : bit) return std_logic is
 86     function cv(A : bit) return std_logic is
 87     begin
 87     begin
 88        if (A = '1') then return '1';
 88        if (A = '1') then return '1';
 89        else              return '0';
 89        else              return '0';
 90        end if;
 90        end if;
 91     end;
 91     end;
 92
 92
 93     function cv1(A : std_logic) return bit is
 93     function cv1(A : std_logic) return bit is
 94     begin
 94     begin
 95        if (A = '1') then return '1';
 95        if (A = '1') then return '1';
 96        else              return '0';
 96        else              return '0';
 97        end if;
 97        end if;
 98     end;
 98     end;
 99
 99
100     signal DATA : bit_vector(4095 downto 0) :=
100     signal DATA : bit_vector(4095 downto 0) :=
101         INIT_0F & INIT_0E & INIT_0D & INIT_0C & INIT_0B & INIT_0A & INIT_09 & INIT_08 &
101         INIT_0F & INIT_0E & INIT_0D & INIT_0C & INIT_0B & INIT_0A & INIT_09 & INIT_08 &
102         INIT_07 & INIT_06 & INIT_05 & INIT_04 & INIT_03 & INIT_02 & INIT_01 & INIT_00;
102         INIT_07 & INIT_06 & INIT_05 & INIT_04 & INIT_03 & INIT_02 & INIT_01 & INIT_00;
103
103
104     begin
104     begin
105
105
106         process(CLKA, CLKB)
106         process(CLKA, CLKB)
107         begin
107         begin
108             if (rising_edge(CLKA)) then
108             if (rising_edge(CLKA)) then
109                 if (ENA = '1') then
109                 if (ENA = '1') then
110                     DOA(3) <= cv(DATA(conv_integer(ADDRA & "11")));
110                     DOA(3) <= cv(DATA(conv_integer(ADDRA & "11")));
111                     DOA(2) <= cv(DATA(conv_integer(ADDRA & "10")));
111                     DOA(2) <= cv(DATA(conv_integer(ADDRA & "10")));
112                     DOA(1) <= cv(DATA(conv_integer(ADDRA & "01")));
112                     DOA(1) <= cv(DATA(conv_integer(ADDRA & "01")));
113                     DOA(0) <= cv(DATA(conv_integer(ADDRA & "00")));
113                     DOA(0) <= cv(DATA(conv_integer(ADDRA & "00")));
114                     if (WEA = '1') then
114                     if (WEA = '1') then
115                         DATA(conv_integer(ADDRA & "11")) <= cv1(DIA(3));
115                         DATA(conv_integer(ADDRA & "11")) <= cv1(DIA(3));
116                         DATA(conv_integer(ADDRA & "10")) <= cv1(DIA(2));
116                         DATA(conv_integer(ADDRA & "10")) <= cv1(DIA(2));
117                         DATA(conv_integer(ADDRA & "01")) <= cv1(DIA(1));
117                         DATA(conv_integer(ADDRA & "01")) <= cv1(DIA(1));
118                         DATA(conv_integer(ADDRA & "00")) <= cv1(DIA(0));
118                         DATA(conv_integer(ADDRA & "00")) <= cv1(DIA(0));
119                     end if;
119                     end if;
120                end if;
120                end if;
121             end if;
121             end if;
122
122
123             if (rising_edge(CLKB)) then
123             if (rising_edge(CLKB)) then
124                 if (ENB = '1') then
124                 if (ENB = '1') then
125                     DOB(3) <= cv(DATA(conv_integer(ADDRB & "11")));
125                     DOB(3) <= cv(DATA(conv_integer(ADDRB & "11")));
126                     DOB(2) <= cv(DATA(conv_integer(ADDRB & "10")));
126                     DOB(2) <= cv(DATA(conv_integer(ADDRB & "10")));
127                     DOB(1) <= cv(DATA(conv_integer(ADDRB & "01")));
127                     DOB(1) <= cv(DATA(conv_integer(ADDRB & "01")));
128                     DOB(0) <= cv(DATA(conv_integer(ADDRB & "00")));
128                     DOB(0) <= cv(DATA(conv_integer(ADDRB & "00")));
129                     if (WEB = '1') then
129                     if (WEB = '1') then
130                         DATA(conv_integer(ADDRB & "11")) <= cv1(DIB(3));
130                         DATA(conv_integer(ADDRB & "11")) <= cv1(DIB(3));
131                         DATA(conv_integer(ADDRB & "10")) <= cv1(DIB(2));
131                         DATA(conv_integer(ADDRB & "10")) <= cv1(DIB(2));
132                         DATA(conv_integer(ADDRB & "01")) <= cv1(DIB(1));
132                         DATA(conv_integer(ADDRB & "01")) <= cv1(DIB(1));
133                         DATA(conv_integer(ADDRB & "00")) <= cv1(DIB(0));
133                         DATA(conv_integer(ADDRB & "00")) <= cv1(DIB(0));
134                     end if;
134                     end if;
135                 end if;
135                 end if;
136             end if;
136             end if;
137         end process;
137         end process;
138
138
139     end Behavioral;
139     end Behavioral;
140
140
<pre class="filename">
<pre class="filename">
test/RAMB4_S4_S4.vhd
test/RAMB4_S4_S4.vhd
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H3><A NAME="section_1_5_3">8.5.3 Creating the testbench executable</A></H3>
<H3><A NAME="section_1_5_3">8.5.3 Creating the testbench executable</A></H3>
 
 
<P>We assume the following file structure:
<P>We assume the following file structure:
 
 
<UL>
<UL>
  <LI>a <STRONG>test</STRONG> directory that contains the testbench (<STRONG>test_tb.vhd</STRONG>) and the
  <LI>a <STRONG>test</STRONG> directory that contains the testbench (<STRONG>test_tb.vhd</STRONG>) and the
  memory module (<STRONG>RAMB4_S4_S4.vhd</STRONG>).
  memory module (<STRONG>RAMB4_S4_S4.vhd</STRONG>).
  <LI>a <STRONG>src</STRONG> directory that contains all other VHDL files.
  <LI>a <STRONG>src</STRONG> directory that contains all other VHDL files.
  <LI>a <STRONG>simu</STRONG> directory (empty).
  <LI>a <STRONG>simu</STRONG> directory (empty).
  <LI>A <STRONG>Makefile</STRONG> like this:
  <LI>A <STRONG>Makefile</STRONG> like this:
</UL>
</UL>
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     PROJECT=avr_core
  1     PROJECT=avr_core
  2
  2
  3     # the vhdl source files (except testbench)
  3     # the vhdl source files (except testbench)
  4     #
  4     #
  5     FILES           += src/*.vhd
  5     FILES           += src/*.vhd
  6
  6
  7     # the testbench sources and binary.
  7     # the testbench sources and binary.
  8     #
  8     #
  9     SIMFILES        = test/test_tb.vhd test/RAMB4_S4_S4.vhd
  9     SIMFILES        =  test/test_tb.vhd
 10     SIMTOP          = testbench
 10     SIMFILES        += test/RAMB4_S4_S4.vhd
 11
 11     SIMFILES        += test/RAM32X1S.vhd
 12     # When to stop the simulation
 12     SIMTOP          = testbench
 13     #
 13
 14     # GHDL_SIM_OPT  = --assert-level=error
 14     # When to stop the simulation
 15     GHDL_SIM_OPT    = --stop-time=40us
 15     #
 16
 16     # GHDL_SIM_OPT  = --assert-level=error
 17     SIMDIR          = simu
 17     GHDL_SIM_OPT    = --stop-time=40us
 18
 18
 19     FLAGS           = --ieee=synopsys --warn-no-vital-generic -fexplicit --std=93c
 19     SIMDIR          = simu
 20
 20
 21     all:
 21     FLAGS           = --ieee=synopsys --warn-no-vital-generic -fexplicit --std=93c
 22             make compile
 22
 23             make run 2>& 1 | grep -v std_logic_arith
 23     all:
 24             make view
 24             make compile
 25
 25             make run 2>& 1 | grep -v std_logic_arith
 26     compile:
 26             make view
 27             @mkdir -p simu
 27
 28             @echo -----------------------------------------------------------------
 28     compile:
 29             ghdl -i $(FLAGS) --workdir=simu --work=work $(SIMFILES) $(FILES)
 29             @mkdir -p simu
 30             @echo
 30             @echo -----------------------------------------------------------------
 31             @echo -----------------------------------------------------------------
 31             ghdl -i $(FLAGS) --workdir=simu --work=work $(SIMFILES) $(FILES)
 32             ghdl -m $(FLAGS) --workdir=simu --work=work $(SIMTOP)
 32             @echo
 33             @echo
 33             @echo -----------------------------------------------------------------
 34             @mv $(SIMTOP) simu/$(SIMTOP)
 34             ghdl -m $(FLAGS) --workdir=simu --work=work $(SIMTOP)
 35
 35             @echo
 36     run:
 36             @mv $(SIMTOP) simu/$(SIMTOP)
 37             @$(SIMDIR)/$(SIMTOP) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(SIMTOP).vcdgz
 37
 38
 38     run:
 39     view:
 39             @$(SIMDIR)/$(SIMTOP) $(GHDL_SIM_OPT) --vcdgz=$(SIMDIR)/$(SIMTOP).vcdgz
 40             gunzip --stdout $(SIMDIR)/$(SIMTOP).vcdgz | gtkwave --vcd gtkwave.save
 40
 41
 41     view:
 42     clean:
 42             gunzip --stdout $(SIMDIR)/$(SIMTOP).vcdgz | gtkwave --vcd gtkwave.save
 43             ghdl --clean --workdir=simu
 43
 44
 44     clean:
 
 45             ghdl --clean --workdir=simu
 
 46
<pre class="filename">
<pre class="filename">
Makefile
Makefile
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<DL>
<DL>
  <DT>Then</DT>
  <DT>Then</DT>
<DD>
<DD>
</DL>
</DL>
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
# Run the functional simulation.
# Run the functional simulation.
make
make
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>It will take a moment, but then a <STRONG>gtkwave</STRONG> window like the one shown
<P>It will take a moment, but then a <STRONG>gtkwave</STRONG> window like the one shown
earlier in this lesson will appear. It my look a little different due
earlier in this lesson will appear. It my look a little different due
due to different default settings (like background color). In that
due to different default settings (like background color). In that
window you can add new signals from the design that you would like
window you can add new signals from the design that you would like
to investigate, remove signals you are not interested in, and so on.
to investigate, remove signals you are not interested in, and so on.
At the first time, no signals will be shown; you can add some by selecting
At the first time, no signals will be shown; you can add some by selecting
a component instance at the right, selecting a signal in that component,
a component instance at the right, selecting a signal in that component,
and then pushing the <STRONG>append</STRONG> button on the right.
and then pushing the <STRONG>append</STRONG> button on the right.
 
 
<P>The <STRONG>make</STRONG> command has actually made 3 things:
<P>The <STRONG>make</STRONG> command has actually made 3 things:
 
 
<UL>
<UL>
  <LI>make compile (compile the VHLD files)
  <LI>make compile (compile the VHLD files)
  <LI>make run (run the simulation), and
  <LI>make run (run the simulation), and
  <LI>make view
  <LI>make view
</UL>
</UL>
<P>The first two steps (which took most of the total time) need only be run
<P>The first two steps (which took most of the total time) need only be run
after changes to the VHDL files.
after changes to the VHDL files.
 
 
<H2><A NAME="section_1_6">8.6 Building the Design</A></H2>
<H2><A NAME="section_1_6">8.6 Building the Design</A></H2>
 
 
<P>When the functional simulation looks OK, it is time to implement the design
<P>When the functional simulation looks OK, it is time to implement the design
and check the timing. We describe this only briefly, since the Xilinx
and check the timing. We describe this only briefly, since the Xilinx
documentation of the Xilinx toolchain is a much better source of
documentation of the Xilinx toolchain is a much better source of
information.
information.
 
 
<H3><A NAME="section_1_6_1">8.6.1 Creating an UCF file</A></H3>
<H3><A NAME="section_1_6_1">8.6.1 Creating an UCF file</A></H3>
 
 
<P>Before implementing the design, we need an <STRONG>UCF</STRONG> file. That file
<P>Before implementing the design, we need an <STRONG>UCF</STRONG> file. That file
describes timing requirements, pin properties (like pull-ups for our
describes timing requirements, pin properties (like pull-ups for our
DIP switch), and pin-to-signal mappings:
DIP switch), and pin-to-signal mappings:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  1     NET     I_CLK_100       PERIOD = 10 ns;
  1     NET     I_CLK_100       PERIOD = 10 ns;
  2     NET     L_CLK           PERIOD = 35 ns;
  2     NET     L_CLK           PERIOD = 45 ns;
  3
  3
  4     NET     I_CLK_100       TNM_NET = I_CLK_100;
  4     NET     I_CLK_100       TNM_NET = I_CLK_100;
  5     NET     L_CLK           TNM_NET = L_CLK;
  5     NET     L_CLK           TNM_NET = L_CLK;
  6
  6
  7     NET     I_CLK_100       LOC = AA12;
  7     NET     I_CLK_100       LOC = AA12;
  8     NET     I_RX            LOC = M3;
  8     NET     I_RX            LOC = M3;
  9     NET     Q_TX            LOC = M4;
  9     NET     Q_TX            LOC = M4;
 10
 10
 11     # 7 segment LED display
 11     # 7 segment LED display
 12     #
 12     #
 13     NET     Q_7_SEGMENT<0>  LOC = V3;
 13     NET     Q_7_SEGMENT<0>  LOC = V3;
 14     NET     Q_7_SEGMENT<1>  LOC = V4;
 14     NET     Q_7_SEGMENT<1>  LOC = V4;
 15     NET     Q_7_SEGMENT<2>  LOC = W3;
 15     NET     Q_7_SEGMENT<2>  LOC = W3;
 16     NET     Q_7_SEGMENT<3>  LOC = T4;
 16     NET     Q_7_SEGMENT<3>  LOC = T4;
 17     NET     Q_7_SEGMENT<4>  LOC = T3;
 17     NET     Q_7_SEGMENT<4>  LOC = T3;
 18     NET     Q_7_SEGMENT<5>  LOC = U3;
 18     NET     Q_7_SEGMENT<5>  LOC = U3;
 19     NET     Q_7_SEGMENT<6>  LOC = U4;
 19     NET     Q_7_SEGMENT<6>  LOC = U4;
 20
 20
 21     # single LEDs
 21     # single LEDs
 22     #
 22     #
 23     NET     Q_LEDS<0>       LOC = N1;
 23     NET     Q_LEDS<0>       LOC = N1;
 24     NET     Q_LEDS<1>       LOC = N2;
 24     NET     Q_LEDS<1>       LOC = N2;
 25     NET     Q_LEDS<2>       LOC = P1;
 25     NET     Q_LEDS<2>       LOC = P1;
 26     NET     Q_LEDS<3>       LOC = P2;
 26     NET     Q_LEDS<3>       LOC = P2;
 27
 27
 28     # DIP switch(0 ... 7) and two pushbuttons (8, 9)
 28     # DIP switch(0 ... 7) and two pushbuttons (8, 9)
 29     #
 29     #
 30     NET     I_SWITCH<0>     LOC = H2;
 30     NET     I_SWITCH<0>     LOC = H2;
 31     NET     I_SWITCH<1>     LOC = H1;
 31     NET     I_SWITCH<1>     LOC = H1;
 32     NET     I_SWITCH<2>     LOC = J2;
 32     NET     I_SWITCH<2>     LOC = J2;
 33     NET     I_SWITCH<3>     LOC = J1;
 33     NET     I_SWITCH<3>     LOC = J1;
 34     NET     I_SWITCH<4>     LOC = K2;
 34     NET     I_SWITCH<4>     LOC = K2;
 35     NET     I_SWITCH<5>     LOC = K1;
 35     NET     I_SWITCH<5>     LOC = K1;
 36     NET     I_SWITCH<6>     LOC = L2;
 36     NET     I_SWITCH<6>     LOC = L2;
 37     NET     I_SWITCH<7>     LOC = L1;
 37     NET     I_SWITCH<7>     LOC = L1;
 38     NET     I_SWITCH<8>     LOC = R1;
 38     NET     I_SWITCH<8>     LOC = R1;
 39     NET     I_SWITCH<9>     LOC = R2;
 39     NET     I_SWITCH<9>     LOC = R2;
 40
 40
 41     NET     I_SWITCH<*>     PULLUP;
 41     NET     I_SWITCH<*>     PULLUP;
 42
 42
<pre class="filename">
<pre class="filename">
src/avr_fpga.ucf
src/avr_fpga.ucf
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<H3><A NAME="section_1_6_2">8.6.2 Synthesis and Implementation</A></H3>
<H3><A NAME="section_1_6_2">8.6.2 Synthesis and Implementation</A></H3>
 
 
<UL>
<UL>
  <LI>Start the ISE project manager and open a new project with the desired
  <LI>Start the ISE project manager and open a new project with the desired
  FPGA device.
  FPGA device.
  <LI>Add the VHDL files and the <STRONG>UCF</STRONG> file in the <STRONG>src</STRONG> directory to the
  <LI>Add the VHDL files and the <STRONG>UCF</STRONG> file in the <STRONG>src</STRONG> directory to the
  project (Project-&gt;Add Source).
  project (Project-&gt;Add Source).
  <LI>Synthesize and implement the design (Process-&gt;Implement top Module).
  <LI>Synthesize and implement the design (Process-&gt;Implement top Module).
</UL>
</UL>
<P>This generates a number of reports, netlists, and other files.
<P>This generates a number of reports, netlists, and other files.
There should be no errors. There will be warnings though, including
There should be no errors. There will be warnings though, including
timing constraints that are not met.
timing constraints that are not met.
 
 
<P>It is important to understand the reason for each warning. Warnings often
<P>It is important to understand the reason for each warning. Warnings often
point to faults in the design.
point to faults in the design.
 
 
<P>The next thing to check is the timing reports. We were lucky:
<P>The next thing to check is the timing reports. We were lucky:
 
 
<P><br>
<P><br>
 
 
<pre class="cmd">
<pre class="cmd">
 
 
#Timing report fragment:
#Timing report fragment:
================================================================================
================================================================================
Timing constraint: NET "L_CLK" PERIOD = 35 ns HIGH 50%;
Timing constraint: NET "L_CLK" PERIOD = 35 ns HIGH 50%;
 
 
 676756190 paths analyzed, 2342 endpoints analyzed, 0 failing endpoints
 676756190 paths analyzed, 2342 endpoints analyzed, 0 failing endpoints
 0 timing errors detected. (0 setup errors, 0 hold errors)
 0 timing errors detected. (0 setup errors, 0 hold errors)
 Minimum period is  34.981ns.
 Minimum period is  34.981ns.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
 
================================================================================
================================================================================
Timing constraint: NET "I_CLK_100_BUFGP/IBUFG" PERIOD = 10 ns HIGH 50%;
Timing constraint: NET "I_CLK_100_BUFGP/IBUFG" PERIOD = 10 ns HIGH 50%;
 
 
 19 paths analyzed, 11 endpoints analyzed, 0 failing endpoints
 19 paths analyzed, 11 endpoints analyzed, 0 failing endpoints
 0 timing errors detected. (0 setup errors, 0 hold errors)
 0 timing errors detected. (0 setup errors, 0 hold errors)
 Minimum period is   3.751ns.
 Minimum period is   3.751ns.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
 
 
 
All constraints were met.
All constraints were met.
 
 
</pre>
</pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>This tells us that we have enough slack on the crystal CLK_100 signal
<P>This tells us that we have enough slack on the crystal CLK_100 signal
(8.048ns would allow for up to 124 MHz). We had specified a period
(8.048ns would allow for up to 124 MHz). We had specified a period
of 35 ns irequirement for the CPU clock:
of 35 ns irequirement for the CPU clock:
 
 
<P><br>
<P><br>
 
 
<pre class="vhdl">
<pre class="vhdl">
 
 
  2     NET     L_CLK           PERIOD = 35 ns;
  2     NET     L_CLK           PERIOD = 45 ns;
<pre class="filename">
<pre class="filename">
src/avr_fpga.ucf
src/avr_fpga.ucf
</pre></pre>
</pre></pre>
<P>
<P>
 
 
<P><br>
<P><br>
 
 
<P>The CPU runs at 25 MHz, or 40 ns. The 35 ns come from the 40 ms minus
<P>The CPU runs at 25 MHz, or 40 ns. The 35 ns come from the 40 ms minus
a slack of 5 ns. With some tweaking of optimization options, we could
a slack of 5 ns. With some tweaking of optimization options, we could
have reached 33 MHz, but then the slack would have been pretty small.
have reached 33 MHz, but then the slack would have been pretty small.
 
 
<P>However, we rather stay on th safe side.
<P>However, we rather stay on th safe side.
 
 
<H2><A NAME="section_1_7">8.7 Creating a Programming File</A></H2>
<H2><A NAME="section_1_7">8.7 Creating a Programming File</A></H2>
 
 
<P>Next we double-click "Generate Programming file" in the ISE project navigator.
<P>Next we double-click "Generate Programming file" in the ISE project navigator.
This generates a file <STRONG>avr_fpga.bit</STRONG> in the project directory. This can also
This generates a file <STRONG>avr_fpga.bit</STRONG> in the project directory. This can also
be run from a Makefile or from the command line (the command is <STRONG>bitgen</STRONG>).
be run from a Makefile or from the command line (the command is <STRONG>bitgen</STRONG>).
 
 
<H2><A NAME="section_1_8">8.8 Configuring the FPGA</A></H2>
<H2><A NAME="section_1_8">8.8 Configuring the FPGA</A></H2>
 
 
<P>At this point, we have the choice between configuring the FPGA directly
<P>At this point, we have the choice between configuring the FPGA directly
via JTAG, or flashing an EEPROM and then loading the FPGA from the EEPROM.
via JTAG, or flashing an EEPROM and then loading the FPGA from the EEPROM.
 
 
<H3><A NAME="section_1_8_1">8.8.1 Configuring the FPGA via JTAG Boundary Scan</A></H3>
<H3><A NAME="section_1_8_1">8.8.1 Configuring the FPGA via JTAG Boundary Scan</A></H3>
 
 
<P>Configuring the FPGA can be done with the Xilinx tool called <STRONG>impact</STRONG>.
<P>Configuring the FPGA can be done with the Xilinx tool called <STRONG>impact</STRONG>.
The file needed by <STRONG>impact</STRONG> is <STRONG>avr_fpga.bit</STRONG> from above. The configuration
The file needed by <STRONG>impact</STRONG> is <STRONG>avr_fpga.bit</STRONG> from above. The configuration
loaded via JTAG will be lost when the FPGA looses power.
loaded via JTAG will be lost when the FPGA looses power.
 
 
<P>Choose "Boundary Scan" in <STRONG>impact</STRONG>, select the FPGA and follow the instructions.
<P>Choose "Boundary Scan" in <STRONG>impact</STRONG>, select the FPGA and follow the instructions.
 
 
<H3><A NAME="section_1_8_2">8.8.2 Flashing PROMs</A></H3>
<H3><A NAME="section_1_8_2">8.8.2 Flashing PROMs</A></H3>
 
 
<P>In theory this can also be done from ISE. In practice it could (and actually
<P>In theory this can also be done from ISE. In practice it could (and actually
did) happen that the programming cable (I use an old parallel 3 cable)
did) happen that the programming cable (I use an old parallel 3 cable)
is not detected by impact.
is not detected by impact.
 
 
<P>Before flashing the PROM, the <STRONG>avr_fpga.bit</STRONG> from the previous step needs to
<P>Before flashing the PROM, the <STRONG>avr_fpga.bit</STRONG> from the previous step needs to
translated into a format suitable for the PROM. My PROM is of the serial
translated into a format suitable for the PROM. My PROM is of the serial
variety, so I start <STRONG>impact</STRONG>, choose "PROM File Formatter" and follow the
variety, so I start <STRONG>impact</STRONG>, choose "PROM File Formatter" and follow the
instructions.
instructions.
 
 
<P>After converting <STRONG>avr_fpga.bit</STRONG> into, for example, <STRONG>avr_fpga.mcs</STRONG>, the
<P>After converting <STRONG>avr_fpga.bit</STRONG> into, for example, <STRONG>avr_fpga.mcs</STRONG>, the
PROM can be flashed. Like before choose "Boundary Scan" in #impact. This
PROM can be flashed. Like before choose "Boundary Scan" in #impact. This
time, however, you select the PROM and not the FPGA, and follow the
time, however, you select the PROM and not the FPGA, and follow the
instructions.
instructions.
 
 
<P>This concludes the description of the design flow and also of the CPU.
<P>This concludes the description of the design flow and also of the CPU.
The remaining lessons contain the complete listings of all sources files
The remaining lessons contain the complete listings of all sources files
discussed in this lectures.
discussed in this lectures.
 
 
<P>Thank you very much for your attention.
<P>Thank you very much for your attention.
 
 
<P><hr><BR>
<P><hr><BR>
<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>
<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>
</BODY>
</BODY>
</HTML>
</HTML>
 
 

powered by: WebSVN 2.1.0

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