Sei sulla pagina 1di 127

DE NAYER Instituut J. De Nayerlaan 5 B-2860 Sint-Katelijne-Waver Tel. (015) 31 69 44 Fax. (015) 31 74 53 e-mail: ppe@denayer.wenk.be ddr@denayer.wenk.be tti@denayer.wenk.be pvp@denayer.wenk.

be website: emsys.denayer.wenk.be

Learning about VHDL & FPGAs


Version 1.0

HOBU-Fonds Project IWT 020079


Title : Embedded Systeemontwerp op basis van Soft- en Hardcore FPGAs Ing. Patrick Pelgrims Ing. Dries Driessens Ing. Tom Tierens Ing. Philip Van Pelt

Projectleader Projectassistants

: :

Copyright (c) 2003 by Patrick Pelgrims, Tom Tierens, Dries Driessens and Philip Van Pelt. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/).

Page 1 of 127

I. Introduction
Traditionally, digital logic was implemented using the classic TTL-logic, a collection of digital functions (ports, counters, ...).

Figure 1: TTL NAND port Figure 1 gives an example of a NAND TTL port with the corresponding DIP-package. More complex systems can be designed by combining these basic structures. To illustrate this, an XOR function is implemented using AND, OR and NOT ports. TTL logic contains XOR- functions and the design is therefore only intended as an example. It is also possible to design an XOR by only using 4 NAND gates. A

A
0 0 1 1

B
0 1 0 1

Out
0 1 1 0

B Figure 2: Possible TTL implementation of XOR port

Out

As the complexity of designs grew, these methods became inadequate. The large amount of ICs together with the difficult routing and placement on the PCB made development and testing too complex. The first attempts to overcome these problems were to integrate a basic programmable structure into one Integrated Circuit (IC). This building block could now replace several classic TTLcomponents, thus reducing IC count. A Programmable Array Logic (or PAL) consists of a programmable ROM with added logic capacity (see Figure 3).

Page 2 of 127

Figure 3: PAL schematic These devices were an enormous success. Instead of having a separate IC for each function, there now was one component that could be programmed to behave as any other TTL module. Figure 4 illustrates the XOR function implemented on a PAL.

Figure 4: XOR implementation on PAL

Because of the fixed topology, designs were limited to a few gates. Techniques evolved and the next generation of programmable hardware is called FPGA.

Page 3 of 127

II. FPGA

FPGAs (Field Programmable Gate Array) are devices that contain lots of building blocks (ports, logic, ) with a complete interconnection structure (see Figure 5a). By programming these connections, different logical blocks or slices can be linked to obtain the desired circuit.

(a)

(b)

(c) Figure 5: (a) Xilinx FPGA structure (b) Altera FPGA structure (c) Programmable interconnections (Xilinx) (d) I/O block (Altera Stratix)

(d)

Page 4 of 127

Figures 6 and 7 give an example of a logical element (LE) and a Configurable Logic Block (CLB). A LE or CLB consists out of three parts: a Look-Up Table (LUT), a Flip-flop (FF) and a multiplexer (MUX). The LUT is similar to the PAL structure. It is the combinatorial part of the cell and describes the function of that element, just like a truth table that maps the input to the output. Therefore the table can behave as any function: F=f(F1,F2,F3,F4) with Fi being the inputs and F the output. If needed, the LUT can also be used as fast RAM. A FF latches the data to be able to work synchronously. Finally the MUX will send the data to the appropriate line where it can be used by the next LE, CLB or block. The MUX maps the outputs of the LUT to the different output lines. A 4-bit signal selects 16 possible LUT outputs. An FPGA uses different kinds of lines to transport signals across the device. Each LE or CLB is connected to its neighbours with direct lines. This assures fast communication to combine several LEs or CLBs together. Longer lines connect clusters of LEs or CLBs, whereas long lines run over the complete FPGA. Together with the programmable interconnections (see Figure 5c) and the programmable I/O blocks, a complete design can be developed using only one programmable digital IC. The two major vendors of programmable logic are Altera and Xilinx. Each uses different approaches and will therefore be discussed next to each other.

Logical Element (LE) of an Altera Cyclone Figure 6: LE overview

Page 5 of 127

Configurable Logic Block (CLB) with 2 slices of a Xilinx Spartan Figure 7: CLB overview The advantages of using these techniques over a classical TTL-based system are speed and adaptability. When an error is made or a system upgrade is ready, reprogramming the device is sufficient to alter the system. Thus, cutting down design time. The automatic syntheses, easy testability and in-system logic analysers shorten this even more. On the other hand, the same device can perform different tasks according to the configuration downloaded into it (this can even be done on board without removing the component). Due to the increased complexity of FPGAs, it is possible to implement more complex and demanding structures and even integrate a complete design on one chip. The difference with e.g. a microprocessor is that the logic can execute in parallel. In a microprocessor all instructions are performed one after the other. The software gives the sequence of instructions that will execute. When comparing to a normal processor, FPGAs can perform better. The parallelism allows for more efficient computation. If the latter can carry out 100 instructions at the same time, the clock can be 100 times slower without losing any execution speed. An FPGA running at 50MHz can therefore be faster than a processor running at 500MHz, depending on the application. All this is possible by the large amount of transistors available in FPGAs. Programming these devices isnt easy. Each Look-Up Table (LUT), I/O block and interconnection needs to be programmed. This is the price you pay for flexibility. Luckily a programming language and tools were developed to make this a less complex task. The hardware isnt programmed bit by bit, but described in a high-level description language. By describing the behaviour, design can be completed in a shorter period and the code will be more readable and portable than a schematic entry.

Page 6 of 127

III.

VHDL language

VHDL is an acronym that stands for VHSIC Hardware Description Language. VHSIC is yet another acronym meaning Very High Speed Integrated Circuits. It can be used to describe, simulate, synthesize and document any digital electronic circuit. By downloading a configuration into an FPGA, a physical system is obtained. This system will be a combination of different logical elements (AND-, OR-ports, ...) and other digital structures (Memory, ...). Because this language is an international standard, it is independent of the FPGA manufacturer. The same code can be compiled for different ICs of different vendors. The final implementations may be different, but the functional properties will be the same for all devices. Notice that VHDL is not a programming language but a descriptive language. You always have to keep the hardware in mind. Think in hardware, not software. There are some alternatives to VHDL, of which VERILOG and ABEL are the most important ones. Building blocks are the basic structures of the VHDL language. The top-level block is composed of different building blocks. Each sub-block can also be composed of other blocks (see Figure 8).

Block A

Block B

Block C

Block D

Block E Figure 8: VHDL block structure

Block F

Each block consists of two parts: an entity and an architecture element (see Figure 9). The entity describes the interface to that block and a separate part, the architecture, associated with the entity describes how that block operates. The entity is like a pin description in a data book, specifying the inputs and outputs to the block. The architecture can be compared to a schematic for the block, describing in words (not symbols) what the block does.

Page 7 of 127

VHDL file Entity declaration Architecture declaration Figure 9: VHDL-file structure This is illustrated in the following example: Figure 10a is the interface of a building block. Only the in-and outputs are given. The block itself is a black box. What it does is described by the architecture. If you want to design a XOR function, the architecture will be: C<=A xor B (cfr. C=A xor B). The VHDL code representing this block is given in figure 10b. entity XORport is port ( A,B: in BIT; C: out BIT ); end XORport; Architecture architecture dataflow of XORport is begin C<=A xor B; end dataflow; (b) Figure 10: (a) Interface (b) Architecture structure
Entity

A B

(a)

In the XORport entity declaration, A and B are declared as input bits, whereas C is declared as output bit. The architecture describes what the box will do; in this case the dataflow architecture uses the XORport entity and describes the behaviour of a XOR-port. A signal assignment statement describes how data flows from the signals on the right side of the <= operator to the signal on the left side.

Note: the <= symbol was chosen carefully to avoid confusion with the variable assignment operator (usually =) of typical programming languages. The signal assignment operator in VHDL specifies a relationship between signals, not a transfer of data as in most programming languages.
Evaluating the expression is performed by substituting the values of the signals in the expression and computing the result of each operator in the expression. The implementation of this XOR port is indicated in the next figures (see Figures 11 and 12). The first image gives a complete overview of the FPGA, whereas the next ones represent a zoomed in portion of the complete design. The second figure shows clearly the two input pins and the output pin. The logical unit is depicted in the last figure. Figure 13 shows the XORport-entity compiled by the Xilinx tool chain. Compare this to the schematic you would have expected to see.

Page 8 of 127

Figure 11: XOR implementation on Altera Cyclone

(a)

(b)

(c) Figure 12: XOR implementation on Xilinx Spartan (a) Overview (b) Routing (c) CLB overview

Page 9 of 127

Figure 13: Generated XOR design by Xilinx

When analysing the code in figure 10b, a syntax for writing VHDL code can be derived (see figure 14a and 14b).

Entity

Architecture

entity entity-name is architecture architecture-name of entity-name is variable declarations port ( signal declarations signal-names : mode signal-type; constant declarations signal-names : mode signal-type; function definitions component declarations signal-names : mode signal-type); end entity-name; begin concurrent-statement; concurrent-statement; end architecture-name; (a) (b) Figure 14: (a) Overview of entity (b) Architecture syntax

Different signal-types are given in figure 15. Because the bit-types are not always satisfactory, its best to use the std_logic-types. They can describe the status of a signal/pin more accurately (e.g. low, high, high impedance, dont care, ).

Signal-type

Signal-mode

bit (1 or 0) in bit_vector (combination of bits) out boolean (true or false) buffer integer (-231+1 to +231-1) inout real user-defined types (defined by libraries) std_logic std_logic_vector Figure 15: Overview of signal-types and signal-modes Page 10 of 127

Signals are the wires of VHDL. They are used to connect different blocks. Syntax: signal signal-names : signal-type Variable declarations Same as signals, but no physical significance. Syntax: variable variable-names : variable-type Constant declarations Fixed numbers can de declared constant to improve readability Syntax: constant constant-names : constant-type := constant-value Functions have the same meaning in VHDL as in most programming Function definitions languages. They can be used to define subroutines. Definitions of the components (blocks) you want to use in your Component design. declarations Figure 16: Overview of architecture declarations

Signal declarations

There are three ways to write an architecture: dataflow, behavioural and structural. These three will become clear while completing this course. In short, the dataflow structure will assign signals to certain outputs, given the inputs. This is done completely in parallel. Sometimes it is easier to write the code in a behavioural way. This means that different classic statements, like if-then-else, can be used. It will be executed sequential, thus one line after the other. The structural method is used to add the blocks described above to your architecture. A design can combine these different techniques. In this way each part of the code can be written in the most optimal approach. But more about this is explained later. Lets start by actually making our first design.

Page 11 of 127

IV.

First design

IMPORTANT:
Before powering up your development board or downloading a design, check everything and ask the instructor for confirmation. Make sure you are using the correct wall adaptor and be careful with lingering metal pieces or wires.

Design an application to let the GPIO LEDs (general purpose input/output LED) react to the buttons.

Figure 17: VHDL block scheme

First the general design flow (see Figure 18) is illustrated. A step-by-step tutorial for both programming an Altera and a Xilinx device is worked out below. In the two designs, similar steps can be extracted:

Design Synthese Mapping Routing Fitting Generate programming file

Page 12 of 127

(a)

(b) Figure 18: (a) Altera design flow (b) Xilinx design flow

Page 13 of 127

A) ALTERA (Quartus)
1. Create a new project
First close any existing projects (Quartus automatically loads the last project used). File -> New Project Wizard Enter the filename and project name: E.g.: Filename: c:\qdesigns\laboVHDL Project name: exercise1 Press Next No need to add extra files to project Press Next Press Next Choose the family and type of FPGA (Stratix: EP1S10F780C6ES, Cyclone: EP1C20F400C7). Press Next Press Finish

2. Make a new VHDL file


File -> New Select VHDL-file. File -> Save As (give your file the same name as you will give your entity) E.g.: button_to_led.vhd Now select this new file as the top entity of our design. This will be the entity used to connect to the pins of the FPGA. Select the Files-tab of the Project Navigator (View -> Utility Windows) Right click on the newly added file (Device Design Files) and select Set Compiler Focus To Current Entity.

3. Write an entity/architecture description


Now write the VHDL-code in the new file:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity button_to_led is port ( sw : IN std_logic_vector (3 downto 0); ledout : OUT std_logic_vector (3 downto 0) ); end button_to_led; architecture button_to_led_arch of button_to_led is begin ledout <= sw; end button_to_led_arch;

Figure 19: Button_to_led VHDL code

Page 14 of 127

The first two lines indicate which library to use. Normally the standard logic library (std_logic) is used. It consists of a more complete set of states to correctly represent internal behaviour. From now on, only use these types (std_logic and std_logic_vector). Possible includes are: IEEE.STD_LOGIC_1164.ALL => adding basic std_logic functions IEEE.STD_LOGIC_ARITH.ALL => adding arrhythmic functions IEEE.STD_LOGIC_UNSIGNED.ALL => adding unsigned arrhythmic functions IEEE.STD_LOGIC_SIGNED.ALL => adding signed arrhythmic functions The suffix ALL indicates that all functions of that library are included. The entity consists of 4 inputs (buttons) and 4 outputs (LEDs). A single input for each button can be assigned, but it is easier to define them together (see Figure 19 & 20) as an array of input pins. This will make the design much more readable. Notice the definition of the size of our input vector (n-1 downto 0). This method can be used to access any part of the array. E.g.: sw(2) sw(3 downto 2)

entity button_to_led is port ( sw1 : IN std_logic; sw2 : IN std_logic; sw3 : IN std_logic; sw4 : IN std_logic; ledout1 : OUT std_logic; ledout2 : OUT std_logic; ledout3 : OUT std_logic; ledout4 : OUT std_logic ); end button_to_led; Figure 20: Button_to_led entity code without using vectors

The architecture is quite straightforward: send the status of the sw-vector to the ledout-vector. A little more explanation is needed, though. This is the dataflow-structure discussed earlier. Every line written after the begin-statement executes in parallel. This means that the code written, wont execute one step after the other. All is done simultaneously. The results of the calculations therefore arent available until the next update cycle is reached. You can look at the code as one big loop, starting with the BEGIN-statement until the END-statement. The signals are never updated inside the loop, only at the end. The next example (see Figure 21) illustrates this. Assume that a is defined as INOUT (multidirectional pin). architecture button_to_led_arch of button_to_led is begin a <= b; c <= a; end button_to_led_arch; Figure 21: Example of dataflow-structure

Page 15 of 127

Intuitively, after execution a, b and c should have the same value. Because these processes work in parallel, this is not true. The signal a is only changed at the end of the file. So assume that a=1, b=2 and c=3 before execution. At first, one would expect a to hold the value of b after the first statement. Then the next line would send this value to c. At the end a would equal b and c (a=b=c=2). But is not the case at all. Actually the two statements are executed at the same time. So when c <= a is carried out, the new value of a isnt available yet and therefore the old value is used. The signal a gets the old value of b and the signal c gets the old value of a. After one cycle, the result will be: a=2, b=2 and c=1. When all signals are updated, a new cycle starts. The next time step will result in the following values: a=2, b=2, c=2.

4. Analyse design
Before continuing the design, the synthesis tool needs to analyse the code written and checks it for the correct syntax. Processing -> Start -> Start analysis and synthesis If the code has no syntactical errors, everything should work fine. Otherwise some debugging needs to be done (more about that later).

5. Assign pins
If the desired circuit is implemented on a physical device, the design must to be mapped on the available programmable component by assigning signals to the pins of the FPGA. The integrated design environment needs to know how to allocate the signals to the available pins. Here you define which pin corresponds with which signal in your design. In appendix A an overview of the pins used in this tutorial can be found. For this design only the Button and the LED pins are of importance. See schematics in appendix E for more details. The easiest way is to use the pin assigner, but it is also possible to adapt the assignment in notepad. Start the pin assigner: Assignments -> Assign pins For each pin select the corresponding number and press the ...- button next to the pin name field. Press start and select the pin name you want to assign to this physical pin. Press > and OK E.g.: w5 => sw[0] Press add Repeat this until all pins are assigned. After assigning all pins press OK

IMPORTANT:
Before exiting the Settings menu. Press the Device & pin options button. Go to the Unused pins tab and select As inputs, tri-stated. We protect the hardware to define unused pins as input. This way we are sure not to cause short-circuits. Internally a pull-up resistor is foreseen to prevent the pin from oscillating. When you forget to do this, your design wont work.

Press ok

Page 16 of 127

6. Synthesis and fitting


Processing -> Start Compilation Firstly the tool chain will generate all needed data from your VHDL-files. It will then try to fit this design into the desired device and performs some tests. The result is a bit-file (*.SOF) that can be downloaded to a physical device using a JTAG cable.

7. Programming the device


Connect the parallel cable to your parallel port and extend it with the Altera ByteBlaster II cable. This extension can be plugged onto the evaluation board on the JTAG-port (indicated with ByteBlaster). Make sure the red wire is pointing to the Ethernet connector on the Stratix board and not to the serial port. The programmer will send the data through the parallel cable where the ByteBlaster will convert it to JTAG signals. The FPGA or a controller IC will then download the new configuration after reset. Tools -> Programmer Check the Program/Configure-checkbox and press the Program-icon (left-top corner).

8. Testing the design


Normally a design is verified by a simulator before testing it in physical hardware. Your design could destroy some hardware on your development board. This simple project normally wont cause any problems. How to simulate a design is explained later in this course. On start-up, all LEDs are lit. This is because the buttons are active low (Button pressed = 0). Remember this for the next designs.

Page 17 of 127

B) XILINX (ISE)
1. Create a new project
First close any existing projects (ISE automatically loads the last project used). File -> New Project Enter the project name and project location: E.g.: Filename: c:\xdesigns\laboVHDL Project name: exercise1 Press Next Choose the family and type of FPGA (Spartan2E: xc2s200e pq208 6, Spartan3: xc3s200 ft256). Choose following settings: Top-level Module Type: HDL Synthesis tool: XST Simulator: other Generated simulation language: VHDL Press Next Press Next Press Finish

2. Make a new VHDL file


Right click on device (xc2s200e, xc3s200) -> New Source Select VHDL-Module and enter file name. E.g.: button_to_led.vhd Press Next Press Next Press Finish

3. Write an entity/architecture description


Now write the VHDL-code in the new file:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity button_to_led is port ( sw : IN std_logic_vector (3 downto 0); ledout : OUT std_logic_vector (3 downto 0) ); end button_to_led; architecture button_to_led_arch of button_to_led is begin ledout <= sw; end button_to_led_arch;

Figure 22: Button_to_led VHDL code

Page 18 of 127

The first two lines indicate which library to use. Normally the standard logic library (std_logic) is used. It consists of a more complete set of states to correctly represent internal behaviour. From now on, only use these types (std_logic and std_logic_vector). Possible includes are: IEEE.STD_LOGIC_1164.ALL => adding basic std_logic functions IEEE.STD_LOGIC_ARITH.ALL => adding arrhythmic functions IEEE.STD_LOGIC_UNSIGNED.ALL => adding unsigned arrhythmic functions IEEE.STD_LOGIC_SIGNED.ALL => adding signed arrhythmic functions The suffix ALL indicates that all functions of that library are included. The entity consists of 4 inputs (buttons) and 4 outputs (LEDs). A single input for each button can be assigned, but it is easier to define them together (see Figure 22 & 23) as an array of input pins. This will make the design much more readable. Notice the definition of the size of our input vector (n-1 downto 0). This method can be used to access any part of the array. E.g.: sw(2) sw(3 downto 2)

entity button_to_led is port ( sw1 : IN std_logic; sw2 : IN std_logic; sw3 : IN std_logic; sw4 : IN std_logic; ledout1 : OUT std_logic; ledout2 : OUT std_logic; ledout3 : OUT std_logic; ledout4 : OUT std_logic ); end button_to_led; Figure 23: Button_to_led entity code without using vectors The architecture is quite straightforward: send the status of the sw-vector to the ledout-vector. A little more explanation is needed, though. This is the dataflow-structure discussed earlier. Every line written after the begin-statement executes in parallel. This means that the code written, wont execute one step after the other. All is done simultaneously. The results of the calculations therefore arent available until the next update cycle is reached. You can look at the code as one big loop, starting with the BEGIN-statement until the END-statement. The signals are never updated inside the loop, only at the end. The next example (see Figure 24) illustrates this. Assume that a is defined as INOUT (multidirectional pin).

architecture button_to_led_arch of button_to_led is begin a <= b; c <= a; end button_to_led_arch; Figure 24: Example of dataflow-structure

Page 19 of 127

Intuitively, after execution a, b and c should have the same value. Because these processes work in parallel, this is not true. The signal a is only changed at the end of the file. So assume that a=1, b=2 and c=3 before execution. At first, one would expect a to hold the value of b after the first statement. Then the next line would send this value to c. At the end a would equal b and c (a=b=c=2). But is not the case at all. Actually the two statements are executed at the same time. So when c <= a is carried out, the new value of a isnt available yet and therefore the old value is used. The signal a gets the old value of b and the signal c gets the old value of a. After one cycle, the result will be: a=2, b=2 and c=1. When all signals are updated, a new cycle starts. The next time step will result in the following values: a=2, b=2, c=2.

4. Assign pins
If the desired circuit needs to be implemented on a physical device, the design needs to be mapped on the available programmable component by assigning signals to the pins of the FPGA. The integrated design environment needs to know how to allocate the signals to the available pins. Here you define which pin corresponds with which signal in your design. In appendix A an overview of the pins used in this tutorial can be found. For this design only the Button and the LED pins are of importance. See schematics in appendix E for more details. Select the top-entity in the Sources in Project-list. Right click and select New Source. Select User Document and enter the filename (<top-entity>.ucf) For each pin write the following line of code: NET "<pin-name>" LOC = "<pin-location>"; E.g.: NET "button" LOC = "P40"; NET "sw<0>" LOC = "P16";

5. Synthesis and fitting


Firstly the tool chain will generate all needed data from your VHDL-files. It will then try to fit this design into the desired device and performs some tests. The result is a bit-file (*.BIT) that can be downloaded to a physical device using a JTAG cable. Select the top-entity in the Sources in Project-list. Right click on Generate Programming File in the Processes for Source-window and select Run

Page 20 of 127

6. Programming the device


Connect the parallel cable to your parallel port and to the parallel port on the evaluation board. The programmer will send the date through the parallel cable to the evaluation board where it will be converted to JTAG signals. The FPGA or a controller IC will then download the new configuration on reset. Open iMPACT program. File -> New Select Configure devices. Press Next Select Boundary-scan Mode. Press Next Select Automatically connect. Make sure the parallel cable is connected correctly, SW1 is set to JTAG and the power of your development board is switched on. Press Finish Select the download file (<top-entity>.bit) Press Open Program by right clicking on the device icon and select Program.

7. Testing the design


Normally a design is verified by a simulator before testing it in physical hardware. Your design could destroy some hardware on your development board. This simple project normally wont cause any problems. How to simulate a design is explained later in this course. On start-up, all LEDs are lit. This is because the buttons are active low (Button pressed = 0). Remember this for the next designs.

Page 21 of 127

V. Exercises
All schematics and code can be found in appendix D. For more information consult these files.

A) Implementing a 4-bit to 7-segment decoder


Next design will be a little more complicated. Decode the input switches and visualise the states on the 7-segment displays. So when the binary code 5 (1001) is applied to the switches, the number 5 will show on the display. Four inputs and seven outputs are necessary for this design. The architecture will be a bit more difficult. For each output pin, we need a combination of the input pins to decide if that element should be lit or not. Figure 25 gives the layout of the 7-segement displays.

Figure 25: 7-segment display

This problem can be solved using Karnaugh-cards. The result will be like: A <= { [ b(0) and b(2) ] or [ b(2) and b(1) and b(0)] }; Remember that the buttons are inverted (active low). Assign the correct pins and test the application on the board. Board schematics can be found in appendix E.

Page 22 of 127

B) Adapting the 7-segment decoder


The implementation of the previous 7-segment decoder was a lot of work. Luckily there exist some techniques that can speed up the design of different components. In the beginning of the course the three methods to write an architecture in VHDL are explained. So far only the dataflow approach was used. Using the behavioural architecture can improve things (see figure 26). The input bits arent inverted because this block of code is used later on in other designs.

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity decode7segment is port ( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end decode7segment; architecture dec7seg_arch of decode7segment is begin process(code) begin case code is when "0000" => seg7(6 downto 0) <= "1000000"; when "0001" => seg7(6 downto 0) <= "1111001"; ... when others => seg7(6 downto 0) <= "1111111"; end case; end process; end dec7seg_arch; Figure 26: 7-segment decoder using behavioural architecture

All code, written in the behavioural way must be included in the process tags. Next to this tag, the processs starting condition is defined. In this case this block of code should be executed each time the code parameter changes (process(code)). Within this block, different sequential lines of code can be written. For the 7-segment decoder a case is used. The parameter code is evaluated. If it equals 0000 set seg7 to "1000000". If it equals 0001 to "1111001". Board schematics can be found in appendix E.

Page 23 of 127

The more general behavioural processes are summarised bellow.

process(signal-names) begin -- sequential code: e.g.: case (signal-name) is when condition => action1; ... when others => action2; end case; if (condition) then action1; elsif (condition) then action2; ... else action3; end if; for variable/signal-name in start-value to stop-value loop action; end loop; end process;
Figure 27: Overview behavioural architecture

Page 24 of 127

C) Implementing a 4bit counter


In the next case, a counter will be implemented. To visualize the values of the counter, the 7-segment decoder designed above can be used. Try to make a counter that counts from 0 to F using behavioural techniques. The counter should be synchronized (changes only occur at clock transition) and react to the rising edge of the clock. When a button is pressed, the counter is incremented on each clock cycle. Clock Count

process(clk) begin if (clk'EVENT and clk='1') then COUNTER action; end if; end process; (a) (b) Figure 28: (a) counter schematic (b) rising edge detection
4-bit Output

Notice that after the if-statement, no more else or elsif-statements are possible. It looks strange but when you keep the hardware in mind its obvious. A rising edge can be detected but what is a not rising edge? (A falling edge?, No edge?, ...)

Hint: define an internal signal that represents the state of the counter.
The counter and the 7-segment decoder are two VHDL blocks (and files) that need to be put together to visualise the counter. This will be done using the third and last method that can be used to describe hardware in VHDL: the structural method. This powerful technique allows programmers to combine different blocks and build a design from pre-defined structures. Make a new VHDL-file that will contain the actual top-entity for our counter. The design should look like figure 29.

--component declarations component entity-name port (signal-names : mode signal-type); end component;
Clock 7-segment Out 7

--signals to connect blocks signal-names : mode signal-type; begin

(a)

component-name : component port map (signal-mapping); (b) Figure 29: (a) block schematic of counter_main (b) Overview structural architecture Page 25 of 127

Figure 29b gives an overview of the structural architecture. Use this to make the counter work. Signal mapping is done by assigning a signal or value to each in- and output pin of the component. E.g.: clk => MyClockSignal, Enable => 1 By assigning the same signal to different pins, a connection is made between these pins. This is the equivalent of wiring different hardware components together. Try to check the syntax of the design, synthesise and implement this new exercise on the design board. Dont forget to make it your new top-entity. Why does the display only show the number 8?

Page 26 of 127

D) Working with clock-dividers


To overcome the problems detected in the previous exercise, downscaling of the clock is needed. Try to write an entity that is able to achieve this. Two inputs, the clock and the scale factor, and 1 output, the scaled-down clock are needed. Its important that the output is synchronous with the input and that the output is a clock-signal, not a pulse-signal. Remember that the onboard clock runs at 50MHz.

Try to implement the previous counter, but this time with a scaled-down clock. This should solve the problem encountered in the last exercise. The schematic should look like this:

Clock (50MHz)

Clock (scaled) Clock divider Enable (1) Counter

4-bit code 4 7-segment decoder Display 7

Scale factor

Figure 30: Schematic of scaled counter

Page 27 of 127

VI.

Simulating design in ModelSim

To analyse the VHDL design, a program called ModelSim is used. This program can simulate complete designs or parts of them. Before programming an FPGA, always simulate everything so you know what can be expected during operation. It is possible to damage the hardware when downloading incorrect designs.

1. Opening New Project


File -> New -> Project Choose a project name and location. Press OK Press Add existing design Add all the VHDL-files.

2. Making a Test Bench


To be able to test the design, a test bench must be written. This file is a VHDL file that describes and defines in- and outputs for simulation (see Figure 31). This will be the current top-level entity. The Unit Under Test (UUT) is the entity to be tested. By selecting different entities you can simulate different parts of your design. The test bench will be your new top-level entity for the simulator. All other files need to be connected to this file as if they are a part of this entity. An example of a test bench is given in Figure 32. Adapt this file so it will match your design.

Figure 31: Test bench

Page 28 of 127

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity tstbench is port(outp : OUT std_logic_vector (6 downto 0)); end tstbench; architecture test of tstbench is --- component declarations => adding your design to the test bench -component counter_main is port (clock : IN std_logic; ledout : OUT std_logic_vector (6 downto 0)); end component; --- signal declarations -signal clk : std_logic := '0'; -- generate clocks begin process(clk) begin clk <= not clk after 20 ns; -- 50MHz end process; --- hook up components => connect your design to the correct signals -u1: counter_main port map (clock => clk, ledout => outp); end test; Figure 32: Test Bench example

The after-command can only be used in simulation. It cant be implemented in hardware. By inverting the clock signal every 20ns we make a 50MHz clock. Some programs are able to generate a test bench. But as there is no common graphical user interface for generated test benches, its better to learn to write one by hand. Signals can be initialised to a certain value by using the := operator. This only works in simulation. An FPGA cant automatically preload values to its signals.

Page 29 of 127

3. Compiling files
Compile -> Compile All Errors can be seen by double clicking on the red error line (Compile of ... failed with ... errors). If an error occurs in a certain file (probably the test bench), first try the following: Right click on the file->Properties->VHDL-tab->Use 1993 Language Syntax must be checked

4. Simulate
Simulate->Simulate Select the top-entity file (the test bench). Press OK Right click on the test bench-file and select Add->Add to Wave A new window will open with all the signals from the test bench. Press Run for each time step Analyse the behaviour of the entity by looking at the waveforms.

5. Alternatives
A Logic State Analyser (LSA) can be used to look to the FPGA pins or even at all the signals inside a design. Those systems are really expensive. Some vendors provide an on-chip analyser (Alteras Signal Tap and Xilinx ILA). Unfortunately these are not included in the web-pack version of Quartus.

Page 30 of 127

VII.

Exercises continued A) Advanced counter

Expand the counter with an asynchronous reset and a start/stop button (start counter when pressed, stop counter when pressed again). To get started, an example of a reset is given.

process(clk, reset) process(clk) begin begin if (reset = '0') then if (clk'EVENT and clk='1') then reset code; if (reset = '0') then elsif (clk'EVENT and clk='1') then reset code; synchronous code; end if; end if; synchronous code; end process; end if; end process; (a) (b) Figure 33: Example of an asynchronous (a) and synchronous (b) reset

Page 31 of 127

B) Exotic counter
Expand the basic counter to output following sequence.

Sequence:

01A5FE3C98B2746D

Use a Finite State Machine (FSM) to achieve this (see appendix C). An FSM can easily be implemented in VHDL using the case-statements in combination with an internal state-signal.

Ex.:

type states is (s0, s1, s2, ); signal state : states; begin case state is when s0 => output <= "0010"; state<=s1; when s1 => output <= "0001"; state<=s2; when others => output <= "1001"; state<=s0; end case; Figure 34: Example VHDL FSM

Page 32 of 127

C) Dual-display counter
Expand the basic counter so it can use 2 displays. The range is from 00 to FF. When using the Xilinx Spartan development board, multiplexing is needed. In turn apply the data for the first and second display while changing the select signals (see Figure 35). When the transistor a1 is high, the data will be sent to display one. Other displays can be selected in a similar way.

Figure 35: Multiplexed LEDs

Page 33 of 127

VIII. Final projects A) UART: Universal Asynchronous Receiver and Transmitter


The purpose of this case is to design a complete sender and receiver module that uses the UART-serial connection. Work together in groups and divide the work - Agree on interfaces and topology - Design individual blocks - Simulate and test each block and the complete design - Combine blocks - Send and receive data with other teams using a general-purpose serial cable. Following top-level designs can be used to design the transmitter/receiver and the UART block. These designs are only intended as guidelines. Other implementations can be used also. When the enable signal is high the counter is active and increments its value. This value is displayed by the first 7-segment display and transmitted by the UART on the send command. See remarks for more details.

Enable Clock

4 Counter

7Segment1 (TX data) 4 UART

Send data TX RX Serial port

7Segment2 (RX data)

Figure 36: Block scheme UART sender-receiver

Page 34 of 127

Data In 4

Buffer

Parity check

CS Send data Write Control (state node) Busy Clock

CS 1 0

Muli- TX plexer CS

Clock divider (a) Buffer Data Out 4

RX

Buffer 4 CS

Parity check

parity CS

CS Read Control Error

Clock

Clock divider

CLK

Read ready (b) Figure 37: Schematics UART (a) write port (b) read port

Page 35 of 127

Remarks: - All blocks should be synchronous. - A multiplexer can be used to easily send serial data. - Send the serial data at 24.4KHz (=50MHz/2048). If everybody uses the same transmission speed, you can connect to each other later on. - The parity bit is defined as follows: when the amount of 1-bits in the data is odd then the parity bit is set, otherwise it is cleared. - Start bit=0, Stop bit=1, transmit data with LSB first. - Try to sample in the middle of the waveform when the RX signal is stable, not at the edges. Use sampling clock that is 8 or 16 times higher than the UART clock. - The output signals (Busy, Error, Read ready) can be connected to LEDs to view if everything works properly. - For testing, connect pin 2 (TX) and 3 (RX) of the serial connector with a wire. This creates a loop back to easily test your system. - Board schematics can be found in appendix E.

Idle

Start bit D0 D1 D2 D3 D4 D5 D6 D7 Parity Figure 38: Timing RX en TX

Idle

Page 36 of 127

B) LCD controller
Another possibility is to make an LCD controller. Try to adapt the previous counters so they are able to output to the LCD display. As the LCD module is only available for the Altera development board, this project cant be made on a Xilinx board. Follow the same procedure as in the previous project.

Clock PLL/ DLL Start/Stop Counter Reset CLK

Data 4 Reset Character control

Data 10 Enable LCD control

LCD 10

Figure 39: Block scheme LCD controller Clock mSec 4 Carry Counter Sec 4 Carry Counter Min 4

Counter

Figure 40: Counter

Character control: This block generates the commands that need to be sent to the display. On reset, an initialisation is performed. Afterwards it sequentially writes all the characters to be displayed, returns to the starting position and repeats this loop. LCD control: Here the timing for the LCD takes place. For each command, a specific timing is required (See figure 44). This block takes as input the command coming from the previous block and makes sure it is delivered to the display in the correct way.

Page 37 of 127

Pin number 1
2 3 4 5 6 7 8 9 10 11 12 13 14

Symbol
Vss Vcc Vee RS R/W E DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7

Level
0/1 0/1 1, 1->0 0/1 0/1 0/1 0/1 0/1 0/1 0/1

I/O
I I I I/O I/O I/O I/O I/O I/O I/O

Function
Power supply (GND) Power supply (+5V) Contrast adjust 0 = Instruction input 1 = Data input 0 = Write to LCD module 1 = Read from LCD module Enable signal Data bus line 0 (LSB) Data bus line 1 Data bus line 2 Data bus line 3 Data bus line 4 Data bus line 5 Data bus line 6

0/1 I/O Data bus line 7 (MSB) Figure 41: LCD pin configuration

Instruction Clear display


Cursor home

Code (RS R/W DB7->DB0) 0000000001

Entry mode set

Display control Cursor control

Function set

Write data

Description Execution time Clears display and returns cursor to 1.64mS the home position (address 0). 1.64mS 000000001* Returns cursor to home position (address 0). Also returns display being shifted to the original position. DDRAM contents remains unchanged. 40uS 0 0 0 0 0 0 0 1 I/D S Sets cursor move direction (I/D), specifies to shift the display (S). These operations are performed during data read/write. 40uS 0000001DCB Sets On/Off of all display (D), cursor On/Off and blink of cursor position character (B). 40uS 0 0 0 0 0 1 S/C R/L * * Sets cursor-move or display-shift (S/C), shift direction (R/L). DDRAM contents remains unchanged. 40uS 0 0 0 0 1 DL N F * * Sets interface data length (DL), number of display line (N) and character font (F). 1 0 DATA (see figure 45) Writes data to CGRAM or DDRAM. 40uS Figure 42: LCD commands

Page 38 of 127

Bit name Setting / Status I/D 0 = Decrement cursor position 1 = Increment cursor position
S D C B S/C R/L DL N F 0 = No display shift 0 = Display off 0 = Cursor off 0 = Cursor blink off 0 = Move cursor 0 = Shift left 0 = 4-bit interface 0 = 1/8 or 1/11 Duty (1 line) 0 = 5x7 dots 1 = Display shift 1 = Display on 1 = Cursor on 1 = Cursor blink on 1 = Shift display 1 = Shift right 1 = 8-bit interface 1 = 1/16 Duty (2 lines) 1 = 5x10 dots Figure 43: Bit names

Figure 44: LCD timing

Figure 45: Character set

Page 39 of 127

Remarks: - All blocks should be synchronous. - Try to use the build-in PLL/DLL to divide your clock signal. Quartus and ISE have a wizard to make your own PLLs/DLLs. Quartus: Mega wizard Plug-in ISE: Create new source -> IP (CoreGen) - The LCD is very time critical. If you write the data too fast, errors will occur. The display controller needs time to be able to process the commands. - Not all commands take the same time to execute. - Try to make a counter for each character to be displayed. This means that you need 2 timers for the seconds (34sec=>3 & 4). - The other displays (seven segment, LEDs, ..) can be used to output some debug data or help you visualise the process. - Board schematics can be found in appendix E. - Start with something simple and try to expand your project. e.g.: First try to display one character before moving on.

Page 40 of 127

C) Audio filter with memory control


The purpose of this project is to write an audio file into the FPGAs SRAM. This file will then be looped, passed through a filter and sent to the audio lineout interface. As the audio module is only available for the Altera development board, this project cant be made as easy on the Xilinx board. The latter hasnt got the correct connectors for the LCD module. Follow the same procedures as the previous projects. The grey coloured blocks in figure 46 are available together with a software program to load an audio file to the hardware module. Input control
Clock

Clock
RX
TX (not used) Clock

UART
Data

Data 8 Rate CLK Filter(s)

Data 8 PWM

Audio

R/W

RX
Address

Ready Memory 8 control


Data

18

CLK

Memory See figure 47

42 Figure 46: Block scheme audio filter

Memory control: This block takes care of the communications with the SRAM. It consists of a read and a write procedure. Each cycle consists of three synchronous commands as depicted in Figure 47. First initialise SDRAM, afterwards read or write the date and finally restore the bus. Filter(s): The audio coming from the memory is filtered. The coefficients of four FIR-filters, together covering the complete spectrum, are given later in this text (figure 48). PWM: In order to convert the digital data back to an analogue voltage, Pulse Width Modulation is used. Use 8-bit data words.

Read

Write Figure 47: Read and write SRAM timing

Page 41 of 127

Figure 48: Finite Impulse Response filter

FIR1
(...-110Hz)

VARIABLE

GAIN

FIR2
(110-630Hz)

VARIABLE

GAIN 6 8

8 FIR3
(630Hz-3.5kHz) VARIABLE

GAIN

FIR4
(3.5kHz-...)

VARIABLE

GAIN

Figure 49: Possible filter implementation (4 bands Equaliser)

Page 42 of 127

B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 B16

FIR2 (BP 110 - 630 Hz) FIR3 (BP 630 Hz - 3.5 kHz) FIR4 (HP 3.5 kHz) FIR1 (LP 110 Hz) 0.009548 0.001962 -0.000360 0.000905 0.014398 0.006199 -0.010500 0.006026 0.028087 0.018324 -0.016603 -0.009473 0.048371 0.041571 0.000243 -0.023836 0.071792 0.074699 -0.054629 0.057537 0.094288 0.111809 -0.163179 0.048434 0.111923 0.144091 0.004730 -0.298381 0.121593 0.162894 0.386648 0.439930 0.121593 0.162894 0.386648 -0.298381 0.111923 0.144091 0.004730 0.048434 0.094288 0.111809 -0.163179 0.057537 0.071792 0.074699 -0.054629 -0.023836 0.048371 0.041571 0.000243 -0.009473 0.028087 0.018324 -0.016603 0.006026 0.014398 0.006199 -0.010500 0.000905 0.009548 0.001962 -0.000360 0 Figure 50: Possible filter coefficients (FIR Hamming window)

Figure 51: Visual Basic interface The Visual Basic program reads an audio file with consists of 8-bit words, sampled at 12.5kHz. It will send this data to its serial port.

Remarks: - All blocks should be synchronous. - To be able to use the audio lineout, an extension board (Lancelot VGA) is available. Attach this board correctly to the development kit before powering up. Therefore use connectors J11, J12 and J13. - Make an interface so you can view and change some settings (e.g. gain). - The values given in figure 50 are generated by MatLab. They need to be adapted before they can be used in VHDL. - Two SRAMs are used in parallel to have a 24-bit wide memory. Some signals are shared, other signals are IC specific. See pin configuration in appendix A for more details. - Board schematics can be found in appendix E.

Page 43 of 127

IX.

Appendix A (Pins) A) Altera Stratix (NIOS development board)

(a)

(b) Figure 52: Altera development board

Page 44 of 127

Switches SW0 SW1 SW2 SW3 LEDs D0 D1 D2 D3 D4 D5 D6 D7 UART TDX RDX SRAM CS WE OE BHE0 BHE1 BLE0 BLE1 A0 A1 A2 A3 A4 A5 A6 A9 A12 A15

W5 W6 AB2 AB1

H27 H28 L23 L24 J25 J26 L20 L19

7-segment 1 A B C D E F G DP 7-segment 2 A B C D E F G DP

A18 C18 D18 A19 B19 C19 E19 D19

U21 Y28

B18 B20 A20 C20 A21 B21 C21 D21

LCD E RS R/W D0 D1 D2 D3 D4 D5 D6 D7 Clock

K3 M7 M8 H3 L7 L8 H2 H1 L6 L5 J4 K17

CPU reset AC9 Audio Left M8 Right H3

B24 C24 B26 F17 L17 M18 J18 B3 B5 B4 C4 A5 C5 D5 B7 D7 B6

D0 D2 D4 D6 D8 D10 D12 D14 D16 D18 D20 D22

B8 A9 E10 C10 A11 D11 D10 F10 G11 J9 L13 L11

D1 D3 D5 D7 D9 D11 D13 D15 D17 D19 D21 D23

A8 C9 A10 B10 C11 B11 G10 H11 F8 J13 M11 G7

A7 E6 A8 A10 D6 A11 A13 C6 A14 A16 D8 A17 Figure 53: Pin configuration Stratix

A6 A7 C7 C8

Page 45 of 127

B) Xilinx Spartan2E (Digilent development board)

(a)

(b)

(c)

(d) Figure 54: Digilent FPGA and I/O board

IMPORTANT:
Connect the I/O board to connectors J6(E) and J7(F) otherwise the pins bellow arent correct.

Buttons BTN1 BTN2 BTN3 BTN4 BTN5 LEDs D1 D2 D3 D4 D5 D6 D7 D8

P40 P41 P42 P43 P64

P44 P46 P48 UART P55 TX P57 RX P59 P61 P80 Clock P63 Figure 55: Pin configuration Spartan

7-segment A B C D E F G DP Select1 Select2 Select3 Select4

P17 P20 P22 P24 P29 P31 P34 P36 P45 P47 P49 P56

Switches SW1 SW2 SW3 SW4 SW5 SW6 SW7 SW8

P16 P18 P21 P23 P27 P30 P33 P35

P201 P202

Page 46 of 127

C) Xilinx Spartan3 (Digilent development board)

(a) Figure 54: Digilent FPGA board

(b)

Buttons BTN0 BTN1 BTN2 BTN3 LEDs LD0 LD1 LD2 LD3 LD4 LD5 LD6 LD7

M13 M14 L13 L14

K12 P14 L12 N14 UART P13 TX N12 RX P12 P11 T9 Clock Figure 55: Pin configuration Spartan

7-segment A B C D E F G DP AN0 AN1 AN2 AN3

E14 G13 N15 P15 R16 F13 N16 P16 D14 G14 F14 E13

Switches SW0 SW1 SW2 SW3 SW4 SW5 SW6 SW7

F12 G12 H14 H13 J14 J13 K14 K13

R13 T13

Page 47 of 127

X. Appendix B (Operators)
The logical operators NOT, AND, OR, NAND, NOR, and XOR can be used with any bit type or bit vector. When used as operators on bits they have their usual meaning. When used with bit vectors, the bit vectors must have the same number of elements, and the operation is performed bit wise. For example, "00101001" xor "11100101" results in "11001100".

Note: just as '0' and '1' represent constant bit values, constant bit vectors can be written in VHDL as a list of bit values in double quotes. For example, if d is a bit vector(3 downto 0) the following statement gives d the permanent values d(3)='1', d(2)='1', d(1)='0', and d(0)='0'.
d<="1100"; Also predefined are the normal relational operators. They are =, /=, <, <=, > and >= and have their usual meanings (/= denotes the not equal operator). The result of all these operators is a boolean value (TRUE or FALSE). The arguments to the = and /= operators may be of any type. The arguments of the <, <=, > and >= operators may be any scalar type (integer, real, and physical types) or the bit vector type. If the arguments are bit vectors, then the arguments must be the same length and the result is TRUE only if the relation is true for each corresponding element of the array arguments. The &-operator is a built-in VHDL operator that performs the concatenation of bit vectors. For example, with the following declarations: signal a: bit vector (3 downto 0); signal b: bit vector (7 downto 0); The following statement would connect a to the right half of b and make the left half of b constant '0'. b<="0000" & a;

Page 48 of 127

XI.

Appendix C (Finite State Machine)

A finite state machine (FSM) is an abstract computational device that has a finite number of different states. The system always resides in a specific state. According to the input, the transition to the next one can be selected. With each state a certain output is generated. Thus, by describing each state individually and the transitions between them, a complete design can be modelled. FSM can represent almost every possible system, also the complex ones. Therefore these FSMs are used frequently. Following figure will explain a FSM model.

S1 S6 S2

S5

S3

S4

Figure 56: FSM flowchart

For each state an output vector is defined. E.g.: State 1: output <= 0100; State 2: output <= 1111; For each state a transition is defined to another state, depending on the input. E.g.: State 1: to S1 if input=1 to S2 if input=0 State 2: to S1 if input=1 to S3 if input=0

Page 49 of 127

XII.

Appendix D: Source code A) First design

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity button_to_led is port( sw : IN std_logic_vector (3 downto 0); ledout : OUT std_logic_vector (3 downto 0) ); end button_to_led; architecture button_to_led_arch of button_to_led is begin ledout <= sw; end button_to_led_arch;

Page 50 of 127

B) 4-bit to 7-segment decoder


library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity decode7segment_comb is port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end decode7segment_comb; architecture dec7seg_comb_arch of decode7segment_comb is begin seg7(6) <= (code(3) and code(2) and code(1)) or (code(3) and not code(2) and not code(1) and not code(0)); seg7(5) <= (not code(1) and not code(0)) or (code(3) and code(2) and not code(1) and code(0)); seg7(4) <= not ( (not code(1) and code(0)) or (not code(3) and code(2) and code(1) and code(0)) or (code(3) and code(2) and code(1)) ); seg7(3) <= ( (code(3) and not code(2) and code(1) and code(0)) or ( code(3) and code(2) and code(1) and not code(0)) or (code(3) and not code(2) and not code(1) and not code(0)) ); seg7(2) <= ( (code(3) and code(2) and code(1) and not code(0)) or (code(3) and code(2) and not code(1) and code(0)) ); seg7(1) <= ( (code(3) and code(1) and not code(0)) or (code(3) and not code(2) and not code(1) and code(0)) ); seg7(0) <= ( (code(3) and code(2) and code(1) and not code(0)) or (code(3) and not code(2) and code(1) and code(0)) ); end dec7seg_comb_arch;

Page 51 of 127

C) 4-bit to 7-segment decoder (behavioural)


library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity decode7segment is port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end decode7segment; architecture dec7seg_arch of decode7segment is begin process(code) begin case code is when "0000" => seg7(6 downto 0) <= "1000000"; when "0001" => seg7(6 downto 0) <= "1001111"; when "0010" => seg7(6 downto 0) <= "0100100"; when "0011" => seg7(6 downto 0) <= "0110000"; when "0100" => seg7(6 downto 0) <= "0011001"; when "0101" => seg7(6 downto 0) <= "0010010"; when "0110" => seg7(6 downto 0) <= "0000010"; when "0111" => seg7(6 downto 0) <= "1111000"; when "1000" => seg7(6 downto 0) <= "0000000"; when others => seg7(6 downto 0) <= "0010000"; end case; end process; end dec7seg_arch;

Page 52 of 127

D) 4-bit counter
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity counter_main is port( clock : IN std_logic; ledout : OUT std_logic_vector (6 downto 0) ); end counter_main; architecture counter_main_arch of counter_main is component counter port( clk : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; signal s_waarde : std_logic_vector (3 downto 0); begin LED1 : decode7segment port map( code => s_waarde, seg7 => ledout ); count1 : counter port map( clk => clock, c => s_waarde ); end counter_main_arch;

Page 53 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity counter is port( clk : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end counter; architecture counter_arch of counter is signal tel : std_logic_vector (3 downto 0) :="0000"; --initialisation for simulator begin process(clk) begin if (clk'EVENT and clk='1') then tel <= tel + 1; end if; end process; c <= tel; end counter_arch;

Page 54 of 127

E) 4-bit counter (with clock-divider)


library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity counter_pll_main is port( clock : IN std_logic; ledout : OUT std_logic_vector (6 downto 0) ); end counter_pll_main; architecture counter_pll_main_arch of counter_pll_main is component counter port( clk : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component downscale port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end component; signal s_waarde : std_logic_vector (3 downto 0); signal s_pll_clock : std_logic; begin LED1 : decode7segment port map( code => s_waarde, seg7 => ledout );

Page 55 of 127

count1 : counter port map( clk => s_pll_clock, c => s_waarde ); pll1 : downscale port map( clkin => clock, decimator => "1111", clkout => s_pll_clock ); end counter_pll_main_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity downscale is port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end downscale; architecture down_arch of downscale is signal teller : std_logic_vector(21 downto 0); signal s_out : std_logic; begin process(clkin) begin if (clkin'EVENT and clkin='1') then teller <= teller - 1; if teller = 0 then teller <= decimator & "000000000000000000"; s_out <= not s_out; end if; end if; end process; clkout <= s_out; end down_arch;

Page 56 of 127

F) Advanced counter
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity counter_rst_main is port( clock : IN std_logic; r : IN std_logic; ss : IN std_logic; ledout : OUT std_logic_vector (6 downto 0) ); end counter_rst_main; architecture counter_rst_main_arch of counter_rst_main is component counter_adv port( clk : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component downscale port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end component; signal s_waarde : std_logic_vector (3 downto 0); signal s_pll_clock : std_logic;

Page 57 of 127

begin LED1 : decode7segment port map( code => s_waarde, seg7 => ledout ); count1 : counter_adv port map( clk => s_pll_clock, reset => r, start_stop => ss, c => s_waarde ); pll1 : downscale port map( clkin => clock, decimator => "1111", clkout => s_pll_clock ); end counter_rst_main_arch;

Page 58 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity counter_adv is port( clk : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end counter_adv; architecture counter_arch of counter_adv is signal tel : std_logic_vector(3 downto 0); signal run : std_logic := '0'; signal vorige_ss : std_logic; begin process(clk, reset) begin if (reset = '0') then tel <= 0000; elsif (clk'EVENT and clk='1') then if run = '1' then tel <= tel + 1; if tel > 8 then tel <= 0000; end if; end if; if (start_stop = '0' and vorige_ss = 1) then run <= not run; end if; vorige_ss<=start_stop; end if; c <= tel; end process; end counter_arch;

Page 59 of 127

G)Exotic counter
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity exotic_main is port( clock : IN std_logic; ledout : OUT std_logic_vector (6 downto 0) ); end exotic_main; architecture exotic_arch of exotic_main is component exotic_counter port( clk : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component downscale port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end component; signal s_waarde2 : std_logic_vector (3 downto 0); signal s_pll_clock : std_logic; begin LED2 : decode7segment port map( code => s_waarde2, seg7 => ledout );

Page 60 of 127

count1 : exotic_counter port map( clk => s_pll_clock, c => s_waarde2 ); pll1 : downscale port map( clkin => clock, decimator => "1111", clkout => s_pll_clock ); end exotic_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity exotic_counter is port ( clk : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end exotic_counter; architecture exotic_counter_arch of exotic_counter is type state is (p0,p1,p2,p3,p4,p5,p6,p7,p8,p9); signal toestand : state; begin process(clk) begin if (clk'EVENT and clk='1') then case toestand is when p0 => c <= "0000"; toestand<=p1; when p1 => c <= "0001"; toestand<=p2; when p2 => c <= "0101"; toestand<=p3; when p3 => c <= "0011"; toestand<=p4; when p4 => c <= "1001"; toestand<=p5;

Page 61 of 127

when p5 => c <= "1000"; toestand<=p6; when p6 => c <= "0010"; toestand<=p7; when p7 => c <= "0111"; toestand<=p8; when p8 => c <= "0100"; toestand<=p9; when others => c <= "0110"; toestand<=p0; end case; end if; end process; end exotic_counter_arch;

Page 62 of 127

H) Dual display counter (Altera)


library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity counter_dual_main is port( clock : IN std_logic; r : IN std_logic; ss : IN std_logic; ledout1 : OUT std_logic_vector (6 downto 0); ledout2 : OUT std_logic_vector (6 downto 0) ); end counter_dual_main; architecture counter_dual_main_arch of counter_dual_main is component counter_dual port( clk : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; c1 : OUT std_logic_vector (3 downto 0); c2 : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component downscale port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end component; signal s_waarde1 : std_logic_vector (3 downto 0); signal s_waarde2 : std_logic_vector (3 downto 0); signal s_pll_clock : std_logic;

Page 63 of 127

Begin LED1 : decode7segment port map( code => s_waarde1, seg7 => ledout1 ); LED2 : decode7segment port map( code => s_waarde2, seg7 => ledout2 ); count1 : counter_dual port map( clk => s_pll_clock, reset => r, start_stop => ss, c1 => s_waarde1, c2 => s_waarde2 ); pll1 : downscale port map( clkin => clock, decimator => "1111", clkout => s_pll_clock ); end counter_dual_main_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity counter_dual is port ( clk : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; c1 : OUT std_logic_vector (3 downto 0); c2 : OUT std_logic_vector (3 downto 0) ); end counter_dual; architecture counter_dual of counter_dual is signal tel1 : std_logic_vector(3 downto 0); signal tel2 : std_logic_vector(3 downto 0); signal run : std_logic := '0'; signal vorig_ss : std_logic;

Page 64 of 127

begin process(clk, reset) begin if (reset = '0') then tel1 <= 0000; tel2 <= 0000; elsif (clk'EVENT and clk='1') then if run = '1' then tel1 <= tel1 + 1; if tel1 > 8 then tel1 <= 0000; tel2 <= tel2 + 1; if tel2 > 8 then tel2 <= 0000; end if; end if; end if; if (start_stop=1 and vorig_ss = '0') then run <= not run; end if; vorig_ss<=start_stop; end if; c1 <=tel1; c2 <= tel2; end process; end counter_dual;

Page 65 of 127

I) Dual display counter (Xilinx)


library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity counter_dual_main2 is port( clock : IN std_logic; r : IN std_logic; ss : IN std_logic; ledout1 : OUT std_logic_vector (6 downto 0); select1 : OUT std_logic; select2 : OUT std_logic ); end counter_dual_main2; architecture counter_dual_main_arch of counter_dual_main2 is component counter_dual port( clk : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; c1 : OUT std_logic_vector (3 downto 0); c2 : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component downscale port( clkin : IN std_logic; decimator : IN std_logic_vector (3 downto 0); clkout : OUT std_logic ); end component; signal s_waarde1 : std_logic_vector (3 downto 0); signal s_waarde2 : std_logic_vector (3 downto 0); signal s_waarde_out : std_logic_vector (3 downto 0); signal s_pll_clock : std_logic; signal s_select : std_logic; signal delay : std_logic_vector(15 downto 0);

Page 66 of 127

Begin LED1 : decode7segment port map( code => s_waarde_out, seg7 => ledout1 ); count1 : counter_dual port map( clk => s_pll_clock, reset => not r, start_stop => not ss, c1 => s_waarde1, c2 => s_waarde2 ); pll1 : downscale port map( clkin => clock, decimator => "1111", clkout => s_pll_clock ); process(clock) begin if (clock'EVENT and clock='1') then if (delay=0) then if (s_select='1') then s_waarde_out<=s_waarde1; select1<='0'; select2<='1'; else s_waarde_out<=s_waarde2; select1<='1'; select2<='0'; end if; s_select<= not s_select; end if; delay<=delay+1; end if; end process; end counter_dual_main_arch;

Page 67 of 127

J) UART project
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity datatransfer is port( send : IN std_logic; sw : IN std_logic; ledout1 : OUT std_logic_vector (6 downto 0); ledout2 : OUT std_logic_vector (6 downto 0); clock : IN std_logic; uart_rx : IN std_logic; uart_tx : OUT std_logic; ); end datatransfer; architecture datatransfer_arch of datatransfer is component counter port( clk : IN std_logic; addone : IN std_logic; c : OUT std_logic_vector (3 downto 0) ); end component; component decode7segment port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; component UART port( dataIn : IN std_logic_vector (7 downto 0); loadData : IN std_logic; dataOut : OUT std_logic_vector (7 downto 0); readDataReady : OUT std_logic; busy : OUT std_logic; error : OUT std_logic; clk : IN std_logic; rst : IN std_logic; rx : IN std_logic; tx : OUT std_logic ); end component;

Page 68 of 127

signal dIn : std_logic_vector (7 downto 0); signal dOut : std_logic_vector (7 downto 0); signal rdr : std_logic; signal b : std_logic; signal e : std_logic; begin LED1 : decode7segment port map( code => dIn(3 downto 0), seg7 => ledout2 ); LED2 : decode7segment port map( code => dOut(3 downto 0), seg7 => ledout1 ); count1 : counter port map( clk => clock, addone => not sw, c => dIn(3 downto 0) ); uart1 : UART port map( dataIn => dIn, loadData => not send, dataOut => dOut, readDataReady => rdr, busy => b, error => e, clk =>clock, rst => '0', rx => uart_rx, tx => uart_tx ); end datatransfer_arch;

Page 69 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity UART is port( dataIn : IN std_logic_vector (7 downto 0); loadData : IN std_logic; dataOut : OUT std_logic_vector (7 downto 0); readDataReady : OUT std_logic; busy : OUT std_logic; error : OUT std_logic; clk : IN std_logic; rst : IN std_logic; rx : IN std_logic; tx : OUT std_logic ); end UART; architecture UART_arch of UART is component mux port( muxIn : IN std_logic_vector (15 downto 0); sel : IN std_logic_vector (3 downto 0); clkIn : IN std_logic; muxOut : OUT std_logic ); end component; component parity port( parIn : IN std_logic_vector (7 downto 0); clkIn : IN std_logic; calc : IN std_logic; parOut : OUT std_logic ); end component; component buf port( bufIn : IN std_logic_vector (7 downto 0); clk : IN std_logic; send : IN std_logic; bufOut : OUT std_logic_vector (7 downto 0) ); end component;

Page 70 of 127

component UART_writecontrol port( loadData : IN std_logic; wr_busy : OUT std_logic; clkIn : IN std_logic; rstIn : IN std_logic; shift : OUT std_logic; par : OUT std_logic; mux_sel : OUT std_logic_vector (3 downto 0) ); end component; component UART_readcontrol port( rxIn : IN std_logic; par : IN std_logic; ready : OUT std_logic; err : OUT std_logic; clkIn : IN std_logic; readOut : OUT std_logic_vector (7 downto 0) ); end component; signal data_in_buf : std_logic_vector (7 downto 0); signal parbit : std_logic; signal calc_parity : std_logic; signal shiftData : std_logic; signal muxData : std_logic_vector (15 downto 0); signal s_sel : std_logic_vector (3 downto 0); signal readPar : std_logic; signal readReg : std_logic_vector (7 downto 0); signal readReady : std_logic; begin mux1 : mux port map( muxIn => muxData, sel => s_sel, clkIn => clk, muxOut => tx );

Page 71 of 127

parity1 : parity port map( parIn => data_in_buf, clkIn => clk, calc => calc_parity, parOut => parbit ); buf1 : buf port map( bufIn => dataIn, clk => clk, send => shiftData, bufOut => data_in_buf ); write1 : UART_writecontrol port map( loadData => loadData, wr_busy => busy, clkIn => clk, rstIn => rst, shift => shiftData, par => calc_parity, mux_sel => s_sel ); read1 : UART_readcontrol port map( rxIn => rx, par => readPar, ready => readReady, err => error, clkIn => clk, readOut => readReg ); buf2 : buf port map( bufIn => readReg, clk => clk, send => readReady, bufOut => dataOut );

Page 72 of 127

parity2 : parity port map( parIn => readReg, clkIn => clk, calc => clk, parOut => readPar ); muxData <= "10" & data_in_buf & parbit & "00000"; readDataReady <= readReady; end UART_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity parity is port( parIn : IN std_logic_vector (7 downto 0); ckIn : IN std_logic; calc : IN std_logic; parOut : OUT std_logic ); end parity; architecture parity_arch of parity is signal vorige_calc : std_logic; signal count : std_logic_vector(3 downto 0); begin process(clkIn) begin if (clkIn'EVENT and clkIn='1') then vorige_calc<=calc; if calc='1' and vorige_calc='0' then count <= (("000" & parIn(0)) + ("000" & parIn(1)) + ("000" & parIn(2)) + ("000" & parIn(3)) + ("000" & parIn(4)) + ("000" & parIn(5)) + ("000" & parIn(6)) + ("000" & parIn(7))); vorige_calc<='1'; end if; parOut <= count(0); end if; end process; end parity_arch;

Page 73 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity mux is port( muxIn : IN std_logic_vector (15 downto 0); sel : IN std_logic_vector (3 downto 0); clkIn : IN std_logic; muxOut : OUT std_logic ); end mux; architecture mux_arch of mux is begin process(clkIn) begin if (clkIn'EVENT and clkIn='1') then case sel is when "0000" => muxOut <= muxIn(0); when "0001" => muxOut <= muxIn(1); when "0010" => muxOut <= muxIn(2); when "0011" => muxOut <= muxIn(3); when "0100" => muxOut <= muxIn(4); when "0101" => muxOut <= muxIn(5); when "0110" => muxOut <= muxIn(6); when "0111" => muxOut <= muxIn(7); when "1000" => muxOut <= muxIn(8); when "1001" => muxOut <= muxIn(9); when "1010" => muxOut <= muxIn(10); when "1011" => muxOut <= muxIn(11); when "1100" => muxOut <= muxIn(12); when "1101" => muxOut <= muxIn(13); when "1110" => muxOut <= muxIn(14);

Page 74 of 127

when "1111" => muxOut <= muxIn(15); end case; end if; end process; end mux_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity buf is port( bufIn : IN std_logic_vector (7 downto 0); clk : IN std_logic; send : IN std_logic; bufOut : OUT std_logic_vector (7 downto 0) ); end buf; architecture buf_arch of buf is signal vorige : std_logic :='0'; begin process(clk) begin if (clk'EVENT and clk='1') then if (vorige='0' and send='1') then bufOut <= bufIn; end if; vorige <= send; end if; end process; end buf_arch;

Page 75 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity UART_writecontrol is port( loadData : IN std_logic; wr_busy : OUT std_logic; clkIn : IN std_logic; rstIn : IN std_logic; shift : OUT std_logic; par : OUT std_logic; mux_sel : OUT std_logic_vector (3 downto 0) ); end UART_writecontrol; architecture UART_wc_arch of UART_writecontrol is type state is (idle,load,start,d0,d1,d2,d3,d4,d5,d6,d7,pari,stop); signal toestand : state; signal vorige_loadData : std_logic := '0'; signal delay : std_logic_vector (9 downto 0) := "0000000000"; begin process(clkIn, rstIn) begin if rstIn='1' then toestand <= idle; elsif (clkIn'EVENT and clkIn='1') then if delay=0 then delay <= "1000000000"; case toestand is when idle => if loadData='1' and vorige_loadData='0' then toestand <= load; wr_busy <= '1'; else wr_busy <= '0'; shift <= '0'; par <= '0'; mux_sel <= "1111"; end if; vorige_loadData <= loadData;

Page 76 of 127

when load => shift <= '1'; toestand <= start; when start => shift <= '0'; par <= '1'; mux_sel <= "1110"; toestand <= d0; when d0 => par <= '0'; mux_sel <= "0110"; toestand <= d1; when d1 => mux_sel <= "0111"; toestand <= d2; when d2 => mux_sel <= "1000"; toestand <= d3; when d3 => mux_sel <= "1001"; toestand <= d4; when d4 => mux_sel <= "1010"; toestand <= d5; when d5 => mux_sel <= "1011"; toestand <= d6; when d6 => mux_sel <= "1100"; toestand <= d7; when d7 => mux_sel <= "1101"; toestand <= pari; when pari => mux_sel <= "0101"; toestand <= stop; when stop => mux_sel <= "1111"; wr_busy <= '0'; toestand <= idle; when others => toestand <= idle; end case; else delay <= delay - 1; end if; end if; end process; end UART_wc_arch;

Page 77 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity UART_readcontrol is port( rxIn : IN std_logic; par : IN std_logic; ready : OUT std_logic; err : OUT std_logic; clkIn : IN std_logic; readOut : OUT std_logic_vector (7 downto 0) ); end UART_readcontrol; architecture UART_rc_arch of UART_readcontrol is type state is (idle,d0,d1,d2,d3,d4,d5,d6,d7,pari,chk_par, w1); signal toestand : state; signal parity : std_logic; signal clk_div : std_logic_vector (9 downto 0) := "0000000000"; begin process(clkIn) begin if (clkIn'EVENT and clkIn='1') then if clk_div = 0 then case toestand is when idle => if rxIn='0' then err <= '0'; ready <= '0'; clk_div <= "1100000000"; toestand <= d0; else clk_div <= "0000100000"; end if; when d0 => readOut(0) <= rxIn; clk_div <= "1000000000"; toestand <= d1; when d1 => readOut(1) <= rxIn; clk_div <= "1000000000"; toestand <= d2;

Page 78 of 127

when d2 => readOut(2) <= rxIn; clk_div <= "1000000000"; toestand <= d3; when d3 => readOut(3) <= rxIn; clk_div <= "1000000000"; toestand <= d4; when d4 => readOut(4) <= rxIn; clk_div <= "1000000000"; toestand <= d5; when d5 => readOut(5) <= rxIn; clk_div <= "1000000000"; toestand <= d6; when d6 => readOut(6) <= rxIn; clk_div <= "1000000000"; toestand <= d7; when d7 => readOut(7) <= rxIn; clk_div <= "1000000000"; toestand <= pari; when pari => parity <= rxIn; clk_div <= "1000000000"; toestand <= chk_par; when chk_par => if par=parity then ready <= '1'; else err <= '1'; end if; clk_div <= "1000000000"; toestand <= w1; when w1 => clk_div <= "1000000000"; toestand <= idle; when others => toestand <= idle; end case; else clk_div <= clk_div - 1; end if; end if; end process; end UART_rc_arch;

Page 79 of 127

K) LCD project
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity lcd_proj is port( clk : IN std_logic; sw : IN std_logic_vector(1 downto 0); lcd_out : OUT std_logic_vector(10 downto 0) ); end lcd_proj; architecture lcd_watch_arch of lcd_proj is signal dat : std_logic_vector (9 downto 0); signal en : std_logic; signal srst : std_logic; signal scaled_clk : std_logic; component counter is port ( clock : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; start : OUT std_logic; data : OUT std_logic_vector(9 downto 0) ); end component; component lcd_control is port ( clock_in : IN std_logic; data : IN std_logic_vector(9 downto 0); start : IN std_logic; lcd : OUT std_logic_vector(10 downto 0) ); end component; component pll IS --GENERATED BY Mega wizard Plug-in port ( inclk0 : IN STD_LOGIC := 0; c0 : OUT STD_LOGIC ); end component;

Page 80 of 127

begin c1 : counter port map( clock => scaled_clk, reset => srst, start_stop => sw(0), start => en, data => dat ); driver1 : lcd_control port map( clock_in => scaled_clk, data => dat, start => en, lcd => lcd_out ); pll1 : pll port map( inclk0 => clk, c0 => scaled_clk ); srst <= not sw(1); end lcd_watch_arch;

Page 81 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity counter is port ( clock : IN std_logic; reset : IN std_logic; start_stop : IN std_logic; data : OUT std_logic_vector(9 downto 0); start : OUT std_logic ); end counter; architecture counter_arch of counter is signal enable100hz : std_logic; signal enable10hz : std_logic; signal enablesec : std_logic; signal enable10sec : std_logic; signal enablemin : std_logic; signal enable10min : std_logic; signal run : std_logic := 0; signal data_honderd0 : std_logic_vector (15 downto 0); signal data_honderd1 : std_logic_vector (15 downto 0); signal data_sec0 : std_logic_vector (15 downto 0); signal data_sec1 : std_logic_vector (15 downto 0); signal data_min0 : std_logic_vector (15 downto 0); signal data_min1 : std_logic_vector (15 downto 0); signal h_out : std_logic_vector (7 downto 0); signal s_out : std_logic_vector (7 downto 0); signal m_out : std_logic_vector (7 downto 0); component count24bit is port ( clock_in : IN std_logic; enable : IN std_logic; rst : IN std_logic; max : IN std_logic_vector(15 downto 0); carry : OUT std_logic; data : OUT std_logic_vector(15 downto 0) ); end component;

Page 82 of 127

component display_control is port ( clock_in : IN std_logic; honderd : IN std_logic_vector(7 downto 0); sec : IN std_logic_vector(7 downto 0); min : IN std_logic_vector(7 downto 0); rst : IN std_logic; data_out : OUT std_logic_vector(9 downto 0); go : OUT std_logic ); end component; begin downscale_5Mto100 : count24bit port map( clock_in => clock, enable => run, rst => reset, max => 0000111110011111, carry => enable100hz ); count_honderd0 : count24bit port map( clock_in => clock, enable => enable100hz, rst => reset, max => 0000000000001001, carry => enable10hz, data => data_honderd0 ); count_honderd1 : count24bit port map( clock_in => clock, enable => enable10hz, rst => reset, max => 0000000000001001, carry => enablesec, data => data_honderd1 ); count_sec0 : count24bit port map( clock_in => clock, enable => enablesec, rst => reset, max => 0000000000001001, carry => enable10sec, data => data_sec0 );

Page 83 of 127

count_sec1 : count24bit port map( clock_in => clock, enable => enable10sec, rst => reset, max => 0000000000000101, carry => enablemin, data => data_sec1 ); count_min0 : count24bit port map( clock_in => clock, enable => enablemin, rst => reset, max => 0000000000001001, carry => enable10min, data => data_min0 ); count_min1 : count24bit port map( clock_in => clock, enable => enable10min, rst => reset, max => 0000000000000101, data => data_min1 ); d_con1 : display_control port map( clock_in => clock, honderd => h_out, sec => s_out, min => m_out, data_out => data, go => start, rst => reset ); process(start_stop) begin if (start_stop = 0) then run <= not run; end if; end process; h_out <= data_honderd1(3 downto 0) & data_honderd0(3 downto 0); s_out <= data_sec1(3 downto 0) & data_sec0(3 downto 0); m_out <= data_min1(3 downto 0) & data_min0(3 downto 0); end counter_arch;

Page 84 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity count24bit is port( clock_in : IN std_logic; enable : IN std_logic; rst : IN std_logic; max : IN std_logic_vector(15 downto 0); carry : OUT std_logic; data : OUT std_logic_vector (15 downto 0) ); end count24bit; architecture count24bit_arch of count24bit is signal count : std_logic_vector(15 downto 0) := 0000000000000001; signal s_carry : std_logic :=0; begin process(clock_in, rst) begin if (rst = 1) then count <= max; elsif (clock_inEVENT and clock_in = 1) then if enable = 1 then count <= count 1; if count = 0 then count <= max; s_carry <= 1; end if; end if; if s_carry = 1 then s_carry <= 0; end if; end if; data <= max-count; carry <= s_carry; end process; end count24bit_arch;

Page 85 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity display_control is port ( clock_in : IN std_logic; honderd : IN std_logic_vector(7 downto 0); sec : IN std_logic_vector(7 downto 0); min : IN std_logic_vector(7 downto 0); rst : IN std_logic; go : OUT std_logic; data_out : OUT std_logic_vector(9 downto 0) ); end display_control; architecture display_control_arch of display_control is signal space : std_logic_vector(7 downto 0); signal delay : std_logic_vector(3 downto 0); type states is (s0,sw1,s1,sw2,s2,sw3,s3,sw4,p0,w1,p1,w2,p2,w3,p3,w4,p4,w5,p5, w6,p6,w7,p7,w8,p8,w9,stop); signal state : states; begin process(clock_in,rst) variable I : std_logic_vector(26 downto 0); begin if (rst=1) then state<=s0; delay<=1111; elsif (clock_inEVENT and clock_in=1) then --send data case state is when s0 => if delay>0 then delay<=delay-1; else data_out <= 0000011100; state <= sw1; delay<=1111; go<=1; end if; when sw1 => go<=0; if delay>0 then delay<=delay-1; else state <= s1; end if;

Page 86 of 127

when s1 => data_out <= 0000110000; state <= sw2; delay<=1111; go<=1; when sw2 => go<=0; if delay>0 then delay<=delay-1; else state <= s2; end if; when s2 => data_out <= 0001100000; state <= sw3; delay<=1111; go<=1; when sw3 => go<=0; if delay>0 then delay<=delay-1; else state <= s3; end if; when s3 => data_out <= 0010000000; state <= sw4; delay<=1111; space<=11111111; go<=1; when sw4 => go<=0; if delay>0 then delay<=delay-1; else if space>0 then space<=space-1; delay<=1111; else state <= p0; end if; end if; when p0 => data_out <= (10 & min(4) & min(5) & min(6) & min(7) & 1100); state <= w1; delay<=1111; go<=1;

Page 87 of 127

when w1 => go<=0; if delay>0 then delay<=delay-1; else state <= p1; end if; when p1 => data_out <= (10 & min(0) & min(1) & min(2) & min(3) & 1100); state <= w2; delay<=1111; go<=1; when w2 => go<=0; if delay>0 then delay<=delay-1; else state <= p2; end if; when p2 => data_out <= 1001011100; state <= w3; delay<=1111; go<=1; when w3 => go<=0; if delay>0 then delay<=delay-1; else state <= p3; end if; when p3 => data_out <= (10 & sec(4) & sec(5) & sec(6) & sec(7) & 1100); state <= w4; delay<=1111; go<=1; when w4 => go<=0; if delay>0 then delay<=delay-1; else state <= p4; end if;

Page 88 of 127

when p4 => data_out <= (10 & sec(0) & sec(1) & sec(2) & sec(3) & 1100); state <= w5; delay<=1111; go<=1; when w5 => go<=0; if delay>0 then delay<=delay-1; else state <= p5; end if; when p5 => data_out <= 1001011100; state <= w6; delay<=1111; go<=1; when w6 => go<=0; if delay>0 then delay<=delay-1; else state <= p6; end if; when p6 => data_out <= (10 & honderd(4) & honderd(5) & honderd(6) & honderd(7) & 1100); state <= w7; delay<=1111; go<=1; when w7 => go<=0; if delay>0 then delay<=delay-1; else state <= p7; end if; when p7 => data_out <= (10 & honderd(0) & honderd(1) & honderd(2) & honderd(3) & 1100); state <= w8; delay<=1111; go<=1;

Page 89 of 127

when w8 => go<=0; if delay>0 then delay<=delay-1; else state <= p8; end if; when p8 => go <=1; data_out <= 0001000000; delay<=1111; space<=11111111; state<=w9; when w9 => go<=0; if delay>0 then delay<=delay-1; else if space>0 then space<=space-1; delay<=1111; else state<=p0; end if; end if; when stop => when others => state <= s0; end case; end if; end process; end display_control_arch;

Page 90 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity lcd_control is port( clock_in : IN std_logic; data : IN std_logic_vector(9 downto 0); start : in std_logic; lcd : OUT std_logic_vector(10 downto 0) ); end lcd_control; architecture lcd_control_arch of lcd_control is signal cmd : std_logic_vector(9 downto 0); signal en : std_logic; type states is (s0,s1,s2,s3); signal state : states; begin process(clock_in, start) begin if (start=1) then state<=s0; elsif (clock_inEVENT and clock_in=1) then case state is when s0 => cmd<=data; en<=0; state <= s1; when s1 => en<=1; state <= s2; when s2 => en<=0; state<=s3; when s3 => end case; end if; lcd <= en & cmd; end process; end lcd_control_arch;

Page 91 of 127

L) Audio filter project


library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity audio_proj is port( clock : IN std_logic; uart_rx : IN std_logic; uart_tx : OUT std_logic; left : OUT std_logic; right : OUT std_logic; leds : OUT std_logic_vector(7 downto 0); buts : IN std_logic_vector(3 downto 0); reset : IN std_logic; oe : OUT std_logic; bhe0 : OUT std_logic; ble0 : OUT std_logic; bhe1 : OUT std_logic; ble1 : OUT std_logic; cs : OUT std_logic; we : OUT std_logic; adr_out : OUT std_logic_vector(17 downto 0); data_inout : INOUT std_logic_vector(23 downto 0); seg7 : OUT std_logic_vector(6 downto 0) ); end audio_proj; architecture audio_arch of audio_proj is component input_control is port( clock_in : std_logic; rx_in : IN std_logic; data_out : OUT std_logic_vector(7 downto 0); enable_out : OUT std_logic; rst : IN std_logic; sram_oe : OUT std_logic; sram_bhe : OUT std_logic; sram_ble : OUT std_logic; sram_cs : OUT std_logic; sram_we : OUT std_logic; sram_adr : OUT std_logic_vector(17 downto 0); sram_data : INOUT std_logic_vector(23 downto 0) ); end component;

Page 92 of 127

component PWM is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(7 downto 0); pwm_out : OUT std_logic ); end component; component EQ_effect is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(7 downto 0); enable : IN std_logic; amp0 : IN std_logic_vector(2 downto 0); amp1 : IN std_logic_vector(2 downto 0); amp2 : IN std_logic_vector(2 downto 0); amp3 : IN std_logic_vector(2 downto 0) ); end component; component decode7segment is port( code : IN std_logic_vector (3 downto 0); seg7 : OUT std_logic_vector (6 downto 0) ); end component; signal sample : std_logic_vector(7 downto 0); signal delay_audio : std_logic_vector(7 downto 0); signal sample_rate : std_logic; signal bhe : std_logic; signal ble : std_logic; signal audio_out : std_logic; signal amp0 : std_logic_vector(2 downto 0); signal amp1 : std_logic_vector(2 downto 0); signal amp2 : std_logic_vector(2 downto 0); signal amp3 : std_logic_vector(2 downto 0); signal vorig_l : std_logic; signal vorig_r : std_logic; signal vorig_u : std_logic; signal vorig_d : std_logic; signal buf_l : std_logic; signal buf_r : std_logic;

Page 93 of 127

signal buf_u : std_logic; signal buf_d : std_logic; signal sel : std_logic_vector(1 downto 0); signal seg_in : std_logic_vector(3 downto 0); signal buf_rst : std_logic; signal rx : std_logic; begin input : input_control port map( clock_in => clock, rx_in => rx, data_out => sample, enable_out => sample_rate, rst => buf_rst, sram_oe => oe, sram_bhe => bhe, sram_ble => ble, sram_cs => cs, sram_we => we, sram_adr => adr_out, sram_data => data_inout ); pwm1 : PWM port map( clock_in => clock, data_in => delay_audio, pwm_out => audio_out ); eff1 : EQ_effect port map( clock_in => clock, data_in => sample, data_out => delay_audio, enable => sample_rate, amp0 => amp0, amp1 => amp1, amp2 => amp2, amp3 => amp3 );

Page 94 of 127

segm7 : decode7segment port map( code => seg_in, seg7 => seg7 ); bhe0<=bhe; bhe1<=bhe; ble0<=ble; ble1<=ble; left<= audio_out; right<= audio_out; uart_tx<='1'; buf_rst<=not reset; process(clock) begin if (clock'EVENT and clock='1') then if (buf_l='1' and vorig_l='0') then if sel>"00" then sel<=sel-1; end if; end if; if (buf_r='1' and vorig_r='0') then if sel<"11" then sel<=sel+1; end if; end if; if (buf_u='1' and vorig_u='0') then case sel is when "00" => if amp0<"111" then amp0<=amp0+1; end if; when "01" => if amp1<"111" then amp1<=amp1+1; end if; when "10" => if amp2<"111" then amp2<=amp2+1; end if; when "11" => if amp3<"111" then amp3<=amp3+1; end if; end case; end if;

Page 95 of 127

if (buf_d='1' and vorig_d='0') then case sel is when "00" => if amp0>"00" then amp0<=amp0-1; end if; when "01" => if amp1>"000" then amp1<=amp1-1; end if; when "10" => if amp2>"000" then amp2<=amp2-1; end if; when "11" => if amp3>"000" then amp3<=amp3-1; end if; end case; end if; vorig_l<=buf_l; vorig_r<=buf_r; vorig_u<=buf_u; vorig_d<=buf_d; buf_l<=not buts(0); buf_r<=not buts(1); buf_u<=not buts(2); buf_d<=not buts(3); rx<=uart_rx; case sel is when "00" => leds<=11000000; seg_in<='0' & amp0; when "01" => leds<=00110000; seg_in<='0' & amp1; when "10" => leds<=00001100; seg_in<='0' & amp2; when "11" => leds<=00000011; seg_in<='0' & amp3; end case; end if; end process; end audio_arch;

Page 96 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity input_control is port( clock_in : IN std_logic; --50MHz rx_in : IN std_logic; data_out : OUT std_logic_vector(7 downto 0); enable_out : OUT std_logic; rst : IN std_logic; sram_oe : OUT std_logic; sram_bhe : OUT std_logic; sram_ble : OUT std_logic; sram_cs : OUT std_logic; sram_we : OUT std_logic; sram_adr : OUT std_logic_vector(17 downto 0); sram_data : INOUT std_logic_vector(23 downto 0) ); end input_control; architecture in_arch of input_control is component UART is port( dataIn : IN std_logic_vector (7 downto 0); loadData : IN std_logic; dataOut : OUT std_logic_vector (7 downto 0); readDataReady : OUT std_logic; busy : OUT std_logic; error : OUT std_logic; mode : IN std_logic_vector(1 downto 0); clk : IN std_logic; rst : IN std_logic; rx : IN std_logic; tx : OUT std_logic ); end component;

Page 97 of 127

component mem_control is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(23 downto 0); data_out : OUT std_logic_vector(23 downto 0); adr_in : IN std_logic_vector(17 downto 0); r_w : IN std_logic; enable : IN std_logic; oe : OUT std_logic; bhe : OUT std_logic; ble : OUT std_logic; cs : OUT std_logic; we : OUT std_logic; adr_out : OUT std_logic_vector(17 downto 0); data_inout : INOUT std_logic_vector(23 downto 0) ); end component; component count16bit is port ( clock_in : IN std_logic; enable : IN std_logic; rst : IN std_logic; max : IN std_logic_vector(15 downto 0); carry : OUT std_logic; data : OUT std_logic_vector (15 downto 0) ); end component; signal uart_d : std_logic_vector(7 downto 0); signal uart_ready : std_logic; type states is (s0,s2,start); signal state : states; signal tel : std_logic_vector(17 downto 0); signal mem_data_in : std_logic_vector(23 downto 0); signal mem_data_out : std_logic_vector(23 downto 0); signal mem_adr : std_logic_vector(17 downto 0); signal mem_rw : std_logic; signal mem_en : std_logic; signal mem_data_out_buf : std_logic_vector(23 downto 0); signal vorige_ready : std_logic; signal vorige_ready2 : std_logic; signal byte_count : std_logic_vector(1 downto 0); signal curr_addr : std_logic_vector(17 downto 0);

Page 98 of 127

signal en_rate : std_logic; signal go : std_logic; signal dat_out_buf : std_logic_vector (7 downto 0); signal uart_err : std_logic; signal vorige_err : std_logic; signal vorige_err2 : std_logic; signal timeout : std_logic_vector(20 downto 0); signal len : std_logic_vector(17 downto 0); signal rst_buf : std_logic; constant start_addr : std_logic_vector (17 downto 0) := "000000000000000000"; constant deflen : std_logic_vector(17 downto 0) := "001100100101011110"; begin uart1 : UART port map( dataOut => uart_d, readDataReady => uart_ready, clk => clock_in, rx => rx_in, dataIn=>"00000000", loadData=>'0', rst=>rst, mode=>"10", error=>uart_err ); mem : mem_control port map( clock_in => clock_in, data_in => mem_data_in, data_out => mem_data_out, adr_in => mem_adr, r_w => mem_rw, enable => mem_en, oe => sram_oe, bhe => sram_bhe, ble => sram_ble, cs => sram_cs, we => sram_we, adr_out => sram_adr, data_inout => sram_data );

Page 99 of 127

srate : count16bit port map( clock_in => clock_in, enable => go, rst => '0', max => "0000111110011111", carry => en_rate ); process(clock_in, rst_buf) begin if rst_buf='1' then state<=s0; elsif (clock_in'EVENT and clock_in='1') then vorige_ready<=vorige_ready2; vorige_ready2<=uart_ready; vorige_err<=vorige_err2; vorige_err2<=uart_err; data_out<=dat_out_buf; enable_out<=en_rate; case state is when s0 => dat_out_buf<="00000000"; go<='0'; byte_count<="00"; tel<="000000000000000000"; curr_addr<=start_addr; state <= s2; timeout<="111111111111111111111"; len<=deflen; enable_out<='0';

Page 100 of 127

when s2 => if (uart_ready='1' and vorige_ready='0') then timeout<="111111111111111111111"; vorige_ready<='1'; if tel<=len then --write data to mem if byte_count<2 then mem_en<='0'; if byte_count=0 then mem_data_in(7 downto 0)<=uart_d; else mem_data_in(15 downto 8)<=uart_d; end if; byte_count<=byte_count+1; else mem_data_in(23 downto 16)<=uart_d; byte_count<="00"; mem_en<='1'; mem_rw<='0'; mem_adr<=curr_addr; curr_addr<=curr_addr+1; end if; tel<=tel+1; end if; elsif tel>len or (timeout=0 and tel>0) then state <= start; curr_addr<=start_addr; tel<="000000000000000000"; byte_count<="00"; mem_en<='0'; len<=tel; else mem_en<='0'; if timeout>0 then timeout<=timeout-1; end if; end if;

Page 101 of 127

when start => go<='1'; if en_rate='1' then case byte_count is when "00" => mem_adr<=curr_addr; mem_en<='1'; mem_rw<='1'; dat_out_buf<=mem_data_out_buf(23 downto 16); curr_addr<=curr_addr+1; byte_count<="01"; when "01" => dat_out_buf<=mem_data_out_buf(7 downto 0); byte_count<="10"; when "10" => dat_out_buf<=mem_data_out_buf(15 downto 8); byte_count<="00"; when others => byte_count<="00"; end case; tel<=tel+1; if tel>len then curr_addr<=start_addr; tel<="000000000000000000"; end if; else mem_en<='0'; end if; when others => state <=s0; end case; mem_data_out_buf <= mem_data_out; rst_buf<=rst; end if; end process; end in_arch;

Page 102 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity mem_control is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(23 downto 0); data_out : OUT std_logic_vector(23 downto 0); adr_in : IN std_logic_vector(17 downto 0); r_w : IN std_logic; enable : IN std_logic; oe : OUT std_logic; bhe : OUT std_logic; ble : OUT std_logic; cs : OUT std_logic; we : OUT std_logic; adr_out : OUT std_logic_vector(17 downto 0); data_inout : INOUT std_logic_vector(23 downto 0) ); end mem_control; architecture mem_arch of mem_control is type states is (s0,s1,s2); signal state : states; begin process(clock_in) begin if (clock_in'EVENT and clock_in='1') then if r_w='1' then --read case state is when s0 => if enable='1' then oe<='0'; bhe<='0'; ble<='0'; cs<='0'; adr_out<=adr_in; state <= s1; else cs<='1'; end if; we<='1'; data_inout<="ZZZZZZZZZZZZZZZZZZZZZ ZZZ";

Page 103 of 127

when s1 => data_out<=data_inout; state <= s2; when s2 => data_inout<="ZZZZZZZZZZZZZZZZZZZZZ ZZZ"; cs<='1'; state <= s0; when others => state <= s0; end case; else --write case state is when s0 => if enable='1' then oe<='0'; bhe<='0'; ble<='0'; cs<='0'; we<='0'; adr_out<=adr_in; state <= s1; data_inout<=data_in; data_out<="000000000000000000000 000"; else data_inout<="ZZZZZZZZZZZZZZZZZZ ZZZZZZ"; cs<='1'; we<='1'; end if; when s1 => state <= s2; cs<='1'; when s2 => data_out<="000000000000000000000000"; data_inout<="ZZZZZZZZZZZZZZZZZZZZZ ZZZ"; we<='1'; state <= s0; when others => state <= s0; end case; end if; end if; end process; end mem_arch;

Page 104 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity UART is port( dataIn : IN std_logic_vector (7 downto 0); loadData : IN std_logic; dataOut : OUT std_logic_vector (7 downto 0); readDataReady : OUT std_logic; busy : OUT std_logic; error : OUT std_logic; clk : IN std_logic; --50MHZ rst : IN std_logic; mode : IN std_logic_vector(1 downto 0); rx : IN std_logic; tx : OUT std_logic ); end UART; architecture UART_arch of UART is component mux port( muxIn : IN std_logic_vector (15 downto 0); sel : IN std_logic_vector (3 downto 0); clkIn : IN std_logic; muxOut : OUT std_logic ); end component; component parity port( parIn : IN std_logic_vector (7 downto 0); clkIn : IN std_logic; calc : IN std_logic; parOut : OUT std_logic ); end component;

Page 105 of 127

component buf port( bufIn : IN std_logic_vector (7 downto 0); clk : IN std_logic; send : IN std_logic; bufOut : OUT std_logic_vector (7 downto 0) ); end component; component UART_writecontrol port( loadData : IN std_logic; wr_busy : OUT std_logic; clkIn : IN std_logic; rstIn : IN std_logic; baud : IN std_logic; shift : OUT std_logic; par : OUT std_logic; mux_sel : OUT std_logic_vector (3 downto 0) ); end component; component UART_readcontrol port( rxIn : IN std_logic; par : IN std_logic; ready : OUT std_logic; err : OUT std_logic; mode : IN std_logic_vector(1 downto 0); clkIn : IN std_logic; baud : IN std_logic; readOut : OUT std_logic_vector (7 downto 0); rst : IN std_logic ); end component; component pll PORT( inclk0 c0 ); end component; : IN STD_LOGIC := '0'; : OUT STD_LOGIC

Page 106 of 127

component count16bit port ( clock_in : IN std_logic; enable : IN std_logic; rst : IN std_logic; max : IN std_logic_vector(15 downto 0); carry : OUT std_logic; data : OUT std_logic_vector (15 downto 0) ); end component; signal data_in_buf : std_logic_vector (7 downto 0); signal parbit : std_logic; signal calc_parity : std_logic := '0'; signal shiftData : std_logic := '0'; signal muxData : std_logic_vector (15 downto 0); signal s_sel : std_logic_vector (3 downto 0) := "1111"; signal readPar : std_logic; signal readReg : std_logic_vector (7 downto 0); signal readReady2 : std_logic; signal readReady : std_logic; signal clk_4800k : std_logic; signal en_38400hz : std_logic; signal clk_sig : std_logic; signal mode_sel : std_logic_vector(2 downto 0); signal baud : std_logic; signal vorige_clk : std_logic; signal rst_buf : std_logic; begin pll1 : pll port map( inclk0 => clk, c0 => clk_4800k ); c0 : count16bit port map( clock_in => clk_4800k, enable => '1', rst => '0', max => "0000000001111100", carry => en_38400hz );

Page 107 of 127

c1 : count16bit port map( clock_in => clk_4800k, enable => en_38400hz, rst => '0', max => ("0000000000000" & mode_sel), carry => clk_sig ); mux1 : mux port map( muxIn => muxData, sel => s_sel, clkIn => clk, muxOut => tx ); parity1 : parity port map( parIn => data_in_buf, clkIn => clk, calc => calc_parity, parOut => parbit ); buf1 : buf port map( bufIn => dataIn, clk => clk, send => shiftData, bufOut => data_in_buf ); write1 : UART_writecontrol port map( loadData => loadData, wr_busy => busy, clkIn => clk, rstIn => rst, shift => shiftData, par => calc_parity, mux_sel => s_sel, baud=>baud );

Page 108 of 127

read1 : UART_readcontrol port map( rxIn => rx, par => readPar, ready => readReady2, err => error, clkIn => clk, readOut => readReg, baud=>baud, mode => mode, rst => rst_buf ); parity2 : parity port map( parIn => readReg, clkIn => clk, calc => clk, parOut => readPar ); muxData <= "10" & data_in_buf & parbit & "00000"; process(clk) begin if (clk'EVENT and clk='1') then if readReady='0' and readReady2='1' then dataOut<=readReg; end if; if (clk_sig='1' and vorige_clk='0' and mode/="11") or (en_38400hz='1' and vorige_clk='0' and mode="11") then case mode is when "10" => mode_sel<="001"; baud <= clk_sig; when "01" => mode_sel<="011"; baud <= clk_sig; when "00" => mode_sel<="111"; baud <= clk_sig; when others => mode_sel<="000"; baud <= en_38400hz; end case; else baud<='0'; end if; if mode="11" then vorige_clk<=en_38400hz; else vorige_clk<=clk_sig; end if;

Page 109 of 127

readDataReady<=readReady2; readReady<=readReady2; rst_buf<=rst; end if; end process; end UART_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity UART_writecontrol is port( loadData : IN std_logic; wr_busy : OUT std_logic; clkIn : IN std_logic; rstIn : IN std_logic; baud : IN std_logic; shift : OUT std_logic; par : OUT std_logic; mux_sel : OUT std_logic_vector (3 downto 0) ); end UART_writecontrol; architecture UART_wc_arch of UART_writecontrol is type state is (idle,load,start,d0,d1,d2,d3,d4,d5,d6,d7,pari,stop); signal toestand : state; signal vorige_loadData : std_logic := '0'; begin process(clkIn, rstIn) begin if rstIn='1' then toestand <= idle; mux_sel <= "1111"; elsif (clkIn'EVENT and clkIn='1') then if baud='1' then

Page 110 of 127

case toestand is when idle => if loadData='1' and vorige_loadData='0' then toestand <= load; wr_busy <= '1'; else wr_busy <= '0'; end if; shift <= '0'; par <= '0'; mux_sel <= "1111"; vorige_loadData <= loadData; when load => shift <= '1'; toestand <= start; when start => shift <= '0'; par <= '1'; mux_sel <= "1110"; toestand <= d0; when d0 => par <= '0'; mux_sel <= "0110"; toestand <= d1; when d1 => mux_sel <= "0111"; toestand <= d2; when d2 => mux_sel <= "1000"; toestand <= d3; when d3 => mux_sel <= "1001"; toestand <= d4; when d4 => mux_sel <= "1010"; toestand <= d5; when d5 => mux_sel <= "1011"; toestand <= d6; when d6 => mux_sel <= "1100"; toestand <= d7; when d7 => mux_sel <= "1101"; toestand <= pari;

Page 111 of 127

when pari => mux_sel <= "0101"; toestand <= stop; when stop => mux_sel <= "1111"; wr_busy <= '0'; toestand <= idle; when others => toestand <= idle; mux_sel <= "1111"; end case; elsif toestand=idle then mux_sel <= "1111"; end if; end if; end process; end UART_wc_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity UART_readcontrol is port( rxIn : IN std_logic; par : IN std_logic; ready : OUT std_logic; err : OUT std_logic; mode : IN std_logic_vector(1 downto 0); clkIn : IN std_logic; baud : IN std_logic; readOut : OUT std_logic_vector (7 downto 0); rst : IN std_logic ); end UART_readcontrol; architecture UART_rc_arch of UART_readcontrol is type state is (idle,wacht1,sample,wacht,check); signal toestand : state; signal offset : std_logic_vector(13 downto 0); signal max_offset : std_logic_vector(13 downto 0); signal clk_div : std_logic_vector(14 downto 0); signal parity : std_logic;

Page 112 of 127

signal vorige_rxIn : std_logic; signal vorige2_rxIn : std_logic; signal rxIn_b : std_logic; signal samples : std_logic_vector(3 downto 0); signal sample_count : std_logic_vector(2 downto 0); signal sample_offset : std_logic_vector(5 downto 0); signal bit_count : std_logic_vector(3 downto 0); signal huidig_offset : std_logic_vector(12 downto 0); constant o_4800 : std_logic_vector(12 downto 0):="1010000011001"; constant o_9600 : std_logic_vector(12 downto 0):="0100111011000"; constant o_19200 : std_logic_vector(12 downto 0):="0010010110111"; constant o_38400 : std_logic_vector(12 downto 0):="0001000100010"; begin process(clkIn, rst) begin if rst='1' then toestand<=idle; elsif (clkIn'EVENT and clkIn='1') then vorige_rxIn<=vorige2_rxIn; vorige2_rxIn<=rxIn_b; rxIn_b<=rxIn; case toestand is when idle => if baud='1' then max_offset<=offset; offset<="00000000000000"; else offset<=offset+1; end if; case mode is when "00" => huidig_offset <= o_4800; when "01" => huidig_offset <= o_9600; when "10" => huidig_offset <= o_19200; when "11" => huidig_offset <= o_38400; end case; if rxIn_b='0' and vorige_rxIn='1' then toestand<=wacht1; end if;

Page 113 of 127

when wacht1 => ready<='0'; err<='0'; if baud='1' then clk_div<=(('0' & offset)+("00" & huidig_offset)); sample_count<="000"; sample_offset<="000000"; bit_count<="0000"; toestand<=sample; end if; when sample => if clk_div=0 or sample_count>0 then if sample_offset=0 then sample_offset<="101010"; sample_count<=sample_count+1; case sample_count is when "000" => samples(0) <= vorige_rxIn; when "001" => samples(1) <= vorige_rxIn; when "010" => samples(2) <= vorige_rxIn; when "011" => samples(3) <= vorige_rxIn; when others => if (("00" & samples(0)) + ("00" & samples(1)) + ("00" & samples(2)) + ("00" & samples(3)) + ("00" & vorige_rxIn))>2 then case bit_count is when "0000" => readOut(0) <= '1'; when "0001" => readOut(1) <= '1'; when "0010" => readOut(2) <= '1'; when "0011" => readOut(3) <= '1'; when "0100" => readOut(4) <= '1'; when "0101" => readOut(5) <= '1'; when "0110" => readOut(6) <= '1'; when "0111" => readOut(7) <= '1';

Page 114 of 127

when others => parity <= '1'; end case; else case bit_count is when "0000" => readOut(0) <= '0'; when "0001" => readOut(1) <= '0'; when "0010" => readOut(2) <= '0'; when "0011" => readOut(3) <= '0'; when "0100" => readOut(4) <= '0'; when "0101" => readOut(5) <= '0'; when "0110" => readOut(6) <= '0'; when "0111" => readOut(7) <= '0'; when others => parity <= '0'; end case; end if; if bit_count<8 then if clk_div=0 then toestand<=wacht; else sample_count<="000"; sample_offset<="000000"; bit_count<=bit_count+1; end if; else toestand<=check; end if; end case; else sample_offset<=sample_offset-1; end if; end if;

Page 115 of 127

if baud='1' then if (offset+('0' & huidig_offset))>=max_offset then clk_div<=((('0' & offset)+ ("00" & huidig_offset))-('0' & max_offset)); else clk_div<=(('0' & offset)+("00" & huidig_offset)); end if; end if; if clk_div>0 then clk_div<=clk_div-1; end if; when wacht => if baud='1' or clk_div>0 then if (offset+('0' & huidig_offset))>=max_offset then clk_div<=((('0' & offset)+ ("00" & huidig_offset))-('0' & max_offset)); else clk_div<=(('0' & offset)+("00" & huidig_offset)); end if; sample_count<="000"; sample_offset<="000000"; bit_count<=bit_count+1; toestand<=sample; end if; when check => if par=parity then ready <= '1'; err <= '0'; else err <= '1'; ready <= '0'; end if; if (offset+('0' & huidig_offset)+"11010") >=max_offset then offset<=((offset+('0' & huidig_offset)+"11010")max_offset); else offset<=(offset+('0' & huidig_offset)+"11010"); end if; toestand <= idle; when others => toestand <= idle; end case; end if; end process; end UART_rc_arch;

Page 116 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity EQ_effect is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(7 downto 0); enable : IN std_logic; amp0 : IN std_logic_vector(2 downto 0); amp1 : IN std_logic_vector(2 downto 0); amp2 : IN std_logic_vector(2 downto 0); amp3 : IN std_logic_vector(2 downto 0) ); end EQ_effect; architecture EQ_effect_arch of EQ_effect is component FIR is port( clock_in : IN std_logic; --50MHz enable : IN std_logic; data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(17 downto 0); c0 : IN std_logic_vector(7 downto 0); c1 : IN std_logic_vector(7 downto 0); c2 : IN std_logic_vector(7 downto 0); c3 : IN std_logic_vector(7 downto 0); c4 : IN std_logic_vector(7 downto 0); c5 : IN std_logic_vector(7 downto 0); c6 : IN std_logic_vector(7 downto 0); c7 : IN std_logic_vector(7 downto 0); c8 : IN std_logic_vector(7 downto 0); c9 : IN std_logic_vector(7 downto 0); c10 : IN std_logic_vector(7 downto 0); c11 : IN std_logic_vector(7 downto 0); c12 : IN std_logic_vector(7 downto 0); c13 : IN std_logic_vector(7 downto 0); c14 : IN std_logic_vector(7 downto 0); c15 : IN std_logic_vector(7 downto 0) ); end component;

Page 117 of 127

component gain is port( clock_in : IN std_logic; --50MHz enable : IN std_logic; data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(7 downto 0); amount : IN std_logic_vector(2 downto 0) ); end component; signal fir0_out : std_logic_vector(17 downto 0); signal fir1_out : std_logic_vector(17 downto 0); signal fir2_out : std_logic_vector(17 downto 0); signal fir3_out : std_logic_vector(17 downto 0); signal db0_out : std_logic_vector(7 downto 0); signal db1_out : std_logic_vector(7 downto 0); signal db2_out : std_logic_vector(7 downto 0); signal db3_out : std_logic_vector(7 downto 0); signal in_buf0 : std_logic_vector(7 downto 0); signal in_buf1 : std_logic_vector(7 downto 0); signal in_buf2 : std_logic_vector(7 downto 0); signal in_buf3 : std_logic_vector(7 downto 0); begin fir0 : FIR port map( clock_in => clock_in, enable => enable, data_in => in_buf0, data_out => fir0_out, c0 =>"00000101", c1 =>"00001000", c2 =>"00010000", c3 =>"00011100", c4 =>"00101010", c5 =>"00110111", c6 =>"01000001", c7 =>"10000111", c8 =>"10000111", c9 =>"01000001", c10 =>"00110111", c11 =>"00101010", c12 =>"00011100", c13 =>"00010000", c14 =>"00001000", c15 =>"00000101" );--*32

Page 118 of 127

fir1 : FIR port map( clock_in => clock_in, enable => enable, data_in => in_buf1, data_out => fir1_out, c0 =>"00000001", c1 =>"00000011", c2 =>"00001001", c3 =>"00010101", c4 =>"00100110", c5 =>"00111001", c6 =>"01001010", c7 =>"01010011", c8 =>"01010011", c9 =>"01001010", c10 =>"00111001", c11 =>"00100110", c12 =>"00010101", c13 =>"00001001", c14 =>"00000011", c15 =>"00000001" );--*8 fir2 : FIR port map( clock_in => clock_in, enable => enable, data_in => in_buf2, data_out => fir2_out, c0 =>"00000000", c1 =>"11111110", c2 =>"11111100", c3 =>"00000000", c4 =>"11110011", c5 =>"11010111", c6 =>"00000001", c7 =>"01100010", c8 =>"01100010", c9 =>"00000001", c10 =>"11010111", c11 =>"11110011", c12 =>"00000000", c13 =>"11111100", c14 =>"11111110", c15 =>"00000000" );--*2 fir3 : FIR port map( clock_in => clock_in, enable => enable, data_in => in_buf3, data_out => fir3_out, c0 =>"00000000", c1 =>"00000001", c2 =>"11111110", c3 =>"11111010", c4 =>"00001110", c5 =>"00001100", c6 =>"10110100", c7 =>"01110000", c8 =>"10110100", c9 =>"00001100", c10 =>"00001110", c11 =>"11111010", c12 =>"11111110", c13 =>"00000001", c14 =>"00000000", c15 =>"00000000" );--*2

Page 119 of 127

db0 : gain port map( clock_in => clock_in, enable => enable, data_in => "0000" & fir0_out(17 downto 14), data_out => db0_out, amount => amp0 ); db1 : gain port map( clock_in => clock_in, enable => enable, data_in => "000" & fir1_out(17 downto 13), data_out => db1_out, amount => amp1 ); db2 : gain port map( clock_in => clock_in, enable => enable, data_in => fir2_out(16 downto 9), data_out => db2_out, amount => amp2 ); db3 : gain port map( clock_in => clock_in, enable => enable, data_in => fir3_out(16 downto 9), data_out => db3_out, amount => amp3 );

Page 120 of 127

process(clock_in) begin if (clock_in'EVENT and clock_in='1') then data_out<=db0_out+db1_out+db2_out+db3_out; in_buf0<=data_in; in_buf1<=data_in; in_buf2<=data_in; in_buf3<=data_in; end if; end process; end EQ_effect_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_signed.all; entity FIR is port( clock_in : IN std_logic; --50MHz enable : IN std_logic; data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(17 downto 0); c0 : IN std_logic_vector(7 downto 0); c1 : IN std_logic_vector(7 downto 0); c2 : IN std_logic_vector(7 downto 0); c3 : IN std_logic_vector(7 downto 0); c4 : IN std_logic_vector(7 downto 0); c5 : IN std_logic_vector(7 downto 0); c6 : IN std_logic_vector(7 downto 0); c7 : IN std_logic_vector(7 downto 0); c8 : IN std_logic_vector(7 downto 0); c9 : IN std_logic_vector(7 downto 0); c10 : IN std_logic_vector(7 downto 0); c11 : IN std_logic_vector(7 downto 0); c12 : IN std_logic_vector(7 downto 0); c13 : IN std_logic_vector(7 downto 0); c14 : IN std_logic_vector(7 downto 0); c15 : IN std_logic_vector(7 downto 0) ); end FIR;

Page 121 of 127

architecture FIR_arch of FIR is signal d0 : std_logic_vector(7 downto 0); signal d1 : std_logic_vector(7 downto 0); signal d2 : std_logic_vector(7 downto 0); signal d3 : std_logic_vector(7 downto 0); signal d4 : std_logic_vector(7 downto 0); signal d5 : std_logic_vector(7 downto 0); signal d6 : std_logic_vector(7 downto 0); signal d7 : std_logic_vector(7 downto 0); signal d8 : std_logic_vector(7 downto 0); signal d9 : std_logic_vector(7 downto 0); signal d10 : std_logic_vector(7 downto 0); signal d11 : std_logic_vector(7 downto 0); signal d12 : std_logic_vector(7 downto 0); signal d13 : std_logic_vector(7 downto 0); signal d14 : std_logic_vector(7 downto 0); signal d15 : std_logic_vector(7 downto 0); signal sum1 : std_logic_vector(17 downto 0); signal sum2 : std_logic_vector(17 downto 0); begin process(clock_in) begin if (clock_in'EVENT and clock_in='1') then if enable='1' then d0<=data_in; d1<=d0; d2<=d1; d3<=d2; d4<=d3; d5<=d4; d6<=d5; d7<=d6; d8<=d7; d9<=d8; d10<=d9; d11<=d10; d12<=d11; d13<=d12; d14<=d13; d15<=d14;

Page 122 of 127

sum1<=(c0*("00" & d0)) + (c1*("00" & d1)) + (c2*("00" & d2)) + (c3*("00" & d3)) + (c4*("00" & d4)) + (c5*("00" & d5)) + (c6*("00" & d6)) + (c7*("00" & d7)); sum2<=(c8*("00" & d8)) + (c9*("00" & d9)) + (c10*("00" & d10)) + (c11*("00" & d11)) + (c12*("00" & d12)) + (c13*("00" & d13)) + (c14*("00" & d14)) + (c15*("00" & d15)); else if (sum1+sum2)<0 then data_out<="000000000000000000"; else data_out<=(sum1+sum2); end if; end if; end if; end process; end FIR_arch; library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity gain is port( clock_in : IN std_logic; --50MHz enable : IN std_logic; data_in : IN std_logic_vector(7 downto 0); data_out : OUT std_logic_vector(7 downto 0); amount : IN std_logic_vector(2 downto 0) ); end gain;

Page 123 of 127

architecture gain_arch of gain is begin process(clock_in) begin if (clock_in'EVENT and clock_in='1') then if enable='1' then case amount is when "000" => data_out <= data_in; when "001" => data_out <= '0' & data_in(7) & data_in(6) & data_in(5) & data_in(4) & data_in(3) & data_in(2) & data_in(1); when "010" => data_out <= "00" & data_in(7) & data_in(6) & data_in(5) & data_in(4) & data_in(3) & data_in(2); when "011" => data_out <="000" & data_in(7) & data_in(6) & data_in(5) & data_in(4) & data_in(3); when "100" =>data_out<="0000" & data_in(7) & data_in(6) & data_in(5) & data_in(4); when "101" => data_out <= "00000" & data_in(7) & data_in(6) & data_in(5); when "110" => data_out <= "000000" & data_in(7) & data_in(6); when "111" => data_out <= "0000000" & data_in(7); end case; end if; end if; end process; end gain_arch;

Page 124 of 127

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.std_logic_unsigned.all; entity PWM is port( clock_in : IN std_logic; --50MHz data_in : IN std_logic_vector(7 downto 0); pwm_out : OUT std_logic ); end PWM; architecture PWM_arch of PWM is signal tel : std_logic_vector(7 downto 0):="00000000"; begin process(clock_in) begin if (clock_in'EVENT and clock_in='1') then if data_in<=tel then pwm_out<='0'; else pwm_out<='1'; end if; tel<=tel+1; end if; end process; end PWM_arch; VISUAL BASIC CODE: Private Sub cmd_load_Click() Dim FileNr As Integer Dim i As Long Dim Data As Integer Dim str As String Dim a cmd.Caption = "Data transfer..." DoEvents uart.PortOpen = True FileNr = FreeFile Open "data.dat" For Input As FileNr Line Input #FileNr, str Close FileNr

Page 125 of 127

a = Split(str, vbLf) i=0 On Error GoTo einde Do While a(i) <> "" Do While uart.CommEvent = comEventTxFull DoEvents Loop uart.Output = Chr(a(i)) i=i+1 Loop einde: On Error GoTo 0 cmd.Caption = "Finished!" uart.PortOpen = False End Sub

Page 126 of 127

XIII. References

http://www.altera.com (Altera official site) http://www.xilinx.com (Xilinx official site) http://www.digilentinc.com (Xilinx I/O board) http://www.fpga.nl (Altera Audio/VGA board) http://home.iae.nl/users/pouweha/lcd/lcd.shtml (LCD displays) http://emsys.denayer.wenk.be (Embedded Systems research group)

Page 127 of 127

Potrebbero piacerti anche